diff options
-rw-r--r-- | drivers/iommu/fsl_pamu.c | 32 |
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; } |