From: Bjorn Helgaas <bhelg...@google.com>

[ Upstream commit d08c30d7a0d1826f771f16cde32bd86e48401791 ]

This reverts commit ec411e02b7a2e785a4ed9ed283207cd14f48699d.

Patrick reported that this commit broke hybrid graphics on a ThinkPad X1
Extreme 2nd with Intel UHD Graphics 630 and NVIDIA GeForce GTX 1650 Mobile:

  nouveau 0000:01:00.0: fifo: PBDMA0: 01000000 [] ch 0 [00ff992000 DRM] subc 0 
mthd 0008 data 00000000

Karol reported that this commit broke Nouveau firmware loading on a Lenovo
P1G2 with Intel UHD Graphics 630 and NVIDIA TU117GLM [Quadro T1000 Mobile]:

  nouveau 0000:01:00.0: acr: AHESASC binary failed

In both cases, reverting ec411e02b7a2 solved the problem.  Unfortunately,
this revert will reintroduce the "Thunderbolt bridges take long time to
resume from D3cold" problem:
https://bugzilla.kernel.org/show_bug.cgi?id=206837

Link: 
https://lore.kernel.org/r/caerspo5stek_my1dehwp7ahd0xop87+ohywktjbl7algdbx...@mail.gmail.com
Link: 
https://lore.kernel.org/r/CACO55tsAEa5GXw5oeJPG=mcn+qxnvspxrejywdjgzby5v82...@mail.gmail.com
Link: https://bugzilla.kernel.org/show_bug.cgi?id=208597
Reported-by: Patrick Volkerding <volke...@gmail.com>
Reported-by: Karol Herbst <kher...@redhat.com>
Fixes: ec411e02b7a2 ("PCI/PM: Assume ports without DLL Link Active train links 
in 100 ms")
Signed-off-by: Bjorn Helgaas <bhelg...@google.com>
Signed-off-by: Sasha Levin <sas...@kernel.org>
---
 drivers/pci/pci.c | 30 +++++++++---------------------
 1 file changed, 9 insertions(+), 21 deletions(-)

diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index d4758518a97bd..a4efc7e0061f5 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -4662,8 +4662,7 @@ static int pci_pm_reset(struct pci_dev *dev, int probe)
  * pcie_wait_for_link_delay - Wait until link is active or inactive
  * @pdev: Bridge device
  * @active: waiting for active or inactive?
- * @delay: Delay to wait after link has become active (in ms). Specify %0
- *        for no delay.
+ * @delay: Delay to wait after link has become active (in ms)
  *
  * Use this to wait till link becomes active or inactive.
  */
@@ -4704,7 +4703,7 @@ static bool pcie_wait_for_link_delay(struct pci_dev 
*pdev, bool active,
                msleep(10);
                timeout -= 10;
        }
-       if (active && ret && delay)
+       if (active && ret)
                msleep(delay);
        else if (ret != active)
                pci_info(pdev, "Data Link Layer Link Active not %s in 1000 
msec\n",
@@ -4825,28 +4824,17 @@ void pci_bridge_wait_for_secondary_bus(struct pci_dev 
*dev)
        if (!pcie_downstream_port(dev))
                return;
 
-       /*
-        * Per PCIe r5.0, sec 6.6.1, for downstream ports that support
-        * speeds > 5 GT/s, we must wait for link training to complete
-        * before the mandatory delay.
-        *
-        * We can only tell when link training completes via DLL Link
-        * Active, which is required for downstream ports that support
-        * speeds > 5 GT/s (sec 7.5.3.6).  Unfortunately some common
-        * devices do not implement Link Active reporting even when it's
-        * required, so we'll check for that directly instead of checking
-        * the supported link speed.  We assume devices without Link Active
-        * reporting can train in 100 ms regardless of speed.
-        */
-       if (dev->link_active_reporting) {
-               pci_dbg(dev, "waiting for link to train\n");
-               if (!pcie_wait_for_link_delay(dev, true, 0)) {
+       if (pcie_get_speed_cap(dev) <= PCIE_SPEED_5_0GT) {
+               pci_dbg(dev, "waiting %d ms for downstream link\n", delay);
+               msleep(delay);
+       } else {
+               pci_dbg(dev, "waiting %d ms for downstream link, after 
activation\n",
+                       delay);
+               if (!pcie_wait_for_link_delay(dev, true, delay)) {
                        /* Did not train, no need to wait any further */
                        return;
                }
        }
-       pci_dbg(child, "waiting %d ms to become accessible\n", delay);
-       msleep(delay);
 
        if (!pci_device_is_present(child)) {
                pci_dbg(child, "waiting additional %d ms to become 
accessible\n", delay);
-- 
2.25.1



Reply via email to