Received: by 2002:a05:7412:8d10:b0:f3:1519:9f41 with SMTP id bj16csp5850127rdb; Thu, 14 Dec 2023 01:01:44 -0800 (PST) X-Google-Smtp-Source: AGHT+IGqVgvAlg1nMPIO8eMKjdSzy4zCh0KTTIejQs+KSmeZe8RbjM6fgqxmqP/IgxgdGG57z6gU X-Received: by 2002:a05:6a20:72a6:b0:18c:3511:665f with SMTP id o38-20020a056a2072a600b0018c3511665fmr5918728pzk.51.1702544503715; Thu, 14 Dec 2023 01:01:43 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1702544503; cv=none; d=google.com; s=arc-20160816; b=gdj3P1k2bUT05rJXtld7jB2G5lpa/rD634ak+S9MqNy0M4QNs6nPqFIN6cHMFZXo0n jw5A6E9kmgkXYq/eJXrfENWFt8XS6/vHEbSwnDBKbpf5O0/905d+HFWPsbktyno5y+jt YkeoHtMAUnBo5l+QVP/nC4s2EduORcdx25dwuHVnFVltLJexKHNRB+mKBXzyz+CYXtLg kOfEe4q4yucje+5FaMFVX1PImmO5zEvPDGg9FaOQ20/hoVT4qOFb/00eUnEz3vYB8tMi l4XqFPtkRPvl7LVGTLUNs/tZBvVDns+Oh254cZbR38uMcIUxTZ38NL+zIhNh04Yam/aG MISw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:cc:to:subject :message-id:date:from:in-reply-to:references:mime-version; bh=xezxLe2KWVfqQZ54Bpgm8Obg8Jp7EyqXEVqJt5A5bTc=; fh=NqRp6AW0Co1XdRChYHW/dzMpnWsvF/f1Mhd7K50b8z4=; b=VwdYw7dHoS28T73fG7c/SCFCvC6sHDELgE1ClU1xReAJ+yk2Q2JdMRudSM0H6qOuP+ g2erBXSx2fFfHQkasn1smpT9+QyO9jva8uTE5PXgDMdyptFC6zQGkZ2MIm9UaFlF5lWI wFqoDLU9cr+MX97zX8tiFP/FFtj0iDgPH9jpns3z1vckmZD7WfpHHD2TFxNqu4DbFEka PK4xALG9mSueyTWcSPLQ7EwdyyBn5sfBOFNguC/vQhB1fGa1pnpD2/TMbxKaBUbbv9kE JX90c1IxytiMMMMEYriChntb/EM7/CgGejdn6B8lH0XHLzT7ngV7SXJORIewmjaz4gOt hQEA== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::3:8 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Return-Path: Received: from fry.vger.email (fry.vger.email. [2620:137:e000::3:8]) by mx.google.com with ESMTPS id a18-20020a170902ecd200b001d098c03fe9si11341897plh.361.2023.12.14.01.01.41 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 14 Dec 2023 01:01:43 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::3:8 as permitted sender) client-ip=2620:137:e000::3:8; Authentication-Results: mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::3:8 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Received: from out1.vger.email (depot.vger.email [IPv6:2620:137:e000::3:0]) by fry.vger.email (Postfix) with ESMTP id 2FEBE804AE03; Thu, 14 Dec 2023 01:01:00 -0800 (PST) X-Virus-Status: Clean X-Virus-Scanned: clamav-milter 0.103.11 at fry.vger.email Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1443426AbjLNJAn convert rfc822-to-8bit (ORCPT + 99 others); Thu, 14 Dec 2023 04:00:43 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:59206 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229441AbjLNJAj (ORCPT ); Thu, 14 Dec 2023 04:00:39 -0500 Received: from mail-ot1-f48.google.com (mail-ot1-f48.google.com [209.85.210.48]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 63C2110A; Thu, 14 Dec 2023 01:00:44 -0800 (PST) Received: by mail-ot1-f48.google.com with SMTP id 46e09a7af769-6d9db92bd71so1256231a34.1; Thu, 14 Dec 2023 01:00:44 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1702544443; x=1703149243; h=content-transfer-encoding:cc:to:subject:message-id:date:from :in-reply-to:references:mime-version:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=8O4nwF4I2AcPkJT1QIWI/cJrF4RlMzbwWSkhPeiGBko=; b=LGWqyRVyHZb9pVLfkZrBr7AsOC12sZshnYVJzOYSlrAkOIdIn5Ukc301HueLdQ4X5q Ks7NzmoQk1K/ko6PW6LDQdusghU3CfYWnShHUgsacEdvMDZiNj7JYY0MYgS8UXqsROeh 5f/xcKrHR8/3EyOxNw5aSxT3oeej+7pMzRbSbSNpbCPdoUlSKhjFq/1KUNYTqde8NDI9 6Gw1sbwzQoO3KEqVdZjHDT+Zox0DwTrRBAAG+Ah/gp9VLUIyv6YFhaoDzCuQXvEo176J aYr2vyBGCfbvx0WRQC1Fmtq97/vrgN/4jtDBmumfeOeGvwwthpIJ1r54s7YUvI1VhMwu beHQ== X-Gm-Message-State: AOJu0YxSqdQGQatT9H/2ooBWPBF7aTc4OLbg+i4zo6qpWx9ageFZkIwW aeMufkyJLrLbUxE0MPAdwA4Ns3VlRW9zDw00Ez8= X-Received: by 2002:a05:6870:b028:b0:1fb:e5f:c530 with SMTP id y40-20020a056870b02800b001fb0e5fc530mr17409236oae.4.1702544443386; Thu, 14 Dec 2023 01:00:43 -0800 (PST) MIME-Version: 1.0 References: <20231213182656.6165-1-mario.limonciello@amd.com> <20231213182656.6165-3-mario.limonciello@amd.com> <766d621c-695d-4ae7-87cf-690cb8d066df@amd.com> In-Reply-To: From: "Rafael J. Wysocki" Date: Thu, 14 Dec 2023 10:00:30 +0100 Message-ID: Subject: Re: [PATCH 2/2] PCI/portdrv: Place PCIe port hierarchy into D3cold at shutdown To: Kai-Heng Feng Cc: "Rafael J. Wysocki" , Mario Limonciello , Bjorn Helgaas , "Rafael J . Wysocki" , linux-pci@vger.kernel.org, linux-acpi@vger.kernel.org, linux-kernel@vger.kernel.org, mpearson-lenovo@squebb.ca Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: 8BIT X-Spam-Status: No, score=-1.0 required=5.0 tests=MAILING_LIST_MULTI, SPF_HELO_NONE,SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=unavailable autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on fry.vger.email Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-Greylist: Sender passed SPF test, not delayed by milter-greylist-4.6.4 (fry.vger.email [0.0.0.0]); Thu, 14 Dec 2023 01:01:01 -0800 (PST) On Thu, Dec 14, 2023 at 4:46 AM Kai-Heng Feng wrote: > > Hi Mario and Rafael, > > On Thu, Dec 14, 2023 at 2:46 AM Rafael J. Wysocki wrote: > > > > On Wed, Dec 13, 2023 at 7:42 PM Mario Limonciello > > wrote: > > > > > > On 12/13/2023 12:38, Rafael J. Wysocki wrote: > > > > On Wed, Dec 13, 2023 at 7:27 PM Mario Limonciello > > > > wrote: > > > >> > > > >> When a system is being powered off it's important that PCIe ports > > > >> have been put into D3cold as there is no other software to turn > > > >> off the devices at S5. > > > >> > > > >> If PCIe ports are left in D0 then any GPIOs toggled by the ACPI > > > >> power resources may be left enabled and devices may consume excess > > > >> power. > > > > > > > > Isn't that a platform firmware issue? > > > > > > > > It is the responsibility of the platform firmware to properly put the > > > > platform into S5, including power removal from devices that are not > > > > armed for power-on. > > > > > > The specific issues that triggered this series were tied to the PCIe > > > ports for dGPUs. There is a GPIO that is toggled by _ON or _OFF. > > > > > > Windows calls _OFF as part of S5.. > > > > I see. > > > > > > > > > >> Cc: mpearson-lenovo@squebb.ca > > > >> Signed-off-by: Mario Limonciello > > > >> --- > > > >> drivers/pci/pcie/portdrv.c | 11 ++++++++--- > > > >> 1 file changed, 8 insertions(+), 3 deletions(-) > > > >> > > > >> diff --git a/drivers/pci/pcie/portdrv.c b/drivers/pci/pcie/portdrv.c > > > >> index 14a4b89a3b83..08238680c481 100644 > > > >> --- a/drivers/pci/pcie/portdrv.c > > > >> +++ b/drivers/pci/pcie/portdrv.c > > > >> @@ -734,9 +734,14 @@ static void pcie_portdrv_remove(struct pci_dev *dev) > > > >> static void pcie_portdrv_shutdown(struct pci_dev *dev) > > > >> { > > > >> if (pci_bridge_d3_possible(dev)) { > > > >> - pm_runtime_forbid(&dev->dev); > > > >> - pm_runtime_get_noresume(&dev->dev); > > > >> - pm_runtime_dont_use_autosuspend(&dev->dev); > > > >> + /* whole hierarchy goes into a low power state for S5 */ > > > >> + if (system_state == SYSTEM_POWER_OFF) { > > > >> + pci_set_power_state(dev, PCI_D3cold); > > > >> + } else { > > > >> + pm_runtime_forbid(&dev->dev); > > > >> + pm_runtime_get_noresume(&dev->dev); > > > >> + pm_runtime_dont_use_autosuspend(&dev->dev); > > > >> + } > > > >> } > > > > > > > > Wouldn't it be better to remove power from the port after running the > > > > code below? > > > > > > > > > > Yes; I think you're right. I'll do some more testing with this. > > > > > > >> pcie_port_device_remove(dev); > > > >> -- > > > > IIRC, to do this all properly, you'd need to rework the shutdown path > > to look like the hibernation power-off one. Or even use the latter > > for shutdown? > > > > There was no reason to do that till now, so it has not been done, but > > it looks like you have one. > > > > I am working on exactly same thing but with a different approach. > Because this is needed for more than just PCI devices. > I haven't written a proper commit message yet, but the implementation > is quite simple: As I said, doing this properly requires something like the hibernation power-off transition to be carried out for S5. I think that the existing hibernation power-off code can be used as-is for this purpose even. > diff --git a/drivers/acpi/device_pm.c b/drivers/acpi/device_pm.c > index f007116a8427..b90c6cf6faf4 100644 > --- a/drivers/acpi/device_pm.c > +++ b/drivers/acpi/device_pm.c > @@ -967,15 +967,17 @@ EXPORT_SYMBOL_GPL(acpi_pm_set_device_wakeup); > * @adev: ACPI device node corresponding to @dev. > * @system_state: System state to choose the device state for. > */ > -static int acpi_dev_pm_low_power(struct device *dev, struct acpi_device *adev, > - u32 system_state) > +static int acpi_dev_pm_low_power(struct acpi_device *adev, void* data) > { > int ret, state; > + u32 *system_state = data; > > if (!acpi_device_power_manageable(adev)) > return 0; > > - ret = acpi_dev_pm_get_state(dev, adev, system_state, NULL, &state); > + acpi_dev_for_each_child(adev, acpi_dev_pm_low_power, data); > + > + ret = acpi_dev_pm_get_state(&adev->dev, adev, *system_state, NULL, &state); > return ret ? ret : acpi_device_set_power(adev, state); > } > > @@ -1016,7 +1018,7 @@ int acpi_dev_suspend(struct device *dev, bool wakeup) > wakeup = false; > } > > - error = acpi_dev_pm_low_power(dev, adev, target_state); > + error = acpi_dev_pm_low_power(adev, &target_state); > if (error && wakeup) > acpi_device_wakeup_disable(adev); > > @@ -1386,6 +1388,7 @@ static struct dev_pm_domain acpi_general_pm_domain = { > static void acpi_dev_pm_detach(struct device *dev, bool power_off) > { > struct acpi_device *adev = ACPI_COMPANION(dev); > + u32 state = ACPI_STATE_S0; > > if (adev && dev->pm_domain == &acpi_general_pm_domain) { > dev_pm_domain_set(dev, NULL); > @@ -1400,7 +1403,7 @@ static void acpi_dev_pm_detach(struct device > *dev, bool power_off) > dev_pm_qos_hide_latency_limit(dev); > dev_pm_qos_hide_flags(dev); > acpi_device_wakeup_disable(adev); > - acpi_dev_pm_low_power(dev, adev, ACPI_STATE_S0); > + acpi_dev_pm_low_power(adev, &state); > } > } > } > @@ -1514,4 +1517,16 @@ bool acpi_dev_state_d0(struct device *dev) > } > EXPORT_SYMBOL_GPL(acpi_dev_state_d0); > > +void acpi_dev_shutdown(struct device *dev) > +{ > + struct acpi_device *adev = ACPI_COMPANION(dev); > + u32 state = ACPI_STATE_S5; > + > + if (!adev) > + return; > + > + acpi_device_wakeup_disable(adev); > + acpi_dev_pm_low_power(adev, &state); > +} > +EXPORT_SYMBOL_GPL(acpi_dev_shutdown); > #endif /* CONFIG_PM */ > diff --git a/drivers/base/core.c b/drivers/base/core.c > index 6ceaf50f5a67..7e7c99eade63 100644 > --- a/drivers/base/core.c > +++ b/drivers/base/core.c > @@ -45,6 +45,15 @@ static void __fw_devlink_link_to_consumers(struct > device *dev); > static bool fw_devlink_drv_reg_done; > static bool fw_devlink_best_effort; > > +#ifdef CONFIG_ACPI > +static inline void fw_dev_shutdown(struct device *dev) > +{ > + acpi_dev_shutdown(dev); > +} > +#else > +static inline void fw_dev_shutdown(struct device *dev) { } > +#endif > + > /** > * __fwnode_link_add - Create a link between two fwnode_handles. > * @con: Consumer end of the link. > @@ -4780,6 +4789,8 @@ void device_shutdown(void) > dev->driver->shutdown(dev); > } > > + fw_dev_shutdown(dev); > + > device_unlock(dev); > if (parent) > device_unlock(parent); > diff --git a/include/linux/acpi.h b/include/linux/acpi.h > index 641dc4843987..374f9eb75c22 100644 > --- a/include/linux/acpi.h > +++ b/include/linux/acpi.h > @@ -1130,6 +1130,7 @@ int acpi_subsys_runtime_resume(struct device *dev); > int acpi_dev_pm_attach(struct device *dev, bool power_on); > bool acpi_storage_d3(struct device *dev); > bool acpi_dev_state_d0(struct device *dev); > +void acpi_dev_shutdown(struct device *dev); > #else > static inline int acpi_subsys_runtime_suspend(struct device *dev) { return 0; } > static inline int acpi_subsys_runtime_resume(struct device *dev) { return 0; } > @@ -1145,6 +1146,7 @@ static inline bool acpi_dev_state_d0(struct device *dev) > { > return true; > } > +static inline void acpi_dev_shutdown(struct device *dev) { } > #endif > > #if defined(CONFIG_ACPI) && defined(CONFIG_PM_SLEEP) >