Commit 815953dc authored by Jisheng Zhang's avatar Jisheng Zhang Committed by Bjorn Helgaas
Browse files

PCI: dwc: Restore MSI Receiver mask during resume



If a host that uses the IP's integrated MSI Receiver lost power
during suspend, we call dw_pcie_setup_rc() to reinit the RC. But
dw_pcie_setup_rc() always sets pp->irq_mask[ctrl] to ~0, so the mask
register is always set as 0xffffffff incorrectly, thus the MSI can't
work after resume.

Fix this issue by moving pp->irq_mask[ctrl] initialization to
dw_pcie_host_init() so we can correctly set the mask reg during both
boot and resume.

Tested-by: default avatarRichard Zhu <hongxing.zhu@nxp.com>
Link: https://lore.kernel.org/r/20211226074019.2556-1-jszhang@kernel.org


Signed-off-by: default avatarJisheng Zhang <jszhang@kernel.org>
Signed-off-by: default avatarLorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Signed-off-by: default avatarBjorn Helgaas <bhelgaas@google.com>
parent e783362e
Loading
Loading
Loading
Loading
+6 −1
Original line number Original line Diff line number Diff line
@@ -362,6 +362,12 @@ int dw_pcie_host_init(struct pcie_port *pp)
			if (ret < 0)
			if (ret < 0)
				return ret;
				return ret;
		} else if (pp->has_msi_ctrl) {
		} else if (pp->has_msi_ctrl) {
			u32 ctrl, num_ctrls;

			num_ctrls = pp->num_vectors / MAX_MSI_IRQS_PER_CTRL;
			for (ctrl = 0; ctrl < num_ctrls; ctrl++)
				pp->irq_mask[ctrl] = ~0;

			if (!pp->msi_irq) {
			if (!pp->msi_irq) {
				pp->msi_irq = platform_get_irq_byname_optional(pdev, "msi");
				pp->msi_irq = platform_get_irq_byname_optional(pdev, "msi");
				if (pp->msi_irq < 0) {
				if (pp->msi_irq < 0) {
@@ -541,7 +547,6 @@ void dw_pcie_setup_rc(struct pcie_port *pp)


		/* Initialize IRQ Status array */
		/* Initialize IRQ Status array */
		for (ctrl = 0; ctrl < num_ctrls; ctrl++) {
		for (ctrl = 0; ctrl < num_ctrls; ctrl++) {
			pp->irq_mask[ctrl] = ~0;
			dw_pcie_writel_dbi(pci, PCIE_MSI_INTR0_MASK +
			dw_pcie_writel_dbi(pci, PCIE_MSI_INTR0_MASK +
					    (ctrl * MSI_REG_CTRL_BLOCK_SIZE),
					    (ctrl * MSI_REG_CTRL_BLOCK_SIZE),
					    pp->irq_mask[ctrl]);
					    pp->irq_mask[ctrl]);