[PATCH v2 17/18] iommu/arm-smmu-v3-sva: Alloc notifier for {smmu,mn}

From: Michael Shavit
Date: Tue Jun 06 2023 - 08:11:54 EST


The arm_smmu_nofitier for an mn can be shared across all devices with
the same upstream smmu. This breaks the last remaining explicit
dependency on the device's primary domain in arm-smmu-v3-sva.

Signed-off-by: Michael Shavit <mshavit@xxxxxxxxxx>
---
.../iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c | 18 +++++++-----------
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 2 +-
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h | 4 ++--
3 files changed, 10 insertions(+), 14 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 9a2da579c3563..3e49838e4f55c 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
@@ -258,17 +258,16 @@ static const struct mmu_notifier_ops arm_smmu_mmu_notifier_ops = {
.free_notifier = arm_smmu_mmu_notifier_free,
};

-/* Allocate or get existing MMU notifier for this {domain, mm} pair */
+/* Allocate or get existing MMU notifier for this {smmu, mm} pair */
static struct arm_smmu_mmu_notifier *
arm_smmu_mmu_notifier_get(struct arm_smmu_device *smmu,
- struct arm_smmu_domain *smmu_domain,
struct mm_struct *mm)
{
int ret;
struct arm_smmu_ctx_desc *cd;
struct arm_smmu_mmu_notifier *smmu_mn;

- list_for_each_entry(smmu_mn, &smmu_domain->mmu_notifiers, list) {
+ list_for_each_entry(smmu_mn, &smmu->mmu_notifiers, list) {
if (smmu_mn->mn.mm == mm) {
refcount_inc(&smmu_mn->refs);
return smmu_mn;
@@ -296,9 +295,8 @@ arm_smmu_mmu_notifier_get(struct arm_smmu_device *smmu,
}
arm_smmu_init_shared_cd_domain(smmu, &smmu_mn->domain, cd);

- list_add(&smmu_mn->list, &smmu_domain->mmu_notifiers);
+ list_add(&smmu_mn->list, &smmu->mmu_notifiers);
return smmu_mn;
-
err_free_cd:
arm_smmu_free_shared_cd(cd);
return ERR_PTR(ret);
@@ -314,7 +312,6 @@ static void arm_smmu_mmu_notifier_put(struct arm_smmu_mmu_notifier *smmu_mn)
return;

list_del(&smmu_mn->list);
-
/*
* If we went through clear(), we've already invalidated, and no
* new TLB entry can have been formed.
@@ -331,18 +328,17 @@ static void arm_smmu_mmu_notifier_put(struct arm_smmu_mmu_notifier *smmu_mn)

static int __arm_smmu_sva_bind(struct device *dev,
struct arm_smmu_sva_domain *sva_domain,
- struct mm_struct *mm)
+ struct mm_struct *mm,
+ ioasid_t id)
{
struct arm_smmu_master *master = dev_iommu_priv_get(dev);
- struct iommu_domain *domain = iommu_get_domain_for_dev(dev);
- struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain);
+ struct arm_smmu_domain *smmu_domain;
int ret;

if (!master || !master->sva_enabled)
return -ENODEV;

sva_domain->smmu_mn = arm_smmu_mmu_notifier_get(master->smmu,
- smmu_domain,
mm);
if (IS_ERR(sva_domain->smmu_mn)) {
sva_domain->smmu_mn = NULL;
@@ -533,7 +529,7 @@ static int arm_smmu_sva_set_dev_pasid(struct iommu_domain *domain,
struct mm_struct *mm = domain->mm;

mutex_lock(&sva_lock);
- ret = __arm_smmu_sva_bind(dev, to_sva_domain(domain), mm);
+ ret = __arm_smmu_sva_bind(dev, to_sva_domain(domain), mm, id);
mutex_unlock(&sva_lock);

return ret;
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 3c5ff4f58934a..e68c5264c6171 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
@@ -2058,7 +2058,6 @@ static void arm_smmu_init_smmu_domain(struct arm_smmu_domain *smmu_domain)
mutex_init(&smmu_domain->init_mutex);
INIT_LIST_HEAD(&smmu_domain->attached_domains);
spin_lock_init(&smmu_domain->attached_domains_lock);
- INIT_LIST_HEAD(&smmu_domain->mmu_notifiers);
}

static struct iommu_domain *arm_smmu_domain_alloc(unsigned type)
@@ -2859,6 +2858,7 @@ static struct iommu_device *arm_smmu_probe_device(struct device *dev)
goto err_free_master;
}

+ INIT_LIST_HEAD(&smmu->mmu_notifiers);
return &smmu->iommu;

err_free_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 2c33c0461036d..041b0e532ac3d 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
@@ -674,6 +674,8 @@ struct arm_smmu_device {

struct rb_root streams;
struct mutex streams_mutex;
+
+ struct list_head mmu_notifiers;
};

struct arm_smmu_stream {
@@ -737,8 +739,6 @@ struct arm_smmu_domain {

struct list_head attached_domains;
spinlock_t attached_domains_lock;
-
- struct list_head mmu_notifiers;
};

static inline struct arm_smmu_domain *to_smmu_domain(struct iommu_domain *dom)
--
2.41.0.rc0.172.g3f132b7071-goog