| From d14053b3c714178525f22660e6aaf41263d00056 Mon Sep 17 00:00:00 2001 |
| From: David Woodhouse <David.Woodhouse@intel.com> |
| Date: Thu, 15 Oct 2015 09:28:06 +0100 |
| Subject: iommu/vt-d: Fix ATSR handling for Root-Complex integrated endpoints |
| MIME-Version: 1.0 |
| Content-Type: text/plain; charset=UTF-8 |
| Content-Transfer-Encoding: 8bit |
| |
| From: David Woodhouse <David.Woodhouse@intel.com> |
| |
| commit d14053b3c714178525f22660e6aaf41263d00056 upstream. |
| |
| The VT-d specification says that "Software must enable ATS on endpoint |
| devices behind a Root Port only if the Root Port is reported as |
| supporting ATS transactions." |
| |
| We walk up the tree to find a Root Port, but for integrated devices we |
| don't find one — we get to the host bridge. In that case we *should* |
| allow ATS. Currently we don't, which means that we are incorrectly |
| failing to use ATS for the integrated graphics. Fix that. |
| |
| We should never break out of this loop "naturally" with bus==NULL, |
| since we'll always find bridge==NULL in that case (and now return 1). |
| |
| So remove the check for (!bridge) after the loop, since it can never |
| happen. If it did, it would be worthy of a BUG_ON(!bridge). But since |
| it'll oops anyway in that case, that'll do just as well. |
| |
| Signed-off-by: David Woodhouse <David.Woodhouse@intel.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| drivers/iommu/intel-iommu.c | 9 ++++++--- |
| 1 file changed, 6 insertions(+), 3 deletions(-) |
| |
| --- a/drivers/iommu/intel-iommu.c |
| +++ b/drivers/iommu/intel-iommu.c |
| @@ -4194,14 +4194,17 @@ int dmar_find_matched_atsr_unit(struct p |
| dev = pci_physfn(dev); |
| for (bus = dev->bus; bus; bus = bus->parent) { |
| bridge = bus->self; |
| - if (!bridge || !pci_is_pcie(bridge) || |
| + /* If it's an integrated device, allow ATS */ |
| + if (!bridge) |
| + return 1; |
| + /* Connected via non-PCIe: no ATS */ |
| + if (!pci_is_pcie(bridge) || |
| pci_pcie_type(bridge) == PCI_EXP_TYPE_PCI_BRIDGE) |
| return 0; |
| + /* If we found the root port, look it up in the ATSR */ |
| if (pci_pcie_type(bridge) == PCI_EXP_TYPE_ROOT_PORT) |
| break; |
| } |
| - if (!bridge) |
| - return 0; |
| |
| rcu_read_lock(); |
| list_for_each_entry_rcu(atsru, &dmar_atsr_units, list) { |