summaryrefslogtreecommitdiffstats
path: root/drivers/iommu/intel-iommu.c
diff options
context:
space:
mode:
authorLu Baolu <baolu.lu@linux.intel.com>2019-08-26 04:50:56 -0400
committerJoerg Roedel <jroedel@suse.de>2019-08-30 10:26:12 -0400
commit0ce4a85f4f015d13a6a6b4954f4e8e63cd83f7b1 (patch)
tree72d8134ccbffcc0d71e9de799a2e5f1189952bd0 /drivers/iommu/intel-iommu.c
parenta55aa89aab90fae7c815b0551b07be37db359d76 (diff)
Revert "iommu/vt-d: Avoid duplicated pci dma alias consideration"
This reverts commit 557529494d79f3f1fadd486dd18d2de0b19be4da. Commit 557529494d79f ("iommu/vt-d: Avoid duplicated pci dma alias consideration") aimed to address a NULL pointer deference issue happened when a thunderbolt device driver returned unexpectedly. Unfortunately, this change breaks a previous pci quirk added by commit cc346a4714a59 ("PCI: Add function 1 DMA alias quirk for Marvell devices"), as the result, devices like Marvell 88SE9128 SATA controller doesn't work anymore. We will continue to try to find the real culprit mentioned in 557529494d79f, but for now we should revert it to fix current breakage. Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=204627 Cc: Stijn Tintel <stijn@linux-ipv6.be> Cc: Petr Vandrovec <petr@vandrovec.name> Reported-by: Stijn Tintel <stijn@linux-ipv6.be> Reported-by: Petr Vandrovec <petr@vandrovec.name> Signed-off-by: Lu Baolu <baolu.lu@linux.intel.com> Signed-off-by: Joerg Roedel <jroedel@suse.de>
Diffstat (limited to 'drivers/iommu/intel-iommu.c')
-rw-r--r--drivers/iommu/intel-iommu.c55
1 files changed, 53 insertions, 2 deletions
diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c
index 12d094d08c0a..c4e0e4a9ee9e 100644
--- a/drivers/iommu/intel-iommu.c
+++ b/drivers/iommu/intel-iommu.c
@@ -339,6 +339,8 @@ static void domain_exit(struct dmar_domain *domain);
339static void domain_remove_dev_info(struct dmar_domain *domain); 339static void domain_remove_dev_info(struct dmar_domain *domain);
340static void dmar_remove_one_dev_info(struct device *dev); 340static void dmar_remove_one_dev_info(struct device *dev);
341static void __dmar_remove_one_dev_info(struct device_domain_info *info); 341static void __dmar_remove_one_dev_info(struct device_domain_info *info);
342static void domain_context_clear(struct intel_iommu *iommu,
343 struct device *dev);
342static int domain_detach_iommu(struct dmar_domain *domain, 344static int domain_detach_iommu(struct dmar_domain *domain,
343 struct intel_iommu *iommu); 345 struct intel_iommu *iommu);
344static bool device_is_rmrr_locked(struct device *dev); 346static bool device_is_rmrr_locked(struct device *dev);
@@ -2105,9 +2107,26 @@ out_unlock:
2105 return ret; 2107 return ret;
2106} 2108}
2107 2109
2110struct domain_context_mapping_data {
2111 struct dmar_domain *domain;
2112 struct intel_iommu *iommu;
2113 struct pasid_table *table;
2114};
2115
2116static int domain_context_mapping_cb(struct pci_dev *pdev,
2117 u16 alias, void *opaque)
2118{
2119 struct domain_context_mapping_data *data = opaque;
2120
2121 return domain_context_mapping_one(data->domain, data->iommu,
2122 data->table, PCI_BUS_NUM(alias),
2123 alias & 0xff);
2124}
2125
2108static int 2126static int
2109domain_context_mapping(struct dmar_domain *domain, struct device *dev) 2127domain_context_mapping(struct dmar_domain *domain, struct device *dev)
2110{ 2128{
2129 struct domain_context_mapping_data data;
2111 struct pasid_table *table; 2130 struct pasid_table *table;
2112 struct intel_iommu *iommu; 2131 struct intel_iommu *iommu;
2113 u8 bus, devfn; 2132 u8 bus, devfn;
@@ -2117,7 +2136,17 @@ domain_context_mapping(struct dmar_domain *domain, struct device *dev)
2117 return -ENODEV; 2136 return -ENODEV;
2118 2137
2119 table = intel_pasid_get_table(dev); 2138 table = intel_pasid_get_table(dev);
2120 return domain_context_mapping_one(domain, iommu, table, bus, devfn); 2139
2140 if (!dev_is_pci(dev))
2141 return domain_context_mapping_one(domain, iommu, table,
2142 bus, devfn);
2143
2144 data.domain = domain;
2145 data.iommu = iommu;
2146 data.table = table;
2147
2148 return pci_for_each_dma_alias(to_pci_dev(dev),
2149 &domain_context_mapping_cb, &data);
2121} 2150}
2122 2151
2123static int domain_context_mapped_cb(struct pci_dev *pdev, 2152static int domain_context_mapped_cb(struct pci_dev *pdev,
@@ -4759,6 +4788,28 @@ out_free_dmar:
4759 return ret; 4788 return ret;
4760} 4789}
4761 4790
4791static int domain_context_clear_one_cb(struct pci_dev *pdev, u16 alias, void *opaque)
4792{
4793 struct intel_iommu *iommu = opaque;
4794
4795 domain_context_clear_one(iommu, PCI_BUS_NUM(alias), alias & 0xff);
4796 return 0;
4797}
4798
4799/*
4800 * NB - intel-iommu lacks any sort of reference counting for the users of
4801 * dependent devices. If multiple endpoints have intersecting dependent
4802 * devices, unbinding the driver from any one of them will possibly leave
4803 * the others unable to operate.
4804 */
4805static void domain_context_clear(struct intel_iommu *iommu, struct device *dev)
4806{
4807 if (!iommu || !dev || !dev_is_pci(dev))
4808 return;
4809
4810 pci_for_each_dma_alias(to_pci_dev(dev), &domain_context_clear_one_cb, iommu);
4811}
4812
4762static void __dmar_remove_one_dev_info(struct device_domain_info *info) 4813static void __dmar_remove_one_dev_info(struct device_domain_info *info)
4763{ 4814{
4764 struct dmar_domain *domain; 4815 struct dmar_domain *domain;
@@ -4779,7 +4830,7 @@ static void __dmar_remove_one_dev_info(struct device_domain_info *info)
4779 PASID_RID2PASID); 4830 PASID_RID2PASID);
4780 4831
4781 iommu_disable_dev_iotlb(info); 4832 iommu_disable_dev_iotlb(info);
4782 domain_context_clear_one(iommu, info->bus, info->devfn); 4833 domain_context_clear(iommu, info->dev);
4783 intel_pasid_free_table(info->dev); 4834 intel_pasid_free_table(info->dev);
4784 } 4835 }
4785 4836