[PATCH v3 2/8] iommu/arm-smmu-v3: Move pgsize out of arm_smmu_inv
From: Jason Gunthorpe <jgg@nvidia.com>
Date: 2026-07-14 18:46:47
Also in:
linux-iommu, linux-patches
Subsystem:
arm smmu drivers, arm smmu sva support, iommu subsystem, the rest · Maintainers:
Will Deacon, Joerg Roedel, Linus Torvalds
pgsize is a constant property of the domain, it is the base translation granule of the page table (4k, 16k, 64k) in log2. Store it to the struct arm_smmu_domain based on how the page table was created. Pass it around in the tlbi. Reviewed-by: Nicolin Chen <redacted> Signed-off-by: Jason Gunthorpe <jgg@nvidia.com> --- .../iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c | 1 + drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 27 ++++++++----------- drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h | 10 ++++--- 3 files changed, 18 insertions(+), 20 deletions(-)
diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c
index 1ed8a6f29dc445..5d4dde3d1cfe87 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c@@ -334,6 +334,7 @@ struct iommu_domain *arm_smmu_sva_domain_alloc(struct device *dev, * ARM_SMMU_FEAT_RANGE_INV is present */ smmu_domain->domain.pgsize_bitmap = PAGE_SIZE; + smmu_domain->tgsz_lg2 = PAGE_SHIFT; smmu_domain->stage = ARM_SMMU_DOMAIN_SVA; smmu_domain->smmu = smmu;
diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
index 604b165be5fbdd..c567e8749f154b 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c@@ -2398,14 +2398,13 @@ static void arm_smmu_tlb_inv_context(void *cookie) static void arm_smmu_cmdq_batch_add_range(struct arm_smmu_device *smmu, struct arm_smmu_cmdq_batch *cmds, struct arm_smmu_cmd *cmd, - struct arm_smmu_tlbi *tlbi, - size_t pgsize) + struct arm_smmu_tlbi *tlbi) { size_t inv_range = tlbi->iopte_size; unsigned long iova = tlbi->iova; unsigned long end = iova + tlbi->size; unsigned long num_pages = 0; - unsigned int tg = pgsize; + u8 tg = tlbi->tgsz_lg2; u64 orig_data0 = cmd->data[0]; u8 ttl = 0, tg_enc = 0;
@@ -2513,7 +2512,7 @@ static void arm_smmu_inv_to_cmdq_batch(struct arm_smmu_inv *inv, return; } - arm_smmu_cmdq_batch_add_range(inv->smmu, cmds, cmd, tlbi, inv->pgsize); + arm_smmu_cmdq_batch_add_range(inv->smmu, cmds, cmd, tlbi); } static inline bool arm_smmu_invs_end_batch(struct arm_smmu_inv *cur,
@@ -2615,6 +2614,7 @@ void arm_smmu_domain_inv_range(struct arm_smmu_domain *smmu_domain, unsigned int granule, bool leaf) { struct arm_smmu_tlbi tlbi = { + .tgsz_lg2 = smmu_domain->tgsz_lg2, .iova = iova, .size = size, .iopte_size = granule,
@@ -2870,6 +2870,7 @@ static int arm_smmu_domain_finalise(struct arm_smmu_domain *smmu_domain, return -ENOMEM; smmu_domain->domain.pgsize_bitmap = pgtbl_cfg.pgsize_bitmap; + smmu_domain->tgsz_lg2 = __ffs(pgtbl_cfg.pgsize_bitmap); smmu_domain->domain.geometry.aperture_end = (1UL << pgtbl_cfg.ias) - 1; smmu_domain->domain.geometry.force_aperture = true; if (enable_dirty && smmu_domain->stage == ARM_SMMU_DOMAIN_S1)
@@ -3104,15 +3105,13 @@ static void arm_smmu_disable_iopf(struct arm_smmu_master *master, static struct arm_smmu_inv * arm_smmu_master_build_inv(struct arm_smmu_master *master, - enum arm_smmu_inv_type type, u32 id, ioasid_t ssid, - size_t pgsize) + enum arm_smmu_inv_type type, u32 id, ioasid_t ssid) { struct arm_smmu_invs *build_invs = master->build_invs; struct arm_smmu_inv *cur, inv = { .smmu = master->smmu, .type = type, .id = id, - .pgsize = pgsize, }; if (WARN_ON(build_invs->num_invs >= build_invs->max_invs))
@@ -3164,28 +3163,24 @@ arm_smmu_master_build_invs(struct arm_smmu_master *master, bool ats_enabled, ioasid_t ssid, struct arm_smmu_domain *smmu_domain) { const bool nesting = smmu_domain->nest_parent; - size_t pgsize = 0, i; + size_t i; iommu_group_mutex_assert(master->dev); master->build_invs->num_invs = 0; - /* Range-based invalidation requires the leaf pgsize for calculation */ - if (master->smmu->features & ARM_SMMU_FEAT_RANGE_INV) - pgsize = __ffs(smmu_domain->domain.pgsize_bitmap); - switch (smmu_domain->stage) { case ARM_SMMU_DOMAIN_SVA: case ARM_SMMU_DOMAIN_S1: if (!arm_smmu_master_build_inv(master, INV_TYPE_S1_ASID, smmu_domain->cd.asid, - IOMMU_NO_PASID, pgsize)) + IOMMU_NO_PASID)) return NULL; break; case ARM_SMMU_DOMAIN_S2: if (!arm_smmu_master_build_inv(master, INV_TYPE_S2_VMID, smmu_domain->s2_cfg.vmid, - IOMMU_NO_PASID, pgsize)) + IOMMU_NO_PASID)) return NULL; break; default:
@@ -3197,7 +3192,7 @@ arm_smmu_master_build_invs(struct arm_smmu_master *master, bool ats_enabled, if (nesting) { if (!arm_smmu_master_build_inv( master, INV_TYPE_S2_VMID_S1_CLEAR, - smmu_domain->s2_cfg.vmid, IOMMU_NO_PASID, 0)) + smmu_domain->s2_cfg.vmid, IOMMU_NO_PASID)) return NULL; }
@@ -3208,7 +3203,7 @@ arm_smmu_master_build_invs(struct arm_smmu_master *master, bool ats_enabled, */ if (!arm_smmu_master_build_inv( master, nesting ? INV_TYPE_ATS_FULL : INV_TYPE_ATS, - master->streams[i].id, ssid, 0)) + master->streams[i].id, ssid)) return NULL; }
diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
index 4806a00844d30e..285a67a9a7a656 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h@@ -733,10 +733,9 @@ struct arm_smmu_inv { u8 size_opcode; u8 nsize_opcode; u32 id; /* ASID or VMID or SID */ - union { - size_t pgsize; /* ARM_SMMU_FEAT_RANGE_INV */ - u32 ssid; /* INV_TYPE_ATS */ - }; + + /* Only used by INV_TYPE_ATS */ + u32 ssid; int users; /* users=0 to mark as a trash to be purged */ };
@@ -807,6 +806,8 @@ struct arm_smmu_tlbi { size_t size; /* page or block size of the leaf iopte */ unsigned int iopte_size; + /* Base Translation Granule of the page table */ + u8 tgsz_lg2; bool leaf_only; };
@@ -1051,6 +1052,7 @@ struct arm_smmu_domain { spinlock_t devices_lock; bool enforce_cache_coherency : 1; bool nest_parent : 1; + u8 tgsz_lg2; struct mmu_notifier mmu_notifier; };
--
2.43.0