summaryrefslogtreecommitdiff
path: root/drivers/iommu/arm-smmu-v3.c
diff options
context:
space:
mode:
authorRobin Murphy <robin.murphy@arm.com>2017-06-22 18:53:53 +0300
committerWill Deacon <will.deacon@arm.com>2017-06-23 19:58:00 +0300
commit81b3c25218447c65f93adf08b099a322b6803536 (patch)
tree6ba8f9f78dfc2604da3885a1e08060f9bb5cbf09 /drivers/iommu/arm-smmu-v3.c
parentb9f1ef30ac2e9942b8628d551f4a21e8cec1415c (diff)
downloadlinux-81b3c25218447c65f93adf08b099a322b6803536.tar.xz
iommu/io-pgtable: Introduce explicit coherency
Once we remove the serialising spinlock, a potential race opens up for non-coherent IOMMUs whereby a caller of .map() can be sure that cache maintenance has been performed on their new PTE, but will have no guarantee that such maintenance for table entries above it has actually completed (e.g. if another CPU took an interrupt immediately after writing the table entry, but before initiating the DMA sync). Handling this race safely will add some potentially non-trivial overhead to installing a table entry, which we would much rather avoid on coherent systems where it will be unnecessary, and where we are stirivng to minimise latency by removing the locking in the first place. To that end, let's introduce an explicit notion of cache-coherency to io-pgtable, such that we will be able to avoid penalising IOMMUs which know enough to know when they are coherent. Signed-off-by: Robin Murphy <robin.murphy@arm.com> Signed-off-by: Will Deacon <will.deacon@arm.com>
Diffstat (limited to 'drivers/iommu/arm-smmu-v3.c')
-rw-r--r--drivers/iommu/arm-smmu-v3.c3
1 files changed, 3 insertions, 0 deletions
diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c
index 029fe0cffee7..d50c8d4b9af9 100644
--- a/drivers/iommu/arm-smmu-v3.c
+++ b/drivers/iommu/arm-smmu-v3.c
@@ -1563,6 +1563,9 @@ static int arm_smmu_domain_finalise(struct iommu_domain *domain)
.iommu_dev = smmu->dev,
};
+ if (smmu->features & ARM_SMMU_FEAT_COHERENCY)
+ pgtbl_cfg.quirks = IO_PGTABLE_QUIRK_NO_DMA;
+
pgtbl_ops = alloc_io_pgtable_ops(fmt, &pgtbl_cfg, smmu_domain);
if (!pgtbl_ops)
return -ENOMEM;