PCI/MSI: Add pci_enable_msi_range() and pci_enable_msix_range()
[firefly-linux-kernel-4.4.55.git] / drivers / pci / msi.c
index bd18ecf74c55d07eceaf7a214511f72717df38e1..e6bd8e57d92d81fd4047702dc05d2ea39751c86b 100644 (file)
@@ -1102,3 +1102,77 @@ void pci_msi_init_pci_dev(struct pci_dev *dev)
        if (dev->msix_cap)
                msix_set_enable(dev, 0);
 }
+
+/**
+ * pci_enable_msi_range - configure device's MSI capability structure
+ * @dev: device to configure
+ * @minvec: minimal number of interrupts to configure
+ * @maxvec: maximum number of interrupts to configure
+ *
+ * This function tries to allocate a maximum possible number of interrupts in a
+ * range between @minvec and @maxvec. It returns a negative errno if an error
+ * occurs. If it succeeds, it returns the actual number of interrupts allocated
+ * and updates the @dev's irq member to the lowest new interrupt number;
+ * the other interrupt numbers allocated to this device are consecutive.
+ **/
+int pci_enable_msi_range(struct pci_dev *dev, int minvec, int maxvec)
+{
+       int nvec = maxvec;
+       int rc;
+
+       if (maxvec < minvec)
+               return -ERANGE;
+
+       do {
+               rc = pci_enable_msi_block(dev, nvec);
+               if (rc < 0) {
+                       return rc;
+               } else if (rc > 0) {
+                       if (rc < minvec)
+                               return -ENOSPC;
+                       nvec = rc;
+               }
+       } while (rc);
+
+       return nvec;
+}
+EXPORT_SYMBOL(pci_enable_msi_range);
+
+/**
+ * pci_enable_msix_range - configure device's MSI-X capability structure
+ * @dev: pointer to the pci_dev data structure of MSI-X device function
+ * @entries: pointer to an array of MSI-X entries
+ * @minvec: minimum number of MSI-X irqs requested
+ * @maxvec: maximum number of MSI-X irqs requested
+ *
+ * Setup the MSI-X capability structure of device function with a maximum
+ * possible number of interrupts in the range between @minvec and @maxvec
+ * upon its software driver call to request for MSI-X mode enabled on its
+ * hardware device function. It returns a negative errno if an error occurs.
+ * If it succeeds, it returns the actual number of interrupts allocated and
+ * indicates the successful configuration of MSI-X capability structure
+ * with new allocated MSI-X interrupts.
+ **/
+int pci_enable_msix_range(struct pci_dev *dev, struct msix_entry *entries,
+                              int minvec, int maxvec)
+{
+       int nvec = maxvec;
+       int rc;
+
+       if (maxvec < minvec)
+               return -ERANGE;
+
+       do {
+               rc = pci_enable_msix(dev, entries, nvec);
+               if (rc < 0) {
+                       return rc;
+               } else if (rc > 0) {
+                       if (rc < minvec)
+                               return -ENOSPC;
+                       nvec = rc;
+               }
+       } while (rc);
+
+       return nvec;
+}
+EXPORT_SYMBOL(pci_enable_msix_range);