summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/iommu/fsl_pamu.c32
1 files changed, 27 insertions, 5 deletions
diff --git a/drivers/iommu/fsl_pamu.c b/drivers/iommu/fsl_pamu.c
index e4be15a..1f69fd1 100644
--- a/drivers/iommu/fsl_pamu.c
+++ b/drivers/iommu/fsl_pamu.c
@@ -834,7 +834,7 @@ irqreturn_t pamu_av_isr(int irq, void *arg)
{
struct pamu_isr_data *data = arg;
phys_addr_t phys;
- unsigned int i, j;
+ unsigned int i, j, ret;
pr_emerg("fsl-pamu: access violation interrupt\n");
@@ -843,9 +843,12 @@ irqreturn_t pamu_av_isr(int irq, void *arg)
u32 pics = in_be32(p + PAMU_PICS);
if (pics & PAMU_ACCESS_VIOLATION_STAT) {
+ struct paace *paace;
+ u32 avs1 = in_be32(p + PAMU_AVS1);
+
pr_emerg("POES1=%08x\n", in_be32(p + PAMU_POES1));
pr_emerg("POES2=%08x\n", in_be32(p + PAMU_POES2));
- pr_emerg("AVS1=%08x\n", in_be32(p + PAMU_AVS1));
+ pr_emerg("AVS1=%08x\n", avs1);
pr_emerg("AVS2=%08x\n", in_be32(p + PAMU_AVS2));
pr_emerg("AVA=%016llx\n", make64(in_be32(p + PAMU_AVAH),
in_be32(p + PAMU_AVAL)));
@@ -864,12 +867,31 @@ irqreturn_t pamu_av_isr(int irq, void *arg)
for (j = 0; j < 4; j++)
pr_emerg("PAACE[%u]=%08x\n", j, in_be32(paace + j));
}
+
+ /* clear access violation condition */
+ out_be32((p + PAMU_AVS1), avs1 & PAMU_AV_MASK);
+ paace = pamu_get_ppaace(avs1 >> PAMU_AVS1_LIODN_SHIFT);
+ BUG_ON(!paace);
+ /* check if we got a violation for a disabled LIODN */
+ if (!get_bf(paace->addr_bitfields, PAACE_AF_V)) {
+ /*
+ * As per hardware erratum A-003638, access
+ * violation can be reported for a disabled
+ * LIODN. If we hit that condition, disable
+ * access violation reporting.
+ */
+ pr_emerg("Disabling access violation reporting\n");
+ pics &= ~PAMU_ACCESS_VIOLATION_ENABLE;
+ } else {
+ /* Disable the LIODN */
+ ret = pamu_disable_liodn(avs1 >> PAMU_AVS1_LIODN_SHIFT);
+ WARN_ON(ret);
+ pr_emerg("Disabling liodn %x\n", avs1 >> PAMU_AVS1_LIODN_SHIFT);
+ }
+ out_be32((p + PAMU_PICS), pics);
}
}
- panic("\n");
- /* NOTREACHED */
-
return IRQ_HANDLED;
}