[PATCH 2/2] powerpc: msi: fsl: add support for multiple MSI interrupts
From: Johannes Thumshirn <hidden>
Date: 2014-11-03 16:18:53
Subsystem:
cell broadband engine architecture, linux for powerpc (32-bit and 64-bit), the rest · Maintainers:
Madhavan Srinivasan, Linus Torvalds
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. Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> Signed-off-by: Johannes Thumshirn <redacted> --- arch/powerpc/kernel/msi.c | 4 ---- arch/powerpc/platforms/cell/axon_msi.c | 3 +++ arch/powerpc/platforms/powernv/pci.c | 3 +++ arch/powerpc/platforms/pseries/msi.c | 3 +++ arch/powerpc/sysdev/fsl_msi.c | 22 ++++++++++++++++------ arch/powerpc/sysdev/mpic_pasemi_msi.c | 3 +++ arch/powerpc/sysdev/mpic_u3msi.c | 3 +++ arch/powerpc/sysdev/ppc4xx_msi.c | 2 ++ 8 files changed, 33 insertions(+), 10 deletions(-)
diff --git a/arch/powerpc/kernel/msi.c b/arch/powerpc/kernel/msi.c
index 71bd161..80ee2f4 100644
--- a/arch/powerpc/kernel/msi.c
+++ b/arch/powerpc/kernel/msi.c@@ -20,10 +20,6 @@ int arch_setup_msi_irqs(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; - return ppc_md.setup_msi_irqs(dev, nvec, type); }
diff --git a/arch/powerpc/platforms/cell/axon_msi.c b/arch/powerpc/platforms/cell/axon_msi.c
index 862b327..537a70e 100644
--- a/arch/powerpc/platforms/cell/axon_msi.c
+++ b/arch/powerpc/platforms/cell/axon_msi.c@@ -250,6 +250,9 @@ static int setup_msi_msg_address(struct pci_dev *dev, struct msi_msg *msg) of_node_put(dn); + 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 b2187d0..de33ec0 100644
--- a/arch/powerpc/platforms/powernv/pci.c
+++ b/arch/powerpc/platforms/powernv/pci.c@@ -63,6 +63,9 @@ static int pnv_setup_msi_irqs(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; + list_for_each_entry(entry, &pdev->msi_list, list) { if (!entry->msi_attrib.is_64 && !phb->msi32_support) { pr_warn("%s: Supports only 64-bit MSIs\n",
diff --git a/arch/powerpc/platforms/pseries/msi.c b/arch/powerpc/platforms/pseries/msi.c
index 8ab5add..544e924 100644
--- a/arch/powerpc/platforms/pseries/msi.c
+++ b/arch/powerpc/platforms/pseries/msi.c@@ -383,6 +383,9 @@ static int rtas_setup_msi_irqs(struct pci_dev *pdev, int nvec_in, int type) int nvec = nvec_in; int use_32bit_msi_hack = 0; + 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/sysdev/fsl_msi.c b/arch/powerpc/sysdev/fsl_msi.c
index de40b48..454e8b1 100644
--- a/arch/powerpc/sysdev/fsl_msi.c
+++ b/arch/powerpc/sysdev/fsl_msi.c@@ -131,13 +131,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;
@@ -180,6 +186,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 (type == PCI_CAP_ID_MSIX) pr_debug("fslmsi: MSI-X untested, trying anyway.\n");
@@ -219,7 +226,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; }
@@ -230,16 +238,18 @@ 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--) + 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 15dccd3..03bace0 100644
--- a/arch/powerpc/sysdev/mpic_pasemi_msi.c
+++ b/arch/powerpc/sysdev/mpic_pasemi_msi.c@@ -139,6 +139,9 @@ static int pasemi_msi_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type) write_msi_msg(virq, &msg); } + if (typpe == 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 623d7fb..5024629 100644
--- a/arch/powerpc/sysdev/mpic_u3msi.c
+++ b/arch/powerpc/sysdev/mpic_u3msi.c@@ -133,6 +133,9 @@ static int u3msi_setup_msi_irqs(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 && find_u4_magic_addr(pdev, 0) == 0) {
diff --git a/arch/powerpc/sysdev/ppc4xx_msi.c b/arch/powerpc/sysdev/ppc4xx_msi.c
index 22b5200..8bbb228 100644
--- a/arch/powerpc/sysdev/ppc4xx_msi.c
+++ b/arch/powerpc/sysdev/ppc4xx_msi.c@@ -89,6 +89,8 @@ static int ppc4xx_setup_msi_irqs(struct pci_dev *dev, 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; msi_data->msi_virqs = kmalloc((msi_irqs) * sizeof(int), GFP_KERNEL); if (!msi_data->msi_virqs)
--
1.9.1