diff options
author | Robin Murphy <robin.murphy@arm.com> | 2016-05-09 12:20:09 -0400 |
---|---|---|
committer | Joerg Roedel <jroedel@suse.de> | 2016-05-09 13:38:39 -0400 |
commit | d546635731317a5f8923b1045d0f4403e8024a7d (patch) | |
tree | 9bc9478a80b2c124cd2ef47d441ecf2349471596 /drivers/iommu/arm-smmu.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.c')
-rw-r--r-- | drivers/iommu/arm-smmu.c | 27 |
1 files changed, 15 insertions, 12 deletions
diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index 7cd4ad98904a..0360919a5737 100644 --- a/drivers/iommu/arm-smmu.c +++ b/drivers/iommu/arm-smmu.c | |||
@@ -351,6 +351,7 @@ struct arm_smmu_device { | |||
351 | unsigned long va_size; | 351 | unsigned long va_size; |
352 | unsigned long ipa_size; | 352 | unsigned long ipa_size; |
353 | unsigned long pa_size; | 353 | unsigned long pa_size; |
354 | unsigned long pgsize_bitmap; | ||
354 | 355 | ||
355 | u32 num_global_irqs; | 356 | u32 num_global_irqs; |
356 | u32 num_context_irqs; | 357 | u32 num_context_irqs; |
@@ -396,8 +397,6 @@ struct arm_smmu_domain { | |||
396 | struct iommu_domain domain; | 397 | struct iommu_domain domain; |
397 | }; | 398 | }; |
398 | 399 | ||
399 | static struct iommu_ops arm_smmu_ops; | ||
400 | |||
401 | static DEFINE_SPINLOCK(arm_smmu_devices_lock); | 400 | static DEFINE_SPINLOCK(arm_smmu_devices_lock); |
402 | static LIST_HEAD(arm_smmu_devices); | 401 | static LIST_HEAD(arm_smmu_devices); |
403 | 402 | ||
@@ -957,7 +956,7 @@ static int arm_smmu_init_domain_context(struct iommu_domain *domain, | |||
957 | } | 956 | } |
958 | 957 | ||
959 | pgtbl_cfg = (struct io_pgtable_cfg) { | 958 | pgtbl_cfg = (struct io_pgtable_cfg) { |
960 | .pgsize_bitmap = arm_smmu_ops.pgsize_bitmap, | 959 | .pgsize_bitmap = smmu->pgsize_bitmap, |
961 | .ias = ias, | 960 | .ias = ias, |
962 | .oas = oas, | 961 | .oas = oas, |
963 | .tlb = &arm_smmu_gather_ops, | 962 | .tlb = &arm_smmu_gather_ops, |
@@ -971,8 +970,8 @@ static int arm_smmu_init_domain_context(struct iommu_domain *domain, | |||
971 | goto out_clear_smmu; | 970 | goto out_clear_smmu; |
972 | } | 971 | } |
973 | 972 | ||
974 | /* Update our support page sizes to reflect the page table format */ | 973 | /* Update the domain's page sizes to reflect the page table format */ |
975 | arm_smmu_ops.pgsize_bitmap = pgtbl_cfg.pgsize_bitmap; | 974 | domain->pgsize_bitmap = pgtbl_cfg.pgsize_bitmap; |
976 | 975 | ||
977 | /* Initialise the context bank with our page table cfg */ | 976 | /* Initialise the context bank with our page table cfg */ |
978 | arm_smmu_init_context_bank(smmu_domain, &pgtbl_cfg); | 977 | arm_smmu_init_context_bank(smmu_domain, &pgtbl_cfg); |
@@ -1814,19 +1813,23 @@ static int arm_smmu_device_cfg_probe(struct arm_smmu_device *smmu) | |||
1814 | } | 1813 | } |
1815 | 1814 | ||
1816 | /* Now we've corralled the various formats, what'll it do? */ | 1815 | /* Now we've corralled the various formats, what'll it do? */ |
1817 | size = 0; | ||
1818 | if (smmu->features & ARM_SMMU_FEAT_FMT_AARCH32_S) | 1816 | if (smmu->features & ARM_SMMU_FEAT_FMT_AARCH32_S) |
1819 | size |= SZ_4K | SZ_64K | SZ_1M | SZ_16M; | 1817 | smmu->pgsize_bitmap |= SZ_4K | SZ_64K | SZ_1M | SZ_16M; |
1820 | if (smmu->features & | 1818 | if (smmu->features & |
1821 | (ARM_SMMU_FEAT_FMT_AARCH32_L | ARM_SMMU_FEAT_FMT_AARCH64_4K)) | 1819 | (ARM_SMMU_FEAT_FMT_AARCH32_L | ARM_SMMU_FEAT_FMT_AARCH64_4K)) |
1822 | size |= SZ_4K | SZ_2M | SZ_1G; | 1820 | smmu->pgsize_bitmap |= SZ_4K | SZ_2M | SZ_1G; |
1823 | if (smmu->features & ARM_SMMU_FEAT_FMT_AARCH64_16K) | 1821 | if (smmu->features & ARM_SMMU_FEAT_FMT_AARCH64_16K) |
1824 | size |= SZ_16K | SZ_32M; | 1822 | smmu->pgsize_bitmap |= SZ_16K | SZ_32M; |
1825 | if (smmu->features & ARM_SMMU_FEAT_FMT_AARCH64_64K) | 1823 | if (smmu->features & ARM_SMMU_FEAT_FMT_AARCH64_64K) |
1826 | size |= SZ_64K | SZ_512M; | 1824 | smmu->pgsize_bitmap |= SZ_64K | SZ_512M; |
1825 | |||
1826 | if (arm_smmu_ops.pgsize_bitmap == -1UL) | ||
1827 | arm_smmu_ops.pgsize_bitmap = smmu->pgsize_bitmap; | ||
1828 | else | ||
1829 | arm_smmu_ops.pgsize_bitmap |= smmu->pgsize_bitmap; | ||
1830 | dev_notice(smmu->dev, "\tSupported page sizes: 0x%08lx\n", | ||
1831 | smmu->pgsize_bitmap); | ||
1827 | 1832 | ||
1828 | arm_smmu_ops.pgsize_bitmap &= size; | ||
1829 | dev_notice(smmu->dev, "\tSupported page sizes: 0x%08lx\n", size); | ||
1830 | 1833 | ||
1831 | if (smmu->features & ARM_SMMU_FEAT_TRANS_S1) | 1834 | if (smmu->features & ARM_SMMU_FEAT_TRANS_S1) |
1832 | dev_notice(smmu->dev, "\tStage-1: %lu-bit VA -> %lu-bit IPA\n", | 1835 | dev_notice(smmu->dev, "\tStage-1: %lu-bit VA -> %lu-bit IPA\n", |