Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit bea64033 authored by Joerg Roedel's avatar Joerg Roedel
Browse files

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: 55d94043 ('iommu/vt-d: Get rid of domain->iommu_lock')
Signed-off-by: default avatarJoerg Roedel <jroedel@suse.de>
parent 8c82d6ec
Loading
Loading
Loading
Loading
+12 −2
Original line number Diff line number Diff line
@@ -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);