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

Reply via email to