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:
parent
ed44d9ce8c
commit
f916f6e039
@ -345,15 +345,14 @@ static irqreturn_t tegra_pcie_rp_irq_handler(struct tegra_pcie_dw *pcie)
|
||||
{
|
||||
struct dw_pcie *pci = &pcie->pci;
|
||||
struct pcie_port *pp = &pci->pp;
|
||||
u32 val, tmp;
|
||||
u32 val, status_l0, status_l1;
|
||||
u16 val_w;
|
||||
|
||||
val = appl_readl(pcie, APPL_INTR_STATUS_L0);
|
||||
if (val & APPL_INTR_STATUS_L0_LINK_STATE_INT) {
|
||||
val = 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, val, APPL_INTR_STATUS_L1_0_0);
|
||||
|
||||
status_l0 = appl_readl(pcie, APPL_INTR_STATUS_L0);
|
||||
if (status_l0 & APPL_INTR_STATUS_L0_LINK_STATE_INT) {
|
||||
status_l1 = appl_readl(pcie, APPL_INTR_STATUS_L1_0_0);
|
||||
appl_writel(pcie, status_l1, 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 */
|
||||
val = appl_readl(pcie, APPL_CAR_RESET_OVRD);
|
||||
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) {
|
||||
val = appl_readl(pcie, APPL_INTR_STATUS_L1_8_0);
|
||||
if (val & APPL_INTR_STATUS_L1_8_0_AUTO_BW_INT_STS) {
|
||||
if (status_l0 & APPL_INTR_STATUS_L0_INT_INT) {
|
||||
status_l1 = appl_readl(pcie, APPL_INTR_STATUS_L1_8_0);
|
||||
if (status_l1 & APPL_INTR_STATUS_L1_8_0_AUTO_BW_INT_STS) {
|
||||
appl_writel(pcie,
|
||||
APPL_INTR_STATUS_L1_8_0_AUTO_BW_INT_STS,
|
||||
APPL_INTR_STATUS_L1_8_0);
|
||||
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_INTR_STATUS_L1_8_0_BW_MGT_INT_STS,
|
||||
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 (val & APPL_INTR_STATUS_L0_CDM_REG_CHK_INT) {
|
||||
val = appl_readl(pcie, APPL_INTR_STATUS_L1_18);
|
||||
tmp = dw_pcie_readl_dbi(pci, PCIE_PL_CHK_REG_CONTROL_STATUS);
|
||||
if (val & APPL_INTR_STATUS_L1_18_CDM_REG_CHK_CMPLT) {
|
||||
if (status_l0 & APPL_INTR_STATUS_L0_CDM_REG_CHK_INT) {
|
||||
status_l1 = appl_readl(pcie, APPL_INTR_STATUS_L1_18);
|
||||
val = dw_pcie_readl_dbi(pci, PCIE_PL_CHK_REG_CONTROL_STATUS);
|
||||
if (status_l1 & APPL_INTR_STATUS_L1_18_CDM_REG_CHK_CMPLT) {
|
||||
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");
|
||||
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");
|
||||
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);
|
||||
tmp = dw_pcie_readl_dbi(pci, PCIE_PL_CHK_REG_ERR_ADDR);
|
||||
dev_err(pci->dev, "CDM Error Address Offset = 0x%08X\n", tmp);
|
||||
dw_pcie_writel_dbi(pci, PCIE_PL_CHK_REG_CONTROL_STATUS, val);
|
||||
val = dw_pcie_readl_dbi(pci, PCIE_PL_CHK_REG_ERR_ADDR);
|
||||
dev_err(pci->dev, "CDM Error Address Offset = 0x%08X\n", val);
|
||||
}
|
||||
|
||||
return IRQ_HANDLED;
|
||||
|
Loading…
Reference in New Issue
Block a user