aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/controller/dwc
diff options
context:
space:
mode:
authorMarc Zyngier <marc.zyngier@arm.com>2018-11-13 17:57:32 -0500
committerLorenzo Pieralisi <lorenzo.pieralisi@arm.com>2018-12-11 05:37:13 -0500
commit830920e065e90db318a0da98bf13a02b641eae7f (patch)
treee86e65c8c848e45a72f75bd863a4bb7b253b3c0c /drivers/pci/controller/dwc
parent651022382c7f8da46cb4872a545ee1da6d097d2a (diff)
PCI: dwc: Use interrupt masking instead of disabling
The dwc driver is showing an interesting level of brokeness, as it insists on using the enable/disable set of registers to mask/unmask MSIs, meaning that an MSIs being generated while the interrupt is in that "disabled" state will simply be lost. Let's move to the mask/unmask set of registers, which offers the expected semantics. 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/ 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.c19
1 files changed, 12 insertions, 7 deletions
diff --git a/drivers/pci/controller/dwc/pcie-designware-host.c b/drivers/pci/controller/dwc/pcie-designware-host.c
index 29a05759a294..0f81b7169147 100644
--- a/drivers/pci/controller/dwc/pcie-designware-host.c
+++ b/drivers/pci/controller/dwc/pcie-designware-host.c
@@ -168,8 +168,8 @@ static void dw_pci_bottom_mask(struct irq_data *data)
168 bit = data->hwirq % MAX_MSI_IRQS_PER_CTRL; 168 bit = data->hwirq % MAX_MSI_IRQS_PER_CTRL;
169 169
170 pp->irq_status[ctrl] &= ~(1 << bit); 170 pp->irq_status[ctrl] &= ~(1 << bit);
171 dw_pcie_wr_own_conf(pp, PCIE_MSI_INTR0_ENABLE + res, 4, 171 dw_pcie_wr_own_conf(pp, PCIE_MSI_INTR0_MASK + res, 4,
172 pp->irq_status[ctrl]); 172 ~pp->irq_status[ctrl]);
173 } 173 }
174 174
175 raw_spin_unlock_irqrestore(&pp->lock, flags); 175 raw_spin_unlock_irqrestore(&pp->lock, flags);
@@ -191,8 +191,8 @@ static void dw_pci_bottom_unmask(struct irq_data *data)
191 bit = data->hwirq % MAX_MSI_IRQS_PER_CTRL; 191 bit = data->hwirq % MAX_MSI_IRQS_PER_CTRL;
192 192
193 pp->irq_status[ctrl] |= 1 << bit; 193 pp->irq_status[ctrl] |= 1 << bit;
194 dw_pcie_wr_own_conf(pp, PCIE_MSI_INTR0_ENABLE + res, 4, 194 dw_pcie_wr_own_conf(pp, PCIE_MSI_INTR0_MASK + res, 4,
195 pp->irq_status[ctrl]); 195 ~pp->irq_status[ctrl]);
196 } 196 }
197 197
198 raw_spin_unlock_irqrestore(&pp->lock, flags); 198 raw_spin_unlock_irqrestore(&pp->lock, flags);
@@ -658,10 +658,15 @@ void dw_pcie_setup_rc(struct pcie_port *pp)
658 num_ctrls = pp->num_vectors / MAX_MSI_IRQS_PER_CTRL; 658 num_ctrls = pp->num_vectors / MAX_MSI_IRQS_PER_CTRL;
659 659
660 /* Initialize IRQ Status array */ 660 /* Initialize IRQ Status array */
661 for (ctrl = 0; ctrl < num_ctrls; ctrl++) 661 for (ctrl = 0; ctrl < num_ctrls; ctrl++) {
662 dw_pcie_rd_own_conf(pp, PCIE_MSI_INTR0_ENABLE + 662 dw_pcie_wr_own_conf(pp, PCIE_MSI_INTR0_MASK +
663 (ctrl * MSI_REG_CTRL_BLOCK_SIZE), 663 (ctrl * MSI_REG_CTRL_BLOCK_SIZE),
664 4, &pp->irq_status[ctrl]); 664 4, ~0);
665 dw_pcie_wr_own_conf(pp, PCIE_MSI_INTR0_ENABLE +
666 (ctrl * MSI_REG_CTRL_BLOCK_SIZE),
667 4, ~0);
668 pp->irq_status[ctrl] = 0;
669 }
665 670
666 /* Setup RC BARs */ 671 /* Setup RC BARs */
667 dw_pcie_writel_dbi(pci, PCI_BASE_ADDRESS_0, 0x00000004); 672 dw_pcie_writel_dbi(pci, PCI_BASE_ADDRESS_0, 0x00000004);