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)
committerBjorn Helgaas <bhelgaas@google.com>
Fri, 30 May 2014 17:24:58 +0000 (11:24 -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>
drivers/pci/host/pci-exynos.c
drivers/pci/host/pcie-designware.c
drivers/pci/host/pcie-designware.h

index 3de6bfbbe8e95b4805b216662a013f03ee8a7367..b616d34922d8b1a3137d372f41483118577679e0 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 509a29d84509364b366ef1e130ed5ea37b40a091..77a649dd1473d01cac35b2581722b509628be872 100644 (file)
@@ -155,15 +155,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,
@@ -176,6 +178,8 @@ void dw_handle_msi_irq(struct pcie_port *pp)
                        }
                }
        }
+
+       return ret;
 }
 
 void dw_pcie_msi_init(struct pcie_port *pp)
index 3063b3594d8875c9f38b76780045e640ddc61e4a..a169d22d517e027fc629545201184e4096b5d90c 100644 (file)
@@ -68,7 +68,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);