]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
iommu/arm-smmu-v3: Fix smmu_domain->nr_ats_masters decrement
authorNicolin Chen <nicolinc@nvidia.com>
Fri, 1 Aug 2025 03:01:27 +0000 (20:01 -0700)
committerJoerg Roedel <joerg.roedel@amd.com>
Fri, 22 Aug 2025 06:41:20 +0000 (08:41 +0200)
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>
Acked-by: Will Deacon <will@kernel.org>
Reviewed-by: Jason Gunthorpe <jgg@nvidia.com>
Reviewed-by: Pranjal Shrivastava <praan@google.com>
Link: https://lore.kernel.org/r/20250801030127.2006979-1-nicolinc@nvidia.com
Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c

index 5968043ac80235f59382a1982680fd3c96cbd5aa..2a8b46b948f050e003e66424bee383c9ac38a815 100644 (file)
@@ -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)