From: "Peng Fan (OSS)" <peng.fan@oss.nxp.com>
To: Will Deacon <will@kernel.org>,
Robin Murphy <robin.murphy@arm.com>,
"Joerg Roedel (AMD)" <joro@8bytes.org>,
Jean-Philippe Brucker <jpb@kernel.org>,
Nicolin Chen <nicolinc@nvidia.com>,
Jason Gunthorpe <jgg@ziepe.ca>,
Thierry Reding <thierry.reding@kernel.org>,
Krishna Reddy <vdumpa@nvidia.com>,
Jonathan Hunter <jonathanh@nvidia.com>,
Jason Gunthorpe <jgg@ziepe.ca>
Cc: linux-arm-kernel@lists.infradead.org, iommu@lists.linux.dev,
linux-kernel@vger.kernel.org, linux-tegra@vger.kernel.org,
Peng Fan <peng.fan@nxp.com>
Subject: [PATCH RFC v8 3/9] iommu/arm-smmu-v3: Plumb the CD table into the CD helpers
Date: Fri, 13 Nov 2026 21:27:15 +0800 [thread overview]
Message-ID: <20261113-b4-smmu-shared-sid-ver8-v8-3-587307a77f3a@nxp.com> (raw)
In-Reply-To: <20261113-b4-smmu-shared-sid-ver8-v8-0-587307a77f3a@nxp.com>
From: Peng Fan <peng.fan@nxp.com>
Refactor the CD table allocation, freeing, lookup and STE-building helpers
to take a struct arm_smmu_ctx_desc_cfg pointer instead of always deriving
it from struct arm_smmu_master. Add master wrappers so existing callers
keep the same behaviour.
Prepare for domain-owned CD tables, where non-PASID streams will point
their STE at a CD table stored in the IOMMU domain rather than in the
master.
No functional change.
Reviewed-by: Nicolin Chen <nicolinc@nvidia.com>
Signed-off-by: Peng Fan <peng.fan@nxp.com>
---
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c | 4 +-
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-test.c | 3 +-
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 64 +++++++++++++++---------
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h | 7 +--
4 files changed, 48 insertions(+), 30 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 faeec656da9e..7f89bb7a2e9c 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
@@ -25,7 +25,7 @@ arm_smmu_update_s1_domain_cd_entry(struct arm_smmu_domain *smmu_domain)
struct arm_smmu_master *master = master_domain->master;
struct arm_smmu_cd *cdptr;
- cdptr = arm_smmu_get_cd_ptr(master, master_domain->ssid);
+ cdptr = arm_smmu_master_get_cd_ptr(master, master_domain->ssid);
if (WARN_ON(!cdptr))
continue;
@@ -173,7 +173,7 @@ static void arm_smmu_mm_release(struct mmu_notifier *mn, struct mm_struct *mm)
struct arm_smmu_cd target;
struct arm_smmu_cd *cdptr;
- cdptr = arm_smmu_get_cd_ptr(master, master_domain->ssid);
+ cdptr = arm_smmu_master_get_cd_ptr(master, master_domain->ssid);
if (WARN_ON(!cdptr))
continue;
arm_smmu_make_sva_cd(&target, master, NULL,
diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-test.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-test.c
index 5a4e45e15125..864d9f2350bc 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-test.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-test.c
@@ -215,7 +215,8 @@ static void arm_smmu_test_make_cdtable_ste(struct arm_smmu_ste *ste,
.stall_enabled = stall_enabled,
};
- arm_smmu_make_cdtable_ste(ste, &master, ats_enabled, s1dss);
+ arm_smmu_make_cdtable_ste(ste, &master, &master.cd_table, ats_enabled,
+ s1dss);
if (feat & ARM_SMMU_MASTER_TEST_NESTED) {
struct arm_smmu_ste s2ste;
int i;
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 339b94f2a8a4..b24a4684202e 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
@@ -122,7 +122,7 @@ static const char * const event_class_str[] = {
[3] = "Reserved",
};
-static int arm_smmu_alloc_cd_tables(struct arm_smmu_master *master);
+static int arm_smmu_master_alloc_cd_tables(struct arm_smmu_master *master);
static bool arm_smmu_ats_supported(struct arm_smmu_master *master);
static void parse_driver_options(struct arm_smmu_device *smmu)
@@ -1545,11 +1545,10 @@ static dma_addr_t arm_smmu_cd_l1_get_desc(const struct arm_smmu_cdtab_l1 *src)
return le64_to_cpu(src->l2ptr) & CTXDESC_L1_DESC_L2PTR_MASK;
}
-struct arm_smmu_cd *arm_smmu_get_cd_ptr(struct arm_smmu_master *master,
- u32 ssid)
+static struct arm_smmu_cd *
+arm_smmu_get_cd_ptr(struct arm_smmu_ctx_desc_cfg *cd_table, u32 ssid)
{
struct arm_smmu_cdtab_l2 *l2;
- struct arm_smmu_ctx_desc_cfg *cd_table = &master->cd_table;
if (!arm_smmu_cdtab_allocated(cd_table))
return NULL;
@@ -1563,6 +1562,12 @@ struct arm_smmu_cd *arm_smmu_get_cd_ptr(struct arm_smmu_master *master,
return &l2->cds[arm_smmu_cdtab_l2_idx(ssid)];
}
+struct arm_smmu_cd *arm_smmu_master_get_cd_ptr(struct arm_smmu_master *master,
+ u32 ssid)
+{
+ return arm_smmu_get_cd_ptr(&master->cd_table, ssid);
+}
+
static struct arm_smmu_cd *arm_smmu_alloc_cd_ptr(struct arm_smmu_master *master,
u32 ssid)
{
@@ -1573,7 +1578,7 @@ static struct arm_smmu_cd *arm_smmu_alloc_cd_ptr(struct arm_smmu_master *master,
iommu_group_mutex_assert(master->dev);
if (!arm_smmu_cdtab_allocated(cd_table)) {
- if (arm_smmu_alloc_cd_tables(master))
+ if (arm_smmu_master_alloc_cd_tables(master))
return NULL;
}
@@ -1595,7 +1600,7 @@ static struct arm_smmu_cd *arm_smmu_alloc_cd_ptr(struct arm_smmu_master *master,
arm_smmu_sync_cd(master, ssid, false);
}
}
- return arm_smmu_get_cd_ptr(master, ssid);
+ return arm_smmu_get_cd_ptr(cd_table, ssid);
}
struct arm_smmu_cd_writer {
@@ -1712,7 +1717,7 @@ void arm_smmu_clear_cd(struct arm_smmu_master *master, ioasid_t ssid)
if (!arm_smmu_cdtab_allocated(&master->cd_table))
return;
- cdptr = arm_smmu_get_cd_ptr(master, ssid);
+ cdptr = arm_smmu_master_get_cd_ptr(master, ssid);
if (!cdptr) {
/* Only ats_always_on allows a NULL CD on default substream */
WARN_ON(!master->ats_always_on || ssid);
@@ -1721,15 +1726,15 @@ void arm_smmu_clear_cd(struct arm_smmu_master *master, ioasid_t ssid)
arm_smmu_write_cd_entry(master, ssid, cdptr, &target);
}
-static int arm_smmu_alloc_cd_tables(struct arm_smmu_master *master)
+static int arm_smmu_alloc_cd_tables(struct arm_smmu_device *smmu,
+ struct arm_smmu_ctx_desc_cfg *cd_table,
+ u8 ssid_bits, bool ats_always_on)
{
int ret;
size_t l1size;
size_t max_contexts;
- struct arm_smmu_device *smmu = master->smmu;
- struct arm_smmu_ctx_desc_cfg *cd_table = &master->cd_table;
- cd_table->s1cdmax = master->ssid_bits;
+ cd_table->s1cdmax = ssid_bits;
/*
* When a device doesn't support PASID (non default SSID), ssid_bits is
@@ -1744,7 +1749,7 @@ static int arm_smmu_alloc_cd_tables(struct arm_smmu_master *master)
* Set S1CDMAX no lower than 1. This would add a dummy substream in the
* CD table but it should never be used by an actual CD.
*/
- if (master->ats_always_on)
+ if (ats_always_on)
cd_table->s1cdmax = max_t(u8, cd_table->s1cdmax, 1);
max_contexts = 1 << cd_table->s1cdmax;
@@ -1786,11 +1791,20 @@ static int arm_smmu_alloc_cd_tables(struct arm_smmu_master *master)
return ret;
}
-static void arm_smmu_free_cd_tables(struct arm_smmu_master *master)
+static int arm_smmu_master_alloc_cd_tables(struct arm_smmu_master *master)
+{
+ return arm_smmu_alloc_cd_tables(master->smmu, &master->cd_table,
+ master->ssid_bits,
+ master->ats_always_on);
+}
+
+static void arm_smmu_free_cd_tables(struct arm_smmu_device *smmu,
+ struct arm_smmu_ctx_desc_cfg *cd_table)
{
int i;
- struct arm_smmu_device *smmu = master->smmu;
- struct arm_smmu_ctx_desc_cfg *cd_table = &master->cd_table;
+
+ if (!arm_smmu_cdtab_allocated(cd_table))
+ return;
if (cd_table->s1fmt != STRTAB_STE_0_S1FMT_LINEAR) {
for (i = 0; i < cd_table->l2.num_l1_ents; i++) {
@@ -1900,10 +1914,10 @@ EXPORT_SYMBOL_IF_KUNIT(arm_smmu_make_bypass_ste);
VISIBLE_IF_KUNIT
void arm_smmu_make_cdtable_ste(struct arm_smmu_ste *target,
- struct arm_smmu_master *master, bool ats_enabled,
- unsigned int s1dss)
+ struct arm_smmu_master *master,
+ struct arm_smmu_ctx_desc_cfg *cd_table,
+ bool ats_enabled, unsigned int s1dss)
{
- struct arm_smmu_ctx_desc_cfg *cd_table = &master->cd_table;
struct arm_smmu_device *smmu = master->smmu;
memset(target, 0, sizeof(*target));
@@ -3865,7 +3879,8 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev,
arm_smmu_make_s1_cd(&target_cd, master, smmu_domain);
arm_smmu_write_cd_entry(master, IOMMU_NO_PASID, cdptr,
&target_cd);
- arm_smmu_make_cdtable_ste(&target, master, state.ats_enabled,
+ arm_smmu_make_cdtable_ste(&target, master, &master->cd_table,
+ state.ats_enabled,
STRTAB_STE_1_S1DSS_SSID0);
arm_smmu_install_ste_for_dev(master, &target);
break;
@@ -3932,7 +3947,8 @@ static void arm_smmu_update_ste(struct arm_smmu_master *master,
* the S1DSS is correct and this will just update the EATS. Otherwise it
* installs the entire thing. This will be hitless.
*/
- arm_smmu_make_cdtable_ste(&ste, master, ats_enabled, s1dss);
+ arm_smmu_make_cdtable_ste(&ste, master, &master->cd_table, ats_enabled,
+ s1dss);
arm_smmu_install_ste_for_dev(master, &ste);
}
@@ -4065,7 +4081,8 @@ static void arm_smmu_attach_dev_ste(struct iommu_domain *domain,
*/
state.cd_needs_ats = true;
arm_smmu_attach_prepare(&state, domain);
- arm_smmu_make_cdtable_ste(ste, master, state.ats_enabled, s1dss);
+ arm_smmu_make_cdtable_ste(ste, master, &master->cd_table,
+ state.ats_enabled, s1dss);
} else {
arm_smmu_attach_prepare(&state, domain);
}
@@ -4436,7 +4453,7 @@ static int arm_smmu_master_prepare_ats(struct arm_smmu_master *master)
master->ats_always_on = true;
- return arm_smmu_alloc_cd_tables(master);
+ return arm_smmu_master_alloc_cd_tables(master);
}
static struct iommu_device *arm_smmu_probe_device(struct device *dev)
@@ -4509,8 +4526,7 @@ static void arm_smmu_release_device(struct device *dev)
arm_smmu_disable_pasid(master);
arm_smmu_remove_master(master);
- if (arm_smmu_cdtab_allocated(&master->cd_table))
- arm_smmu_free_cd_tables(master);
+ arm_smmu_free_cd_tables(master->smmu, &master->cd_table);
kfree(master);
}
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 56ed6ad1dd52..b02163a48c97 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
@@ -1143,8 +1143,9 @@ void arm_smmu_get_cd_used(const __le64 *ent, __le64 *used_bits);
void arm_smmu_make_bypass_ste(struct arm_smmu_device *smmu,
struct arm_smmu_ste *target);
void arm_smmu_make_cdtable_ste(struct arm_smmu_ste *target,
- struct arm_smmu_master *master, bool ats_enabled,
- unsigned int s1dss);
+ struct arm_smmu_master *master,
+ struct arm_smmu_ctx_desc_cfg *cd_table,
+ bool ats_enabled, unsigned int s1dss);
void arm_smmu_make_sva_cd(struct arm_smmu_cd *target,
struct arm_smmu_master *master, struct mm_struct *mm,
u16 asid);
@@ -1193,7 +1194,7 @@ static inline void arm_smmu_domain_free(struct arm_smmu_domain *smmu_domain)
}
void arm_smmu_clear_cd(struct arm_smmu_master *master, ioasid_t ssid);
-struct arm_smmu_cd *arm_smmu_get_cd_ptr(struct arm_smmu_master *master,
+struct arm_smmu_cd *arm_smmu_master_get_cd_ptr(struct arm_smmu_master *master,
u32 ssid);
void arm_smmu_make_s1_cd(struct arm_smmu_cd *target,
struct arm_smmu_master *master,
--
2.34.1
next prev parent reply other threads:[~2026-11-13 13:22 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-13 13:27 [PATCH RFC v8 0/9] iommu/arm-smmu-v3: Support shared Stream IDs Peng Fan (OSS)
2026-11-13 13:27 ` [PATCH RFC v8 1/9] iommu/arm-smmu-v3: Allocate streams individually Peng Fan (OSS)
2026-11-13 13:27 ` [PATCH RFC v8 2/9] iommu/arm-smmu-v3: Delay stream allocation to inside the mutex Peng Fan (OSS)
2026-11-13 13:27 ` Peng Fan (OSS) [this message]
2026-11-13 13:27 ` [PATCH RFC v8 4/9] iommu/arm-smmu-v3: Use a per-domain CD table for non-PASID streams Peng Fan (OSS)
2026-11-13 13:27 ` [PATCH RFC v8 5/9] iommu/arm-smmu-v3: Support shared SIDs in insert/remove_master Peng Fan (OSS)
2026-11-13 13:27 ` [PATCH RFC v8 6/9] iommu/arm-smmu-v3: Group aliasing devices into the same IOMMU group Peng Fan (OSS)
2026-11-13 13:27 ` [PATCH RFC v8 7/9] iommu/arm-smmu-v3: Wire up shared-SID STE ordering and feature gating Peng Fan (OSS)
2026-11-13 13:27 ` [PATCH RFC v8 8/9] iommu/arm-smmu-v3: Serialize shared-SID changes with attach Peng Fan (OSS)
2026-11-13 13:27 ` [PATCH RFC v8 9/9] iommu/arm-smmu-v3: Quiesce PASID before mm release unlinks Peng Fan (OSS)
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261113-b4-smmu-shared-sid-ver8-v8-3-587307a77f3a@nxp.com \
--to=peng.fan@oss.nxp.com \
--cc=iommu@lists.linux.dev \
--cc=jgg@ziepe.ca \
--cc=jonathanh@nvidia.com \
--cc=joro@8bytes.org \
--cc=jpb@kernel.org \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-tegra@vger.kernel.org \
--cc=nicolinc@nvidia.com \
--cc=peng.fan@nxp.com \
--cc=robin.murphy@arm.com \
--cc=thierry.reding@kernel.org \
--cc=vdumpa@nvidia.com \
--cc=will@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®