drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
The arm_smmu_attach_commit() updates master->ats_enabled before calling
arm_smmu_remove_master_domain() that is supposed to clean up everything
in the old domain, including the old domain's nr_ats_masters. So, it is
supposed to use the old ats_enabled state of the device, not an updated
state.
This isn't a problem if switching between two domains where:
- old ats_enabled = false; new ats_enabled = false
- old ats_enabled = true; new ats_enabled = true
but can fail cases where:
- old ats_enabled = false; new ats_enabled = true
(old domain should keep the counter but incorrectly decreased it)
- old ats_enabled = true; new ats_enabled = false
(old domain needed to decrease the counter but incorrectly missed it)
Update master->ats_enabled after arm_smmu_remove_master_domain() to fix
this.
Fixes: 7497f4211f4f ("iommu/arm-smmu-v3: Make changing domains be hitless for ATS")
Cc: stable@vger.kernel.org
Signed-off-by: Nicolin Chen <nicolinc@nvidia.com>
---
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
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 312bc31d7e8eb..3c81139faecae 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
@@ -2997,9 +2997,9 @@ void arm_smmu_attach_commit(struct arm_smmu_attach_state *state)
/* ATS is being switched off, invalidate the entire ATC */
arm_smmu_atc_inv_master(master, IOMMU_NO_PASID);
}
- master->ats_enabled = state->ats_enabled;
arm_smmu_remove_master_domain(master, state->old_domain, state->ssid);
+ master->ats_enabled = state->ats_enabled;
}
static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev)
--
2.43.0
On Thu, Jul 31, 2025 at 08:01:27PM -0700, Nicolin Chen wrote: > The arm_smmu_attach_commit() updates master->ats_enabled before calling > arm_smmu_remove_master_domain() that is supposed to clean up everything > in the old domain, including the old domain's nr_ats_masters. So, it is > supposed to use the old ats_enabled state of the device, not an updated > state. > > This isn't a problem if switching between two domains where: > - old ats_enabled = false; new ats_enabled = false > - old ats_enabled = true; new ats_enabled = true > but can fail cases where: > - old ats_enabled = false; new ats_enabled = true > (old domain should keep the counter but incorrectly decreased it) > - old ats_enabled = true; new ats_enabled = false > (old domain needed to decrease the counter but incorrectly missed it) > > Update master->ats_enabled after arm_smmu_remove_master_domain() to fix > this. > > Fixes: 7497f4211f4f ("iommu/arm-smmu-v3: Make changing domains be hitless for ATS") > Cc: stable@vger.kernel.org > Signed-off-by: Nicolin Chen <nicolinc@nvidia.com> arm_smmu_remove_master_domain() needs to see the old ats_enabled state for the cleanup. Reviewed-by: Pranjal Shrivastava <praan@google.com> Thanks, Praan > --- > drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) > > 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 312bc31d7e8eb..3c81139faecae 100644 > --- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c > +++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c > @@ -2997,9 +2997,9 @@ void arm_smmu_attach_commit(struct arm_smmu_attach_state *state) > /* ATS is being switched off, invalidate the entire ATC */ > arm_smmu_atc_inv_master(master, IOMMU_NO_PASID); > } > - master->ats_enabled = state->ats_enabled; > > arm_smmu_remove_master_domain(master, state->old_domain, state->ssid); > + master->ats_enabled = state->ats_enabled; > } > > static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev) > -- > 2.43.0 > >
On Thu, Jul 31, 2025 at 08:01:27PM -0700, Nicolin Chen wrote: > drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) Applied for -rc, thanks.
On Thu, Jul 31, 2025 at 08:01:27PM -0700, Nicolin Chen wrote: > The arm_smmu_attach_commit() updates master->ats_enabled before calling > arm_smmu_remove_master_domain() that is supposed to clean up everything > in the old domain, including the old domain's nr_ats_masters. So, it is > supposed to use the old ats_enabled state of the device, not an updated > state. > > This isn't a problem if switching between two domains where: > - old ats_enabled = false; new ats_enabled = false > - old ats_enabled = true; new ats_enabled = true > but can fail cases where: > - old ats_enabled = false; new ats_enabled = true > (old domain should keep the counter but incorrectly decreased it) > - old ats_enabled = true; new ats_enabled = false > (old domain needed to decrease the counter but incorrectly missed it) > > Update master->ats_enabled after arm_smmu_remove_master_domain() to fix > this. > > Fixes: 7497f4211f4f ("iommu/arm-smmu-v3: Make changing domains be hitless for ATS") > Cc: stable@vger.kernel.org > Signed-off-by: Nicolin Chen <nicolinc@nvidia.com> > --- > drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) > > 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 312bc31d7e8eb..3c81139faecae 100644 > --- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c > +++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c > @@ -2997,9 +2997,9 @@ void arm_smmu_attach_commit(struct arm_smmu_attach_state *state) > /* ATS is being switched off, invalidate the entire ATC */ > arm_smmu_atc_inv_master(master, IOMMU_NO_PASID); > } > - master->ats_enabled = state->ats_enabled; > > arm_smmu_remove_master_domain(master, state->old_domain, state->ssid); > + master->ats_enabled = state->ats_enabled; > } > > static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev) > -- > 2.43.0 Acked-by: Will Deacon <will@kernel.org> Joerg -- please can you pick this up as a fix? Thanks, Will
On Thu, Jul 31, 2025 at 08:01:27PM -0700, Nicolin Chen wrote: > The arm_smmu_attach_commit() updates master->ats_enabled before calling > arm_smmu_remove_master_domain() that is supposed to clean up everything > in the old domain, including the old domain's nr_ats_masters. So, it is > supposed to use the old ats_enabled state of the device, not an updated > state. > > This isn't a problem if switching between two domains where: > - old ats_enabled = false; new ats_enabled = false > - old ats_enabled = true; new ats_enabled = true > but can fail cases where: > - old ats_enabled = false; new ats_enabled = true > (old domain should keep the counter but incorrectly decreased it) > - old ats_enabled = true; new ats_enabled = false > (old domain needed to decrease the counter but incorrectly missed it) > > Update master->ats_enabled after arm_smmu_remove_master_domain() to fix > this. > > Fixes: 7497f4211f4f ("iommu/arm-smmu-v3: Make changing domains be hitless for ATS") > Cc: stable@vger.kernel.org > Signed-off-by: Nicolin Chen <nicolinc@nvidia.com> > --- > drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) Reviewed-by: Jason Gunthorpe <jgg@nvidia.com> Jason
© 2016 - 2025 Red Hat, Inc.