iommu/vt-d: Fix dead-locks in disable_dmar_iommu() path
It turns out that the disable_dmar_iommu() code-path tried
to get the device_domain_lock recursivly, which will
dead-lock when this code runs on dmar removal. Fix both
code-paths that could lead to the dead-lock.
Fixes: 55d940430a
('iommu/vt-d: Get rid of domain->iommu_lock')
Signed-off-by: Joerg Roedel <jroedel@suse.de>
This commit is contained in:
parent
8c82d6ec5a
commit
bea64033dd
|
@ -1711,6 +1711,7 @@ static void disable_dmar_iommu(struct intel_iommu *iommu)
|
|||
if (!iommu->domains || !iommu->domain_ids)
|
||||
return;
|
||||
|
||||
again:
|
||||
spin_lock_irqsave(&device_domain_lock, flags);
|
||||
list_for_each_entry_safe(info, tmp, &device_domain_list, global) {
|
||||
struct dmar_domain *domain;
|
||||
|
@ -1723,10 +1724,19 @@ static void disable_dmar_iommu(struct intel_iommu *iommu)
|
|||
|
||||
domain = info->domain;
|
||||
|
||||
dmar_remove_one_dev_info(domain, info->dev);
|
||||
__dmar_remove_one_dev_info(info);
|
||||
|
||||
if (!domain_type_is_vm_or_si(domain))
|
||||
if (!domain_type_is_vm_or_si(domain)) {
|
||||
/*
|
||||
* The domain_exit() function can't be called under
|
||||
* device_domain_lock, as it takes this lock itself.
|
||||
* So release the lock here and re-run the loop
|
||||
* afterwards.
|
||||
*/
|
||||
spin_unlock_irqrestore(&device_domain_lock, flags);
|
||||
domain_exit(domain);
|
||||
goto again;
|
||||
}
|
||||
}
|
||||
spin_unlock_irqrestore(&device_domain_lock, flags);
|
||||
|
||||
|
|
Loading…
Reference in New Issue