]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
PCI: Indicate context lost if L1SS exit is broken during resume from system suspend
authorManivannan Sadhasivam <manivannan.sadhasivam@oss.qualcomm.com>
Tue, 19 May 2026 08:11:21 +0000 (13:41 +0530)
committerBjorn Helgaas <bhelgaas@google.com>
Sat, 23 May 2026 11:52:50 +0000 (06:52 -0500)
Per PCIe v7.0, sec 5.5.3.3.1, when exiting L1.2 due to an endpoint
asserting CLKREQ# signal, the REFCLK must be turned on within the latency
advertised in the LTR message.  This requirement 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 turn off the
PHY analog circuitry during suspend to maximize power savings while keeping
the link in L1SS.

Consequently, when the endpoint asserts CLKREQ# to wake up, the RC driver
must restore the PHY and enable the REFCLK.  When this recovery process
exceeds the L1SS exit latency time (roughly L10_REFCLK_ON + T_COMMONMODE),
the endpoint may treat it as a fatal condition and trigger Link Down (LDn).
This results in a reset that destroys the internal device state.

So to indicate this platform limitation to the client drivers, introduce a
new flag 'pci_host_bridge::broken_l1ss_resume' and check it in
pci_suspend_retains_context(). 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@oss.qualcomm.com>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Link: https://patch.msgid.link/20260519-l1ss-fix-v2-2-b2c3a4bdeb15@oss.qualcomm.com
drivers/pci/pci.c
include/linux/pci.h

index 86961551ec5154c436a40f97c26792c1f984ef8e..2f7e7e186b478e768e4d1cbed0f13c74c7d7982e 100644 (file)
@@ -2910,6 +2910,8 @@ void pci_config_pm_runtime_put(struct pci_dev *pdev)
  */
 bool pci_suspend_retains_context(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.
@@ -2917,6 +2919,16 @@ bool pci_suspend_retains_context(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 L1SS from this condition
+        * may violate timing requirements and result in Link Down (LDn),
+        * which causes a reset of the device.  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;
 }
index f60f9e4e7b39582efe7ec8addaed180ce1fd189d..4fee00ec59d793422cbd538356ba10727020d1ae 100644 (file)
@@ -660,6 +660,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,