PCI: tegra194: Fix Root Port interrupt handling

[ Upstream commit 6646e99bcec627e866bc84365af37942c72b4b76 ]

As part of Root Port interrupt handling, level-0 register is read first and
based on the bits set in that, corresponding level-1 registers are read for
further interrupt processing. Since both these values are currently read
into the same 'val' variable, checking level-0 bits the second time around
is happening on the 'val' variable value of level-1 register contents
instead of freshly reading the level-0 value again.

Fix by using different variables to store level-0 and level-1 registers
contents.

Link: https://lore.kernel.org/r/20220721142052.25971-11-vidyas@nvidia.com
Fixes: 56e15a238d ("PCI: tegra: Add Tegra194 PCIe support")
Signed-off-by: Vidya Sagar <vidyas@nvidia.com>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
Vidya Sagar 2022-07-21 19:50:46 +05:30 committed by Greg Kroah-Hartman
parent ed44d9ce8c
commit f916f6e039

View File

@ -345,15 +345,14 @@ static irqreturn_t tegra_pcie_rp_irq_handler(struct tegra_pcie_dw *pcie)
{ {
struct dw_pcie *pci = &pcie->pci; struct dw_pcie *pci = &pcie->pci;
struct pcie_port *pp = &pci->pp; struct pcie_port *pp = &pci->pp;
u32 val, tmp; u32 val, status_l0, status_l1;
u16 val_w; u16 val_w;
val = appl_readl(pcie, APPL_INTR_STATUS_L0); status_l0 = appl_readl(pcie, APPL_INTR_STATUS_L0);
if (val & APPL_INTR_STATUS_L0_LINK_STATE_INT) { if (status_l0 & APPL_INTR_STATUS_L0_LINK_STATE_INT) {
val = appl_readl(pcie, APPL_INTR_STATUS_L1_0_0); status_l1 = appl_readl(pcie, APPL_INTR_STATUS_L1_0_0);
if (val & APPL_INTR_STATUS_L1_0_0_LINK_REQ_RST_NOT_CHGED) { appl_writel(pcie, status_l1, APPL_INTR_STATUS_L1_0_0);
appl_writel(pcie, val, APPL_INTR_STATUS_L1_0_0); if (status_l1 & APPL_INTR_STATUS_L1_0_0_LINK_REQ_RST_NOT_CHGED) {
/* SBR & Surprise Link Down WAR */ /* SBR & Surprise Link Down WAR */
val = appl_readl(pcie, APPL_CAR_RESET_OVRD); val = appl_readl(pcie, APPL_CAR_RESET_OVRD);
val &= ~APPL_CAR_RESET_OVRD_CYA_OVERRIDE_CORE_RST_N; val &= ~APPL_CAR_RESET_OVRD_CYA_OVERRIDE_CORE_RST_N;
@ -369,15 +368,15 @@ static irqreturn_t tegra_pcie_rp_irq_handler(struct tegra_pcie_dw *pcie)
} }
} }
if (val & APPL_INTR_STATUS_L0_INT_INT) { if (status_l0 & APPL_INTR_STATUS_L0_INT_INT) {
val = appl_readl(pcie, APPL_INTR_STATUS_L1_8_0); status_l1 = appl_readl(pcie, APPL_INTR_STATUS_L1_8_0);
if (val & APPL_INTR_STATUS_L1_8_0_AUTO_BW_INT_STS) { if (status_l1 & APPL_INTR_STATUS_L1_8_0_AUTO_BW_INT_STS) {
appl_writel(pcie, appl_writel(pcie,
APPL_INTR_STATUS_L1_8_0_AUTO_BW_INT_STS, APPL_INTR_STATUS_L1_8_0_AUTO_BW_INT_STS,
APPL_INTR_STATUS_L1_8_0); APPL_INTR_STATUS_L1_8_0);
apply_bad_link_workaround(pp); apply_bad_link_workaround(pp);
} }
if (val & APPL_INTR_STATUS_L1_8_0_BW_MGT_INT_STS) { if (status_l1 & APPL_INTR_STATUS_L1_8_0_BW_MGT_INT_STS) {
appl_writel(pcie, appl_writel(pcie,
APPL_INTR_STATUS_L1_8_0_BW_MGT_INT_STS, APPL_INTR_STATUS_L1_8_0_BW_MGT_INT_STS,
APPL_INTR_STATUS_L1_8_0); APPL_INTR_STATUS_L1_8_0);
@ -389,25 +388,24 @@ static irqreturn_t tegra_pcie_rp_irq_handler(struct tegra_pcie_dw *pcie)
} }
} }
val = appl_readl(pcie, APPL_INTR_STATUS_L0); if (status_l0 & APPL_INTR_STATUS_L0_CDM_REG_CHK_INT) {
if (val & APPL_INTR_STATUS_L0_CDM_REG_CHK_INT) { status_l1 = appl_readl(pcie, APPL_INTR_STATUS_L1_18);
val = appl_readl(pcie, APPL_INTR_STATUS_L1_18); val = dw_pcie_readl_dbi(pci, PCIE_PL_CHK_REG_CONTROL_STATUS);
tmp = dw_pcie_readl_dbi(pci, PCIE_PL_CHK_REG_CONTROL_STATUS); if (status_l1 & APPL_INTR_STATUS_L1_18_CDM_REG_CHK_CMPLT) {
if (val & APPL_INTR_STATUS_L1_18_CDM_REG_CHK_CMPLT) {
dev_info(pci->dev, "CDM check complete\n"); dev_info(pci->dev, "CDM check complete\n");
tmp |= PCIE_PL_CHK_REG_CHK_REG_COMPLETE; val |= PCIE_PL_CHK_REG_CHK_REG_COMPLETE;
} }
if (val & APPL_INTR_STATUS_L1_18_CDM_REG_CHK_CMP_ERR) { if (status_l1 & APPL_INTR_STATUS_L1_18_CDM_REG_CHK_CMP_ERR) {
dev_err(pci->dev, "CDM comparison mismatch\n"); dev_err(pci->dev, "CDM comparison mismatch\n");
tmp |= PCIE_PL_CHK_REG_CHK_REG_COMPARISON_ERROR; val |= PCIE_PL_CHK_REG_CHK_REG_COMPARISON_ERROR;
} }
if (val & APPL_INTR_STATUS_L1_18_CDM_REG_CHK_LOGIC_ERR) { if (status_l1 & APPL_INTR_STATUS_L1_18_CDM_REG_CHK_LOGIC_ERR) {
dev_err(pci->dev, "CDM Logic error\n"); dev_err(pci->dev, "CDM Logic error\n");
tmp |= PCIE_PL_CHK_REG_CHK_REG_LOGIC_ERROR; val |= PCIE_PL_CHK_REG_CHK_REG_LOGIC_ERROR;
} }
dw_pcie_writel_dbi(pci, PCIE_PL_CHK_REG_CONTROL_STATUS, tmp); dw_pcie_writel_dbi(pci, PCIE_PL_CHK_REG_CONTROL_STATUS, val);
tmp = dw_pcie_readl_dbi(pci, PCIE_PL_CHK_REG_ERR_ADDR); val = dw_pcie_readl_dbi(pci, PCIE_PL_CHK_REG_ERR_ADDR);
dev_err(pci->dev, "CDM Error Address Offset = 0x%08X\n", tmp); dev_err(pci->dev, "CDM Error Address Offset = 0x%08X\n", val);
} }
return IRQ_HANDLED; return IRQ_HANDLED;