From 5fbb0fa7327667ade8fa61921425bd4f8803e272 Mon Sep 17 00:00:00 2001 From: Lu Baolu Date: Mon, 28 Sep 2026 11:27:21 +0800 Subject: [PATCH] iommu/vt-d: Drop old iopf ref only after attach succeeds MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit identity_domain_attach_dev() currently removes the old domain’s iopf reference before programming pass-through. If pass-through setup fails, attach fails but the old domain is still effectively attached — now with its IOPF ref already dropped. This can undercount info->iopf_refcount and may disable iopf queue handling while the old domain can still issue page requests. Fix it by removing the old domain’s iopf reference only after pass-through setup succeeds, matching other attach paths. Fixes: 236dd58fabd2 ("iommu/vt-d: Fix iopf_refcount leak on RID domain replacement") Signed-off-by: Lu Baolu Reviewed-by: Kevin Tian Signed-off-by: Joerg Roedel --- drivers/iommu/intel/iommu.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c index 1fb9b80f3b5e..e3ec7f3b7826 100644 --- a/drivers/iommu/intel/iommu.c +++ b/drivers/iommu/intel/iommu.c @@ -3985,6 +3985,14 @@ static int identity_domain_attach_dev(struct iommu_domain *domain, if (dev_is_real_dma_subdevice(dev)) return 0; + if (sm_supported(iommu)) + ret = intel_pasid_setup_pass_through(iommu, dev, IOMMU_NO_PASID); + else + ret = device_setup_pass_through(dev); + + if (ret) + return ret; + /* * The identity domain has no iopf_handler, so no IOPF reference is * taken for it. The reference held by the old domain must still be @@ -3992,16 +4000,9 @@ static int identity_domain_attach_dev(struct iommu_domain *domain, * not affect the IOPF reference count. */ iopf_for_domain_remove(old, dev); + info->domain_attached = true; - if (sm_supported(iommu)) - ret = intel_pasid_setup_pass_through(iommu, dev, IOMMU_NO_PASID); - else - ret = device_setup_pass_through(dev); - - if (!ret) - info->domain_attached = true; - - return ret; + return 0; } static int identity_domain_set_dev_pasid(struct iommu_domain *domain,