aboutsummaryrefslogtreecommitdiffstats
path: root/patches/0092-iommu-io-pgtable-arm-Convert-to-IOMMU-API-TLB-sync.patch
diff options
context:
space:
mode:
Diffstat (limited to 'patches/0092-iommu-io-pgtable-arm-Convert-to-IOMMU-API-TLB-sync.patch')
-rw-r--r--patches/0092-iommu-io-pgtable-arm-Convert-to-IOMMU-API-TLB-sync.patch182
1 files changed, 182 insertions, 0 deletions
diff --git a/patches/0092-iommu-io-pgtable-arm-Convert-to-IOMMU-API-TLB-sync.patch b/patches/0092-iommu-io-pgtable-arm-Convert-to-IOMMU-API-TLB-sync.patch
new file mode 100644
index 00000000000000..eb948c157dc939
--- /dev/null
+++ b/patches/0092-iommu-io-pgtable-arm-Convert-to-IOMMU-API-TLB-sync.patch
@@ -0,0 +1,182 @@
+From 3f621158aee6b5f054f52a56d58a6824e9fb8723 Mon Sep 17 00:00:00 2001
+From: Robin Murphy <robin.murphy@arm.com>
+Date: Thu, 28 Sep 2017 15:55:01 +0100
+Subject: [PATCH 0092/1795] iommu/io-pgtable-arm: Convert to IOMMU API TLB sync
+
+Now that the core API issues its own post-unmap TLB sync call, push that
+operation out from the io-pgtable-arm internals into the users. For now,
+we leave the invalidation implicit in the unmap operation, since none of
+the current users would benefit much from any change to that.
+
+CC: Magnus Damm <damm+renesas@opensource.se>
+CC: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Signed-off-by: Robin Murphy <robin.murphy@arm.com>
+Signed-off-by: Joerg Roedel <jroedel@suse.de>
+(cherry picked from commit 32b124492bdf974f68eaef1bde80dc8058aef002)
+Signed-off-by: Simon Horman <horms+renesas@verge.net.au>
+Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
+---
+ drivers/iommu/arm-smmu-v3.c | 10 ++++++++++
+ drivers/iommu/arm-smmu.c | 20 +++++++++++++++-----
+ drivers/iommu/io-pgtable-arm.c | 7 +------
+ drivers/iommu/ipmmu-vmsa.c | 10 ++++++++++
+ 4 files changed, 36 insertions(+), 11 deletions(-)
+
+diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c
+index 8f7a3c00b6cf..193f8c860010 100644
+--- a/drivers/iommu/arm-smmu-v3.c
++++ b/drivers/iommu/arm-smmu-v3.c
+@@ -1752,6 +1752,14 @@ arm_smmu_unmap(struct iommu_domain *domain, unsigned long iova, size_t size)
+ return ops->unmap(ops, iova, size);
+ }
+
++static void arm_smmu_iotlb_sync(struct iommu_domain *domain)
++{
++ struct arm_smmu_device *smmu = to_smmu_domain(domain)->smmu;
++
++ if (smmu)
++ __arm_smmu_tlb_sync(smmu);
++}
++
+ static phys_addr_t
+ arm_smmu_iova_to_phys(struct iommu_domain *domain, dma_addr_t iova)
+ {
+@@ -1972,6 +1980,8 @@ static struct iommu_ops arm_smmu_ops = {
+ .map = arm_smmu_map,
+ .unmap = arm_smmu_unmap,
+ .map_sg = default_iommu_map_sg,
++ .flush_iotlb_all = arm_smmu_iotlb_sync,
++ .iotlb_sync = arm_smmu_iotlb_sync,
+ .iova_to_phys = arm_smmu_iova_to_phys,
+ .add_device = arm_smmu_add_device,
+ .remove_device = arm_smmu_remove_device,
+diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
+index 2c436376f13e..335bcc18b97a 100644
+--- a/drivers/iommu/arm-smmu.c
++++ b/drivers/iommu/arm-smmu.c
+@@ -250,6 +250,7 @@ enum arm_smmu_domain_stage {
+ struct arm_smmu_domain {
+ struct arm_smmu_device *smmu;
+ struct io_pgtable_ops *pgtbl_ops;
++ const struct iommu_gather_ops *tlb_ops;
+ struct arm_smmu_cfg cfg;
+ enum arm_smmu_domain_stage stage;
+ struct mutex init_mutex; /* Protects smmu pointer */
+@@ -735,7 +736,6 @@ static int arm_smmu_init_domain_context(struct iommu_domain *domain,
+ enum io_pgtable_fmt fmt;
+ struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain);
+ struct arm_smmu_cfg *cfg = &smmu_domain->cfg;
+- const struct iommu_gather_ops *tlb_ops;
+
+ mutex_lock(&smmu_domain->init_mutex);
+ if (smmu_domain->smmu)
+@@ -813,7 +813,7 @@ static int arm_smmu_init_domain_context(struct iommu_domain *domain,
+ ias = min(ias, 32UL);
+ oas = min(oas, 32UL);
+ }
+- tlb_ops = &arm_smmu_s1_tlb_ops;
++ smmu_domain->tlb_ops = &arm_smmu_s1_tlb_ops;
+ break;
+ case ARM_SMMU_DOMAIN_NESTED:
+ /*
+@@ -833,9 +833,9 @@ static int arm_smmu_init_domain_context(struct iommu_domain *domain,
+ oas = min(oas, 40UL);
+ }
+ if (smmu->version == ARM_SMMU_V2)
+- tlb_ops = &arm_smmu_s2_tlb_ops_v2;
++ smmu_domain->tlb_ops = &arm_smmu_s2_tlb_ops_v2;
+ else
+- tlb_ops = &arm_smmu_s2_tlb_ops_v1;
++ smmu_domain->tlb_ops = &arm_smmu_s2_tlb_ops_v1;
+ break;
+ default:
+ ret = -EINVAL;
+@@ -863,7 +863,7 @@ static int arm_smmu_init_domain_context(struct iommu_domain *domain,
+ .pgsize_bitmap = smmu->pgsize_bitmap,
+ .ias = ias,
+ .oas = oas,
+- .tlb = tlb_ops,
++ .tlb = smmu_domain->tlb_ops,
+ .iommu_dev = smmu->dev,
+ };
+
+@@ -1259,6 +1259,14 @@ static size_t arm_smmu_unmap(struct iommu_domain *domain, unsigned long iova,
+ return ops->unmap(ops, iova, size);
+ }
+
++static void arm_smmu_iotlb_sync(struct iommu_domain *domain)
++{
++ struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain);
++
++ if (smmu_domain->tlb_ops)
++ smmu_domain->tlb_ops->tlb_sync(smmu_domain);
++}
++
+ static phys_addr_t arm_smmu_iova_to_phys_hard(struct iommu_domain *domain,
+ dma_addr_t iova)
+ {
+@@ -1562,6 +1570,8 @@ static struct iommu_ops arm_smmu_ops = {
+ .map = arm_smmu_map,
+ .unmap = arm_smmu_unmap,
+ .map_sg = default_iommu_map_sg,
++ .flush_iotlb_all = arm_smmu_iotlb_sync,
++ .iotlb_sync = arm_smmu_iotlb_sync,
+ .iova_to_phys = arm_smmu_iova_to_phys,
+ .add_device = arm_smmu_add_device,
+ .remove_device = arm_smmu_remove_device,
+diff --git a/drivers/iommu/io-pgtable-arm.c b/drivers/iommu/io-pgtable-arm.c
+index e8018a308868..51e5c43caed1 100644
+--- a/drivers/iommu/io-pgtable-arm.c
++++ b/drivers/iommu/io-pgtable-arm.c
+@@ -609,7 +609,6 @@ static int __arm_lpae_unmap(struct arm_lpae_io_pgtable *data,
+ static int arm_lpae_unmap(struct io_pgtable_ops *ops, unsigned long iova,
+ size_t size)
+ {
+- size_t unmapped;
+ struct arm_lpae_io_pgtable *data = io_pgtable_ops_to_data(ops);
+ arm_lpae_iopte *ptep = data->pgd;
+ int lvl = ARM_LPAE_START_LVL(data);
+@@ -617,11 +616,7 @@ static int arm_lpae_unmap(struct io_pgtable_ops *ops, unsigned long iova,
+ if (WARN_ON(iova >= (1ULL << data->iop.cfg.ias)))
+ return 0;
+
+- unmapped = __arm_lpae_unmap(data, iova, size, lvl, ptep);
+- if (unmapped)
+- io_pgtable_tlb_sync(&data->iop);
+-
+- return unmapped;
++ return __arm_lpae_unmap(data, iova, size, lvl, ptep);
+ }
+
+ static phys_addr_t arm_lpae_iova_to_phys(struct io_pgtable_ops *ops,
+diff --git a/drivers/iommu/ipmmu-vmsa.c b/drivers/iommu/ipmmu-vmsa.c
+index 195d6e93ac71..af8140054273 100644
+--- a/drivers/iommu/ipmmu-vmsa.c
++++ b/drivers/iommu/ipmmu-vmsa.c
+@@ -619,6 +619,14 @@ static size_t ipmmu_unmap(struct iommu_domain *io_domain, unsigned long iova,
+ return domain->iop->unmap(domain->iop, iova, size);
+ }
+
++static void ipmmu_iotlb_sync(struct iommu_domain *io_domain)
++{
++ struct ipmmu_vmsa_domain *domain = to_vmsa_domain(io_domain);
++
++ if (domain->mmu)
++ ipmmu_tlb_flush_all(domain);
++}
++
+ static phys_addr_t ipmmu_iova_to_phys(struct iommu_domain *io_domain,
+ dma_addr_t iova)
+ {
+@@ -876,6 +884,8 @@ static const struct iommu_ops ipmmu_ops = {
+ .detach_dev = ipmmu_detach_device,
+ .map = ipmmu_map,
+ .unmap = ipmmu_unmap,
++ .flush_iotlb_all = ipmmu_iotlb_sync,
++ .iotlb_sync = ipmmu_iotlb_sync,
+ .map_sg = default_iommu_map_sg,
+ .iova_to_phys = ipmmu_iova_to_phys,
+ .add_device = ipmmu_add_device_dma,
+--
+2.19.0
+