From: "Peng Fan (OSS)" <peng.fan@oss.nxp.com>
To: Will Deacon <will@kernel.org>,
Robin Murphy <robin.murphy@arm.com>,
Jason Gunthorpe <jgg@ziepe.ca>,
Nicolin Chen <nicolinc@nvidia.com>,
"Joerg Roedel (AMD)" <joro@8bytes.org>,
Thierry Reding <thierry.reding@kernel.org>,
Krishna Reddy <vdumpa@nvidia.com>,
Jonathan Hunter <jonathanh@nvidia.com>,
Jean-Philippe Brucker <jpb@kernel.org>
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 v7 3/7] iommu/arm-smmu-v3: Plumb the CD table into the CD helpers
Date: Fri, 30 Oct 2026 20:09:35 +0800 [thread overview]
Message-ID: <20261030-smmu-shared-sid-ver7-2026-10-26-v7-3-961726ebd6ab@Example.Com> (raw)
In-Reply-To: <20261030-smmu-shared-sid-ver7-2026-10-26-v7-0-961726ebd6ab@Example.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.
Signed-off-by: Peng Fan <peng.fan@nxp.com>
---
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-test.c | 3 +-
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 63 +++++++++++++++---------
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h | 5 +-
3 files changed, 46 insertions(+), 25 deletions(-)
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 5a4e45e151258..864d9f2350bc1 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 0ea755ea82192..51de3a0b8e76b 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_alloc_master_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_in(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_get_cd_ptr(struct arm_smmu_master *master,
+ u32 ssid)
+{
+ return arm_smmu_get_cd_ptr_in(&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_alloc_master_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_in(cd_table, ssid);
}
struct arm_smmu_cd_writer {
@@ -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,17 @@ 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_alloc_master_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 (cd_table->s1fmt != STRTAB_STE_0_S1FMT_LINEAR) {
for (i = 0; i < cd_table->l2.num_l1_ents; i++) {
@@ -1816,6 +1827,11 @@ static void arm_smmu_free_cd_tables(struct arm_smmu_master *master)
}
}
+static void arm_smmu_free_master_cd_tables(struct arm_smmu_master *master)
+{
+ arm_smmu_free_cd_tables(master->smmu, &master->cd_table);
+}
+
/* Stream table manipulation functions */
static void arm_smmu_write_strtab_l1_desc(struct arm_smmu_strtab_l1 *dst,
dma_addr_t l2ptr_dma)
@@ -1900,10 +1916,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 +3881,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 +3949,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 +4083,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 +4455,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_alloc_master_cd_tables(master);
}
static struct iommu_device *arm_smmu_probe_device(struct device *dev)
@@ -4510,7 +4529,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_master_cd_tables(master);
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 56ed6ad1dd523..0256119e9c137 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);
--
2.34.1
next prev parent reply other threads:[~2026-10-30 12:05 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-30 12:09 [PATCH RFC v7 0/7] iommu/arm-smmu-v3: Support shared Stream IDs Peng Fan (OSS)
2026-10-30 12:09 ` [PATCH RFC v7 1/7] iommu/arm-smmu-v3: Allocate streams individually Peng Fan (OSS)
2026-10-30 12:09 ` [PATCH RFC v7 2/7] iommu/arm-smmu-v3: Delay stream allocation to inside the mutex Peng Fan (OSS)
2026-10-30 12:09 ` Peng Fan (OSS) [this message]
2026-10-30 20:54 ` [PATCH RFC v7 3/7] iommu/arm-smmu-v3: Plumb the CD table into the CD helpers Nicolin Chen
2026-10-30 12:09 ` [PATCH RFC v7 4/7] iommu/arm-smmu-v3: Use a per-domain CD table for non-PASID streams Peng Fan (OSS)
2026-10-31 1:07 ` Nicolin Chen
2026-10-30 12:09 ` [PATCH RFC v7 5/7] iommu/arm-smmu-v3: Support shared SIDs in insert/remove_master Peng Fan (OSS)
2026-10-30 12:09 ` [PATCH RFC v7 6/7] iommu/arm-smmu-v3: Group aliasing devices into the same IOMMU group Peng Fan (OSS)
2026-10-30 12:09 ` [PATCH RFC v7 7/7] iommu/arm-smmu-v3: Wire up shared-SID STE ordering and feature gating 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=20261030-smmu-shared-sid-ver7-2026-10-26-v7-3-961726ebd6ab@Example.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®