After "drm/amdgpu: Fix GPU PCIe link capability reporting" there are now a few areas of walking topology.
Use the cached GPU-side link device for ASPM queries and switch state caching instead of walking the PCI topology independently in each path. Validate the internal downstream/upstream switch pair when initializing the cached link devices so all consumers share the existing topology checks. Signed-off-by: Mario Limonciello <[email protected]> --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 62 ++++++++-------------- 1 file changed, 21 insertions(+), 41 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 0d277516fd55e..07121d4aed3dc 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -1353,31 +1353,6 @@ static bool amdgpu_device_aspm_support_quirk(struct amdgpu_device *adev) #endif } -/* - * Some dGPUs expose their display endpoint below an internal PCIe switch. - * Use the switch upstream port to query the host-facing link. - */ -static struct pci_dev *amdgpu_device_get_aspm_pdev(struct amdgpu_device *adev) -{ - struct pci_dev *swds, *swus; - - swds = pci_upstream_bridge(adev->pdev); - if (!swds || - (swds->vendor != PCI_VENDOR_ID_ATI && - swds->vendor != PCI_VENDOR_ID_AMD) || - pci_pcie_type(swds) != PCI_EXP_TYPE_DOWNSTREAM) - return adev->pdev; - - swus = pci_upstream_bridge(swds); - if (!swus || - (swus->vendor != PCI_VENDOR_ID_ATI && - swus->vendor != PCI_VENDOR_ID_AMD) || - pci_pcie_type(swus) != PCI_EXP_TYPE_UPSTREAM) - return adev->pdev; - - return swus; -} - /** * amdgpu_device_should_use_aspm - check if the device should program ASPM * @@ -1413,7 +1388,7 @@ bool amdgpu_device_should_use_aspm(struct amdgpu_device *adev) * the immediate upstream bridge. Use SWUS for dGPUs with an * internal switch so that this is the host-facing link. */ - aspm_pdev = amdgpu_device_get_aspm_pdev(adev); + aspm_pdev = adev->link_dev; parent = pci_upstream_bridge(aspm_pdev); if (!parent) { dev_dbg(adev->dev, "ASPM: no upstream PCIe link for %s\n", @@ -1961,15 +1936,26 @@ static void amdgpu_uid_fini(struct amdgpu_device *adev) static void amdgpu_device_init_pcie_links(struct amdgpu_device *adev) { + struct pci_dev *swds, *swus; + adev->link_dev = adev->pdev; adev->link_partner = pci_upstream_bridge(adev->link_dev); - /* Skip upstream/downstream switches internal to the dGPU. */ - while (adev->link_partner && - adev->link_partner->vendor == PCI_VENDOR_ID_ATI) { - adev->link_dev = adev->link_partner; - adev->link_partner = pci_upstream_bridge(adev->link_dev); - } + /* Skip an upstream/downstream switch internal to the dGPU. */ + swds = adev->link_partner; + if (!swds || swds->vendor != PCI_VENDOR_ID_ATI || + pci_pcie_type(swds) != PCI_EXP_TYPE_DOWNSTREAM) + return; + + swus = pci_upstream_bridge(swds); + if (!swus || + (swus->vendor != PCI_VENDOR_ID_ATI && + swus->vendor != PCI_VENDOR_ID_AMD) || + pci_pcie_type(swus) != PCI_EXP_TYPE_UPSTREAM) + return; + + adev->link_dev = swus; + adev->link_partner = pci_upstream_bridge(swus); } /** @@ -6428,16 +6414,10 @@ static void amdgpu_device_cache_switch_state(struct amdgpu_device *adev) struct pci_dev *swus, *swds; int r; - swds = pci_upstream_bridge(adev->pdev); - if (!swds || swds->vendor != PCI_VENDOR_ID_ATI || - pci_pcie_type(swds) != PCI_EXP_TYPE_DOWNSTREAM) - return; - swus = pci_upstream_bridge(swds); - if (!swus || - (swus->vendor != PCI_VENDOR_ID_ATI && - swus->vendor != PCI_VENDOR_ID_AMD) || - pci_pcie_type(swus) != PCI_EXP_TYPE_UPSTREAM) + swus = adev->link_dev != adev->pdev ? adev->link_dev : NULL; + if (!swus) return; + swds = pci_upstream_bridge(adev->pdev); /* If already saved, return */ if (adev->pcie_reset_ctx.swus) -- 2.43.0
