Commit d08c30d7 authored by Bjorn Helgaas's avatar Bjorn Helgaas
Browse files

Revert "PCI/PM: Assume ports without DLL Link Active train links in 100 ms"

This reverts commit ec411e02.

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 ec411e02 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: default avatarPatrick Volkerding <volkerdi@gmail.com>
Reported-by: default avatarKarol Herbst <kherbst@redhat.com>
Fixes: ec411e02 ("PCI/PM: Assume ports without DLL Link Active train links in 100 ms")
Signed-off-by: default avatarBjorn Helgaas <bhelgaas@google.com>
parent 62ca18a0
Loading
Loading
Loading
Loading
+9 −21
Original line number Diff line number Diff line
@@ -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);