| 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 |
| |
| 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> |
| [lizf: Backported to 3.4: |
| - adjust context |
| - drop the last part of the changes of the patch] |
| Signed-off-by: Zefan Li <lizefan@huawei.com> |
| --- |
| drivers/iommu/intel-iommu.c | 7 ++++++- |
| 1 file changed, 6 insertions(+), 1 deletion(-) |
| |
| --- a/drivers/iommu/intel-iommu.c |
| +++ b/drivers/iommu/intel-iommu.c |
| @@ -3586,10 +3586,15 @@ found: |
| for (bus = dev->bus; bus; bus = bus->parent) { |
| struct pci_dev *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) || |
| bridge->pcie_type == PCI_EXP_TYPE_PCI_BRIDGE) |
| return 0; |
| |
| + /* If we found the root port, look it up in the ATSR */ |
| if (bridge->pcie_type == PCI_EXP_TYPE_ROOT_PORT) { |
| for (i = 0; i < atsru->devices_cnt; i++) |
| if (atsru->devices[i] == bridge) |