diff options
| -rw-r--r-- | drivers/iommu/intel-iommu.c | 25 |
1 files changed, 22 insertions, 3 deletions
diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c index 0204b62480b0..2297ec193eb4 100644 --- a/drivers/iommu/intel-iommu.c +++ b/drivers/iommu/intel-iommu.c | |||
| @@ -4125,8 +4125,13 @@ static int intel_iommu_add_device(struct device *dev) | |||
| 4125 | } else | 4125 | } else |
| 4126 | dma_pdev = pci_dev_get(pdev); | 4126 | dma_pdev = pci_dev_get(pdev); |
| 4127 | 4127 | ||
| 4128 | /* Account for quirked devices */ | ||
| 4128 | swap_pci_ref(&dma_pdev, pci_get_dma_source(dma_pdev)); | 4129 | swap_pci_ref(&dma_pdev, pci_get_dma_source(dma_pdev)); |
| 4129 | 4130 | ||
| 4131 | /* | ||
| 4132 | * If it's a multifunction device that does not support our | ||
| 4133 | * required ACS flags, add to the same group as function 0. | ||
| 4134 | */ | ||
| 4130 | if (dma_pdev->multifunction && | 4135 | if (dma_pdev->multifunction && |
| 4131 | !pci_acs_enabled(dma_pdev, REQ_ACS_FLAGS)) | 4136 | !pci_acs_enabled(dma_pdev, REQ_ACS_FLAGS)) |
| 4132 | swap_pci_ref(&dma_pdev, | 4137 | swap_pci_ref(&dma_pdev, |
| @@ -4134,14 +4139,28 @@ static int intel_iommu_add_device(struct device *dev) | |||
| 4134 | PCI_DEVFN(PCI_SLOT(dma_pdev->devfn), | 4139 | PCI_DEVFN(PCI_SLOT(dma_pdev->devfn), |
| 4135 | 0))); | 4140 | 0))); |
| 4136 | 4141 | ||
| 4142 | /* | ||
| 4143 | * Devices on the root bus go through the iommu. If that's not us, | ||
| 4144 | * find the next upstream device and test ACS up to the root bus. | ||
| 4145 | * Finding the next device may require skipping virtual buses. | ||
| 4146 | */ | ||
| 4137 | while (!pci_is_root_bus(dma_pdev->bus)) { | 4147 | while (!pci_is_root_bus(dma_pdev->bus)) { |
| 4138 | if (pci_acs_path_enabled(dma_pdev->bus->self, | 4148 | struct pci_bus *bus = dma_pdev->bus; |
| 4139 | NULL, REQ_ACS_FLAGS)) | 4149 | |
| 4150 | while (!bus->self) { | ||
| 4151 | if (!pci_is_root_bus(bus)) | ||
| 4152 | bus = bus->parent; | ||
| 4153 | else | ||
| 4154 | goto root_bus; | ||
| 4155 | } | ||
| 4156 | |||
| 4157 | if (pci_acs_path_enabled(bus->self, NULL, REQ_ACS_FLAGS)) | ||
| 4140 | break; | 4158 | break; |
| 4141 | 4159 | ||
| 4142 | swap_pci_ref(&dma_pdev, pci_dev_get(dma_pdev->bus->self)); | 4160 | swap_pci_ref(&dma_pdev, pci_dev_get(bus->self)); |
| 4143 | } | 4161 | } |
| 4144 | 4162 | ||
| 4163 | root_bus: | ||
| 4145 | group = iommu_group_get(&dma_pdev->dev); | 4164 | group = iommu_group_get(&dma_pdev->dev); |
| 4146 | pci_dev_put(dma_pdev); | 4165 | pci_dev_put(dma_pdev); |
| 4147 | if (!group) { | 4166 | if (!group) { |
