@@ -407,7 +407,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;
@@ -71,9 +71,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"},
@@ -2246,9 +2243,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 = {
@@ -2278,11 +2275,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;
}
@@ -2545,7 +2542,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);
master_domain = kzalloc(sizeof(*master_domain), GFP_KERNEL);
if (!master_domain)
@@ -2584,7 +2581,7 @@ static int arm_smmu_attach_prepare(struct arm_smmu_master *master,
static void arm_smmu_attach_commit(struct arm_smmu_master *master,
ioasid_t ssid, struct attach_state *state)
{
- lockdep_assert_held(&arm_smmu_asid_lock);
+ lockdep_assert_held(&master->smmu->asid_lock);
if (!state->want_ats) {
WARN_ON(master->ats_enabled);
@@ -2647,12 +2644,12 @@ 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, smmu_domain, IOMMU_NO_PASID,
&state);
if (ret) {
- mutex_unlock(&arm_smmu_asid_lock);
+ mutex_unlock(&smmu->asid_lock);
return ret;
}
@@ -2677,7 +2674,7 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev)
}
arm_smmu_attach_commit(master, IOMMU_NO_PASID, &state);
- mutex_unlock(&arm_smmu_asid_lock);
+ mutex_unlock(&smmu->asid_lock);
return 0;
}
@@ -2701,7 +2698,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, pasid, &state);
if (ret)
goto out_unlock;
@@ -2711,7 +2708,7 @@ int arm_smmu_set_pasid(struct arm_smmu_master *master,
arm_smmu_attach_commit(master, pasid, &state);
out_unlock:
- mutex_unlock(&arm_smmu_asid_lock);
+ mutex_unlock(&master->smmu->asid_lock);
return 0;
}
@@ -2727,12 +2724,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, pasid);
- mutex_unlock(&arm_smmu_asid_lock);
+ mutex_unlock(&master->smmu->asid_lock);
}
static int arm_smmu_attach_dev_ste(struct device *dev,
@@ -2749,7 +2746,7 @@ static int arm_smmu_attach_dev_ste(struct device *dev,
* 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
@@ -2778,7 +2775,7 @@ static int arm_smmu_attach_dev_ste(struct device *dev,
master->ats_enabled = false;
- mutex_unlock(&arm_smmu_asid_lock);
+ mutex_unlock(&master->smmu->asid_lock);
/*
* This has to be done after removing the master from the
@@ -3436,6 +3433,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;
}
@@ -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;
@@ -768,9 +770,6 @@ to_smmu_domain_safe(struct iommu_domain *domain)
return NULL;
}
-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);
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@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(-)