aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/controller/dwc
diff options
context:
space:
mode:
authorMarc Zyngier <marc.zyngier@arm.com>2018-11-13 17:57:34 -0500
committerLorenzo Pieralisi <lorenzo.pieralisi@arm.com>2018-12-11 05:37:58 -0500
commit3f7bb2ec20ce07c02b2002349d256c91a463fcc5 (patch)
tree6ac71be7712de7854c078116debcefb34fbcd6aa /drivers/pci/controller/dwc
parentfce5423e4f431c71933d6c1f850b540a314aa6ee (diff)
PCI: dwc: Move interrupt acking into the proper callback
The write to the status register is really an ACK for the HW, and should be treated as such by the driver. Let's move it to the irq_ack() callback, which will prevent people from moving it around in order to paper over other bugs. Fixes: 8c934095fa2f ("PCI: dwc: Clear MSI interrupt status after it is handled, not before") Fixes: 7c5925afbc58 ("PCI: dwc: Move MSI IRQs allocation to IRQ domains hierarchical API") Link: https://lore.kernel.org/linux-pci/20181113225734.8026-1-marc.zyngier@arm.com/ Reported-by: Trent Piepho <tpiepho@impinj.com> Tested-by: Niklas Cassel <niklas.cassel@linaro.org> Tested-by: Gustavo Pimentel <gustavo.pimentel@synopsys.com> Tested-by: Stanimir Varbanov <svarbanov@mm-sol.com> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com> [lorenzo.pieralisi@arm.com: updated commit log] Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com> Cc: stable@vger.kernel.org
Diffstat (limited to 'drivers/pci/controller/dwc')
-rw-r--r--drivers/pci/controller/dwc/pcie-designware-host.c13
1 files changed, 7 insertions, 6 deletions
diff --git a/drivers/pci/controller/dwc/pcie-designware-host.c b/drivers/pci/controller/dwc/pcie-designware-host.c
index 610a5e018d27..0fa9e8fdce66 100644
--- a/drivers/pci/controller/dwc/pcie-designware-host.c
+++ b/drivers/pci/controller/dwc/pcie-designware-host.c
@@ -99,9 +99,6 @@ irqreturn_t dw_handle_msi_irq(struct pcie_port *pp)
99 (i * MAX_MSI_IRQS_PER_CTRL) + 99 (i * MAX_MSI_IRQS_PER_CTRL) +
100 pos); 100 pos);
101 generic_handle_irq(irq); 101 generic_handle_irq(irq);
102 dw_pcie_wr_own_conf(pp, PCIE_MSI_INTR0_STATUS +
103 (i * MSI_REG_CTRL_BLOCK_SIZE),
104 4, 1 << pos);
105 pos++; 102 pos++;
106 } 103 }
107 } 104 }
@@ -200,14 +197,18 @@ static void dw_pci_bottom_unmask(struct irq_data *data)
200 197
201static void dw_pci_bottom_ack(struct irq_data *d) 198static void dw_pci_bottom_ack(struct irq_data *d)
202{ 199{
203 struct msi_desc *msi = irq_data_get_msi_desc(d); 200 struct pcie_port *pp = irq_data_get_irq_chip_data(d);
204 struct pcie_port *pp; 201 unsigned int res, bit, ctrl;
205 unsigned long flags; 202 unsigned long flags;
206 203
207 pp = msi_desc_to_pci_sysdata(msi); 204 ctrl = d->hwirq / MAX_MSI_IRQS_PER_CTRL;
205 res = ctrl * MSI_REG_CTRL_BLOCK_SIZE;
206 bit = d->hwirq % MAX_MSI_IRQS_PER_CTRL;
208 207
209 raw_spin_lock_irqsave(&pp->lock, flags); 208 raw_spin_lock_irqsave(&pp->lock, flags);
210 209
210 dw_pcie_wr_own_conf(pp, PCIE_MSI_INTR0_STATUS + res, 4, 1 << bit);
211
211 if (pp->ops->msi_irq_ack) 212 if (pp->ops->msi_irq_ack)
212 pp->ops->msi_irq_ack(d->hwirq, pp); 213 pp->ops->msi_irq_ack(d->hwirq, pp);
213 214