commit: a97590e56d0d58e1dd262353f7cbd84e81d8e600
From: Alex Williamson <[email protected]>
Date: Fri, 4 Mar 2011 14:52:16 -0700
Subject: [PATCH] intel-iommu: Unlink domain from iommu

When we remove a device, we unlink the iommu from the domain, but
we never do the reverse unlinking of the domain from the iommu.
This means that we never clear iommu->domain_ids, eventually leading
to resource exhaustion if we repeatedly bind and unbind a device
to a driver.  Also free empty domains to avoid a resource leak.

Signed-off-by: Alex Williamson <[email protected]>
Acked-by: Donald Dutile <[email protected]>
Signed-off-by: David Woodhouse <[email protected]>
Cc: [email protected]
---
 drivers/pci/intel-iommu.c |   13 ++++++++++++-
 1 files changed, 12 insertions(+), 1 deletions(-)

diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c
index 35463dd..292f223 100644
--- a/drivers/pci/intel-iommu.c
+++ b/drivers/pci/intel-iommu.c
@@ -3260,9 +3260,15 @@ static int device_notifier(struct notifier_block *nb,
        if (!domain)
                return 0;
 
-       if (action == BUS_NOTIFY_UNBOUND_DRIVER && !iommu_pass_through)
+       if (action == BUS_NOTIFY_UNBOUND_DRIVER && !iommu_pass_through) {
                domain_remove_one_dev_info(domain, pdev);
 
+               if (!(domain->flags & DOMAIN_FLAG_VIRTUAL_MACHINE) &&
+                   !(domain->flags & DOMAIN_FLAG_STATIC_IDENTITY) &&
+                   list_empty(&domain->devices))
+                       domain_exit(domain);
+       }
+
        return 0;
 }
 
@@ -3411,6 +3417,11 @@ static void domain_remove_one_dev_info(struct 
dmar_domain *domain,
                domain->iommu_count--;
                domain_update_iommu_cap(domain);
                spin_unlock_irqrestore(&domain->iommu_lock, tmp_flags);
+
+               spin_lock_irqsave(&iommu->lock, tmp_flags);
+               clear_bit(domain->id, iommu->domain_ids);
+               iommu->domains[domain->id] = NULL;
+               spin_unlock_irqrestore(&iommu->lock, tmp_flags);
        }
 
        spin_unlock_irqrestore(&device_domain_lock, flags);

_______________________________________________
stable mailing list
[email protected]
http://linux.kernel.org/mailman/listinfo/stable

Reply via email to