iommu/arm-smmu: Use STE.S1STALLD only when supported
authorPrem Mallappa <pmallapp@broadcom.com>
Mon, 14 Dec 2015 16:31:23 +0000 (22:01 +0530)
committerWill Deacon <will.deacon@arm.com>
Thu, 17 Dec 2015 12:05:36 +0000 (12:05 +0000)
It is ILLEGAL to set STE.S1STALLD to 1 if stage 1 is enabled and
either the stall or terminate models are not supported.

This patch fixes the STALLD check and ensures that we don't set STALLD
in the STE when it is not supported.

Signed-off-by: Prem Mallappa <pmallapp@broadcom.com>
[will: consistently use IDR0_STALL_MODEL_* prefix]
Signed-off-by: Will Deacon <will.deacon@arm.com>
drivers/iommu/arm-smmu-v3.c

index 488f763..2087534 100644 (file)
 #define IDR0_ST_LVL_SHIFT              27
 #define IDR0_ST_LVL_MASK               0x3
 #define IDR0_ST_LVL_2LVL               (1 << IDR0_ST_LVL_SHIFT)
-#define IDR0_STALL_MODEL               (3 << 24)
+#define IDR0_STALL_MODEL_SHIFT         24
+#define IDR0_STALL_MODEL_MASK          0x3
+#define IDR0_STALL_MODEL_STALL         (0 << IDR0_STALL_MODEL_SHIFT)
+#define IDR0_STALL_MODEL_FORCE         (2 << IDR0_STALL_MODEL_SHIFT)
 #define IDR0_TTENDIAN_SHIFT            21
 #define IDR0_TTENDIAN_MASK             0x3
 #define IDR0_TTENDIAN_LE               (2 << IDR0_TTENDIAN_SHIFT)
@@ -1062,12 +1065,14 @@ static void arm_smmu_write_strtab_ent(struct arm_smmu_device *smmu, u32 sid,
                         STRTAB_STE_1_S1C_CACHE_WBRA
                         << STRTAB_STE_1_S1COR_SHIFT |
                         STRTAB_STE_1_S1C_SH_ISH << STRTAB_STE_1_S1CSH_SHIFT |
-                        STRTAB_STE_1_S1STALLD |
 #ifdef CONFIG_PCI_ATS
                         STRTAB_STE_1_EATS_TRANS << STRTAB_STE_1_EATS_SHIFT |
 #endif
                         STRTAB_STE_1_STRW_NSEL1 << STRTAB_STE_1_STRW_SHIFT);
 
+               if (smmu->features & ARM_SMMU_FEAT_STALLS)
+                       dst[1] |= cpu_to_le64(STRTAB_STE_1_S1STALLD);
+
                val |= (ste->s1_cfg->cdptr_dma & STRTAB_STE_0_S1CTXPTR_MASK
                        << STRTAB_STE_0_S1CTXPTR_SHIFT) |
                        STRTAB_STE_0_CFG_S1_TRANS;
@@ -2464,8 +2469,12 @@ static int arm_smmu_device_probe(struct arm_smmu_device *smmu)
                dev_warn(smmu->dev, "IDR0.COHACC overridden by dma-coherent property (%s)\n",
                         coherent ? "true" : "false");
 
-       if (reg & IDR0_STALL_MODEL)
+       switch (reg & IDR0_STALL_MODEL_MASK << IDR0_STALL_MODEL_SHIFT) {
+       case IDR0_STALL_MODEL_STALL:
+               /* Fallthrough */
+       case IDR0_STALL_MODEL_FORCE:
                smmu->features |= ARM_SMMU_FEAT_STALLS;
+       }
 
        if (reg & IDR0_S1P)
                smmu->features |= ARM_SMMU_FEAT_TRANS_S1;