iommu/io-pgtable: Replace ->tlb_add_flush() with ->tlb_add_page()
authorWill Deacon <will@kernel.org>
Tue, 2 Jul 2019 15:44:41 +0000 (16:44 +0100)
committerWill Deacon <will@kernel.org>
Mon, 29 Jul 2019 16:22:57 +0000 (17:22 +0100)
The ->tlb_add_flush() callback in the io-pgtable API now looks a bit
silly:

  - It takes a size and a granule, which are always the same
  - It takes a 'bool leaf', which is always true
  - It only ever flushes a single page

With that in mind, replace it with an optional ->tlb_add_page() callback
that drops the useless parameters.

Signed-off-by: Will Deacon <will@kernel.org>
drivers/gpu/drm/panfrost/panfrost_mmu.c
drivers/iommu/arm-smmu-v3.c
drivers/iommu/arm-smmu.c
drivers/iommu/io-pgtable-arm-v7s.c
drivers/iommu/io-pgtable-arm.c
drivers/iommu/ipmmu-vmsa.c
drivers/iommu/msm_iommu.c
drivers/iommu/mtk_iommu.c
drivers/iommu/qcom_iommu.c
include/linux/io-pgtable.h

index 651858147bd69aac8ce24d61fe2a219646fb57c7..ff9af320cacc4280365c10397954c33ff556fd67 100644 (file)
@@ -247,10 +247,6 @@ static void mmu_tlb_inv_context_s1(void *cookie)
        mmu_hw_do_operation(pfdev, 0, 0, ~0UL, AS_COMMAND_FLUSH_MEM);
 }
 
-static void mmu_tlb_inv_range_nosync(unsigned long iova, size_t size,
-                                    size_t granule, bool leaf, void *cookie)
-{}
-
 static void mmu_tlb_sync_context(void *cookie)
 {
        //struct panfrost_device *pfdev = cookie;
@@ -273,7 +269,6 @@ static const struct iommu_flush_ops mmu_tlb_ops = {
        .tlb_flush_all  = mmu_tlb_inv_context_s1,
        .tlb_flush_walk = mmu_tlb_flush_walk,
        .tlb_flush_leaf = mmu_tlb_flush_leaf,
-       .tlb_add_flush  = mmu_tlb_inv_range_nosync,
        .tlb_sync       = mmu_tlb_sync_context,
 };
 
index 79819b003b0719336b611b5bbd8657121a9a1669..98c90a1b4b229c4de9223fddb6a31810fc03b9d8 100644 (file)
@@ -1603,6 +1603,12 @@ static void arm_smmu_tlb_inv_range_nosync(unsigned long iova, size_t size,
        } while (size -= granule);
 }
 
+static void arm_smmu_tlb_inv_page_nosync(unsigned long iova, size_t granule,
+                                        void *cookie)
+{
+       arm_smmu_tlb_inv_range_nosync(iova, granule, granule, true, cookie);
+}
+
 static void arm_smmu_tlb_inv_walk(unsigned long iova, size_t size,
                                  size_t granule, void *cookie)
 {
@@ -1627,7 +1633,7 @@ static const struct iommu_flush_ops arm_smmu_flush_ops = {
        .tlb_flush_all  = arm_smmu_tlb_inv_context,
        .tlb_flush_walk = arm_smmu_tlb_inv_walk,
        .tlb_flush_leaf = arm_smmu_tlb_inv_leaf,
-       .tlb_add_flush  = arm_smmu_tlb_inv_range_nosync,
+       .tlb_add_page   = arm_smmu_tlb_inv_page_nosync,
        .tlb_sync       = arm_smmu_tlb_sync,
 };
 
index e9f01b860ae32129b52ed3adc4253f0214d79e41..f056164a94b0929616fc82c30ecf5bb4e810c1ef 100644 (file)
@@ -248,10 +248,16 @@ enum arm_smmu_domain_stage {
        ARM_SMMU_DOMAIN_BYPASS,
 };
 
+struct arm_smmu_flush_ops {
+       struct iommu_flush_ops          tlb;
+       void (*tlb_inv_range)(unsigned long iova, size_t size, size_t granule,
+                             bool leaf, void *cookie)
+};
+
 struct arm_smmu_domain {
        struct arm_smmu_device          *smmu;
        struct io_pgtable_ops           *pgtbl_ops;
-       const struct iommu_flush_ops    *tlb_ops;
+       const struct arm_smmu_flush_ops *flush_ops;
        struct arm_smmu_cfg             cfg;
        enum arm_smmu_domain_stage      stage;
        bool                            non_strict;
@@ -551,42 +557,62 @@ static void arm_smmu_tlb_inv_walk(unsigned long iova, size_t size,
                                  size_t granule, void *cookie)
 {
        struct arm_smmu_domain *smmu_domain = cookie;
+       const struct arm_smmu_flush_ops *ops = smmu_domain->flush_ops;
 
-       smmu_domain->tlb_ops->tlb_add_flush(iova, size, granule, false, cookie);
-       smmu_domain->tlb_ops->tlb_sync(cookie);
+       ops->tlb_inv_range(iova, size, granule, false, cookie);
+       ops->tlb.tlb_sync(cookie);
 }
 
 static void arm_smmu_tlb_inv_leaf(unsigned long iova, size_t size,
                                  size_t granule, void *cookie)
 {
        struct arm_smmu_domain *smmu_domain = cookie;
+       const struct arm_smmu_flush_ops *ops = smmu_domain->flush_ops;
+
+       ops->tlb_inv_range(iova, size, granule, true, cookie);
+       ops->tlb.tlb_sync(cookie);
+}
+
+static void arm_smmu_tlb_add_page(unsigned long iova, size_t granule,
+                                 void *cookie)
+{
+       struct arm_smmu_domain *smmu_domain = cookie;
+       const struct arm_smmu_flush_ops *ops = smmu_domain->flush_ops;
 
-       smmu_domain->tlb_ops->tlb_add_flush(iova, size, granule, true, cookie);
-       smmu_domain->tlb_ops->tlb_sync(cookie);
+       ops->tlb_inv_range(iova, granule, granule, true, cookie);
 }
 
-static const struct iommu_flush_ops arm_smmu_s1_tlb_ops = {
-       .tlb_flush_all  = arm_smmu_tlb_inv_context_s1,
-       .tlb_flush_walk = arm_smmu_tlb_inv_walk,
-       .tlb_flush_leaf = arm_smmu_tlb_inv_leaf,
-       .tlb_add_flush  = arm_smmu_tlb_inv_range_nosync,
-       .tlb_sync       = arm_smmu_tlb_sync_context,
+static const struct arm_smmu_flush_ops arm_smmu_s1_tlb_ops = {
+       .tlb = {
+               .tlb_flush_all  = arm_smmu_tlb_inv_context_s1,
+               .tlb_flush_walk = arm_smmu_tlb_inv_walk,
+               .tlb_flush_leaf = arm_smmu_tlb_inv_leaf,
+               .tlb_add_page   = arm_smmu_tlb_add_page,
+               .tlb_sync       = arm_smmu_tlb_sync_context,
+       },
+       .tlb_inv_range          = arm_smmu_tlb_inv_range_nosync,
 };
 
-static const struct iommu_flush_ops arm_smmu_s2_tlb_ops_v2 = {
-       .tlb_flush_all  = arm_smmu_tlb_inv_context_s2,
-       .tlb_flush_walk = arm_smmu_tlb_inv_walk,
-       .tlb_flush_leaf = arm_smmu_tlb_inv_leaf,
-       .tlb_add_flush  = arm_smmu_tlb_inv_range_nosync,
-       .tlb_sync       = arm_smmu_tlb_sync_context,
+static const struct arm_smmu_flush_ops arm_smmu_s2_tlb_ops_v2 = {
+       .tlb = {
+               .tlb_flush_all  = arm_smmu_tlb_inv_context_s2,
+               .tlb_flush_walk = arm_smmu_tlb_inv_walk,
+               .tlb_flush_leaf = arm_smmu_tlb_inv_leaf,
+               .tlb_add_page   = arm_smmu_tlb_add_page,
+               .tlb_sync       = arm_smmu_tlb_sync_context,
+       },
+       .tlb_inv_range          = arm_smmu_tlb_inv_range_nosync,
 };
 
-static const struct iommu_flush_ops arm_smmu_s2_tlb_ops_v1 = {
-       .tlb_flush_all  = arm_smmu_tlb_inv_context_s2,
-       .tlb_flush_walk = arm_smmu_tlb_inv_walk,
-       .tlb_flush_leaf = arm_smmu_tlb_inv_leaf,
-       .tlb_add_flush  = arm_smmu_tlb_inv_vmid_nosync,
-       .tlb_sync       = arm_smmu_tlb_sync_vmid,
+static const struct arm_smmu_flush_ops arm_smmu_s2_tlb_ops_v1 = {
+       .tlb = {
+               .tlb_flush_all  = arm_smmu_tlb_inv_context_s2,
+               .tlb_flush_walk = arm_smmu_tlb_inv_walk,
+               .tlb_flush_leaf = arm_smmu_tlb_inv_leaf,
+               .tlb_add_page   = arm_smmu_tlb_add_page,
+               .tlb_sync       = arm_smmu_tlb_sync_vmid,
+       },
+       .tlb_inv_range          = arm_smmu_tlb_inv_vmid_nosync,
 };
 
 static irqreturn_t arm_smmu_context_fault(int irq, void *dev)
@@ -866,7 +892,7 @@ static int arm_smmu_init_domain_context(struct iommu_domain *domain,
                        ias = min(ias, 32UL);
                        oas = min(oas, 32UL);
                }
-               smmu_domain->tlb_ops = &arm_smmu_s1_tlb_ops;
+               smmu_domain->flush_ops = &arm_smmu_s1_tlb_ops;
                break;
        case ARM_SMMU_DOMAIN_NESTED:
                /*
@@ -886,9 +912,9 @@ static int arm_smmu_init_domain_context(struct iommu_domain *domain,
                        oas = min(oas, 40UL);
                }
                if (smmu->version == ARM_SMMU_V2)
-                       smmu_domain->tlb_ops = &arm_smmu_s2_tlb_ops_v2;
+                       smmu_domain->flush_ops = &arm_smmu_s2_tlb_ops_v2;
                else
-                       smmu_domain->tlb_ops = &arm_smmu_s2_tlb_ops_v1;
+                       smmu_domain->flush_ops = &arm_smmu_s2_tlb_ops_v1;
                break;
        default:
                ret = -EINVAL;
@@ -917,7 +943,7 @@ static int arm_smmu_init_domain_context(struct iommu_domain *domain,
                .ias            = ias,
                .oas            = oas,
                .coherent_walk  = smmu->features & ARM_SMMU_FEAT_COHERENT_WALK,
-               .tlb            = smmu_domain->tlb_ops,
+               .tlb            = &smmu_domain->flush_ops->tlb,
                .iommu_dev      = smmu->dev,
        };
 
@@ -1346,9 +1372,9 @@ static void arm_smmu_flush_iotlb_all(struct iommu_domain *domain)
        struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain);
        struct arm_smmu_device *smmu = smmu_domain->smmu;
 
-       if (smmu_domain->tlb_ops) {
+       if (smmu_domain->flush_ops) {
                arm_smmu_rpm_get(smmu);
-               smmu_domain->tlb_ops->tlb_flush_all(smmu_domain);
+               smmu_domain->flush_ops->tlb.tlb_flush_all(smmu_domain);
                arm_smmu_rpm_put(smmu);
        }
 }
@@ -1359,9 +1385,9 @@ static void arm_smmu_iotlb_sync(struct iommu_domain *domain,
        struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain);
        struct arm_smmu_device *smmu = smmu_domain->smmu;
 
-       if (smmu_domain->tlb_ops) {
+       if (smmu_domain->flush_ops) {
                arm_smmu_rpm_get(smmu);
-               smmu_domain->tlb_ops->tlb_sync(smmu_domain);
+               smmu_domain->flush_ops->tlb.tlb_sync(smmu_domain);
                arm_smmu_rpm_put(smmu);
        }
 }
index 8d4914fe73bcf888fee44c3a78502958154d83b6..b3f975c95f763b9f6bfab4b613de49c34dff096d 100644 (file)
@@ -584,7 +584,7 @@ static size_t arm_v7s_split_blk_unmap(struct arm_v7s_io_pgtable *data,
                return __arm_v7s_unmap(data, iova, size, 2, tablep);
        }
 
-       io_pgtable_tlb_add_flush(&data->iop, iova, size, size, true);
+       io_pgtable_tlb_add_page(&data->iop, iova, size);
        return size;
 }
 
@@ -647,8 +647,7 @@ static size_t __arm_v7s_unmap(struct arm_v7s_io_pgtable *data,
                                 */
                                smp_wmb();
                        } else {
-                               io_pgtable_tlb_add_flush(iop, iova, blk_size,
-                                                        blk_size, true);
+                               io_pgtable_tlb_add_page(iop, iova, blk_size);
                        }
                        iova += blk_size;
                }
@@ -809,10 +808,9 @@ static void dummy_tlb_flush(unsigned long iova, size_t size, size_t granule,
        WARN_ON(!(size & cfg_cookie->pgsize_bitmap));
 }
 
-static void dummy_tlb_add_flush(unsigned long iova, size_t size,
-                               size_t granule, bool leaf, void *cookie)
+static void dummy_tlb_add_page(unsigned long iova, size_t granule, void *cookie)
 {
-       dummy_tlb_flush(iova, size, granule, cookie);
+       dummy_tlb_flush(iova, granule, granule, cookie);
 }
 
 static void dummy_tlb_sync(void *cookie)
@@ -824,7 +822,7 @@ static const struct iommu_flush_ops dummy_tlb_ops = {
        .tlb_flush_all  = dummy_tlb_flush_all,
        .tlb_flush_walk = dummy_tlb_flush,
        .tlb_flush_leaf = dummy_tlb_flush,
-       .tlb_add_flush  = dummy_tlb_add_flush,
+       .tlb_add_page   = dummy_tlb_add_page,
        .tlb_sync       = dummy_tlb_sync,
 };
 
index b58338c863232f9171aa09bc1608b6f8b13c829a..a5c0db01533eaf5c93cdf93923cc178acb8a0217 100644 (file)
@@ -582,7 +582,7 @@ static size_t arm_lpae_split_blk_unmap(struct arm_lpae_io_pgtable *data,
 
                tablep = iopte_deref(pte, data);
        } else if (unmap_idx >= 0) {
-               io_pgtable_tlb_add_flush(&data->iop, iova, size, size, true);
+               io_pgtable_tlb_add_page(&data->iop, iova, size);
                return size;
        }
 
@@ -623,7 +623,7 @@ static size_t __arm_lpae_unmap(struct arm_lpae_io_pgtable *data,
                         */
                        smp_wmb();
                } else {
-                       io_pgtable_tlb_add_flush(iop, iova, size, size, true);
+                       io_pgtable_tlb_add_page(iop, iova, size);
                }
 
                return size;
@@ -1075,10 +1075,9 @@ static void dummy_tlb_flush(unsigned long iova, size_t size, size_t granule,
        WARN_ON(!(size & cfg_cookie->pgsize_bitmap));
 }
 
-static void dummy_tlb_add_flush(unsigned long iova, size_t size,
-                               size_t granule, bool leaf, void *cookie)
+static void dummy_tlb_add_page(unsigned long iova, size_t granule, void *cookie)
 {
-       dummy_tlb_flush(iova, size, granule, cookie);
+       dummy_tlb_flush(iova, granule, granule, cookie);
 }
 
 static void dummy_tlb_sync(void *cookie)
@@ -1090,7 +1089,7 @@ static const struct iommu_flush_ops dummy_tlb_ops __initconst = {
        .tlb_flush_all  = dummy_tlb_flush_all,
        .tlb_flush_walk = dummy_tlb_flush,
        .tlb_flush_leaf = dummy_tlb_flush,
-       .tlb_add_flush  = dummy_tlb_add_flush,
+       .tlb_add_page   = dummy_tlb_add_page,
        .tlb_sync       = dummy_tlb_sync,
 };
 
index 9cc7bcb7e39d38460d8b301269f23aa3f4920e56..c4da271af90ea750dfed9630787114f4517f64f0 100644 (file)
@@ -367,17 +367,10 @@ static void ipmmu_tlb_flush(unsigned long iova, size_t size,
        ipmmu_tlb_flush_all(cookie);
 }
 
-static void ipmmu_tlb_add_flush(unsigned long iova, size_t size,
-                               size_t granule, bool leaf, void *cookie)
-{
-       /* The hardware doesn't support selective TLB flush. */
-}
-
 static const struct iommu_flush_ops ipmmu_flush_ops = {
        .tlb_flush_all = ipmmu_tlb_flush_all,
        .tlb_flush_walk = ipmmu_tlb_flush,
        .tlb_flush_leaf = ipmmu_tlb_flush,
-       .tlb_add_flush = ipmmu_tlb_add_flush,
        .tlb_sync = ipmmu_tlb_flush_all,
 };
 
index 64132093751affdb5f68905724933677f200d032..2cd83295a8415d51bfc528adfe0896e50fcbe219 100644 (file)
@@ -192,11 +192,16 @@ static void __flush_iotlb_leaf(unsigned long iova, size_t size,
        __flush_iotlb_sync(cookie);
 }
 
+static void __flush_iotlb_page(unsigned long iova, size_t granule, void *cookie)
+{
+       __flush_iotlb_range(iova, granule, granule, true, cookie);
+}
+
 static const struct iommu_flush_ops msm_iommu_flush_ops = {
        .tlb_flush_all = __flush_iotlb,
        .tlb_flush_walk = __flush_iotlb_walk,
        .tlb_flush_leaf = __flush_iotlb_leaf,
-       .tlb_add_flush = __flush_iotlb_range,
+       .tlb_add_page = __flush_iotlb_page,
        .tlb_sync = __flush_iotlb_sync,
 };
 
index 85a7176bf9ae222d1b57319f8b28d09994f8c6af..a0b4b4dc4b908b72e1f1b61be0ff4921220d7fa8 100644 (file)
@@ -202,11 +202,17 @@ static void mtk_iommu_tlb_flush_leaf(unsigned long iova, size_t size,
        mtk_iommu_tlb_sync(cookie);
 }
 
+static void mtk_iommu_tlb_flush_page_nosync(unsigned long iova, size_t granule,
+                                           void *cookie)
+{
+       mtk_iommu_tlb_add_flush_nosync(iova, granule, granule, true, cookie);
+}
+
 static const struct iommu_flush_ops mtk_iommu_flush_ops = {
        .tlb_flush_all = mtk_iommu_tlb_flush_all,
        .tlb_flush_walk = mtk_iommu_tlb_flush_walk,
        .tlb_flush_leaf = mtk_iommu_tlb_flush_leaf,
-       .tlb_add_flush = mtk_iommu_tlb_add_flush_nosync,
+       .tlb_add_page = mtk_iommu_tlb_flush_page_nosync,
        .tlb_sync = mtk_iommu_tlb_sync,
 };
 
index 643079e52e694bb03d8ae96b17114f35d4a83e48..7d8411dee4cfeeebe7e8fdbd269c7abf16a2fc2d 100644 (file)
@@ -178,11 +178,17 @@ static void qcom_iommu_tlb_flush_leaf(unsigned long iova, size_t size,
        qcom_iommu_tlb_sync(cookie);
 }
 
+static void qcom_iommu_tlb_add_page(unsigned long iova, size_t granule,
+                                   void *cookie)
+{
+       qcom_iommu_tlb_inv_range_nosync(iova, granule, granule, true, cookie);
+}
+
 static const struct iommu_flush_ops qcom_flush_ops = {
        .tlb_flush_all  = qcom_iommu_tlb_inv_context,
        .tlb_flush_walk = qcom_iommu_tlb_flush_walk,
        .tlb_flush_leaf = qcom_iommu_tlb_flush_leaf,
-       .tlb_add_flush  = qcom_iommu_tlb_inv_range_nosync,
+       .tlb_add_page   = qcom_iommu_tlb_add_page,
        .tlb_sync       = qcom_iommu_tlb_sync,
 };
 
index 0618aac59e747cf5697c305abb93386b571f8072..99e04bd2baa112a17cb695911a16e9f8a93e1623 100644 (file)
@@ -25,12 +25,11 @@ enum io_pgtable_fmt {
  *                  address range.
  * @tlb_flush_leaf: Synchronously invalidate all leaf TLB state for a virtual
  *                  address range.
- * @tlb_add_flush:  Optional callback to queue up leaf TLB invalidation for a
- *                  virtual address range.  This function exists purely as an
- *                  optimisation for IOMMUs that cannot batch TLB invalidation
- *                  operations efficiently and are therefore better suited to
- *                  issuing them early rather than deferring them until
- *                  iommu_tlb_sync().
+ * @tlb_add_page:   Optional callback to queue up leaf TLB invalidation for a
+ *                  single page. This function exists purely as an optimisation
+ *                  for IOMMUs that cannot batch TLB invalidation operations
+ *                  efficiently and are therefore better suited to issuing them
+ *                  early rather than deferring them until iommu_tlb_sync().
  * @tlb_sync:       Ensure any queued TLB invalidation has taken effect, and
  *                  any corresponding page table updates are visible to the
  *                  IOMMU.
@@ -44,8 +43,7 @@ struct iommu_flush_ops {
                               void *cookie);
        void (*tlb_flush_leaf)(unsigned long iova, size_t size, size_t granule,
                               void *cookie);
-       void (*tlb_add_flush)(unsigned long iova, size_t size, size_t granule,
-                             bool leaf, void *cookie);
+       void (*tlb_add_page)(unsigned long iova, size_t granule, void *cookie);
        void (*tlb_sync)(void *cookie);
 };
 
@@ -212,10 +210,12 @@ io_pgtable_tlb_flush_leaf(struct io_pgtable *iop, unsigned long iova,
        iop->cfg.tlb->tlb_flush_leaf(iova, size, granule, iop->cookie);
 }
 
-static inline void io_pgtable_tlb_add_flush(struct io_pgtable *iop,
-               unsigned long iova, size_t size, size_t granule, bool leaf)
+static inline void
+io_pgtable_tlb_add_page(struct io_pgtable *iop, unsigned long iova,
+                       size_t granule)
 {
-       iop->cfg.tlb->tlb_add_flush(iova, size, granule, leaf, iop->cookie);
+       if (iop->cfg.tlb->tlb_add_page)
+               iop->cfg.tlb->tlb_add_page(iova, granule, iop->cookie);
 }
 
 static inline void io_pgtable_tlb_sync(struct io_pgtable *iop)