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@google.com>
---
.../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(-)
@@ -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;
@@ -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:
@@ -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)