diff options
author | Lu Baolu <baolu.lu@linux.intel.com> | 2019-08-05 20:14:08 -0400 |
---|---|---|
committer | Joerg Roedel <jroedel@suse.de> | 2019-08-09 11:35:25 -0400 |
commit | ae23bfb68f2896835e54a137688906713cb607e7 (patch) | |
tree | 792fcee847d247f73362cc1a1ec87134f617c4d5 /drivers/iommu/intel-iommu.c | |
parent | ab2cbeb0ed301a9f0460078e91b09f39958212ef (diff) |
iommu/vt-d: Detach domain before using a private one
When the default domain of a group doesn't work for a device,
the iommu driver will try to use a private domain. The domain
which was previously attached to the device must be detached.
Cc: Ashok Raj <ashok.raj@intel.com>
Cc: Jacob Pan <jacob.jun.pan@linux.intel.com>
Cc: Kevin Tian <kevin.tian@intel.com>
Cc: Alex Williamson <alex.williamson@redhat.com>
Fixes: 942067f1b6b97 ("iommu/vt-d: Identify default domains replaced with private")
Reported-by: Alex Williamson <alex.williamson@redhat.com>
Link: https://lkml.org/lkml/2019/8/2/1379
Signed-off-by: Lu Baolu <baolu.lu@linux.intel.com>
Tested-by: Alex Williamson <alex.williamson@redhat.com>
Signed-off-by: Joerg Roedel <jroedel@suse.de>
Diffstat (limited to 'drivers/iommu/intel-iommu.c')
-rw-r--r-- | drivers/iommu/intel-iommu.c | 6 |
1 files changed, 5 insertions, 1 deletions
diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c index 3e22fa6ae8c8..37259b7f95a7 100644 --- a/drivers/iommu/intel-iommu.c +++ b/drivers/iommu/intel-iommu.c | |||
@@ -3449,6 +3449,7 @@ static bool iommu_need_mapping(struct device *dev) | |||
3449 | dmar_domain = to_dmar_domain(domain); | 3449 | dmar_domain = to_dmar_domain(domain); |
3450 | dmar_domain->flags |= DOMAIN_FLAG_LOSE_CHILDREN; | 3450 | dmar_domain->flags |= DOMAIN_FLAG_LOSE_CHILDREN; |
3451 | } | 3451 | } |
3452 | dmar_remove_one_dev_info(dev); | ||
3452 | get_private_domain_for_dev(dev); | 3453 | get_private_domain_for_dev(dev); |
3453 | } | 3454 | } |
3454 | 3455 | ||
@@ -4803,7 +4804,8 @@ static void dmar_remove_one_dev_info(struct device *dev) | |||
4803 | 4804 | ||
4804 | spin_lock_irqsave(&device_domain_lock, flags); | 4805 | spin_lock_irqsave(&device_domain_lock, flags); |
4805 | info = dev->archdata.iommu; | 4806 | info = dev->archdata.iommu; |
4806 | __dmar_remove_one_dev_info(info); | 4807 | if (info) |
4808 | __dmar_remove_one_dev_info(info); | ||
4807 | spin_unlock_irqrestore(&device_domain_lock, flags); | 4809 | spin_unlock_irqrestore(&device_domain_lock, flags); |
4808 | } | 4810 | } |
4809 | 4811 | ||
@@ -5281,6 +5283,7 @@ static int intel_iommu_add_device(struct device *dev) | |||
5281 | if (device_def_domain_type(dev) == IOMMU_DOMAIN_IDENTITY) { | 5283 | if (device_def_domain_type(dev) == IOMMU_DOMAIN_IDENTITY) { |
5282 | ret = iommu_request_dm_for_dev(dev); | 5284 | ret = iommu_request_dm_for_dev(dev); |
5283 | if (ret) { | 5285 | if (ret) { |
5286 | dmar_remove_one_dev_info(dev); | ||
5284 | dmar_domain->flags |= DOMAIN_FLAG_LOSE_CHILDREN; | 5287 | dmar_domain->flags |= DOMAIN_FLAG_LOSE_CHILDREN; |
5285 | domain_add_dev_info(si_domain, dev); | 5288 | domain_add_dev_info(si_domain, dev); |
5286 | dev_info(dev, | 5289 | dev_info(dev, |
@@ -5291,6 +5294,7 @@ static int intel_iommu_add_device(struct device *dev) | |||
5291 | if (device_def_domain_type(dev) == IOMMU_DOMAIN_DMA) { | 5294 | if (device_def_domain_type(dev) == IOMMU_DOMAIN_DMA) { |
5292 | ret = iommu_request_dma_domain_for_dev(dev); | 5295 | ret = iommu_request_dma_domain_for_dev(dev); |
5293 | if (ret) { | 5296 | if (ret) { |
5297 | dmar_remove_one_dev_info(dev); | ||
5294 | dmar_domain->flags |= DOMAIN_FLAG_LOSE_CHILDREN; | 5298 | dmar_domain->flags |= DOMAIN_FLAG_LOSE_CHILDREN; |
5295 | if (!get_private_domain_for_dev(dev)) { | 5299 | if (!get_private_domain_for_dev(dev)) { |
5296 | dev_warn(dev, | 5300 | dev_warn(dev, |