diff options
author | Will Deacon <will.deacon@arm.com> | 2014-02-06 09:59:05 -0500 |
---|---|---|
committer | Will Deacon <will.deacon@arm.com> | 2014-02-10 12:02:23 -0500 |
commit | 57ca90f6800987ac274d7ba065ae6692cdf9bcd7 (patch) | |
tree | 8b7ddc5f80bc4eb6dce0a9131b3e184899cf730b | |
parent | 6dd35f45b8dac827b6f9dd86f5aca6436cdd2410 (diff) |
iommu/arm-smmu: set CBARn.BPSHCFG to NSH for s1-s2-bypass contexts
Whilst trying to bring-up an SMMUv2 implementation with the table
walker plumbed into a coherent interconnect, I noticed that the memory
transactions targetting the CPU caches from the SMMU were marked as
outer-shareable instead of inner-shareable.
After a bunch of digging, it seems that we actually need to program
CBARn.BPSHCFG for s1-s2-bypass contexts to act as non-shareable in order
for the shareability configured in the corresponding TTBCR not to be
overridden with an outer-shareable attribute.
Cc: <stable@vger.kernel.org>
Signed-off-by: Will Deacon <will.deacon@arm.com>
-rw-r--r-- | drivers/iommu/arm-smmu.c | 16 |
1 files changed, 12 insertions, 4 deletions
diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index 509f01f054d9..0ae4dd39197f 100644 --- a/drivers/iommu/arm-smmu.c +++ b/drivers/iommu/arm-smmu.c | |||
@@ -190,6 +190,9 @@ | |||
190 | #define ARM_SMMU_GR1_CBAR(n) (0x0 + ((n) << 2)) | 190 | #define ARM_SMMU_GR1_CBAR(n) (0x0 + ((n) << 2)) |
191 | #define CBAR_VMID_SHIFT 0 | 191 | #define CBAR_VMID_SHIFT 0 |
192 | #define CBAR_VMID_MASK 0xff | 192 | #define CBAR_VMID_MASK 0xff |
193 | #define CBAR_S1_BPSHCFG_SHIFT 8 | ||
194 | #define CBAR_S1_BPSHCFG_MASK 3 | ||
195 | #define CBAR_S1_BPSHCFG_NSH 3 | ||
193 | #define CBAR_S1_MEMATTR_SHIFT 12 | 196 | #define CBAR_S1_MEMATTR_SHIFT 12 |
194 | #define CBAR_S1_MEMATTR_MASK 0xf | 197 | #define CBAR_S1_MEMATTR_MASK 0xf |
195 | #define CBAR_S1_MEMATTR_WB 0xf | 198 | #define CBAR_S1_MEMATTR_WB 0xf |
@@ -671,11 +674,16 @@ static void arm_smmu_init_context_bank(struct arm_smmu_domain *smmu_domain) | |||
671 | if (smmu->version == 1) | 674 | if (smmu->version == 1) |
672 | reg |= root_cfg->irptndx << CBAR_IRPTNDX_SHIFT; | 675 | reg |= root_cfg->irptndx << CBAR_IRPTNDX_SHIFT; |
673 | 676 | ||
674 | /* Use the weakest memory type, so it is overridden by the pte */ | 677 | /* |
675 | if (stage1) | 678 | * Use the weakest shareability/memory types, so they are |
676 | reg |= (CBAR_S1_MEMATTR_WB << CBAR_S1_MEMATTR_SHIFT); | 679 | * overridden by the ttbcr/pte. |
677 | else | 680 | */ |
681 | if (stage1) { | ||
682 | reg |= (CBAR_S1_BPSHCFG_NSH << CBAR_S1_BPSHCFG_SHIFT) | | ||
683 | (CBAR_S1_MEMATTR_WB << CBAR_S1_MEMATTR_SHIFT); | ||
684 | } else { | ||
678 | reg |= ARM_SMMU_CB_VMID(root_cfg) << CBAR_VMID_SHIFT; | 685 | reg |= ARM_SMMU_CB_VMID(root_cfg) << CBAR_VMID_SHIFT; |
686 | } | ||
679 | writel_relaxed(reg, gr1_base + ARM_SMMU_GR1_CBAR(root_cfg->cbndx)); | 687 | writel_relaxed(reg, gr1_base + ARM_SMMU_GR1_CBAR(root_cfg->cbndx)); |
680 | 688 | ||
681 | if (smmu->version > 1) { | 689 | if (smmu->version > 1) { |