]> rtime.felk.cvut.cz Git - linux-imx.git/blobdiff - arch/powerpc/platforms/pseries/msi.c
powerpc/pseries: Round up MSI-X requests
[linux-imx.git] / arch / powerpc / platforms / pseries / msi.c
index 109fdb75578d780a6a1edf162e556be58570f085..8bc89e4ecb5099f7fa90845fc7a558b78e96e712 100644 (file)
@@ -387,12 +387,13 @@ static int check_msix_entries(struct pci_dev *pdev)
        return 0;
 }
 
-static int rtas_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)
+static int rtas_setup_msi_irqs(struct pci_dev *pdev, int nvec_in, int type)
 {
        struct pci_dn *pdn;
        int hwirq, virq, i, rc;
        struct msi_desc *entry;
        struct msi_msg msg;
+       int nvec = nvec_in;
 
        pdn = get_pdn(pdev);
        if (!pdn)
@@ -401,11 +402,24 @@ static int rtas_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)
        if (type == PCI_CAP_ID_MSIX && check_msix_entries(pdev))
                return -EINVAL;
 
+       /*
+        * Firmware currently refuse any non power of two allocation
+        * so we round up if the quota will allow it.
+        */
+       if (type == PCI_CAP_ID_MSIX) {
+               int m = roundup_pow_of_two(nvec);
+               int quota = msi_quota_for_device(pdev, m);
+
+               if (quota >= m)
+                       nvec = m;
+       }
+
        /*
         * Try the new more explicit firmware interface, if that fails fall
         * back to the old interface. The old interface is known to never
         * return MSI-Xs.
         */
+again:
        if (type == PCI_CAP_ID_MSI) {
                rc = rtas_change_msi(pdn, RTAS_CHANGE_MSI_FN, nvec);
 
@@ -417,6 +431,10 @@ static int rtas_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)
                rc = rtas_change_msi(pdn, RTAS_CHANGE_MSIX_FN, nvec);
 
        if (rc != nvec) {
+               if (nvec != nvec_in) {
+                       nvec = nvec_in;
+                       goto again;
+               }
                pr_debug("rtas_msi: rtas_change_msi() failed\n");
                return rc;
        }