static int its_pci_msi_vec_count(struct pci_dev *pdev) { int msi, msix; msi = max(pci_msi_vec_count(pdev), 0); msix = max(pci_msix_vec_count(pdev), 0); return max(msi, msix); }
static int its_pci_msi_vec_count(struct pci_dev *pdev, void *data) { int msi, msix, *count = data; msi = max(pci_msi_vec_count(pdev), 0); msix = max(pci_msix_vec_count(pdev), 0); *count += max(msi, msix); return 0; }
static void qib_msix_setup(struct qib_devdata *dd, int pos, u32 *msixcnt, struct qib_msix_entry *qib_msix_entry) { int ret; int nvec = *msixcnt; struct msix_entry *msix_entry; int i; ret = pci_msix_vec_count(dd->pcidev); if (ret < 0) goto do_intx; nvec = min(nvec, ret); /* We can't pass qib_msix_entry array to qib_msix_setup * so use a dummy msix_entry array and copy the allocated * irq back to the qib_msix_entry array. */ msix_entry = kcalloc(nvec, sizeof(*msix_entry), GFP_KERNEL); if (!msix_entry) goto do_intx; for (i = 0; i < nvec; i++) msix_entry[i] = qib_msix_entry[i].msix; ret = pci_enable_msix_range(dd->pcidev, msix_entry, 1, nvec); if (ret < 0) goto free_msix_entry; else nvec = ret; for (i = 0; i < nvec; i++) qib_msix_entry[i].msix = msix_entry[i]; kfree(msix_entry); *msixcnt = nvec; return; free_msix_entry: kfree(msix_entry); do_intx: qib_dev_err( dd, "pci_enable_msix_range %d vectors failed: %d, falling back to INTx\n", nvec, ret); *msixcnt = 0; qib_enable_intx(dd->pcidev); }
/** * pcie_port_enable_msix - try to set up MSI-X as interrupt mode for given port * @dev: PCI Express port to handle * @vectors: Array of interrupt vectors to populate * @mask: Bitmask of port capabilities returned by get_port_device_capability() * * Return value: 0 on success, error code on failure */ static int pcie_port_enable_msix(struct pci_dev *dev, int *vectors, int mask) { struct msix_entry *msix_entries; int idx[PCIE_PORT_DEVICE_MAXSERVICES]; int nr_entries, status, pos, i, nvec; u16 reg16; u32 reg32; nr_entries = pci_msix_vec_count(dev); if (nr_entries < 0) return nr_entries; BUG_ON(!nr_entries); if (nr_entries > PCIE_PORT_MAX_MSIX_ENTRIES) nr_entries = PCIE_PORT_MAX_MSIX_ENTRIES; msix_entries = kzalloc(sizeof(*msix_entries) * nr_entries, GFP_KERNEL); if (!msix_entries) return -ENOMEM; /* * Allocate as many entries as the port wants, so that we can check * which of them will be useful. Moreover, if nr_entries is correctly * equal to the number of entries this port actually uses, we'll happily * go through without any tricks. */ for (i = 0; i < nr_entries; i++) msix_entries[i].entry = i; status = pci_enable_msix_exact(dev, msix_entries, nr_entries); if (status) goto Exit; for (i = 0; i < PCIE_PORT_DEVICE_MAXSERVICES; i++) idx[i] = -1; status = -EIO; nvec = 0; if (mask & (PCIE_PORT_SERVICE_PME | PCIE_PORT_SERVICE_HP)) { int entry; /* * The code below follows the PCI Express Base Specification 2.0 * stating in Section 6.1.6 that "PME and Hot-Plug Event * interrupts (when both are implemented) always share the same * MSI or MSI-X vector, as indicated by the Interrupt Message * Number field in the PCI Express Capabilities register", where * according to Section 7.8.2 of the specification "For MSI-X, * the value in this field indicates which MSI-X Table entry is * used to generate the interrupt message." */ pcie_capability_read_word(dev, PCI_EXP_FLAGS, ®16); entry = (reg16 & PCI_EXP_FLAGS_IRQ) >> 9; if (entry >= nr_entries) goto Error; i = pcie_port_msix_add_entry(msix_entries, entry, nvec); if (i == nvec) nvec++; idx[PCIE_PORT_SERVICE_PME_SHIFT] = i; idx[PCIE_PORT_SERVICE_HP_SHIFT] = i; }