diff options
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.patch | 182 |
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 + |