]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
PCI: designware: Make MSI ISR shared IRQ aware
authorLucas Stach <l.stach@pengutronix.de>
Fri, 28 Mar 2014 16:52:58 +0000 (17:52 +0100)
committerNitin Garg <nitin.garg@freescale.com>
Fri, 16 Jan 2015 03:18:44 +0000 (21:18 -0600)
On i.MX6 the host controller MSI IRQ is shared with PCI legacy INTD.  Make
sure we don't bail too early from the IRQ handler.

The issue is fairly theoretical as it would require a system setup with a
PCIe switch where one connected device is using legacy INTD and another one
using MSI, but better fix it now.

Signed-off-by: Lucas Stach <l.stach@pengutronix.de>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Acked-by: Jingoo Han <jg1.han@samsung.com>
Acked-by: Richard Zhu <r65037@freescale.com>
(cherry picked from commit 7f4f16eef5aeba31bdfb7702ced06a42f2777e04)

drivers/pci/host/pci-exynos.c
drivers/pci/host/pcie-designware.c
drivers/pci/host/pcie-designware.h

index 3b5d4d78364a40af3d053ef42482db1133d53c21..c5d0ca3845028d65e1476ea2e279a70beb6a7049 100644 (file)
@@ -415,9 +415,7 @@ static irqreturn_t exynos_pcie_msi_irq_handler(int irq, void *arg)
 {
        struct pcie_port *pp = arg;
 
-       dw_handle_msi_irq(pp);
-
-       return IRQ_HANDLED;
+       return dw_handle_msi_irq(pp);
 }
 
 static void exynos_pcie_msi_init(struct pcie_port *pp)
index 495846037ca7dae172ba92b59e74db242f43a932..1eaf4df3618a18a57e0eee175272d5a19646f2bf 100644 (file)
@@ -156,15 +156,17 @@ static struct irq_chip dw_msi_irq_chip = {
 };
 
 /* MSI int handler */
-void dw_handle_msi_irq(struct pcie_port *pp)
+irqreturn_t dw_handle_msi_irq(struct pcie_port *pp)
 {
        unsigned long val;
        int i, pos, irq;
+       irqreturn_t ret = IRQ_NONE;
 
        for (i = 0; i < MAX_MSI_CTRLS; i++) {
                dw_pcie_rd_own_conf(pp, PCIE_MSI_INTR0_STATUS + i * 12, 4,
                                (u32 *)&val);
                if (val) {
+                       ret = IRQ_HANDLED;
                        pos = 0;
                        while ((pos = find_next_bit(&val, 32, pos)) != 32) {
                                irq = irq_find_mapping(pp->irq_domain,
@@ -177,6 +179,8 @@ void dw_handle_msi_irq(struct pcie_port *pp)
                        }
                }
        }
+
+       return ret;
 }
 
 void dw_pcie_msi_init(struct pcie_port *pp)
index a10747d58cd7ae350a3dc03ab0965e868524df66..77f592faa7bf28ee6d86f84cad6ee7cdfd345158 100644 (file)
@@ -67,7 +67,7 @@ struct pcie_host_ops {
 
 int dw_pcie_cfg_read(void __iomem *addr, int where, int size, u32 *val);
 int dw_pcie_cfg_write(void __iomem *addr, int where, int size, u32 val);
-void dw_handle_msi_irq(struct pcie_port *pp);
+irqreturn_t dw_handle_msi_irq(struct pcie_port *pp);
 void dw_pcie_msi_init(struct pcie_port *pp);
 int dw_pcie_link_up(struct pcie_port *pp);
 void dw_pcie_setup_rc(struct pcie_port *pp);