4.20-stable review patch. If anyone has any objections, please let me know.
------------------ From: Marc Zyngier <marc.zyng...@arm.com> commit 830920e065e90db318a0da98bf13a02b641eae7f upstream. 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.zyng...@arm.com/ Tested-by: Niklas Cassel <niklas.cas...@linaro.org> Tested-by: Gustavo Pimentel <gustavo.pimen...@synopsys.com> Tested-by: Stanimir Varbanov <svarba...@mm-sol.com> Signed-off-by: Marc Zyngier <marc.zyng...@arm.com> [lorenzo.pieral...@arm.com: updated commit log] Signed-off-by: Lorenzo Pieralisi <lorenzo.pieral...@arm.com> Cc: sta...@vger.kernel.org Signed-off-by: Greg Kroah-Hartman <gre...@linuxfoundation.org> --- drivers/pci/controller/dwc/pcie-designware-host.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) --- 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 ir bit = data->hwirq % MAX_MSI_IRQS_PER_CTRL; pp->irq_status[ctrl] &= ~(1 << bit); - dw_pcie_wr_own_conf(pp, PCIE_MSI_INTR0_ENABLE + res, 4, - pp->irq_status[ctrl]); + dw_pcie_wr_own_conf(pp, PCIE_MSI_INTR0_MASK + res, 4, + ~pp->irq_status[ctrl]); } raw_spin_unlock_irqrestore(&pp->lock, flags); @@ -191,8 +191,8 @@ static void dw_pci_bottom_unmask(struct bit = data->hwirq % MAX_MSI_IRQS_PER_CTRL; pp->irq_status[ctrl] |= 1 << bit; - dw_pcie_wr_own_conf(pp, PCIE_MSI_INTR0_ENABLE + res, 4, - pp->irq_status[ctrl]); + dw_pcie_wr_own_conf(pp, PCIE_MSI_INTR0_MASK + res, 4, + ~pp->irq_status[ctrl]); } raw_spin_unlock_irqrestore(&pp->lock, flags); @@ -658,10 +658,15 @@ void dw_pcie_setup_rc(struct pcie_port * num_ctrls = pp->num_vectors / MAX_MSI_IRQS_PER_CTRL; /* Initialize IRQ Status array */ - for (ctrl = 0; ctrl < num_ctrls; ctrl++) - dw_pcie_rd_own_conf(pp, PCIE_MSI_INTR0_ENABLE + + for (ctrl = 0; ctrl < num_ctrls; ctrl++) { + dw_pcie_wr_own_conf(pp, PCIE_MSI_INTR0_MASK + (ctrl * MSI_REG_CTRL_BLOCK_SIZE), - 4, &pp->irq_status[ctrl]); + 4, ~0); + dw_pcie_wr_own_conf(pp, PCIE_MSI_INTR0_ENABLE + + (ctrl * MSI_REG_CTRL_BLOCK_SIZE), + 4, ~0); + pp->irq_status[ctrl] = 0; + } /* Setup RC BARs */ dw_pcie_writel_dbi(pci, PCI_BASE_ADDRESS_0, 0x00000004);