diff options
author | Robin Murphy <robin.murphy@arm.com> | 2016-05-09 17:20:09 +0100 |
---|---|---|
committer | Joerg Roedel <jroedel@suse.de> | 2016-05-09 19:38:39 +0200 |
commit | d546635731317a5f8923b1045d0f4403e8024a7d (patch) | |
tree | 9bc9478a80b2c124cd2ef47d441ecf2349471596 /drivers/iommu/arm-smmu-v3.c | |
parent | 3b6b7e19e31a816ee02a8d4372cbea9ad7db3784 (diff) |
iommu/arm-smmu: Use per-domain page sizes.
Now that we can accurately reflect the context format we choose for each
domain, do that instead of imposing the global lowest-common-denominator
restriction and potentially ending up with nothing. We currently have a
strict 1:1 correspondence between domains and context banks, so we don't
need to entertain the possibility of multiple formats _within_ a domain.
Signed-off-by: Will Deacon <will.deacon@arm.com>
[rm: split from original patch, added SMMUv3]
Signed-off-by: Robin Murphy <robin.murphy@arm.com>
Signed-off-by: Joerg Roedel <jroedel@suse.de>
Diffstat (limited to 'drivers/iommu/arm-smmu-v3.c')
-rw-r--r-- | drivers/iommu/arm-smmu-v3.c | 19 |
1 files changed, 10 insertions, 9 deletions
diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c index 4ff73ff64e49..ebab33e77d67 100644 --- a/drivers/iommu/arm-smmu-v3.c +++ b/drivers/iommu/arm-smmu-v3.c @@ -590,6 +590,7 @@ struct arm_smmu_device { unsigned long ias; /* IPA */ unsigned long oas; /* PA */ + unsigned long pgsize_bitmap; #define ARM_SMMU_MAX_ASIDS (1 << 16) unsigned int asid_bits; @@ -1516,8 +1517,6 @@ static int arm_smmu_domain_finalise_s2(struct arm_smmu_domain *smmu_domain, return 0; } -static struct iommu_ops arm_smmu_ops; - static int arm_smmu_domain_finalise(struct iommu_domain *domain) { int ret; @@ -1555,7 +1554,7 @@ static int arm_smmu_domain_finalise(struct iommu_domain *domain) } pgtbl_cfg = (struct io_pgtable_cfg) { - .pgsize_bitmap = arm_smmu_ops.pgsize_bitmap, + .pgsize_bitmap = smmu->pgsize_bitmap, .ias = ias, .oas = oas, .tlb = &arm_smmu_gather_ops, @@ -1566,7 +1565,7 @@ static int arm_smmu_domain_finalise(struct iommu_domain *domain) if (!pgtbl_ops) return -ENOMEM; - arm_smmu_ops.pgsize_bitmap = pgtbl_cfg.pgsize_bitmap; + domain->pgsize_bitmap = pgtbl_cfg.pgsize_bitmap; smmu_domain->pgtbl_ops = pgtbl_ops; ret = finalise_stage_fn(smmu_domain, &pgtbl_cfg); @@ -2410,7 +2409,6 @@ static int arm_smmu_device_probe(struct arm_smmu_device *smmu) { u32 reg; bool coherent; - unsigned long pgsize_bitmap = 0; /* IDR0 */ reg = readl_relaxed(smmu->base + ARM_SMMU_IDR0); @@ -2541,13 +2539,16 @@ static int arm_smmu_device_probe(struct arm_smmu_device *smmu) /* Page sizes */ if (reg & IDR5_GRAN64K) - pgsize_bitmap |= SZ_64K | SZ_512M; + smmu->pgsize_bitmap |= SZ_64K | SZ_512M; if (reg & IDR5_GRAN16K) - pgsize_bitmap |= SZ_16K | SZ_32M; + smmu->pgsize_bitmap |= SZ_16K | SZ_32M; if (reg & IDR5_GRAN4K) - pgsize_bitmap |= SZ_4K | SZ_2M | SZ_1G; + smmu->pgsize_bitmap |= SZ_4K | SZ_2M | SZ_1G; - arm_smmu_ops.pgsize_bitmap &= pgsize_bitmap; + if (arm_smmu_ops.pgsize_bitmap == -1UL) + arm_smmu_ops.pgsize_bitmap = smmu->pgsize_bitmap; + else + arm_smmu_ops.pgsize_bitmap |= smmu->pgsize_bitmap; /* Output address size */ switch (reg & IDR5_OAS_MASK << IDR5_OAS_SHIFT) { |