diff options
author | Tuomas Tynkkynen <ttynkkynen@nvidia.com> | 2013-06-11 06:11:19 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2013-06-17 19:46:06 -0400 |
commit | 36dd68319c7b56a76ed450b0e470067b5d74b9b2 (patch) | |
tree | a52728d996ead41a45953a3c6b585b8cdc32a85b /drivers/memory | |
parent | d777f98bfa44e5a2748603276e9e9fb6ab999079 (diff) |
memory: tegra30-mc: Fix IRQ handler.
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 <ttynkkynen@nvidia.com>
Reviewed-by: Stephen Warren <swarren@nvidia.com>
Reviewed-by: Thierry Reding <thierry.reding@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/memory')
-rw-r--r-- | drivers/memory/tegra30-mc.c | 9 |
1 files changed, 6 insertions, 3 deletions
diff --git a/drivers/memory/tegra30-mc.c b/drivers/memory/tegra30-mc.c index f4ae074badc3..58d2979b4035 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) | |||
218 | return; | 218 | return; |
219 | } | 219 | } |
220 | 220 | ||
221 | err = readl(mc + MC_ERR_STATUS); | 221 | err = mc_readl(mc, MC_ERR_STATUS); |
222 | 222 | ||
223 | type = (err & MC_ERR_TYPE_MASK) >> MC_ERR_TYPE_SHIFT; | 223 | type = (err & MC_ERR_TYPE_MASK) >> MC_ERR_TYPE_SHIFT; |
224 | perm = (err & MC_ERR_INVALID_SMMU_PAGE_MASK) >> | 224 | perm = (err & MC_ERR_INVALID_SMMU_PAGE_MASK) >> |
@@ -235,7 +235,7 @@ static void tegra30_mc_decode(struct tegra30_mc *mc, int n) | |||
235 | if (cid < ARRAY_SIZE(tegra30_mc_client)) | 235 | if (cid < ARRAY_SIZE(tegra30_mc_client)) |
236 | client = tegra30_mc_client[cid]; | 236 | client = tegra30_mc_client[cid]; |
237 | 237 | ||
238 | addr = readl(mc + MC_ERR_ADR); | 238 | addr = mc_readl(mc, MC_ERR_ADR); |
239 | 239 | ||
240 | dev_err_ratelimited(mc->dev, "%s (0x%08x): 0x%08x %s (%s %s %s %s)\n", | 240 | dev_err_ratelimited(mc->dev, "%s (0x%08x): 0x%08x %s (%s %s %s %s)\n", |
241 | mc_int_err[idx], err, addr, client, | 241 | mc_int_err[idx], err, addr, client, |
@@ -313,8 +313,11 @@ static irqreturn_t tegra30_mc_isr(int irq, void *data) | |||
313 | mask &= stat; | 313 | mask &= stat; |
314 | if (!mask) | 314 | if (!mask) |
315 | return IRQ_NONE; | 315 | return IRQ_NONE; |
316 | while ((bit = ffs(mask)) != 0) | 316 | while ((bit = ffs(mask)) != 0) { |
317 | tegra30_mc_decode(mc, bit - 1); | 317 | tegra30_mc_decode(mc, bit - 1); |
318 | mask &= ~BIT(bit - 1); | ||
319 | } | ||
320 | |||
318 | mc_writel(mc, stat, MC_INTSTATUS); | 321 | mc_writel(mc, stat, MC_INTSTATUS); |
319 | return IRQ_HANDLED; | 322 | return IRQ_HANDLED; |
320 | } | 323 | } |