Skip to content

Commit

Permalink
iommu/vt-d: Fix dead-locks in disable_dmar_iommu() path
Browse files Browse the repository at this point in the history
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: 55d9404 ('iommu/vt-d: Get rid of domain->iommu_lock')
Signed-off-by: Joerg Roedel <jroedel@suse.de>
  • Loading branch information
Joerg Roedel committed Nov 8, 2016
1 parent 8c82d6e commit bea6403
Showing 1 changed file with 12 additions and 2 deletions.
14 changes: 12 additions & 2 deletions drivers/iommu/intel-iommu.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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);

Expand Down

0 comments on commit bea6403

Please sign in to comment.