[PATCH 1/1] PCI: Fix secondary bus wait return value when D3cold delay = 0
From: Ilpo Järvinen
Date: Tue Jun 10 2025 - 07:56:11 EST
If D3cold delay is zero, pci_bridge_wait_for_secondary_bus()
immediately returns 0 which is inconsistent with the rest of the
function.
When D3cold delay is 0, infer the return value like in the other cases.
With link_active_reporting, use Data Link Layer Link Active (PCIe spec
r6.2 sec. 7.5.3.8) and otherwise call pci_dev_wait() with zero delay.
Fixes: ad9001f2f411 ("PCI/PM: Add missing link delays required by the PCIe spec")
Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@xxxxxxxxxxxxxxx>
---
I've not seen this to cause issue anywhere, it's just the inconsistency
that caught my eye while trying to figure an entirely unrelated issue.
drivers/pci/pci.c | 15 +++++++++------
1 file changed, 9 insertions(+), 6 deletions(-)
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index e9448d55113b..a6182261b433 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -4848,6 +4848,7 @@ int pci_bridge_wait_for_secondary_bus(struct pci_dev *dev, char *reset_type)
{
struct pci_dev *child __free(pci_dev_put) = NULL;
int delay;
+ u16 status;
if (pci_dev_is_disconnected(dev))
return 0;
@@ -4870,15 +4871,19 @@ int pci_bridge_wait_for_secondary_bus(struct pci_dev *dev, char *reset_type)
/* Take d3cold_delay requirements into account */
delay = pci_bus_max_d3cold_delay(dev->subordinate);
- if (!delay) {
- up_read(&pci_bus_sem);
- return 0;
- }
child = pci_dev_get(list_first_entry(&dev->subordinate->devices,
struct pci_dev, bus_list));
up_read(&pci_bus_sem);
+ if (!delay) {
+ if (dev->link_active_reporting) {
+ pcie_capability_read_word(dev, PCI_EXP_LNKSTA, &status);
+ return status & PCI_EXP_LNKSTA_DLLLA ? 0 : -ENOTTY;
+ }
+ return pci_dev_wait(child, reset_type, 0);
+ }
+
/*
* Conventional PCI and PCI-X we need to wait Tpvrh + Trhfa before
* accessing the device after reset (that is 1000 ms + 100 ms).
@@ -4908,8 +4913,6 @@ int pci_bridge_wait_for_secondary_bus(struct pci_dev *dev, char *reset_type)
return 0;
if (pcie_get_speed_cap(dev) <= PCIE_SPEED_5_0GT) {
- u16 status;
-
pci_dbg(dev, "waiting %d ms for downstream link\n", delay);
msleep(delay);
base-commit: 19272b37aa4f83ca52bdf9c16d5d81bdd1354494
--
2.39.5