@@ -1126,15 +1126,16 @@ int arm_smmu_write_ctx_desc(struct arm_smmu_domain *smmu_domain, int ssid,
return 0;
}
-static int arm_smmu_alloc_cd_tables(struct arm_smmu_domain *smmu_domain)
+static int arm_smmu_init_s1_cfg(struct arm_smmu_master *master,
+ struct arm_smmu_s1_cfg *cfg)
{
int ret;
size_t l1size;
size_t max_contexts;
- struct arm_smmu_device *smmu = smmu_domain->smmu;
- struct arm_smmu_s1_cfg *cfg = &smmu_domain->s1_cfg;
+ struct arm_smmu_device *smmu = master->smmu;
struct arm_smmu_ctx_desc_cfg *cdcfg = &cfg->cdcfg;
+ cfg->s1cdmax = master->ssid_bits;
max_contexts = 1 << cfg->s1cdmax;
if (!(smmu->features & ARM_SMMU_FEAT_2_LVL_CDTAB) ||
@@ -1175,12 +1176,11 @@ static int arm_smmu_alloc_cd_tables(struct arm_smmu_domain *smmu_domain)
return ret;
}
-static void arm_smmu_free_cd_tables(struct arm_smmu_domain *smmu_domain)
+static void arm_smmu_free_cd_tables(struct arm_smmu_device *smmu,
+ struct arm_smmu_ctx_desc_cfg *cdcfg)
{
int i;
size_t size, l1size;
- struct arm_smmu_device *smmu = smmu_domain->smmu;
- struct arm_smmu_ctx_desc_cfg *cdcfg = &smmu_domain->s1_cfg.cdcfg;
if (cdcfg->l1_desc) {
size = CTXDESC_L2_ENTRIES * (CTXDESC_CD_DWORDS << 3);
@@ -2076,7 +2076,7 @@ static void arm_smmu_domain_free(struct iommu_domain *domain)
/* Prevent SVA from touching the CD while we're freeing it */
mutex_lock(&arm_smmu_asid_lock);
if (cfg->cdcfg.cdtab)
- arm_smmu_free_cd_tables(smmu_domain);
+ arm_smmu_free_cd_tables(smmu, &cfg->cdcfg);
arm_smmu_free_asid(&smmu_domain->cd);
mutex_unlock(&arm_smmu_asid_lock);
} else {
@@ -2108,11 +2108,9 @@ static int arm_smmu_domain_finalise_s1(struct arm_smmu_domain *smmu_domain,
if (ret)
goto out_unlock;
- cfg->s1cdmax = master->ssid_bits;
-
smmu_domain->stall_enabled = master->stall_enabled;
- ret = arm_smmu_alloc_cd_tables(smmu_domain);
+ ret = arm_smmu_init_s1_cfg(master, cfg);
if (ret)
goto out_free_asid;
@@ -2140,7 +2138,7 @@ static int arm_smmu_domain_finalise_s1(struct arm_smmu_domain *smmu_domain,
return 0;
out_free_cd_tables:
- arm_smmu_free_cd_tables(smmu_domain);
+ arm_smmu_free_cd_tables(smmu, &cfg->cdcfg);
out_free_asid:
arm_smmu_free_asid(cd);
out_unlock:
@@ -2704,6 +2702,13 @@ static struct iommu_device *arm_smmu_probe_device(struct device *dev)
smmu->features & ARM_SMMU_FEAT_STALL_FORCE)
master->stall_enabled = true;
+ ret = arm_smmu_init_s1_cfg(master, &master->owned_s1_cfg);
+ if (ret) {
+ arm_smmu_disable_pasid(master);
+ arm_smmu_remove_master(master);
+ goto err_free_master;
+ }
+
return &smmu->iommu;
err_free_master:
@@ -2719,6 +2724,7 @@ static void arm_smmu_release_device(struct device *dev)
if (WARN_ON(arm_smmu_master_sva_enabled(master)))
iopf_queue_remove_device(master->smmu->evtq.iopf, dev);
arm_smmu_detach_dev(master);
+ arm_smmu_free_cd_tables(master->smmu, &master->owned_s1_cfg.cdcfg);
arm_smmu_disable_pasid(master);
arm_smmu_remove_master(master);
kfree(master);
@@ -688,6 +688,7 @@ struct arm_smmu_master {
struct arm_smmu_domain *domain;
struct list_head domain_head;
struct arm_smmu_stream *streams;
+ struct arm_smmu_s1_cfg owned_s1_cfg;
unsigned int num_streams;
bool ats_enabled;
bool stall_enabled;
Except for Nested domains, arm_smmu_master will own the STEs that are inserted into the arm_smmu_device's STE table. Signed-off-by: Michael Shavit <mshavit@google.com> --- drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 28 +++++++++++++-------- drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h | 1 + 2 files changed, 18 insertions(+), 11 deletions(-)