From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 0C3B9CD4F54 for ; Tue, 19 May 2026 22:39:10 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender:List-Subscribe:List-Help :List-Post:List-Archive:List-Unsubscribe:List-Id:In-Reply-To:Content-Type: MIME-Version:Message-ID:Subject:Cc:To:From:Date:Reply-To: Content-Transfer-Encoding:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:References: List-Owner; bh=uhGMUkYK7lJN21Y0KILAaLJAxufhyTf8mTQiKOdsg6M=; b=Cq7dmJ/3kv4iPi rCs7eVyPdikpJgUqox/7RegE4ch8mJK7XjY2XfB0kPkAIcRPHSmulHQHEuEvHE/HyDYwpdaZhxcMv Rp61xgeR6gDMHUC6+pBNfocgjLKHu1gab8qq+YN2LUtRUYRf+x6fTpxjItZuu8VSOV4Q5HcO9dPRb xQhyaKhVBeSxavHfFT0DcvJql5oaGZ8LyQ9Hq+aZDXq+0GgJIQOyx75Oz2hMWXDXbpefxlN54Np+N vmvKOXE+97NTkvGpJlXzHcRvJH6J7IRYQyqn/+zkAjhO/MjiCDB85MO0xoTbjBrDJqbe3IX07A2nW zaCh9qLluTf+9ihMSE3g==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.99.1 #2 (Red Hat Linux)) id 1wPT5d-00000002z9V-1A3E; Tue, 19 May 2026 22:39:05 +0000 Received: from tor.source.kernel.org ([172.105.4.254]) by bombadil.infradead.org with esmtps (Exim 4.99.1 #2 (Red Hat Linux)) id 1wPT5b-00000002z9L-3LSy for linux-arm-kernel@lists.infradead.org; Tue, 19 May 2026 22:39:03 +0000 Received: from smtp.kernel.org (quasi.space.kernel.org [100.103.45.18]) by tor.source.kernel.org (Postfix) with UTF8SMTP id E85DF60216; Tue, 19 May 2026 22:39:02 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with UTF8SMTPSA id 5BCC01F000E9; Tue, 19 May 2026 22:39:02 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1779230342; bh=uhGMUkYK7lJN21Y0KILAaLJAxufhyTf8mTQiKOdsg6M=; h=Date:From:To:Cc:Subject:In-Reply-To; b=acjyTicaIjtkUEZL6fJWCBm/HWBLjz/+5c58S36X8fn7b9V2iaJDRcH/VWXAa4o2p 8ZTg5jzqMHREg4YJRclKWkeX4leIONH8badx1nbph3Y+XhUnr8dR+DRl3QQhfFCjvH Bv8mVmjDhfnDV/+TBS6dgBSclWGF9ft8dhu1/hnoQNmUxNhiaZOirESnQ6vl+Tf5zv 3gpemJ9qYTHhC66Cb92r/tqqqyV4YMFElRT7YWxmsebbOzsb5HeNbOddjId5hsv71/ 5AnjBPliF3pt/lpE/NifwxsIZoBGfMSVlJdVY1aa1Xns6CSy88KLPsZPQa/o/0XLxc bmwIHWhYeC48Q== Date: Tue, 19 May 2026 17:39:01 -0500 From: Bjorn Helgaas To: Krishna Chaitanya Chundru Cc: Jingoo Han , Manivannan Sadhasivam , Lorenzo Pieralisi , Krzysztof =?utf-8?Q?Wilczy=C5=84ski?= , Rob Herring , Bjorn Helgaas , Will Deacon , linux-pci@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-msm@vger.kernel.org, linux-arm-kernel@lists.infradead.org, jonathanh@nvidia.com, bjorn.andersson@oss.qualcomm.com Subject: Re: [PATCH v5 1/5] PCI: host-common: Add helper to determine host bridge D3cold eligibility Message-ID: <20260519223901.GA20376@bhelgaas> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20260429-d3cold-v5-1-89e9735b9df6@oss.qualcomm.com> X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org On Wed, Apr 29, 2026 at 12:12:23PM +0530, Krishna Chaitanya Chundru wrote: > Add a common helper, pci_host_common_d3cold_possible(), to determine > whether PCIe devices under 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 all bridge buses and only allows > the devices 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 devices under 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 devices under host > bridge from entering D3cold. This allows controllers to power down more > aggressively when there are no actively managed endpoints. > > Some devices (e.g. M.2 without auxiliary power) lose PME detection when > main power is removed. Even if such devices advertise PME-from-D3cold > capability, entering D3cold may break wakeup. So, return PME-from-D3cold > capability via an output parameter so PCIe controller drivers can apply > platform-specific handling to preserve wakeup functionality. > > Signed-off-by: Krishna Chaitanya Chundru > --- > drivers/pci/controller/pci-host-common.c | 71 ++++++++++++++++++++++++++++++++ > drivers/pci/controller/pci-host-common.h | 2 + > 2 files changed, 73 insertions(+) > > diff --git a/drivers/pci/controller/pci-host-common.c b/drivers/pci/controller/pci-host-common.c > index d6258c1cffe5..09432d69175c 100644 > --- a/drivers/pci/controller/pci-host-common.c > +++ b/drivers/pci/controller/pci-host-common.c > @@ -17,6 +17,9 @@ > > #include "pci-host-common.h" > > +#define PCI_HOST_D3COLD_ALLOWED BIT(0) > +#define PCI_HOST_PME_D3COLD_CAPABLE BIT(1) > + > static void gen_pci_unmap_cfg(void *ptr) > { > pci_ecam_free((struct pci_config_window *)ptr); > @@ -106,5 +109,73 @@ void pci_host_common_remove(struct platform_device *pdev) > } > EXPORT_SYMBOL_GPL(pci_host_common_remove); > > +static int __pci_host_common_d3cold_possible(struct pci_dev *pdev, void *userdata) > +{ > + u32 *flags = userdata; > + int type; > + > + /* Ignore conventional PCI devices */ > + if (!pci_is_pcie(pdev)) > + return 0; > + > + type = pci_pcie_type(pdev); > + if (type != PCI_EXP_TYPE_ENDPOINT && > + type != PCI_EXP_TYPE_LEG_END && > + type != PCI_EXP_TYPE_RC_END) > + return 0; >From https://sashiko.dev/#/patchset/20260429-d3cold-v5-0-89e9735b9df6%40oss.qualcomm.com: If the topology contains an active conventional PCI device or an intermediate PCIe switch in PCI_D0, returning 0 here allows pci_walk_bus() to continue without clearing the PCI_HOST_D3COLD_ALLOWED flag. Does this create a situation where the host bridge might aggressively power off the link, dropping power to these active components? I guess this is intentional, since you have comment about ignoring conventional PCI devices. But this does seem like a potential problem. Why should we ignore switches here? And I think it's still fairly common to have a PCIe-to-PCI bridge leading to a conventional PCI device, and I don't know why we should ignore them. The commit log consistently refers to "PCIe" devices and endpoints, so maybe there's some reason that I'm missing. There are other sashiko comments on this series that I think should also be looked at. > + > + if (!pdev->dev.driver && !pci_is_enabled(pdev)) > + return 0; > + > + if (pdev->current_state != PCI_D3hot) > + goto exit; > + > + if (device_may_wakeup(&pdev->dev)) { > + if (!pci_pme_capable(pdev, PCI_D3cold)) > + goto exit; > + else > + *flags |= PCI_HOST_PME_D3COLD_CAPABLE; > + } > + > + return 0; > + > +exit: > + *flags &= ~PCI_HOST_D3COLD_ALLOWED; > + > + return -EOPNOTSUPP; > +} > + > +/** > + * pci_host_common_d3cold_possible - Determine whether the host bridge can transition the > + * devices into D3Cold. > + * > + * @bridge: PCI host bridge to check > + * @pme_capable: Pointer to update if there is any device which is capable of generating > + * PME from D3cold. > + * > + * Walk downstream PCIe endpoint devices and determine whether the host bridge > + * is permitted to transition the devices into D3cold. > + * > + * Devices under host bridge can enter D3cold only if all active PCIe endpoints are in > + * PCI_D3hot and any wakeup-enabled endpoint is capable of generating PME from D3cold. > + * Inactive endpoints are ignored. > + * > + * The @pme_capable output allows PCIe controller drivers to apply > + * platform-specific handling to preserve wakeup functionality. > + * > + * Return: %true if the host bridge may enter D3cold, otherwise %false. > + */ > +bool pci_host_common_d3cold_possible(struct pci_host_bridge *bridge, bool *pme_capable) > +{ > + u32 flags = PCI_HOST_D3COLD_ALLOWED; > + > + pci_walk_bus(bridge->bus, __pci_host_common_d3cold_possible, &flags); > + > + *pme_capable = !!(flags & PCI_HOST_PME_D3COLD_CAPABLE); > + > + return !!(flags & PCI_HOST_D3COLD_ALLOWED); > +} > +EXPORT_SYMBOL_GPL(pci_host_common_d3cold_possible); > + > MODULE_DESCRIPTION("Common library for PCI host controller drivers"); > MODULE_LICENSE("GPL v2"); > diff --git a/drivers/pci/controller/pci-host-common.h b/drivers/pci/controller/pci-host-common.h > index b5075d4bd7eb..7eb5599b9ce4 100644 > --- a/drivers/pci/controller/pci-host-common.h > +++ b/drivers/pci/controller/pci-host-common.h > @@ -20,4 +20,6 @@ void pci_host_common_remove(struct platform_device *pdev); > > struct pci_config_window *pci_host_common_ecam_create(struct device *dev, > struct pci_host_bridge *bridge, const struct pci_ecam_ops *ops); > + > +bool pci_host_common_d3cold_possible(struct pci_host_bridge *bridge, bool *pme_capable); > #endif > > -- > 2.34.1 >