Re: [PATCH v2 1/5] PCI: host-common: Add helper to determine host bridge D3cold eligibility

From: Manivannan Sadhasivam

Date: Thu Mar 05 2026 - 02:43:14 EST


On Tue, Feb 17, 2026 at 04:49:06PM +0530, Krishna Chaitanya Chundru wrote:
> Add a common helper, pci_host_common_can_enter_d3cold(), to determine
> whether a PCI host bridge can safely transition to D3cold.
>
> This helper is intended to be used by PCI host controller drivers to
> decide whether they may safely put the host bridge into D3cold based on
> the power state and wakeup capabilities of downstream endpoints.
>
> The helper walks all devices on the bridge's primary bus and only allows
> the host bridge to enter D3cold if all PCIe endpoints are already in
> PCI_D3hot. This ensures that we do not power off the host bridge while
> any active endpoint still requires the link to remain powered.
>
> For devices that may wake the system, the helper additionally requires
> that the device supports PME wake from D3cold (via WAKE#). Devices that
> do not have wakeup enabled are not restricted by this check and do not
> block the host bridge from entering D3cold.
>
> Devices without a bound driver and with PCI not enabled via sysfs are
> treated as inactive and therefore do not prevent the host bridge from
> entering D3cold. This allows controllers to power down more aggressively
> when there are no actively managed endpoints.
>
> Signed-off-by: Krishna Chaitanya Chundru <krishna.chundru@xxxxxxxxxxxxxxxx>
> ---
> drivers/pci/controller/pci-host-common.c | 45 ++++++++++++++++++++++++++++++++
> drivers/pci/controller/pci-host-common.h | 2 ++
> 2 files changed, 47 insertions(+)
>
> diff --git a/drivers/pci/controller/pci-host-common.c b/drivers/pci/controller/pci-host-common.c
> index d6258c1cffe5ec480fd2a7e50b3af39ef6ac4c8c..b0a4a3c995e80e0245657f0273a349334071013c 100644
> --- a/drivers/pci/controller/pci-host-common.c
> +++ b/drivers/pci/controller/pci-host-common.c
> @@ -106,5 +106,50 @@ void pci_host_common_remove(struct platform_device *pdev)
> }
> EXPORT_SYMBOL_GPL(pci_host_common_remove);
>
> +static int pci_host_common_check_d3cold(struct pci_dev *pdev, void *userdata)
> +{
> + bool *d3cold_allow = userdata;

d3cold_possible

> +
> + if (pci_pcie_type(pdev) != PCI_EXP_TYPE_ENDPOINT)
> + return 0;
> +
> + if (!pdev->dev.driver && !pci_is_enabled(pdev))
> + return 0;
> +
> + if (pdev->current_state != PCI_D3hot)
> + goto exit;
> +
> + if (device_may_wakeup(&pdev->dev) && !pci_pme_capable(pdev, PCI_D3cold))
> + goto exit;
> +
> + return 0;

Newline

> +exit:
> + *d3cold_allow = false;

Newline

> + return -EBUSY;

I think -EOPNOTSUPP should be returned here.

> +}
> +
> +/**
> + * pci_host_common_can_enter_d3cold - Determine whether a host bridge may enter D3cold

Since PCI core already has pci_bridge_d3_possible() API, we should try to be in
sync by calling this API as pci_host_common_d3cold_possible().

> + * @bridge: PCI host bridge to check
> + *
> + * Walk downstream PCIe endpoint devices and determine whether the host bridge
> + * is permitted to transition to D3cold.
> + *
> + * The host bridge may enter D3cold only if all active PCIe endpoints are in

s/may/can

> + * %PCI_D3hot and any wakeup-enabled endpoint is capable of generating PME from

Remove %

> + * D3cold. Inactive endpoints are ignored.
> + *
> + * Return: %true if the host bridge may enter D3cold, otherwise %false.
> + */
> +bool pci_host_common_can_enter_d3cold(struct pci_host_bridge *bridge)
> +{
> + bool d3cold_allow = true;
> +
> + pci_walk_bus(bridge->bus, pci_host_common_check_d3cold, &d3cold_allow);

s/pci_host_common_check_d3cold/__pci_host_common_d3cold_possible

- Mani

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