Commit 7f4f16ee authored by Lucas Stach's avatar Lucas Stach Committed by Bjorn Helgaas

PCI: designware: Make MSI ISR shared IRQ aware

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: default avatarLucas Stach <l.stach@pengutronix.de>
Signed-off-by: default avatarBjorn Helgaas <bhelgaas@google.com>
Acked-by: default avatarJingoo Han <jg1.han@samsung.com>
Acked-by: default avatarRichard Zhu <r65037@freescale.com>
parent 5c40eea7
...@@ -415,9 +415,7 @@ static irqreturn_t exynos_pcie_msi_irq_handler(int irq, void *arg) ...@@ -415,9 +415,7 @@ static irqreturn_t exynos_pcie_msi_irq_handler(int irq, void *arg)
{ {
struct pcie_port *pp = arg; struct pcie_port *pp = arg;
dw_handle_msi_irq(pp); return dw_handle_msi_irq(pp);
return IRQ_HANDLED;
} }
static void exynos_pcie_msi_init(struct pcie_port *pp) static void exynos_pcie_msi_init(struct pcie_port *pp)
......
...@@ -155,15 +155,17 @@ static struct irq_chip dw_msi_irq_chip = { ...@@ -155,15 +155,17 @@ static struct irq_chip dw_msi_irq_chip = {
}; };
/* MSI int handler */ /* 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; unsigned long val;
int i, pos, irq; int i, pos, irq;
irqreturn_t ret = IRQ_NONE;
for (i = 0; i < MAX_MSI_CTRLS; i++) { for (i = 0; i < MAX_MSI_CTRLS; i++) {
dw_pcie_rd_own_conf(pp, PCIE_MSI_INTR0_STATUS + i * 12, 4, dw_pcie_rd_own_conf(pp, PCIE_MSI_INTR0_STATUS + i * 12, 4,
(u32 *)&val); (u32 *)&val);
if (val) { if (val) {
ret = IRQ_HANDLED;
pos = 0; pos = 0;
while ((pos = find_next_bit(&val, 32, pos)) != 32) { while ((pos = find_next_bit(&val, 32, pos)) != 32) {
irq = irq_find_mapping(pp->irq_domain, irq = irq_find_mapping(pp->irq_domain,
...@@ -176,6 +178,8 @@ void dw_handle_msi_irq(struct pcie_port *pp) ...@@ -176,6 +178,8 @@ void dw_handle_msi_irq(struct pcie_port *pp)
} }
} }
} }
return ret;
} }
void dw_pcie_msi_init(struct pcie_port *pp) void dw_pcie_msi_init(struct pcie_port *pp)
......
...@@ -68,7 +68,7 @@ struct pcie_host_ops { ...@@ -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_read(void __iomem *addr, int where, int size, u32 *val);
int dw_pcie_cfg_write(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); void dw_pcie_msi_init(struct pcie_port *pp);
int dw_pcie_link_up(struct pcie_port *pp); int dw_pcie_link_up(struct pcie_port *pp);
void dw_pcie_setup_rc(struct pcie_port *pp); void dw_pcie_setup_rc(struct pcie_port *pp);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment