Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Alex Williamson and committed by
Joerg Roedel
783f157b 664b6003

+25
+25
drivers/iommu/intel-iommu.c
··· 4090 4090 return 0; 4091 4091 } 4092 4092 4093 + static 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 + 4093 4101 static int intel_iommu_add_device(struct device *dev) 4094 4102 { 4095 4103 struct pci_dev *pdev = to_pci_dev(dev); ··· 4119 4111 dma_pdev = pci_dev_get(bridge); 4120 4112 } else 4121 4113 dma_pdev = pci_dev_get(pdev); 4114 + 4115 + swap_pci_ref(&dma_pdev, pci_get_dma_source(dma_pdev)); 4116 + 4117 + if (dma_pdev->multifunction && 4118 + !pci_acs_enabled(dma_pdev, REQ_ACS_FLAGS)) 4119 + swap_pci_ref(&dma_pdev, 4120 + pci_get_slot(dma_pdev->bus, 4121 + PCI_DEVFN(PCI_SLOT(dma_pdev->devfn), 4122 + 0))); 4123 + 4124 + while (!pci_is_root_bus(dma_pdev->bus)) { 4125 + if (pci_acs_path_enabled(dma_pdev->bus->self, 4126 + NULL, REQ_ACS_FLAGS)) 4127 + break; 4128 + 4129 + swap_pci_ref(&dma_pdev, pci_dev_get(dma_pdev->bus->self)); 4130 + } 4122 4131 4123 4132 group = iommu_group_get(&dma_pdev->dev); 4124 4133 pci_dev_put(dma_pdev);