summaryrefslogtreecommitdiff
path: root/backport/compat/backport-4.8.c
diff options
context:
space:
mode:
Diffstat (limited to 'backport/compat/backport-4.8.c')
-rw-r--r--backport/compat/backport-4.8.c49
1 files changed, 36 insertions, 13 deletions
diff --git a/backport/compat/backport-4.8.c b/backport/compat/backport-4.8.c
index a53e39c9..11b2e7d7 100644
--- a/backport/compat/backport-4.8.c
+++ b/backport/compat/backport-4.8.c
@@ -148,25 +148,48 @@ EXPORT_SYMBOL_GPL(cdc_parse_cdc_header);
#ifdef CONFIG_PCI
#ifdef CONFIG_PCI_MSI
+
+/**
+ * pci_alloc_irq_vectors - allocate multiple IRQs for a device
+ * @dev: PCI device to operate on
+ * @min_vecs: minimum number of vectors required (must be >= 1)
+ * @max_vecs: maximum (desired) number of vectors
+ * @flags: flags or quirks for the allocation
+ *
+ * Allocate up to @max_vecs interrupt vectors for @dev, using MSI-X or MSI
+ * vectors if available, and fall back to a single legacy vector
+ * if neither is available. Return the number of vectors allocated,
+ * (which might be smaller than @max_vecs) if successful, or a negative
+ * error code on error. If less than @min_vecs interrupt vectors are
+ * available for @dev the function will fail with -ENOSPC.
+ *
+ * To get the Linux IRQ number used for a vector that can be passed to
+ * request_irq() use the pci_irq_vector() helper.
+ */
int pci_alloc_irq_vectors(struct pci_dev *dev, unsigned int min_vecs,
unsigned int max_vecs, unsigned int flags)
{
- int res;
- int msi_nvect = max_vecs;
+ int vecs = -ENOSPC;
- if (max_vecs < min_vecs)
- return -ERANGE;
+ if (flags & PCI_IRQ_MSIX) {
+ vecs = pci_enable_msix_range(dev, NULL, min_vecs, max_vecs);
+ if (vecs > 0)
+ return vecs;
+ }
+
+ if (flags & PCI_IRQ_MSI) {
+ vecs = pci_enable_msi_range(dev, min_vecs, max_vecs);
+ if (vecs > 0)
+ return vecs;
+ }
-#if LINUX_VERSION_IS_LESS(3,15,0)
- res = pci_enable_msi_block(dev, msi_nvect);
- if (res == 0) {
- return msi_nvect;
+ /* use legacy irq if allowed */
+ if ((flags & PCI_IRQ_LEGACY) && min_vecs == 1) {
+ pci_intx(dev, 1);
+ return 1;
}
-#else
- res = pci_enable_msi_range(dev, msi_nvect, msi_nvect);
- return msi_nvect;
-#endif /*LINUX_VERSION_IS_LESS(3,15,0)*/
- return -ENOSPC;
+
+ return vecs;
}
EXPORT_SYMBOL_GPL(pci_alloc_irq_vectors);
#endif /* CONFIG_PCI_MSI */