Revert "PCI/PM: Assume ports without DLL Link Active train links in 100 ms"
authorBjorn Helgaas <bhelgaas@google.com>
Fri, 17 Jul 2020 22:21:28 +0000 (17:21 -0500)
committerBjorn Helgaas <bhelgaas@google.com>
Wed, 22 Jul 2020 15:31:52 +0000 (10:31 -0500)
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+oHYWkTjbL7ALgDbXo-Q@mail.gmail.com
Link: https://lore.kernel.org/r/CACO55tsAEa5GXw5oeJPG=mcn+qxNvspXreJYWDJGZBy5v82JDA@mail.gmail.com
Link: https://bugzilla.kernel.org/show_bug.cgi?id=208597
Reported-by: Patrick Volkerding <volkerdi@gmail.com>
Reported-by: Karol Herbst <kherbst@redhat.com>
Fixes: ec411e02b7a2 ("PCI/PM: Assume ports without DLL Link Active train links in 100 ms")
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
drivers/pci/pci.c

index ce09627..c9338f9 100644 (file)
@@ -4638,8 +4638,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.
  */
@@ -4680,7 +4679,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",
@@ -4801,28 +4800,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);