aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/iommu
diff options
context:
space:
mode:
authorAlex Williamson <alex.williamson@redhat.com>2012-05-30 16:19:43 -0400
committerJoerg Roedel <joerg.roedel@amd.com>2012-06-25 07:48:29 -0400
commit783f157bc5a7fa30ee17b4099b27146bd1b68af4 (patch)
tree5072e1753bbee7b1027d12d175adef9c756f8d27 /drivers/iommu
parent664b600331128146d8ddd3e004defe23ba5c47dc (diff)
intel-iommu: Make use of DMA quirks and ACS checks in IOMMU groups
Work around broken devices and adhere to ACS support when determining IOMMU grouping. Signed-off-by: Alex Williamson <alex.williamson@redhat.com> Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
Diffstat (limited to 'drivers/iommu')
-rw-r--r--drivers/iommu/intel-iommu.c25
1 files changed, 25 insertions, 0 deletions
diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c
index 4a434528cd1..ebf2b310cdd 100644
--- a/drivers/iommu/intel-iommu.c
+++ b/drivers/iommu/intel-iommu.c
@@ -4090,6 +4090,14 @@ static int intel_iommu_domain_has_cap(struct iommu_domain *domain,
4090 return 0; 4090 return 0;
4091} 4091}
4092 4092
4093static void swap_pci_ref(struct pci_dev **from, struct pci_dev *to)
4094{
4095 pci_dev_put(*from);
4096 *from = to;
4097}
4098
4099#define REQ_ACS_FLAGS (PCI_ACS_SV | PCI_ACS_RR | PCI_ACS_CR | PCI_ACS_UF)
4100
4093static int intel_iommu_add_device(struct device *dev) 4101static int intel_iommu_add_device(struct device *dev)
4094{ 4102{
4095 struct pci_dev *pdev = to_pci_dev(dev); 4103 struct pci_dev *pdev = to_pci_dev(dev);
@@ -4112,6 +4120,23 @@ static int intel_iommu_add_device(struct device *dev)
4112 } else 4120 } else
4113 dma_pdev = pci_dev_get(pdev); 4121 dma_pdev = pci_dev_get(pdev);
4114 4122
4123 swap_pci_ref(&dma_pdev, pci_get_dma_source(dma_pdev));
4124
4125 if (dma_pdev->multifunction &&
4126 !pci_acs_enabled(dma_pdev, REQ_ACS_FLAGS))
4127 swap_pci_ref(&dma_pdev,
4128 pci_get_slot(dma_pdev->bus,
4129 PCI_DEVFN(PCI_SLOT(dma_pdev->devfn),
4130 0)));
4131
4132 while (!pci_is_root_bus(dma_pdev->bus)) {
4133 if (pci_acs_path_enabled(dma_pdev->bus->self,
4134 NULL, REQ_ACS_FLAGS))
4135 break;
4136
4137 swap_pci_ref(&dma_pdev, pci_dev_get(dma_pdev->bus->self));
4138 }
4139
4115 group = iommu_group_get(&dma_pdev->dev); 4140 group = iommu_group_get(&dma_pdev->dev);
4116 pci_dev_put(dma_pdev); 4141 pci_dev_put(dma_pdev);
4117 if (!group) { 4142 if (!group) {