diff options
Diffstat (limited to 'drivers/iommu/intel-iommu.c')
| -rw-r--r-- | drivers/iommu/intel-iommu.c | 25 | 
1 files changed, 19 insertions, 6 deletions
diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c index b4f0e28dfa41..eec0d3e04bf5 100644 --- a/drivers/iommu/intel-iommu.c +++ b/drivers/iommu/intel-iommu.c @@ -4182,14 +4182,27 @@ static int intel_iommu_add_device(struct device *dev)  	/*  	 * If it's a multifunction device that does not support our -	 * required ACS flags, add to the same group as function 0. +	 * required ACS flags, add to the same group as lowest numbered +	 * function that also does not suport the required ACS flags.  	 */  	if (dma_pdev->multifunction && -	    !pci_acs_enabled(dma_pdev, REQ_ACS_FLAGS)) -		swap_pci_ref(&dma_pdev, -			     pci_get_slot(dma_pdev->bus, -					  PCI_DEVFN(PCI_SLOT(dma_pdev->devfn), -					  0))); +	    !pci_acs_enabled(dma_pdev, REQ_ACS_FLAGS)) { +		u8 i, slot = PCI_SLOT(dma_pdev->devfn); + +		for (i = 0; i < 8; i++) { +			struct pci_dev *tmp; + +			tmp = pci_get_slot(dma_pdev->bus, PCI_DEVFN(slot, i)); +			if (!tmp) +				continue; + +			if (!pci_acs_enabled(tmp, REQ_ACS_FLAGS)) { +				swap_pci_ref(&dma_pdev, tmp); +				break; +			} +			pci_dev_put(tmp); +		} +	}  	/*  	 * Devices on the root bus go through the iommu.  If that's not us,  | 
