Skip to content

Commit

Permalink
Merge tag 'arm-smmu-fixes' of git://git.kernel.org/pub/scm/linux/kern…
Browse files Browse the repository at this point in the history
…el/git/will/linux into iommu/fixes

Arm SMMU fixes for 6.8

- Fix CD allocation from atomic context when using SVA with SMMUv3

- Revert the conversion of SMMUv2 to domain_alloc_paging(), as it
  breaks the boot for Qualcomm MSM8996 devices
  • Loading branch information
joergroedel committed Feb 23, 2024
2 parents 4578f98 + b5bf777 commit 16b1b39
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 37 deletions.
38 changes: 12 additions & 26 deletions drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c
Original file line number Diff line number Diff line change
Expand Up @@ -292,10 +292,8 @@ arm_smmu_mmu_notifier_get(struct arm_smmu_domain *smmu_domain,
struct mm_struct *mm)
{
int ret;
unsigned long flags;
struct arm_smmu_ctx_desc *cd;
struct arm_smmu_mmu_notifier *smmu_mn;
struct arm_smmu_master *master;

list_for_each_entry(smmu_mn, &smmu_domain->mmu_notifiers, list) {
if (smmu_mn->mn.mm == mm) {
Expand Down Expand Up @@ -325,28 +323,9 @@ arm_smmu_mmu_notifier_get(struct arm_smmu_domain *smmu_domain,
goto err_free_cd;
}

spin_lock_irqsave(&smmu_domain->devices_lock, flags);
list_for_each_entry(master, &smmu_domain->devices, domain_head) {
ret = arm_smmu_write_ctx_desc(master, mm_get_enqcmd_pasid(mm),
cd);
if (ret) {
list_for_each_entry_from_reverse(
master, &smmu_domain->devices, domain_head)
arm_smmu_write_ctx_desc(
master, mm_get_enqcmd_pasid(mm), NULL);
break;
}
}
spin_unlock_irqrestore(&smmu_domain->devices_lock, flags);
if (ret)
goto err_put_notifier;

list_add(&smmu_mn->list, &smmu_domain->mmu_notifiers);
return smmu_mn;

err_put_notifier:
/* Frees smmu_mn */
mmu_notifier_put(&smmu_mn->mn);
err_free_cd:
arm_smmu_free_shared_cd(cd);
return ERR_PTR(ret);
Expand All @@ -363,9 +342,6 @@ static void arm_smmu_mmu_notifier_put(struct arm_smmu_mmu_notifier *smmu_mn)

list_del(&smmu_mn->list);

arm_smmu_update_ctx_desc_devices(smmu_domain, mm_get_enqcmd_pasid(mm),
NULL);

/*
* If we went through clear(), we've already invalidated, and no
* new TLB entry can have been formed.
Expand All @@ -381,7 +357,8 @@ static void arm_smmu_mmu_notifier_put(struct arm_smmu_mmu_notifier *smmu_mn)
arm_smmu_free_shared_cd(cd);
}

static int __arm_smmu_sva_bind(struct device *dev, struct mm_struct *mm)
static int __arm_smmu_sva_bind(struct device *dev, ioasid_t pasid,
struct mm_struct *mm)
{
int ret;
struct arm_smmu_bond *bond;
Expand All @@ -404,9 +381,15 @@ static int __arm_smmu_sva_bind(struct device *dev, struct mm_struct *mm)
goto err_free_bond;
}

ret = arm_smmu_write_ctx_desc(master, pasid, bond->smmu_mn->cd);
if (ret)
goto err_put_notifier;

list_add(&bond->list, &master->bonds);
return 0;

err_put_notifier:
arm_smmu_mmu_notifier_put(bond->smmu_mn);
err_free_bond:
kfree(bond);
return ret;
Expand Down Expand Up @@ -568,6 +551,9 @@ void arm_smmu_sva_remove_dev_pasid(struct iommu_domain *domain,
struct arm_smmu_master *master = dev_iommu_priv_get(dev);

mutex_lock(&sva_lock);

arm_smmu_write_ctx_desc(master, id, NULL);

list_for_each_entry(t, &master->bonds, list) {
if (t->mm == mm) {
bond = t;
Expand All @@ -590,7 +576,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, mm);
ret = __arm_smmu_sva_bind(dev, id, mm);
mutex_unlock(&sva_lock);

return ret;
Expand Down
17 changes: 6 additions & 11 deletions drivers/iommu/arm/arm-smmu/arm-smmu.c
Original file line number Diff line number Diff line change
Expand Up @@ -859,10 +859,14 @@ static void arm_smmu_destroy_domain_context(struct arm_smmu_domain *smmu_domain)
arm_smmu_rpm_put(smmu);
}

static struct iommu_domain *arm_smmu_domain_alloc_paging(struct device *dev)
static struct iommu_domain *arm_smmu_domain_alloc(unsigned type)
{
struct arm_smmu_domain *smmu_domain;

if (type != IOMMU_DOMAIN_UNMANAGED) {
if (using_legacy_binding || type != IOMMU_DOMAIN_DMA)
return NULL;
}
/*
* Allocate the domain and initialise some of its data structures.
* We can't really do anything meaningful until we've added a
Expand All @@ -875,15 +879,6 @@ static struct iommu_domain *arm_smmu_domain_alloc_paging(struct device *dev)
mutex_init(&smmu_domain->init_mutex);
spin_lock_init(&smmu_domain->cb_lock);

if (dev) {
struct arm_smmu_master_cfg *cfg = dev_iommu_priv_get(dev);

if (arm_smmu_init_domain_context(smmu_domain, cfg->smmu, dev)) {
kfree(smmu_domain);
return NULL;
}
}

return &smmu_domain->domain;
}

Expand Down Expand Up @@ -1600,7 +1595,7 @@ static struct iommu_ops arm_smmu_ops = {
.identity_domain = &arm_smmu_identity_domain,
.blocked_domain = &arm_smmu_blocked_domain,
.capable = arm_smmu_capable,
.domain_alloc_paging = arm_smmu_domain_alloc_paging,
.domain_alloc = arm_smmu_domain_alloc,
.probe_device = arm_smmu_probe_device,
.release_device = arm_smmu_release_device,
.probe_finalize = arm_smmu_probe_finalize,
Expand Down

0 comments on commit 16b1b39

Please sign in to comment.