[PATCH 2/4] PCI: Indicate context lost if L1ss exit is broken during resume from system suspend

From: Manivannan Sadhasivam via B4 Relay

Date: Tue Apr 14 2026 - 12:02:11 EST


From: Manivannan Sadhasivam <manivannan.sadhasivam@xxxxxxxxxxxxxxxx>

The PCIe spec v7.0, sec 5.5.3.3.1, states that for exiting L1.2 due to an
endpoint asserting CLKREQ# signal, the refclk must be turned on no earlier
than TL10_REFCLK_ON, and within the latency advertised in the LTR message.
This same behavior applies to L1.1 as well.

On some platforms like Qcom, these requirements are satisfied during OS
runtime, but not while resuming from the system suspend. This happens
because the PCIe RC driver may remove all resource votes and turns off the
PHY during suspend to maximize power savings while keeping the link in
L1ss.

Consequently, when the endpoint asserts CLKREQ# to wake up, the OS must
first resume and the RC driver must restore the PHY and enable the refclk.
This recovery process exceeds the L1ss exit latency time. And this latency
violation results in an L1ss exit timeout, followed by Link Down (LDn). If
the endpoint device is used to host the RootFS, it will result in an OS
crash. For other endpoints, it may result in a complete device
reset/recovery.

So to indicate this platform limitation to the client drivers, introduce a
new flag 'pci_host_bridge::broken_l1ss_resume' and check it in the
pci_dev_suspend_retention_supported() API. If the flag is set by the RC
driver, the API will return 'false' indicating the client drivers that the
device context may not be retained and the drivers must be prepared for
context loss.

Signed-off-by: Manivannan Sadhasivam <manivannan.sadhasivam@xxxxxxxxxxxxxxxx>
---
drivers/pci/pci.c | 11 +++++++++++
include/linux/pci.h | 2 ++
2 files changed, 13 insertions(+)

diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 211616467a77..e871cccf24ae 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -2911,6 +2911,8 @@ void pci_config_pm_runtime_put(struct pci_dev *pdev)
*/
bool pci_dev_suspend_retention_supported(struct pci_dev *pdev)
{
+ struct pci_host_bridge *bridge = pci_find_host_bridge(pdev->bus);
+
/*
* If the platform firmware (like ACPI) is involved at the end of system
* suspend, device context may not be retained.
@@ -2918,6 +2920,15 @@ bool pci_dev_suspend_retention_supported(struct pci_dev *pdev)
if (pm_suspend_via_firmware())
return false;

+ /*
+ * Some host bridges power off the PHY to enter deep low-power modes
+ * during system suspend. Exiting L1 PM Substates from this condition
+ * violates strict timing requirements and results in Link Down (LDn).
+ * On such platforms, the endpoint must be prepared for context loss.
+ */
+ if (bridge && bridge->broken_l1ss_resume)
+ return false;
+
/* Assume that the context is retained by default */
return true;
}
diff --git a/include/linux/pci.h b/include/linux/pci.h
index d9bc7ad4eaa4..860d8a774b51 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -658,6 +658,8 @@ struct pci_host_bridge {
unsigned int preserve_config:1; /* Preserve FW resource setup */
unsigned int size_windows:1; /* Enable root bus sizing */
unsigned int msi_domain:1; /* Bridge wants MSI domain */
+ unsigned int broken_l1ss_resume:1; /* Resuming from L1ss during
+ system suspend is broken */

/* Resource alignment requirements */
resource_size_t (*align_resource)(struct pci_dev *dev,

--
2.51.0