* 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)
+ * @delay: Delay to wait after link has become active (in ms). Specify %0
+ *        for no delay.
  *
  * Use this to wait till link becomes active or inactive.
  */
                msleep(10);
                timeout -= 10;
        }
-       if (active && ret)
+       if (active && ret && delay)
                msleep(delay);
        else if (ret != active)
                pci_info(pdev, "Data Link Layer Link Active not %s in 1000 msec\n",
        if (!pcie_downstream_port(dev))
                return;
 
-       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)) {
+       /*
+        * 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)) {
                        /* 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);