Re: [PATCH v2] PCI: qcom: Use pci_host_set_default_pcie_link_state() API to enable ASPM for all platforms

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Mon, Aug 25, 2025 at 09:56:41AM GMT, Krishna Chaitanya Chundru wrote:
> 
> 
> On 8/23/2025 11:14 PM, Manivannan Sadhasivam via B4 Relay wrote:
> > From: Manivannan Sadhasivam <manivannan.sadhasivam@xxxxxxxxxxxxxxxx>
> > 
> > Commit 9f4f3dfad8cf ("PCI: qcom: Enable ASPM for platforms supporting 1.9.0
> > ops") allowed the Qcom controller driver to enable ASPM for all PCI devices
> > enumerated at the time of the controller driver probe. It proved to be
> > useful for devices already powered on by the bootloader, as it allowed
> > devices to enter ASPM without user intervention.
> > 
> > However, it could not enable ASPM for the hotplug capable devices i.e.,
> > devices enumerated *after* the controller driver probe. This limitation
> > mostly went unnoticed as the Qcom PCI controllers are not hotplug capable
> > and also the bootloader has been enabling the PCI devices before Linux
> > Kernel boots (mostly on the Qcom compute platforms which users use on a
> > daily basis).
> > 
> > But with the advent of the commit b458ff7e8176 ("PCI/pwrctl: Ensure that
> > pwrctl drivers are probed before PCI client drivers"), the pwrctrl driver
> > started to block the PCI device enumeration until it had been probed.
> > Though, the intention of the commit was to avoid race between the pwrctrl
> > driver and PCI client driver, it also meant that the pwrctrl controlled PCI
> > devices may get probed after the controller driver and will no longer have
> > ASPM enabled. So users started noticing high runtime power consumption with
> > WLAN chipsets on Qcom compute platforms like Thinkpad X13s, and Thinkpad
> > T14s, etc...
> > 
> > Obviously, it is the pwrctrl change that caused regression, but it
> > ultimately uncovered a flaw in the ASPM enablement logic of the controller
> > driver. So to address the actual issue, use the newly introduced
> > pci_host_set_default_pcie_link_state() API, which allows the controller
> > drivers to set the default ASPM state for *all* devices. This default state
> > will be honored by the ASPM driver while enabling ASPM for all the devices.
> > 
> > So with this change, we can get rid of the controller driver specific
> > 'qcom_pcie_ops::host_post_init' callback.
> > 
> > Also with this change, ASPM is now enabled by default on all Qcom
> > platforms as I haven't heard of any reported issues (apart from the
> > unsupported L0s on some platorms, which is still handled separately).
> > 
> > Cc: stable+noautosel@xxxxxxxxxx # API dependency
> > Fixes: 9f4f3dfad8cf ("PCI: qcom: Enable ASPM for platforms supporting 1.9.0 ops")
> > Reported-by: Johan Hovold <johan@xxxxxxxxxx>
> > Signed-off-by: Manivannan Sadhasivam <manivannan.sadhasivam@xxxxxxxxxxxxxxxx>
> > ---
> > Changes in v2:
> > 
> > * Used the new API introduced in this patch instead of bus notifier:
> > https://lore.kernel.org/linux-pci/20250822031159.4005529-1-david.e.box@xxxxxxxxxxxxxxx/
> > 
> > * Enabled ASPM on all platforms as there is no specific reason to limit it to a
> > few.
> > ---
> >   drivers/pci/controller/dwc/pcie-qcom.c | 34 ++--------------------------------
> >   1 file changed, 2 insertions(+), 32 deletions(-)
> > 
> > diff --git a/drivers/pci/controller/dwc/pcie-qcom.c b/drivers/pci/controller/dwc/pcie-qcom.c
> > index 294babe1816e4d0c2b2343fe22d89af72afcd6cd..71f14bc3a06ade1da1374e88b0ebef8c4e266064 100644
> > --- a/drivers/pci/controller/dwc/pcie-qcom.c
> > +++ b/drivers/pci/controller/dwc/pcie-qcom.c
> > @@ -247,7 +247,6 @@ struct qcom_pcie_ops {
> >   	int (*get_resources)(struct qcom_pcie *pcie);
> >   	int (*init)(struct qcom_pcie *pcie);
> >   	int (*post_init)(struct qcom_pcie *pcie);
> > -	void (*host_post_init)(struct qcom_pcie *pcie);
> >   	void (*deinit)(struct qcom_pcie *pcie);
> >   	void (*ltssm_enable)(struct qcom_pcie *pcie);
> >   	int (*config_sid)(struct qcom_pcie *pcie);
> > @@ -1040,25 +1039,6 @@ static int qcom_pcie_post_init_2_7_0(struct qcom_pcie *pcie)
> >   	return 0;
> >   }
> > -static int qcom_pcie_enable_aspm(struct pci_dev *pdev, void *userdata)
> > -{
> > -	/*
> > -	 * Downstream devices need to be in D0 state before enabling PCI PM
> > -	 * substates.
> > -	 */
> > -	pci_set_power_state_locked(pdev, PCI_D0);
> > -	pci_enable_link_state_locked(pdev, PCIE_LINK_STATE_ALL);
> > -
> > -	return 0;
> > -}
> > -
> > -static void qcom_pcie_host_post_init_2_7_0(struct qcom_pcie *pcie)
> > -{
> > -	struct dw_pcie_rp *pp = &pcie->pci->pp;
> > -
> > -	pci_walk_bus(pp->bridge->bus, qcom_pcie_enable_aspm, NULL);
> > -}
> > -
> >   static void qcom_pcie_deinit_2_7_0(struct qcom_pcie *pcie)
> >   {
> >   	struct qcom_pcie_resources_2_7_0 *res = &pcie->res.v2_7_0;
> > @@ -1358,19 +1338,9 @@ static void qcom_pcie_host_deinit(struct dw_pcie_rp *pp)
> >   	pcie->cfg->ops->deinit(pcie);
> >   }
> > -static void qcom_pcie_host_post_init(struct dw_pcie_rp *pp)
> > -{
> > -	struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
> > -	struct qcom_pcie *pcie = to_qcom_pcie(pci);
> > -
> > -	if (pcie->cfg->ops->host_post_init)
> > -		pcie->cfg->ops->host_post_init(pcie);
> > -}
> > -
> >   static const struct dw_pcie_host_ops qcom_pcie_dw_ops = {
> >   	.init		= qcom_pcie_host_init,
> >   	.deinit		= qcom_pcie_host_deinit,
> > -	.post_init	= qcom_pcie_host_post_init,
> >   };
> >   /* Qcom IP rev.: 2.1.0	Synopsys IP rev.: 4.01a */
> > @@ -1432,7 +1402,6 @@ static const struct qcom_pcie_ops ops_1_9_0 = {
> >   	.get_resources = qcom_pcie_get_resources_2_7_0,
> >   	.init = qcom_pcie_init_2_7_0,
> >   	.post_init = qcom_pcie_post_init_2_7_0,
> > -	.host_post_init = qcom_pcie_host_post_init_2_7_0,
> >   	.deinit = qcom_pcie_deinit_2_7_0,
> >   	.ltssm_enable = qcom_pcie_2_3_2_ltssm_enable,
> >   	.config_sid = qcom_pcie_config_sid_1_9_0,
> > @@ -1443,7 +1412,6 @@ static const struct qcom_pcie_ops ops_1_21_0 = {
> >   	.get_resources = qcom_pcie_get_resources_2_7_0,
> >   	.init = qcom_pcie_init_2_7_0,
> >   	.post_init = qcom_pcie_post_init_2_7_0,
> > -	.host_post_init = qcom_pcie_host_post_init_2_7_0,
> >   	.deinit = qcom_pcie_deinit_2_7_0,
> >   	.ltssm_enable = qcom_pcie_2_3_2_ltssm_enable,
> >   };
> > @@ -1979,6 +1947,8 @@ static int qcom_pcie_probe(struct platform_device *pdev)
> >   	if (pcie->mhi)
> >   		qcom_pcie_init_debugfs(pcie);
> > +	pci_host_set_default_pcie_link_state(pp->bridge, PCIE_LINK_STATE_ALL);
> > +
> It is better to call this before starting link training,

Not after link training, but before enumeration... But you are right to spot the
issue.

> if the endpoint
> is already powered on by the time execution comes here link enumeration
> and ASPM init might be already done. This might not have any impact.
> 

I've sent v3 after moving this call to qcom_pcie_host_init() which gets called
before attempting the enumeration.

- Mani

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




[Index of Archives]     [DMA Engine]     [Linux Coverity]     [Linux USB]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Greybus]

  Powered by Linux