aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/host
diff options
context:
space:
mode:
authorLucas Stach <l.stach@pengutronix.de>2014-03-28 12:52:58 -0400
committerBjorn Helgaas <bhelgaas@google.com>2014-05-30 13:24:58 -0400
commit7f4f16eef5aeba31bdfb7702ced06a42f2777e04 (patch)
treea10b8f076e0278742ba80181b2d3d3fba56777ad /drivers/pci/host
parent5c40eea7783bbcdd5795cd7d50b7b3fd9a94dc94 (diff)
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: 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>
Diffstat (limited to 'drivers/pci/host')
-rw-r--r--drivers/pci/host/pci-exynos.c4
-rw-r--r--drivers/pci/host/pcie-designware.c6
-rw-r--r--drivers/pci/host/pcie-designware.h2
3 files changed, 7 insertions, 5 deletions
diff --git a/drivers/pci/host/pci-exynos.c b/drivers/pci/host/pci-exynos.c
index 3de6bfbbe8e9..b616d34922d8 100644
--- a/drivers/pci/host/pci-exynos.c
+++ b/drivers/pci/host/pci-exynos.c
@@ -415,9 +415,7 @@ static irqreturn_t exynos_pcie_msi_irq_handler(int irq, void *arg)
415{ 415{
416 struct pcie_port *pp = arg; 416 struct pcie_port *pp = arg;
417 417
418 dw_handle_msi_irq(pp); 418 return dw_handle_msi_irq(pp);
419
420 return IRQ_HANDLED;
421} 419}
422 420
423static void exynos_pcie_msi_init(struct pcie_port *pp) 421static void exynos_pcie_msi_init(struct pcie_port *pp)
diff --git a/drivers/pci/host/pcie-designware.c b/drivers/pci/host/pcie-designware.c
index 509a29d84509..77a649dd1473 100644
--- a/drivers/pci/host/pcie-designware.c
+++ b/drivers/pci/host/pcie-designware.c
@@ -155,15 +155,17 @@ static struct irq_chip dw_msi_irq_chip = {
155}; 155};
156 156
157/* MSI int handler */ 157/* MSI int handler */
158void dw_handle_msi_irq(struct pcie_port *pp) 158irqreturn_t dw_handle_msi_irq(struct pcie_port *pp)
159{ 159{
160 unsigned long val; 160 unsigned long val;
161 int i, pos, irq; 161 int i, pos, irq;
162 irqreturn_t ret = IRQ_NONE;
162 163
163 for (i = 0; i < MAX_MSI_CTRLS; i++) { 164 for (i = 0; i < MAX_MSI_CTRLS; i++) {
164 dw_pcie_rd_own_conf(pp, PCIE_MSI_INTR0_STATUS + i * 12, 4, 165 dw_pcie_rd_own_conf(pp, PCIE_MSI_INTR0_STATUS + i * 12, 4,
165 (u32 *)&val); 166 (u32 *)&val);
166 if (val) { 167 if (val) {
168 ret = IRQ_HANDLED;
167 pos = 0; 169 pos = 0;
168 while ((pos = find_next_bit(&val, 32, pos)) != 32) { 170 while ((pos = find_next_bit(&val, 32, pos)) != 32) {
169 irq = irq_find_mapping(pp->irq_domain, 171 irq = irq_find_mapping(pp->irq_domain,
@@ -176,6 +178,8 @@ void dw_handle_msi_irq(struct pcie_port *pp)
176 } 178 }
177 } 179 }
178 } 180 }
181
182 return ret;
179} 183}
180 184
181void dw_pcie_msi_init(struct pcie_port *pp) 185void dw_pcie_msi_init(struct pcie_port *pp)
diff --git a/drivers/pci/host/pcie-designware.h b/drivers/pci/host/pcie-designware.h
index 3063b3594d88..a169d22d517e 100644
--- a/drivers/pci/host/pcie-designware.h
+++ b/drivers/pci/host/pcie-designware.h
@@ -68,7 +68,7 @@ struct pcie_host_ops {
68 68
69int dw_pcie_cfg_read(void __iomem *addr, int where, int size, u32 *val); 69int dw_pcie_cfg_read(void __iomem *addr, int where, int size, u32 *val);
70int dw_pcie_cfg_write(void __iomem *addr, int where, int size, u32 val); 70int dw_pcie_cfg_write(void __iomem *addr, int where, int size, u32 val);
71void dw_handle_msi_irq(struct pcie_port *pp); 71irqreturn_t dw_handle_msi_irq(struct pcie_port *pp);
72void dw_pcie_msi_init(struct pcie_port *pp); 72void dw_pcie_msi_init(struct pcie_port *pp);
73int dw_pcie_link_up(struct pcie_port *pp); 73int dw_pcie_link_up(struct pcie_port *pp);
74void dw_pcie_setup_rc(struct pcie_port *pp); 74void dw_pcie_setup_rc(struct pcie_port *pp);