Some specific devices are taking time to settle the link in L1ss. So added a retry logic before returning from the suspend op. Signed-off-by: Krishna chaitanya chundru <quic_krichai@xxxxxxxxxxx> --- drivers/pci/controller/dwc/pcie-qcom.c | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/drivers/pci/controller/dwc/pcie-qcom.c b/drivers/pci/controller/dwc/pcie-qcom.c index f7dd5dc..f3201bd 100644 --- a/drivers/pci/controller/dwc/pcie-qcom.c +++ b/drivers/pci/controller/dwc/pcie-qcom.c @@ -1829,15 +1829,30 @@ static int __maybe_unused qcom_pcie_pm_suspend(struct device *dev) { struct qcom_pcie *pcie = dev_get_drvdata(dev); u32 val; + ktime_t timeout, start; if (!pcie->cfg->supports_system_suspend) return 0; - /* if the link is not in l1ss don't turn off clocks */ - val = readl(pcie->parf + PCIE20_PARF_PM_STTS); - if (!(val & PCIE20_PARF_PM_STTS_LINKST_IN_L1SUB)) { - dev_warn(dev, "Link is not in L1ss\n"); - return 0; + start = ktime_get(); + /* Wait max 100 ms */ + timeout = ktime_add_ms(start, 100); + while (1) { + bool timedout = ktime_after(ktime_get(), timeout); + + /* if the link is not in l1ss don't turn off clocks */ + val = readl(pcie->parf + PCIE20_PARF_PM_STTS); + if ((val & PCIE20_PARF_PM_STTS_LINKST_IN_L1SUB)) { + dev_info(dev, "Link enters L1ss after %d ms\n", + ktime_to_ms(ktime_get() - start)); + break; + } + + if (timedout) { + dev_warn(dev, "Link is not in L1ss\n"); + return 0; + } + usleep_range(1000, 1200); } if (pcie->cfg->ops->suspend) -- 2.7.4