[PATCH 3/3] PCI: dwc: Skip PME_Turn_Off and L2/L3 transition if no device is available

Manivannan Sadhasivam posted 3 patches 3 months ago
[PATCH 3/3] PCI: dwc: Skip PME_Turn_Off and L2/L3 transition if no device is available
Posted by Manivannan Sadhasivam 3 months ago
If there is no device available under the Root Ports, there is no point in
sending PME_Turn_Off and waiting for L2/L3 transition, it will result in a
timeout.

Hence, skip those steps if no device is available during suspend. The
resume flow remains unchanged.

Signed-off-by: Manivannan Sadhasivam <manivannan.sadhasivam@oss.qualcomm.com>
---
 drivers/pci/controller/dwc/pcie-designware-host.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/drivers/pci/controller/dwc/pcie-designware-host.c b/drivers/pci/controller/dwc/pcie-designware-host.c
index 20c9333bcb1c..b6b8139e91e3 100644
--- a/drivers/pci/controller/dwc/pcie-designware-host.c
+++ b/drivers/pci/controller/dwc/pcie-designware-host.c
@@ -20,6 +20,7 @@
 #include <linux/platform_device.h>
 
 #include "../../pci.h"
+#include "../pci-host-common.h"
 #include "pcie-designware.h"
 
 static struct pci_ops dw_pcie_ops;
@@ -1129,6 +1130,9 @@ int dw_pcie_suspend_noirq(struct dw_pcie *pci)
 	u32 val;
 	int ret;
 
+	if (!pci_root_ports_have_device(pci->pp.bridge->bus))
+		goto stop_link;
+
 	/*
 	 * If L1SS is supported, then do not put the link into L2 as some
 	 * devices such as NVMe expect low resume latency.
@@ -1162,6 +1166,7 @@ int dw_pcie_suspend_noirq(struct dw_pcie *pci)
 	 */
 	udelay(1);
 
+stop_link:
 	dw_pcie_stop_link(pci);
 	if (pci->pp.ops->deinit)
 		pci->pp.ops->deinit(&pci->pp);
-- 
2.48.1
Re: [PATCH 3/3] PCI: dwc: Skip PME_Turn_Off and L2/L3 transition if no device is available
Posted by kernel test robot 3 months ago
Hi Manivannan,

kernel test robot noticed the following build warnings:

[auto build test WARNING on pci/next]
[also build test WARNING on pci/for-linus linus/master v6.18-rc4 next-20251106]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Manivannan-Sadhasivam/PCI-host-common-Add-an-API-to-check-for-any-device-under-the-Root-Ports/20251106-141822
base:   https://git.kernel.org/pub/scm/linux/kernel/git/pci/pci.git next
patch link:    https://lore.kernel.org/r/20251106061326.8241-4-manivannan.sadhasivam%40oss.qualcomm.com
patch subject: [PATCH 3/3] PCI: dwc: Skip PME_Turn_Off and L2/L3 transition if no device is available
config: arm-randconfig-001-20251107 (https://download.01.org/0day-ci/archive/20251107/202511071025.JM5nTGnO-lkp@intel.com/config)
compiler: clang version 17.0.6 (https://github.com/llvm/llvm-project 6009708b4367171ccdbf4b5905cb6a803753fe18)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20251107/202511071025.JM5nTGnO-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202511071025.JM5nTGnO-lkp@intel.com/

All warnings (new ones prefixed by >>):

>> drivers/pci/controller/dwc/pcie-designware-host.c:1133:6: warning: variable 'ret' is used uninitialized whenever 'if' condition is true [-Wsometimes-uninitialized]
    1133 |         if (!pci_root_ports_have_device(pci->pp.bridge->bus))
         |             ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   drivers/pci/controller/dwc/pcie-designware-host.c:1176:9: note: uninitialized use occurs here
    1176 |         return ret;
         |                ^~~
   drivers/pci/controller/dwc/pcie-designware-host.c:1133:2: note: remove the 'if' if its condition is always false
    1133 |         if (!pci_root_ports_have_device(pci->pp.bridge->bus))
         |         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    1134 |                 goto stop_link;
         |                 ~~~~~~~~~~~~~~
   drivers/pci/controller/dwc/pcie-designware-host.c:1131:9: note: initialize the variable 'ret' to silence this warning
    1131 |         int ret;
         |                ^
         |                 = 0
   1 warning generated.


vim +1133 drivers/pci/controller/dwc/pcie-designware-host.c

  1126	
  1127	int dw_pcie_suspend_noirq(struct dw_pcie *pci)
  1128	{
  1129		u8 offset = dw_pcie_find_capability(pci, PCI_CAP_ID_EXP);
  1130		u32 val;
  1131		int ret;
  1132	
> 1133		if (!pci_root_ports_have_device(pci->pp.bridge->bus))
  1134			goto stop_link;
  1135	
  1136		/*
  1137		 * If L1SS is supported, then do not put the link into L2 as some
  1138		 * devices such as NVMe expect low resume latency.
  1139		 */
  1140		if (dw_pcie_readw_dbi(pci, offset + PCI_EXP_LNKCTL) & PCI_EXP_LNKCTL_ASPM_L1)
  1141			return 0;
  1142	
  1143		if (pci->pp.ops->pme_turn_off) {
  1144			pci->pp.ops->pme_turn_off(&pci->pp);
  1145		} else {
  1146			ret = dw_pcie_pme_turn_off(pci);
  1147			if (ret)
  1148				return ret;
  1149		}
  1150	
  1151		ret = read_poll_timeout(dw_pcie_get_ltssm, val,
  1152					val == DW_PCIE_LTSSM_L2_IDLE ||
  1153					val <= DW_PCIE_LTSSM_DETECT_WAIT,
  1154					PCIE_PME_TO_L2_TIMEOUT_US/10,
  1155					PCIE_PME_TO_L2_TIMEOUT_US, false, pci);
  1156		if (ret) {
  1157			/* Only log message when LTSSM isn't in DETECT or POLL */
  1158			dev_err(pci->dev, "Timeout waiting for L2 entry! LTSSM: 0x%x\n", val);
  1159			return ret;
  1160		}
  1161	
  1162		/*
  1163		 * Per PCIe r6.0, sec 5.3.3.2.1, software should wait at least
  1164		 * 100ns after L2/L3 Ready before turning off refclock and
  1165		 * main power. This is harmless when no endpoint is connected.
  1166		 */
  1167		udelay(1);
  1168	
  1169	stop_link:
  1170		dw_pcie_stop_link(pci);
  1171		if (pci->pp.ops->deinit)
  1172			pci->pp.ops->deinit(&pci->pp);
  1173	
  1174		pci->suspended = true;
  1175	
  1176		return ret;
  1177	}
  1178	EXPORT_SYMBOL_GPL(dw_pcie_suspend_noirq);
  1179	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
Re: [PATCH 3/3] PCI: dwc: Skip PME_Turn_Off and L2/L3 transition if no device is available
Posted by zhangsenchuan 3 months ago


> -----Original Messages-----
> From: "Manivannan Sadhasivam" <manivannan.sadhasivam@oss.qualcomm.com>
> Send time:Thursday, 06/11/2025 14:13:26
> To: lpieralisi@kernel.org, kwilczynski@kernel.org, mani@kernel.org, bhelgaas@google.com
> Cc: will@kernel.org, linux-pci@vger.kernel.org, linux-kernel@vger.kernel.org, robh@kernel.org, linux-arm-msm@vger.kernel.org, zhangsenchuan@eswincomputing.com, "Manivannan Sadhasivam" <manivannan.sadhasivam@oss.qualcomm.com>
> Subject: [PATCH 3/3] PCI: dwc: Skip PME_Turn_Off and L2/L3 transition if no device is available
> 
> If there is no device available under the Root Ports, there is no point in
> sending PME_Turn_Off and waiting for L2/L3 transition, it will result in a
> timeout.
> 
> Hence, skip those steps if no device is available during suspend. The
> resume flow remains unchanged.
> 
> Signed-off-by: Manivannan Sadhasivam <manivannan.sadhasivam@oss.qualcomm.com>
> ---
>  drivers/pci/controller/dwc/pcie-designware-host.c | 5 +++++
>  1 file changed, 5 insertions(+)
> 
> diff --git a/drivers/pci/controller/dwc/pcie-designware-host.c b/drivers/pci/controller/dwc/pcie-designware-host.c
> index 20c9333bcb1c..b6b8139e91e3 100644
> --- a/drivers/pci/controller/dwc/pcie-designware-host.c
> +++ b/drivers/pci/controller/dwc/pcie-designware-host.c
> @@ -20,6 +20,7 @@
>  #include <linux/platform_device.h>
>  
>  #include "../../pci.h"
> +#include "../pci-host-common.h"
>  #include "pcie-designware.h"
>  
>  static struct pci_ops dw_pcie_ops;
> @@ -1129,6 +1130,9 @@ int dw_pcie_suspend_noirq(struct dw_pcie *pci)
>  	u32 val;
>  	int ret;
>  
> +	if (!pci_root_ports_have_device(pci->pp.bridge->bus))
> +		goto stop_link;
> +
>  	/*
>  	 * If L1SS is supported, then do not put the link into L2 as some
>  	 * devices such as NVMe expect low resume latency.
> @@ -1162,6 +1166,7 @@ int dw_pcie_suspend_noirq(struct dw_pcie *pci)
>  	 */
>  	udelay(1);
>  
> +stop_link:
>  	dw_pcie_stop_link(pci);
>  	if (pci->pp.ops->deinit)
>  		pci->pp.ops->deinit(&pci->pp);
> -- 
> 2.48.1

hi, Manivannan

I'd like your advice on a few things.

If there is no device available under the Root Ports, the dw_pcie_wait_for_link
function in dw_pcie_resume_noirq still need to wait for the link_up? Otherwise
linkup will TIMEDOUT. At this time, when the resume function return, -ETIMEDOUT 
returned which will raise "PM: failed to resume noirq: error -110".

Currently, in the pci-imx6.c/pci-layerscape.c/pcie-stm32.c file, the 
dw_pcie_resume_noirq function is directly returned after use.
Does the pci_root_ports_have_device function help vendor avoid 
this problem?

Best Regards,
Senchuan Zhang
Re: [PATCH 3/3] PCI: dwc: Skip PME_Turn_Off and L2/L3 transition if no device is available
Posted by Manivannan Sadhasivam 3 months ago
On Thu, Nov 06, 2025 at 06:02:55PM +0800, zhangsenchuan wrote:
> 
> 
> 
> > -----Original Messages-----
> > From: "Manivannan Sadhasivam" <manivannan.sadhasivam@oss.qualcomm.com>
> > Send time:Thursday, 06/11/2025 14:13:26
> > To: lpieralisi@kernel.org, kwilczynski@kernel.org, mani@kernel.org, bhelgaas@google.com
> > Cc: will@kernel.org, linux-pci@vger.kernel.org, linux-kernel@vger.kernel.org, robh@kernel.org, linux-arm-msm@vger.kernel.org, zhangsenchuan@eswincomputing.com, "Manivannan Sadhasivam" <manivannan.sadhasivam@oss.qualcomm.com>
> > Subject: [PATCH 3/3] PCI: dwc: Skip PME_Turn_Off and L2/L3 transition if no device is available
> > 
> > If there is no device available under the Root Ports, there is no point in
> > sending PME_Turn_Off and waiting for L2/L3 transition, it will result in a
> > timeout.
> > 
> > Hence, skip those steps if no device is available during suspend. The
> > resume flow remains unchanged.
> > 
> > Signed-off-by: Manivannan Sadhasivam <manivannan.sadhasivam@oss.qualcomm.com>
> > ---
> >  drivers/pci/controller/dwc/pcie-designware-host.c | 5 +++++
> >  1 file changed, 5 insertions(+)
> > 
> > diff --git a/drivers/pci/controller/dwc/pcie-designware-host.c b/drivers/pci/controller/dwc/pcie-designware-host.c
> > index 20c9333bcb1c..b6b8139e91e3 100644
> > --- a/drivers/pci/controller/dwc/pcie-designware-host.c
> > +++ b/drivers/pci/controller/dwc/pcie-designware-host.c
> > @@ -20,6 +20,7 @@
> >  #include <linux/platform_device.h>
> >  
> >  #include "../../pci.h"
> > +#include "../pci-host-common.h"
> >  #include "pcie-designware.h"
> >  
> >  static struct pci_ops dw_pcie_ops;
> > @@ -1129,6 +1130,9 @@ int dw_pcie_suspend_noirq(struct dw_pcie *pci)
> >  	u32 val;
> >  	int ret;
> >  
> > +	if (!pci_root_ports_have_device(pci->pp.bridge->bus))
> > +		goto stop_link;
> > +
> >  	/*
> >  	 * If L1SS is supported, then do not put the link into L2 as some
> >  	 * devices such as NVMe expect low resume latency.
> > @@ -1162,6 +1166,7 @@ int dw_pcie_suspend_noirq(struct dw_pcie *pci)
> >  	 */
> >  	udelay(1);
> >  
> > +stop_link:
> >  	dw_pcie_stop_link(pci);
> >  	if (pci->pp.ops->deinit)
> >  		pci->pp.ops->deinit(&pci->pp);
> > -- 
> > 2.48.1
> 
> hi, Manivannan
> 
> I'd like your advice on a few things.
> 
> If there is no device available under the Root Ports, the dw_pcie_wait_for_link
> function in dw_pcie_resume_noirq still need to wait for the link_up? Otherwise
> linkup will TIMEDOUT. At this time, when the resume function return, -ETIMEDOUT 
> returned which will raise "PM: failed to resume noirq: error -110".
> 

I thought about it, but was worried that if there was no device inserted before
suspend, but if one gets inserted during suspend (before resume), then the link
up failure will get un-noticed if the link doesn't come up for the new device
and we skip the timeout.

But thinking more, it occurs to me that it will be a very rare case. So I'll
skip returning timeout from dw_pcie_wait_for_link() if there were no devices
before suspend. However, I do think that the dw_pcie_wait_for_link() should not
be skipped even if there were no devices earlier.

- Mani

-- 
மணிவண்ணன் சதாசிவம்