aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2016-08-26 23:12:35 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2016-08-26 23:12:35 -0400
commit67a8c7d636886ee05cc139833b8f1aef0e685c2c (patch)
tree27b931132dc06b681170c32d6e41ea46a181d073
parentfd1ae514528bfa7136640301523f646f396134e2 (diff)
parent4df36185bb364f9727d1c0816acac3b9a5ae2603 (diff)
Merge tag 'iommu-fixes-v4.8-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu
Pull IOMMU fixes from Joerg Roedel: "Fixes from Will Deacon: - fix a couple of thinkos in the CMDQ error handling and short-descriptor page table code that have been there since day one - disable stalling faults, since they may result in hardware deadlock - fix an accidental BUG() when passing disable_bypass=1 on the cmdline" * tag 'iommu-fixes-v4.8-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu: iommu/arm-smmu: Don't BUG() if we find aborting STEs with disable_bypass iommu/arm-smmu: Disable stalling faults for all endpoints iommu/arm-smmu: Fix CMDQ error handling iommu/io-pgtable-arm-v7s: Fix attributes when splitting blocks
-rw-r--r--drivers/iommu/arm-smmu-v3.c7
-rw-r--r--drivers/iommu/arm-smmu.c34
-rw-r--r--drivers/iommu/io-pgtable-arm-v7s.c4
3 files changed, 15 insertions, 30 deletions
diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c
index ce801170d5f2..641e88761319 100644
--- a/drivers/iommu/arm-smmu-v3.c
+++ b/drivers/iommu/arm-smmu-v3.c
@@ -879,7 +879,7 @@ static void arm_smmu_cmdq_skip_err(struct arm_smmu_device *smmu)
879 * We may have concurrent producers, so we need to be careful 879 * We may have concurrent producers, so we need to be careful
880 * not to touch any of the shadow cmdq state. 880 * not to touch any of the shadow cmdq state.
881 */ 881 */
882 queue_read(cmd, Q_ENT(q, idx), q->ent_dwords); 882 queue_read(cmd, Q_ENT(q, cons), q->ent_dwords);
883 dev_err(smmu->dev, "skipping command in error state:\n"); 883 dev_err(smmu->dev, "skipping command in error state:\n");
884 for (i = 0; i < ARRAY_SIZE(cmd); ++i) 884 for (i = 0; i < ARRAY_SIZE(cmd); ++i)
885 dev_err(smmu->dev, "\t0x%016llx\n", (unsigned long long)cmd[i]); 885 dev_err(smmu->dev, "\t0x%016llx\n", (unsigned long long)cmd[i]);
@@ -890,7 +890,7 @@ static void arm_smmu_cmdq_skip_err(struct arm_smmu_device *smmu)
890 return; 890 return;
891 } 891 }
892 892
893 queue_write(cmd, Q_ENT(q, idx), q->ent_dwords); 893 queue_write(Q_ENT(q, cons), cmd, q->ent_dwords);
894} 894}
895 895
896static void arm_smmu_cmdq_issue_cmd(struct arm_smmu_device *smmu, 896static void arm_smmu_cmdq_issue_cmd(struct arm_smmu_device *smmu,
@@ -1034,6 +1034,9 @@ static void arm_smmu_write_strtab_ent(struct arm_smmu_device *smmu, u32 sid,
1034 case STRTAB_STE_0_CFG_S2_TRANS: 1034 case STRTAB_STE_0_CFG_S2_TRANS:
1035 ste_live = true; 1035 ste_live = true;
1036 break; 1036 break;
1037 case STRTAB_STE_0_CFG_ABORT:
1038 if (disable_bypass)
1039 break;
1037 default: 1040 default:
1038 BUG(); /* STE corruption */ 1041 BUG(); /* STE corruption */
1039 } 1042 }
diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
index 4f49fe29f202..2db74ebc3240 100644
--- a/drivers/iommu/arm-smmu.c
+++ b/drivers/iommu/arm-smmu.c
@@ -686,8 +686,7 @@ static struct iommu_gather_ops arm_smmu_gather_ops = {
686 686
687static irqreturn_t arm_smmu_context_fault(int irq, void *dev) 687static irqreturn_t arm_smmu_context_fault(int irq, void *dev)
688{ 688{
689 int flags, ret; 689 u32 fsr, fsynr;
690 u32 fsr, fsynr, resume;
691 unsigned long iova; 690 unsigned long iova;
692 struct iommu_domain *domain = dev; 691 struct iommu_domain *domain = dev;
693 struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain); 692 struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain);
@@ -701,34 +700,15 @@ static irqreturn_t arm_smmu_context_fault(int irq, void *dev)
701 if (!(fsr & FSR_FAULT)) 700 if (!(fsr & FSR_FAULT))
702 return IRQ_NONE; 701 return IRQ_NONE;
703 702
704 if (fsr & FSR_IGN)
705 dev_err_ratelimited(smmu->dev,
706 "Unexpected context fault (fsr 0x%x)\n",
707 fsr);
708
709 fsynr = readl_relaxed(cb_base + ARM_SMMU_CB_FSYNR0); 703 fsynr = readl_relaxed(cb_base + ARM_SMMU_CB_FSYNR0);
710 flags = fsynr & FSYNR0_WNR ? IOMMU_FAULT_WRITE : IOMMU_FAULT_READ;
711
712 iova = readq_relaxed(cb_base + ARM_SMMU_CB_FAR); 704 iova = readq_relaxed(cb_base + ARM_SMMU_CB_FAR);
713 if (!report_iommu_fault(domain, smmu->dev, iova, flags)) {
714 ret = IRQ_HANDLED;
715 resume = RESUME_RETRY;
716 } else {
717 dev_err_ratelimited(smmu->dev,
718 "Unhandled context fault: iova=0x%08lx, fsynr=0x%x, cb=%d\n",
719 iova, fsynr, cfg->cbndx);
720 ret = IRQ_NONE;
721 resume = RESUME_TERMINATE;
722 }
723
724 /* Clear the faulting FSR */
725 writel(fsr, cb_base + ARM_SMMU_CB_FSR);
726 705
727 /* Retry or terminate any stalled transactions */ 706 dev_err_ratelimited(smmu->dev,
728 if (fsr & FSR_SS) 707 "Unhandled context fault: fsr=0x%x, iova=0x%08lx, fsynr=0x%x, cb=%d\n",
729 writel_relaxed(resume, cb_base + ARM_SMMU_CB_RESUME); 708 fsr, iova, fsynr, cfg->cbndx);
730 709
731 return ret; 710 writel(fsr, cb_base + ARM_SMMU_CB_FSR);
711 return IRQ_HANDLED;
732} 712}
733 713
734static irqreturn_t arm_smmu_global_fault(int irq, void *dev) 714static irqreturn_t arm_smmu_global_fault(int irq, void *dev)
@@ -837,7 +817,7 @@ static void arm_smmu_init_context_bank(struct arm_smmu_domain *smmu_domain,
837 } 817 }
838 818
839 /* SCTLR */ 819 /* SCTLR */
840 reg = SCTLR_CFCFG | SCTLR_CFIE | SCTLR_CFRE | SCTLR_M | SCTLR_EAE_SBOP; 820 reg = SCTLR_CFIE | SCTLR_CFRE | SCTLR_M | SCTLR_EAE_SBOP;
841 if (stage1) 821 if (stage1)
842 reg |= SCTLR_S1_ASIDPNE; 822 reg |= SCTLR_S1_ASIDPNE;
843#ifdef __BIG_ENDIAN 823#ifdef __BIG_ENDIAN
diff --git a/drivers/iommu/io-pgtable-arm-v7s.c b/drivers/iommu/io-pgtable-arm-v7s.c
index 8c6139986d7d..def8ca1c982d 100644
--- a/drivers/iommu/io-pgtable-arm-v7s.c
+++ b/drivers/iommu/io-pgtable-arm-v7s.c
@@ -286,12 +286,14 @@ static int arm_v7s_pte_to_prot(arm_v7s_iopte pte, int lvl)
286 int prot = IOMMU_READ; 286 int prot = IOMMU_READ;
287 arm_v7s_iopte attr = pte >> ARM_V7S_ATTR_SHIFT(lvl); 287 arm_v7s_iopte attr = pte >> ARM_V7S_ATTR_SHIFT(lvl);
288 288
289 if (attr & ARM_V7S_PTE_AP_RDONLY) 289 if (!(attr & ARM_V7S_PTE_AP_RDONLY))
290 prot |= IOMMU_WRITE; 290 prot |= IOMMU_WRITE;
291 if ((attr & (ARM_V7S_TEX_MASK << ARM_V7S_TEX_SHIFT)) == 0) 291 if ((attr & (ARM_V7S_TEX_MASK << ARM_V7S_TEX_SHIFT)) == 0)
292 prot |= IOMMU_MMIO; 292 prot |= IOMMU_MMIO;
293 else if (pte & ARM_V7S_ATTR_C) 293 else if (pte & ARM_V7S_ATTR_C)
294 prot |= IOMMU_CACHE; 294 prot |= IOMMU_CACHE;
295 if (pte & ARM_V7S_ATTR_XN(lvl))
296 prot |= IOMMU_NOEXEC;
295 297
296 return prot; 298 return prot;
297} 299}