aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/intel-iommu.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pci/intel-iommu.c')
-rw-r--r--drivers/pci/intel-iommu.c29
1 files changed, 29 insertions, 0 deletions
diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c
index a0ba568b831c..e541c3bdbf0d 100644
--- a/drivers/pci/intel-iommu.c
+++ b/drivers/pci/intel-iommu.c
@@ -2808,6 +2808,33 @@ static int vm_domain_add_dev_info(struct dmar_domain *domain,
2808 return 0; 2808 return 0;
2809} 2809}
2810 2810
2811static void iommu_detach_dependent_devices(struct intel_iommu *iommu,
2812 struct pci_dev *pdev)
2813{
2814 struct pci_dev *tmp, *parent;
2815
2816 if (!iommu || !pdev)
2817 return;
2818
2819 /* dependent device detach */
2820 tmp = pci_find_upstream_pcie_bridge(pdev);
2821 /* Secondary interface's bus number and devfn 0 */
2822 if (tmp) {
2823 parent = pdev->bus->self;
2824 while (parent != tmp) {
2825 iommu_detach_dev(iommu, parent->bus->number,
2826 parent->devfn);
2827 parent = parent->bus->self;
2828 }
2829 if (tmp->is_pcie) /* this is a PCIE-to-PCI bridge */
2830 iommu_detach_dev(iommu,
2831 tmp->subordinate->number, 0);
2832 else /* this is a legacy PCI bridge */
2833 iommu_detach_dev(iommu,
2834 tmp->bus->number, tmp->devfn);
2835 }
2836}
2837
2811static void vm_domain_remove_one_dev_info(struct dmar_domain *domain, 2838static void vm_domain_remove_one_dev_info(struct dmar_domain *domain,
2812 struct pci_dev *pdev) 2839 struct pci_dev *pdev)
2813{ 2840{
@@ -2833,6 +2860,7 @@ static void vm_domain_remove_one_dev_info(struct dmar_domain *domain,
2833 spin_unlock_irqrestore(&device_domain_lock, flags); 2860 spin_unlock_irqrestore(&device_domain_lock, flags);
2834 2861
2835 iommu_detach_dev(iommu, info->bus, info->devfn); 2862 iommu_detach_dev(iommu, info->bus, info->devfn);
2863 iommu_detach_dependent_devices(iommu, pdev);
2836 free_devinfo_mem(info); 2864 free_devinfo_mem(info);
2837 2865
2838 spin_lock_irqsave(&device_domain_lock, flags); 2866 spin_lock_irqsave(&device_domain_lock, flags);
@@ -2882,6 +2910,7 @@ static void vm_domain_remove_all_dev_info(struct dmar_domain *domain)
2882 2910
2883 iommu = device_to_iommu(info->bus, info->devfn); 2911 iommu = device_to_iommu(info->bus, info->devfn);
2884 iommu_detach_dev(iommu, info->bus, info->devfn); 2912 iommu_detach_dev(iommu, info->bus, info->devfn);
2913 iommu_detach_dependent_devices(iommu, info->dev);
2885 2914
2886 /* clear this iommu in iommu_bmp, update iommu count 2915 /* clear this iommu in iommu_bmp, update iommu count
2887 * and capabilities 2916 * and capabilities