In Tegra30 any memory controller interrupt would cause an infinite loop in the
IRQ handler. Additionally, a garbage pointer was used to read the MC
status registers, which causes wrong values to be printed if a MC error
occurred.

Signed-off-by: Tuomas Tynkkynen <ttynkky...@nvidia.com>
---
 drivers/memory/tegra30-mc.c | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/drivers/memory/tegra30-mc.c b/drivers/memory/tegra30-mc.c
index f4ae074..58d2979 100644
--- a/drivers/memory/tegra30-mc.c
+++ b/drivers/memory/tegra30-mc.c
@@ -218,7 +218,7 @@ static void tegra30_mc_decode(struct tegra30_mc *mc, int n)
                return;
        }
 
-       err = readl(mc + MC_ERR_STATUS);
+       err = mc_readl(mc, MC_ERR_STATUS);
 
        type = (err & MC_ERR_TYPE_MASK) >> MC_ERR_TYPE_SHIFT;
        perm = (err & MC_ERR_INVALID_SMMU_PAGE_MASK) >>
@@ -235,7 +235,7 @@ static void tegra30_mc_decode(struct tegra30_mc *mc, int n)
        if (cid < ARRAY_SIZE(tegra30_mc_client))
                client = tegra30_mc_client[cid];
 
-       addr = readl(mc + MC_ERR_ADR);
+       addr = mc_readl(mc, MC_ERR_ADR);
 
        dev_err_ratelimited(mc->dev, "%s (0x%08x): 0x%08x %s (%s %s %s %s)\n",
                           mc_int_err[idx], err, addr, client,
@@ -313,8 +313,11 @@ static irqreturn_t tegra30_mc_isr(int irq, void *data)
        mask &= stat;
        if (!mask)
                return IRQ_NONE;
-       while ((bit = ffs(mask)) != 0)
+       while ((bit = ffs(mask)) != 0) {
                tegra30_mc_decode(mc, bit - 1);
+               mask &= ~BIT(bit - 1);
+       }
+
        mc_writel(mc, stat, MC_INTSTATUS);
        return IRQ_HANDLED;
 }
-- 
1.8.1.5

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to