From 9ed8dd0cc053829f4e896a2e4416de74961521c0 Mon Sep 17 00:00:00 2001 From: Patrick Daly Date: Thu, 7 Jul 2016 17:14:38 -0700 Subject: [PATCH] iommu/arm-smmu: Print device name in context fault handler Multiple physical devices may use the same smmu, but use different context banks. Increase readabilty by printing a human-readable device name, instead of just the streamid. arm-smmu da0000.arm,smmu-vfe: translation fault on da0000.arm,smmu-vfe! arm-smmu da0000.arm,smmu-vfe: PAR = 0x100000203 arm-smmu da0000.arm,smmu-vfe: ATOS failed. Will issue a TLBIALL and try arm-smmu da0000.arm,smmu-vfe: translation fault on da0000.arm,smmu-vfe! arm-smmu da0000.arm,smmu-vfe: PAR = 0x100000203 arm-smmu da0000.arm,smmu-vfe: ATOS still failed. If the page tables look arm-smmu da0000.arm,smmu-vfe: Context Fault for msm_cam_smmu_cb1 arm-smmu da0000.arm,smmu-vfe: Unhandled context fault: iova=0x00000000, Change-Id: I736657ccb275ab7c343357e842ef61591314252c Signed-off-by: Patrick Daly --- drivers/iommu/arm-smmu.c | 34 +++++++++++++++++++++++++++++++--- 1 file changed, 31 insertions(+), 3 deletions(-) diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index ce3f8713df3e..db4b66bb18ed 100644 --- a/drivers/iommu/arm-smmu.c +++ b/drivers/iommu/arm-smmu.c @@ -568,6 +568,28 @@ static struct arm_smmu_master *find_smmu_master(struct arm_smmu_device *smmu, return NULL; } +static struct arm_smmu_master *find_smmu_master_by_sid( + struct arm_smmu_device *smmu, u32 sid) +{ + struct rb_node *next; + struct arm_smmu_master *master; + struct arm_smmu_master_cfg *cfg; + int i; + + next = rb_first(&smmu->masters); + for (; next; next = rb_next(next)) { + master = container_of(next, struct arm_smmu_master, node); + cfg = &master->cfg; + + for (i = 0; i < cfg->num_streamids; i++) { + if (cfg->streamids[i] == sid) + return master; + } + } + + return NULL; +} + static struct arm_smmu_master_cfg * find_smmu_master_cfg(struct device *dev) { @@ -1175,8 +1197,9 @@ static irqreturn_t arm_smmu_context_fault(int irq, void *dev) bool fatal_asf; void __iomem *gr1_base; phys_addr_t phys_soft; - u32 frsynra; + u32 sid; bool non_fatal_fault = smmu_domain->non_fatal_faults; + struct arm_smmu_master *master; static DEFINE_RATELIMIT_STATE(_rs, DEFAULT_RATELIMIT_INTERVAL, @@ -1231,7 +1254,9 @@ static irqreturn_t arm_smmu_context_fault(int irq, void *dev) iova = far; phys_soft = arm_smmu_iova_to_phys(domain, iova); - frsynra = readl_relaxed(gr1_base + ARM_SMMU_GR1_CBFRSYNRA(cfg->cbndx)); + sid = readl_relaxed(gr1_base + ARM_SMMU_GR1_CBFRSYNRA(cfg->cbndx)); + sid &= 0xffff; + master = find_smmu_master_by_sid(smmu, sid); tmp = report_iommu_fault(domain, smmu->dev, iova, flags); if (!tmp || (tmp == -EBUSY)) { dev_dbg(smmu->dev, @@ -1246,6 +1271,9 @@ static irqreturn_t arm_smmu_context_fault(int irq, void *dev) fsr); if (__ratelimit(&_rs)) { + dev_err(smmu->dev, "Context Fault for %s\n", + master ? master->of_node->name : "Unknown SID"); + dev_err(smmu->dev, "Unhandled context fault: iova=0x%08lx, fsr=0x%x, fsynr=0x%x, cb=%d\n", iova, fsr, fsynr, cfg->cbndx); @@ -1271,7 +1299,7 @@ static irqreturn_t arm_smmu_context_fault(int irq, void *dev) dev_name(smmu->dev)); dev_err(smmu->dev, "hard iova-to-phys (ATOS)=%pa\n", &phys_atos); - dev_err(smmu->dev, "SID=0x%x\n", frsynra & 0xffff); + dev_err(smmu->dev, "SID=0x%x\n", sid); } ret = IRQ_NONE; resume = RESUME_TERMINATE;