[PATCH v4 23/27] iommu/arm-smmu-v3: Move the arm_smmu_asid_xa to per-smmu like vmid
Jason Gunthorpe
jgg at nvidia.com
Fri Jan 26 10:15:25 PST 2024
The SVA BTM and shared cd code was the only thing keeping this as a global
array. Now that is out of the way we can move it to per-smmu.
Signed-off-by: Jason Gunthorpe <jgg at nvidia.com>
---
.../iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c | 2 +-
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 39 +++++++++----------
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h | 5 +--
3 files changed, 22 insertions(+), 24 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 46b4b7626a7c2d..080b84a3b78ce4 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
@@ -418,7 +418,7 @@ struct iommu_domain *arm_smmu_sva_domain_alloc(struct device *dev,
smmu_domain->domain.ops = &arm_smmu_sva_domain_ops;
smmu_domain->smmu = smmu;
- ret = xa_alloc(&arm_smmu_asid_xa, &asid, smmu_domain,
+ ret = xa_alloc(&smmu->asid_map, &asid, smmu_domain,
XA_LIMIT(1, (1 << smmu->asid_bits) - 1), GFP_KERNEL);
if (ret)
goto err_free;
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 fc7824c8decb50..be95f29e80df6a 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
@@ -89,9 +89,6 @@ struct arm_smmu_option_prop {
const char *prop;
};
-DEFINE_XARRAY_ALLOC1(arm_smmu_asid_xa);
-DEFINE_MUTEX(arm_smmu_asid_lock);
-
static struct arm_smmu_option_prop arm_smmu_options[] = {
{ ARM_SMMU_OPT_SKIP_PREFETCH, "hisilicon,broken-prefetch-cmd" },
{ ARM_SMMU_OPT_PAGE0_REGS_ONLY, "cavium,cn9900-broken-page1-regspace"},
@@ -2299,9 +2296,9 @@ void arm_smmu_domain_free_id(struct arm_smmu_domain *smmu_domain)
arm_smmu_tlb_inv_asid(smmu, smmu_domain->cd.asid);
/* Prevent SVA from touching the CD while we're freeing it */
- mutex_lock(&arm_smmu_asid_lock);
- xa_erase(&arm_smmu_asid_xa, smmu_domain->cd.asid);
- mutex_unlock(&arm_smmu_asid_lock);
+ mutex_lock(&smmu->asid_lock);
+ xa_erase(&smmu->asid_map, smmu_domain->cd.asid);
+ mutex_unlock(&smmu->asid_lock);
} else if (smmu_domain->stage == ARM_SMMU_DOMAIN_S2 &&
smmu_domain->s2_cfg.vmid) {
struct arm_smmu_cmdq_ent cmd = {
@@ -2331,11 +2328,11 @@ static int arm_smmu_domain_finalise_s1(struct arm_smmu_device *smmu,
struct arm_smmu_ctx_desc *cd = &smmu_domain->cd;
/* Prevent SVA from modifying the ASID until it is written to the CD */
- mutex_lock(&arm_smmu_asid_lock);
- ret = xa_alloc(&arm_smmu_asid_xa, &asid, smmu_domain,
+ mutex_lock(&smmu->asid_lock);
+ ret = xa_alloc(&smmu->asid_map, &asid, smmu_domain,
XA_LIMIT(1, (1 << smmu->asid_bits) - 1), GFP_KERNEL);
cd->asid = (u16)asid;
- mutex_unlock(&arm_smmu_asid_lock);
+ mutex_unlock(&smmu->asid_lock);
return ret;
}
@@ -2622,7 +2619,7 @@ static int arm_smmu_attach_prepare(struct arm_smmu_master *master,
* arm_smmu_master_domain contents otherwise it could randomly write one
* or the other to the CD.
*/
- lockdep_assert_held(&arm_smmu_asid_lock);
+ lockdep_assert_held(&master->smmu->asid_lock);
state->want_ats = !state->disable_ats && arm_smmu_ats_supported(master);
@@ -2674,7 +2671,7 @@ static int arm_smmu_attach_prepare(struct arm_smmu_master *master,
static void arm_smmu_attach_commit(struct arm_smmu_master *master,
struct attach_state *state)
{
- lockdep_assert_held(&arm_smmu_asid_lock);
+ lockdep_assert_held(&master->smmu->asid_lock);
if (state->want_ats && !master->ats_enabled) {
arm_smmu_enable_ats(master);
@@ -2736,11 +2733,11 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev)
* This allows the STE and the smmu_domain->devices list to
* be inconsistent during this routine.
*/
- mutex_lock(&arm_smmu_asid_lock);
+ mutex_lock(&smmu->asid_lock);
ret = arm_smmu_attach_prepare(master, domain, &state);
if (ret) {
- mutex_unlock(&arm_smmu_asid_lock);
+ mutex_unlock(&smmu->asid_lock);
return ret;
}
@@ -2765,7 +2762,7 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev)
}
arm_smmu_attach_commit(master, &state);
- mutex_unlock(&arm_smmu_asid_lock);
+ mutex_unlock(&smmu->asid_lock);
return 0;
}
@@ -2795,7 +2792,7 @@ int arm_smmu_set_pasid(struct arm_smmu_master *master,
if (!cdptr)
return -ENOMEM;
- mutex_lock(&arm_smmu_asid_lock);
+ mutex_lock(&master->smmu->asid_lock);
ret = arm_smmu_attach_prepare(master, &smmu_domain->domain, &state);
if (ret)
goto out_unlock;
@@ -2805,7 +2802,7 @@ int arm_smmu_set_pasid(struct arm_smmu_master *master,
arm_smmu_attach_commit(master, &state);
out_unlock:
- mutex_unlock(&arm_smmu_asid_lock);
+ mutex_unlock(&master->smmu->asid_lock);
return ret;
}
@@ -2821,12 +2818,12 @@ static void arm_smmu_remove_dev_pasid(struct device *dev, ioasid_t pasid)
smmu_domain = to_smmu_domain(domain);
- mutex_lock(&arm_smmu_asid_lock);
+ mutex_lock(&master->smmu->asid_lock);
arm_smmu_clear_cd(master, pasid);
if (master->ats_enabled)
arm_smmu_atc_inv_master(master, pasid);
arm_smmu_remove_master_domain(master, &smmu_domain->domain, pasid);
- mutex_unlock(&arm_smmu_asid_lock);
+ mutex_unlock(&master->smmu->asid_lock);
}
static int arm_smmu_attach_dev_ste(struct iommu_domain *domain,
@@ -2842,7 +2839,7 @@ static int arm_smmu_attach_dev_ste(struct iommu_domain *domain,
* Do not allow any ASID to be changed while are working on the STE,
* otherwise we could miss invalidations.
*/
- mutex_lock(&arm_smmu_asid_lock);
+ mutex_lock(&master->smmu->asid_lock);
/*
* The SMMU does not support enabling ATS with bypass/abort. When the
@@ -2855,7 +2852,7 @@ static int arm_smmu_attach_dev_ste(struct iommu_domain *domain,
arm_smmu_attach_prepare(master, domain, &state);
arm_smmu_install_ste_for_dev(master, ste);
arm_smmu_attach_commit(master, &state);
- mutex_unlock(&arm_smmu_asid_lock);
+ mutex_unlock(&master->smmu->asid_lock);
/*
* This has to be done after removing the master from the
@@ -3509,6 +3506,8 @@ static int arm_smmu_init_strtab(struct arm_smmu_device *smmu)
smmu->strtab_cfg.strtab_base = reg;
ida_init(&smmu->vmid_map);
+ xa_init_flags(&smmu->asid_map, XA_FLAGS_ALLOC1);
+ mutex_init(&smmu->asid_lock);
return 0;
}
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 4e8806862ebeeb..e8aa78fc0b8a0e 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
@@ -675,6 +675,8 @@ struct arm_smmu_device {
#define ARM_SMMU_MAX_ASIDS (1 << 16)
unsigned int asid_bits;
+ struct xarray asid_map;
+ struct mutex asid_lock;
#define ARM_SMMU_MAX_VMIDS (1 << 16)
unsigned int vmid_bits;
@@ -753,9 +755,6 @@ static inline struct arm_smmu_domain *to_smmu_domain(struct iommu_domain *dom)
return container_of(dom, struct arm_smmu_domain, domain);
}
-extern struct xarray arm_smmu_asid_xa;
-extern struct mutex arm_smmu_asid_lock;
-
struct arm_smmu_domain *arm_smmu_domain_alloc(void);
void arm_smmu_clear_cd(struct arm_smmu_master *master, int ssid);
--
2.43.0
More information about the linux-arm-kernel
mailing list