This patch pushes the check for nvec > 1 && MSI into the check function
of each MSI driver except for FSL's MSI where the functionality is
added.

Cc: Arnd Bergmann <a...@arndb.de>
Cc: Gavin Shan <sha...@linux.vnet.ibm.com>
Cc: Alexey Kardashevskiy <a...@ozlabs.ru>
Cc: Alistair Popple <alist...@popple.id.au>
Cc: Brian King <brk...@linux.vnet.ibm.com>
Cc: Anton Blanchard <an...@samba.org>
Cc: Scott Wood <scottw...@freescale.com>
Cc: Minghuan Lian <minghuan.l...@freescale.com>
Cc: Kumar Gala <ga...@kernel.crashing.org>
Signed-off-by: Sebastian Andrzej Siewior <bige...@linutronix.de>
---
 arch/powerpc/kernel/msi.c              |  4 ----
 arch/powerpc/platforms/cell/axon_msi.c |  3 +++
 arch/powerpc/platforms/powernv/pci.c   |  2 ++
 arch/powerpc/platforms/pseries/msi.c   |  3 +++
 arch/powerpc/platforms/wsp/msi.c       |  8 ++++++++
 arch/powerpc/sysdev/fsl_msi.c          | 29 +++++++++++++++++++++--------
 arch/powerpc/sysdev/mpic_pasemi_msi.c  |  3 ++-
 arch/powerpc/sysdev/mpic_u3msi.c       |  2 ++
 arch/powerpc/sysdev/ppc4xx_msi.c       |  2 ++
 9 files changed, 43 insertions(+), 13 deletions(-)

diff --git a/arch/powerpc/kernel/msi.c b/arch/powerpc/kernel/msi.c
index 8bbc12d..46b1470 100644
--- a/arch/powerpc/kernel/msi.c
+++ b/arch/powerpc/kernel/msi.c
@@ -20,10 +20,6 @@ int arch_msi_check_device(struct pci_dev* dev, int nvec, int 
type)
                return -ENOSYS;
        }
 
-       /* PowerPC doesn't support multiple MSI yet */
-       if (type == PCI_CAP_ID_MSI && nvec > 1)
-               return 1;
-
        if (ppc_md.msi_check_device) {
                pr_debug("msi: Using platform check routine.\n");
                return ppc_md.msi_check_device(dev, nvec, type);
diff --git a/arch/powerpc/platforms/cell/axon_msi.c 
b/arch/powerpc/platforms/cell/axon_msi.c
index 85825b5..6e592ed 100644
--- a/arch/powerpc/platforms/cell/axon_msi.c
+++ b/arch/powerpc/platforms/cell/axon_msi.c
@@ -204,6 +204,9 @@ static int axon_msi_check_device(struct pci_dev *dev, int 
nvec, int type)
        if (!find_msi_translator(dev))
                return -ENODEV;
 
+       if (type == PCI_CAP_ID_MSI && nvec > 1)
+               return 1;
+
        return 0;
 }
 
diff --git a/arch/powerpc/platforms/powernv/pci.c 
b/arch/powerpc/platforms/powernv/pci.c
index 95633d7..1d08040 100644
--- a/arch/powerpc/platforms/powernv/pci.c
+++ b/arch/powerpc/platforms/powernv/pci.c
@@ -54,6 +54,8 @@ static int pnv_msi_check_device(struct pci_dev* pdev, int 
nvec, int type)
 
        if (pdn && pdn->force_32bit_msi && !phb->msi32_support)
                return -ENODEV;
+       if (type == PCI_CAP_ID_MSI && nvec > 1)
+               return 1;
 
        return (phb && phb->msi_bmp.bitmap) ? 0 : -ENODEV;
 }
diff --git a/arch/powerpc/platforms/pseries/msi.c 
b/arch/powerpc/platforms/pseries/msi.c
index 0c882e8..ad5e766 100644
--- a/arch/powerpc/platforms/pseries/msi.c
+++ b/arch/powerpc/platforms/pseries/msi.c
@@ -339,6 +339,9 @@ static int rtas_msi_check_device(struct pci_dev *pdev, int 
nvec, int type)
 {
        int quota, rc;
 
+       if (type == PCI_CAP_ID_MSI && nvec > 1)
+               return 1;
+
        if (type == PCI_CAP_ID_MSIX)
                rc = check_req_msix(pdev, nvec);
        else
diff --git a/arch/powerpc/platforms/wsp/msi.c b/arch/powerpc/platforms/wsp/msi.c
index 380882f..0cabd46 100644
--- a/arch/powerpc/platforms/wsp/msi.c
+++ b/arch/powerpc/platforms/wsp/msi.c
@@ -21,6 +21,13 @@
 #define MSI_ADDR_32            0xFFFF0000ul
 #define MSI_ADDR_64            0x1000000000000000ul
 
+static int wsp_msi_check_device(struct pci_dev *dev, int nvec, int type)
+{
+       if (type == PCI_CAP_ID_MSI && nvec > 1)
+               return 1;
+       return 0;
+}
+
 int wsp_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
 {
        struct pci_controller *phb;
@@ -98,5 +105,6 @@ void wsp_setup_phb_msi(struct pci_controller *phb)
        out_be64(phb->cfg_data + PCIE_REG_IODA_DATA0, 1ull << 63);
 
        ppc_md.setup_msi_irqs = wsp_setup_msi_irqs;
+       ppc_md.msi_check_device = wsp_msi_check_device;
        ppc_md.teardown_msi_irqs = wsp_teardown_msi_irqs;
 }
diff --git a/arch/powerpc/sysdev/fsl_msi.c b/arch/powerpc/sysdev/fsl_msi.c
index 77efbae..f07840f 100644
--- a/arch/powerpc/sysdev/fsl_msi.c
+++ b/arch/powerpc/sysdev/fsl_msi.c
@@ -123,13 +123,19 @@ static void fsl_teardown_msi_irqs(struct pci_dev *pdev)
        struct fsl_msi *msi_data;
 
        list_for_each_entry(entry, &pdev->msi_list, list) {
+               int num;
+               int i;
+
                if (entry->irq == NO_IRQ)
                        continue;
                msi_data = irq_get_chip_data(entry->irq);
                irq_set_msi_desc(entry->irq, NULL);
+               num = 1 << entry->msi_attrib.multiple;
                msi_bitmap_free_hwirqs(&msi_data->bitmap,
-                                      virq_to_hw(entry->irq), 1);
-               irq_dispose_mapping(entry->irq);
+                                      virq_to_hw(entry->irq), num);
+
+               for (i = 0; i < num; i++)
+                       irq_dispose_mapping(entry->irq + i);
        }
 
        return;
@@ -172,6 +178,7 @@ static int fsl_setup_msi_irqs(struct pci_dev *pdev, int 
nvec, int type)
        struct msi_desc *entry;
        struct msi_msg msg;
        struct fsl_msi *msi_data;
+       int i;
 
        /*
         * If the PCI node has an fsl,msi property, then we need to use it
@@ -207,7 +214,8 @@ static int fsl_setup_msi_irqs(struct pci_dev *pdev, int 
nvec, int type)
                        if (phandle && (phandle != msi_data->phandle))
                                continue;
 
-                       hwirq = msi_bitmap_alloc_hwirqs(&msi_data->bitmap, 1);
+                       hwirq = msi_bitmap_alloc_hwirqs(&msi_data->bitmap,
+                                       nvec);
                        if (hwirq >= 0)
                                break;
                }
@@ -218,17 +226,22 @@ static int fsl_setup_msi_irqs(struct pci_dev *pdev, int 
nvec, int type)
                        goto out_free;
                }
 
-               virq = irq_create_mapping(msi_data->irqhost, hwirq);
-
+               virq = irq_create_mapping_block(msi_data->irqhost, hwirq, nvec);
                if (virq == NO_IRQ) {
                        dev_err(&pdev->dev, "fail mapping hwirq %i\n", hwirq);
-                       msi_bitmap_free_hwirqs(&msi_data->bitmap, hwirq, 1);
+                       msi_bitmap_free_hwirqs(&msi_data->bitmap, hwirq, nvec);
                        rc = -ENOSPC;
                        goto out_free;
                }
+               entry->msi_attrib.multiple = get_count_order(nvec);
                /* chip_data is msi_data via host->hostdata in host->map() */
-               irq_set_msi_desc(virq, entry);
-
+               for (i = nvec - 1; i >= 0; i--) {
+                       /*
+                        * write the virq mapping last so entry->irq will point
+                        * to first virq
+                        */
+                       irq_set_msi_desc(virq + i, entry);
+               }
                fsl_compose_msi_msg(pdev, hwirq, &msg, msi_data);
                write_msi_msg(virq, &msg);
        }
diff --git a/arch/powerpc/sysdev/mpic_pasemi_msi.c 
b/arch/powerpc/sysdev/mpic_pasemi_msi.c
index 38e6238..3d36f7e 100644
--- a/arch/powerpc/sysdev/mpic_pasemi_msi.c
+++ b/arch/powerpc/sysdev/mpic_pasemi_msi.c
@@ -67,7 +67,8 @@ static int pasemi_msi_check_device(struct pci_dev *pdev, int 
nvec, int type)
 {
        if (type == PCI_CAP_ID_MSIX)
                pr_debug("pasemi_msi: MSI-X untested, trying anyway\n");
-
+       if (type == PCI_CAP_ID_MSI && nvec > 1)
+               return 1;
        return 0;
 }
 
diff --git a/arch/powerpc/sysdev/mpic_u3msi.c b/arch/powerpc/sysdev/mpic_u3msi.c
index 9a7aa0e..f6f86ac 100644
--- a/arch/powerpc/sysdev/mpic_u3msi.c
+++ b/arch/powerpc/sysdev/mpic_u3msi.c
@@ -109,6 +109,8 @@ static int u3msi_msi_check_device(struct pci_dev *pdev, int 
nvec, int type)
 {
        if (type == PCI_CAP_ID_MSIX)
                pr_debug("u3msi: MSI-X untested, trying anyway.\n");
+       if (type == PCI_CAP_ID_MSI && nvec > 1)
+               return 1;
 
        /* If we can't find a magic address then MSI ain't gonna work */
        if (find_ht_magic_addr(pdev, 0) == 0 &&
diff --git a/arch/powerpc/sysdev/ppc4xx_msi.c b/arch/powerpc/sysdev/ppc4xx_msi.c
index 43948da..af1efeb 100644
--- a/arch/powerpc/sysdev/ppc4xx_msi.c
+++ b/arch/powerpc/sysdev/ppc4xx_msi.c
@@ -140,6 +140,8 @@ static int ppc4xx_msi_check_device(struct pci_dev *pdev, 
int nvec, int type)
                __func__, nvec, type);
        if (type == PCI_CAP_ID_MSIX)
                pr_debug("ppc4xx msi: MSI-X untested, trying anyway.\n");
+       if (type == PCI_CAP_ID_MSI && nvec > 1)
+               return 1;
 
        return 0;
 }
-- 
1.9.0.rc3

_______________________________________________
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev

Reply via email to