From patchwork Sat Apr 9 13:05:28 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Rafael J. Wysocki" X-Patchwork-Id: 559370 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 vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id D6D0DC433F5 for ; Sat, 9 Apr 2022 13:29:10 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S242124AbiDINbN (ORCPT ); Sat, 9 Apr 2022 09:31:13 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:57068 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S242150AbiDINbM (ORCPT ); Sat, 9 Apr 2022 09:31:12 -0400 Received: from cloudserver094114.home.pl (cloudserver094114.home.pl [79.96.170.134]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 0E89CBB914; Sat, 9 Apr 2022 06:29:03 -0700 (PDT) Received: from localhost (127.0.0.1) (HELO v370.home.net.pl) by /usr/run/smtp (/usr/run/postfix/private/idea_relay_lmtp) via UNIX with SMTP (IdeaSmtpServer 5.0.0) id 07983d4bf8017218; Sat, 9 Apr 2022 15:29:02 +0200 Received: from kreacher.localnet (89-77-51-84.dynamic.chello.pl [89.77.51.84]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by v370.home.net.pl (Postfix) with ESMTPSA id B023D66BCE9; Sat, 9 Apr 2022 15:29:01 +0200 (CEST) From: "Rafael J. Wysocki" To: Linux PCI Cc: Linux PM , LKML , Bjorn Helgaas , Mika Westerberg Subject: [PATCH v1 1/7] PCI/PM: Resume subordinate bus in bus type callbacks Date: Sat, 09 Apr 2022 15:05:28 +0200 Message-ID: <1842667.tdWV9SEqCh@kreacher> In-Reply-To: <4419002.LvFx2qVVIh@kreacher> References: <4419002.LvFx2qVVIh@kreacher> MIME-Version: 1.0 X-CLIENT-IP: 89.77.51.84 X-CLIENT-HOSTNAME: 89-77-51-84.dynamic.chello.pl X-VADE-SPAMSTATE: clean X-VADE-SPAMCAUSE: gggruggvucftvghtrhhoucdtuddrgedvvddrudekvddgfeelucetufdoteggodetrfdotffvucfrrhhofhhilhgvmecujffqoffgrffnpdggtffipffknecuuegrihhlohhuthemucduhedtnecusecvtfgvtghiphhivghnthhsucdlqddutddtmdenucfjughrpefhvffufffkjghfggfgtgesthfuredttddtjeenucfhrhhomhepfdftrghfrggvlhculfdrucghhihsohgtkhhifdcuoehrjhifsehrjhifhihsohgtkhhirdhnvghtqeenucggtffrrghtthgvrhhnpedvjeelgffhiedukedtleekkedvudfggefhgfegjefgueekjeelvefggfdvledutdenucfkphepkeelrdejjedrhedurdekgeenucevlhhushhtvghrufhiiigvpedtnecurfgrrhgrmhepihhnvghtpeekledrjeejrdehuddrkeegpdhhvghlohepkhhrvggrtghhvghrrdhlohgtrghlnhgvthdpmhgrihhlfhhrohhmpedftfgrfhgrvghlucflrdcuhgihshhotghkihdfuceorhhjfiesrhhjfiihshhotghkihdrnhgvtheqpdhnsggprhgtphhtthhopeehpdhrtghpthhtoheplhhinhhugidqphgtihesvhhgvghrrdhkvghrnhgvlhdrohhrghdprhgtphhtthhopehlihhnuhigqdhpmhesvhhgvghrrdhkvghrnhgvlhdrohhrghdprhgtphhtthhopehlihhnuhigqdhkvghrnhgvlhesvhhgvghrrdhkvghrnhgvlhdrohhrghdprhgtphhtthhopehhvghlghgrrghssehkvghrnhgvlhdrohhrghdprhgtphhtthhopehmihhkrgdrfigvshht vghrsggvrhhgsehlihhnuhigrdhinhhtvghlrdgtohhm X-DCC--Metrics: v370.home.net.pl 1024; Body=5 Fuz1=5 Fuz2=5 Precedence: bulk List-ID: X-Mailing-List: linux-pm@vger.kernel.org From: Rafael J. Wysocki Calling pci_resume_bus() on the secondary bus from pci_power_up() as it is done now is questionable, because it depends on the mandatory bridge power-up delays that are only covered by the PCI bus type PM callbacks. For this reason, move the subordinate bus resume to those callbacks too and use the observation that if a bridge is being powered-up during resume from system-wide suspend, it may be still desirable to runtime-resume its subordinate bus after completing the system- wide transition (in case the resume of the devices on that bus is skipped during it). Signed-off-by: Rafael J. Wysocki --- drivers/pci/pci-driver.c | 15 +++++++++++++-- drivers/pci/pci.c | 15 --------------- 2 files changed, 13 insertions(+), 17 deletions(-) Index: linux-pm/drivers/pci/pci-driver.c =================================================================== --- linux-pm.orig/drivers/pci/pci-driver.c +++ linux-pm/drivers/pci/pci-driver.c @@ -559,6 +559,17 @@ static void pci_pm_default_resume_early( pci_pme_restore(pci_dev); } +static void pci_pm_bridge_power_up_actions(struct pci_dev *pci_dev) +{ + pci_bridge_wait_for_secondary_bus(pci_dev); + /* + * When powering on a bridge from D3cold, the whole hierarchy may be + * powered on into D0uninitialized state, resume them to give them a + * chance to suspend again + */ + pci_resume_bus(pci_dev->subordinate); +} + #endif #ifdef CONFIG_PM_SLEEP @@ -934,7 +945,7 @@ static int pci_pm_resume_noirq(struct de pcie_pme_root_status_cleanup(pci_dev); if (!skip_bus_pm && prev_state == PCI_D3cold) - pci_bridge_wait_for_secondary_bus(pci_dev); + pci_pm_bridge_power_up_actions(pci_dev); if (pci_has_legacy_pm_support(pci_dev)) return 0; @@ -1321,7 +1332,7 @@ static int pci_pm_runtime_resume(struct pci_pm_default_resume(pci_dev); if (prev_state == PCI_D3cold) - pci_bridge_wait_for_secondary_bus(pci_dev); + pci_pm_bridge_power_up_actions(pci_dev); if (pm && pm->runtime_resume) error = pm->runtime_resume(dev); Index: linux-pm/drivers/pci/pci.c =================================================================== --- linux-pm.orig/drivers/pci/pci.c +++ linux-pm/drivers/pci/pci.c @@ -1310,21 +1310,6 @@ static int pci_dev_wait(struct pci_dev * int pci_power_up(struct pci_dev *dev) { pci_platform_power_transition(dev, PCI_D0); - - /* - * Mandatory power management transition delays are handled in - * pci_pm_resume_noirq() and pci_pm_runtime_resume() of the - * corresponding bridge. - */ - if (dev->runtime_d3cold) { - /* - * When powering on a bridge from D3cold, the whole hierarchy - * may be powered on into D0uninitialized state, resume them to - * give them a chance to suspend again - */ - pci_resume_bus(dev->subordinate); - } - return pci_raw_set_power_state(dev, PCI_D0); } From patchwork Sat Apr 9 13:06:51 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Rafael J. Wysocki" X-Patchwork-Id: 559901 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 vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 22449C433F5 for ; Sat, 9 Apr 2022 13:29:13 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S242119AbiDINbR (ORCPT ); Sat, 9 Apr 2022 09:31:17 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:57036 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S242145AbiDINbM (ORCPT ); Sat, 9 Apr 2022 09:31:12 -0400 Received: from cloudserver094114.home.pl (cloudserver094114.home.pl [79.96.170.134]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 8FD47B822B; Sat, 9 Apr 2022 06:29:02 -0700 (PDT) Received: from localhost (127.0.0.1) (HELO v370.home.net.pl) by /usr/run/smtp (/usr/run/postfix/private/idea_relay_lmtp) via UNIX with SMTP (IdeaSmtpServer 5.0.0) id ee10ece28c743e80; Sat, 9 Apr 2022 15:29:01 +0200 Received: from kreacher.localnet (89-77-51-84.dynamic.chello.pl [89.77.51.84]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by v370.home.net.pl (Postfix) with ESMTPSA id 37BBA66BCD0; Sat, 9 Apr 2022 15:29:00 +0200 (CEST) From: "Rafael J. Wysocki" To: Linux PCI Cc: Linux PM , LKML , Bjorn Helgaas , Mika Westerberg Subject: [PATCH v1 2/7] PCI/PM: Drop the runtime_d3cold PCI device flag Date: Sat, 09 Apr 2022 15:06:51 +0200 Message-ID: <13020273.uLZWGnKmhe@kreacher> In-Reply-To: <4419002.LvFx2qVVIh@kreacher> References: <4419002.LvFx2qVVIh@kreacher> MIME-Version: 1.0 X-CLIENT-IP: 89.77.51.84 X-CLIENT-HOSTNAME: 89-77-51-84.dynamic.chello.pl X-VADE-SPAMSTATE: clean X-VADE-SPAMCAUSE: gggruggvucftvghtrhhoucdtuddrgedvvddrudekvddgfeelucetufdoteggodetrfdotffvucfrrhhofhhilhgvmecujffqoffgrffnpdggtffipffknecuuegrihhlohhuthemucduhedtnecusecvtfgvtghiphhivghnthhsucdlqddutddtmdenucfjughrpefhvffufffkjghfggfgtgesthfuredttddtjeenucfhrhhomhepfdftrghfrggvlhculfdrucghhihsohgtkhhifdcuoehrjhifsehrjhifhihsohgtkhhirdhnvghtqeenucggtffrrghtthgvrhhnpedvjeelgffhiedukedtleekkedvudfggefhgfegjefgueekjeelvefggfdvledutdenucfkphepkeelrdejjedrhedurdekgeenucevlhhushhtvghrufhiiigvpedtnecurfgrrhgrmhepihhnvghtpeekledrjeejrdehuddrkeegpdhhvghlohepkhhrvggrtghhvghrrdhlohgtrghlnhgvthdpmhgrihhlfhhrohhmpedftfgrfhgrvghlucflrdcuhgihshhotghkihdfuceorhhjfiesrhhjfiihshhotghkihdrnhgvtheqpdhnsggprhgtphhtthhopeehpdhrtghpthhtoheplhhinhhugidqphgtihesvhhgvghrrdhkvghrnhgvlhdrohhrghdprhgtphhtthhopehlihhnuhigqdhpmhesvhhgvghrrdhkvghrnhgvlhdrohhrghdprhgtphhtthhopehlihhnuhigqdhkvghrnhgvlhesvhhgvghrrdhkvghrnhgvlhdrohhrghdprhgtphhtthhopehhvghlghgrrghssehkvghrnhgvlhdrohhrghdprhgtphhtthhopehmihhkrgdrfigvshht vghrsggvrhhgsehlihhnuhigrdhinhhtvghlrdgtohhm X-DCC--Metrics: v370.home.net.pl 1024; Body=5 Fuz1=5 Fuz2=5 Precedence: bulk List-ID: X-Mailing-List: linux-pm@vger.kernel.org From: Rafael J. Wysocki This flag is not needed any more, so drop it. Signed-off-by: Rafael J. Wysocki --- drivers/pci/pci-driver.c | 2 -- drivers/pci/pci.c | 3 --- include/linux/pci.h | 4 ---- 3 files changed, 9 deletions(-) Index: linux-pm/drivers/pci/pci-driver.c =================================================================== --- linux-pm.orig/drivers/pci/pci-driver.c +++ linux-pm/drivers/pci/pci-driver.c @@ -1337,8 +1337,6 @@ static int pci_pm_runtime_resume(struct if (pm && pm->runtime_resume) error = pm->runtime_resume(dev); - pci_dev->runtime_d3cold = false; - return error; } Index: linux-pm/drivers/pci/pci.c =================================================================== --- linux-pm.orig/drivers/pci/pci.c +++ linux-pm/drivers/pci/pci.c @@ -2703,8 +2703,6 @@ int pci_finish_runtime_suspend(struct pc if (target_state == PCI_POWER_ERROR) return -EIO; - dev->runtime_d3cold = target_state == PCI_D3cold; - /* * There are systems (for example, Intel mobile chips since Coffee * Lake) where the power drawn while suspended can be significantly @@ -2722,7 +2720,6 @@ int pci_finish_runtime_suspend(struct pc if (error) { pci_enable_wake(dev, target_state, false); pci_restore_ptm_state(dev); - dev->runtime_d3cold = false; } return error; Index: linux-pm/include/linux/pci.h =================================================================== --- linux-pm.orig/include/linux/pci.h +++ linux-pm/include/linux/pci.h @@ -379,10 +379,6 @@ struct pci_dev { unsigned int mmio_always_on:1; /* Disallow turning off io/mem decoding during BAR sizing */ unsigned int wakeup_prepared:1; - unsigned int runtime_d3cold:1; /* Whether go through runtime - D3cold, not set for devices - powered on/off by the - corresponding bridge */ unsigned int skip_bus_pm:1; /* Internal: Skip bus-level PM */ unsigned int ignore_hotplug:1; /* Ignore hotplug events */ unsigned int hotplug_user_indicators:1; /* SlotCtl indicators From patchwork Sat Apr 9 13:08:39 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Rafael J. Wysocki" X-Patchwork-Id: 559369 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 vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id F3CBBC43217 for ; Sat, 9 Apr 2022 13:29:13 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S242133AbiDINbS (ORCPT ); Sat, 9 Apr 2022 09:31:18 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:56608 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S242114AbiDINbH (ORCPT ); Sat, 9 Apr 2022 09:31:07 -0400 Received: from cloudserver094114.home.pl (cloudserver094114.home.pl [79.96.170.134]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id BB93FB0A77; Sat, 9 Apr 2022 06:29:00 -0700 (PDT) Received: from localhost (127.0.0.1) (HELO v370.home.net.pl) by /usr/run/smtp (/usr/run/postfix/private/idea_relay_lmtp) via UNIX with SMTP (IdeaSmtpServer 5.0.0) id 774345feafbd1fe9; Sat, 9 Apr 2022 15:28:59 +0200 Received: from kreacher.localnet (89-77-51-84.dynamic.chello.pl [89.77.51.84]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by v370.home.net.pl (Postfix) with ESMTPSA id 7BE1266BCD0; Sat, 9 Apr 2022 15:28:58 +0200 (CEST) From: "Rafael J. Wysocki" To: Linux PCI Cc: Linux PM , LKML , Bjorn Helgaas , Mika Westerberg Subject: [PATCH v1 3/7] PCI/PM: Rearrange pci_update_current_state() Date: Sat, 09 Apr 2022 15:08:39 +0200 Message-ID: <3191989.aeNJFYEL58@kreacher> In-Reply-To: <4419002.LvFx2qVVIh@kreacher> References: <4419002.LvFx2qVVIh@kreacher> MIME-Version: 1.0 X-CLIENT-IP: 89.77.51.84 X-CLIENT-HOSTNAME: 89-77-51-84.dynamic.chello.pl X-VADE-SPAMSTATE: clean X-VADE-SPAMCAUSE: gggruggvucftvghtrhhoucdtuddrgedvvddrudekvddgfeelucetufdoteggodetrfdotffvucfrrhhofhhilhgvmecujffqoffgrffnpdggtffipffknecuuegrihhlohhuthemucduhedtnecusecvtfgvtghiphhivghnthhsucdlqddutddtmdenucfjughrpefhvffufffkjghfggfgtgesthfuredttddtjeenucfhrhhomhepfdftrghfrggvlhculfdrucghhihsohgtkhhifdcuoehrjhifsehrjhifhihsohgtkhhirdhnvghtqeenucggtffrrghtthgvrhhnpedvjeelgffhiedukedtleekkedvudfggefhgfegjefgueekjeelvefggfdvledutdenucfkphepkeelrdejjedrhedurdekgeenucevlhhushhtvghrufhiiigvpedtnecurfgrrhgrmhepihhnvghtpeekledrjeejrdehuddrkeegpdhhvghlohepkhhrvggrtghhvghrrdhlohgtrghlnhgvthdpmhgrihhlfhhrohhmpedftfgrfhgrvghlucflrdcuhgihshhotghkihdfuceorhhjfiesrhhjfiihshhotghkihdrnhgvtheqpdhnsggprhgtphhtthhopeehpdhrtghpthhtoheplhhinhhugidqphgtihesvhhgvghrrdhkvghrnhgvlhdrohhrghdprhgtphhtthhopehlihhnuhigqdhpmhesvhhgvghrrdhkvghrnhgvlhdrohhrghdprhgtphhtthhopehlihhnuhigqdhkvghrnhgvlhesvhhgvghrrdhkvghrnhgvlhdrohhrghdprhgtphhtthhopehhvghlghgrrghssehkvghrnhgvlhdrohhrghdprhgtphhtthhopehmihhkrgdrfigvshht vghrsggvrhhgsehlihhnuhigrdhinhhtvghlrdgtohhm X-DCC--Metrics: v370.home.net.pl 1024; Body=5 Fuz1=5 Fuz2=5 Precedence: bulk List-ID: X-Mailing-List: linux-pm@vger.kernel.org From: Rafael J. Wysocki Save one config space access in pci_update_current_state() by testing the retireved PCI_PM_CTRL register value against PCI_POSSIBLE_ERROR() instead of invoking pci_device_is_present() separately. While at it, drop a pair of unnecessary parens. No expected functional impact. Signed-off-by: Rafael J. Wysocki --- drivers/pci/pci.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) Index: linux-pm/drivers/pci/pci.c =================================================================== --- linux-pm.orig/drivers/pci/pci.c +++ linux-pm/drivers/pci/pci.c @@ -1201,14 +1201,17 @@ static int pci_raw_set_power_state(struc */ void pci_update_current_state(struct pci_dev *dev, pci_power_t state) { - if (platform_pci_get_power_state(dev) == PCI_D3cold || - !pci_device_is_present(dev)) { + if (platform_pci_get_power_state(dev) == PCI_D3cold) { dev->current_state = PCI_D3cold; } else if (dev->pm_cap) { u16 pmcsr; pci_read_config_word(dev, dev->pm_cap + PCI_PM_CTRL, &pmcsr); - dev->current_state = (pmcsr & PCI_PM_CTRL_STATE_MASK); + if (PCI_POSSIBLE_ERROR(pmcsr)) { + dev->current_state = PCI_D3cold; + return; + } + dev->current_state = pmcsr & PCI_PM_CTRL_STATE_MASK; } else { dev->current_state = state; } From patchwork Sat Apr 9 13:22:54 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Rafael J. Wysocki" X-Patchwork-Id: 559903 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 vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id F3C06C433FE for ; Sat, 9 Apr 2022 13:29:07 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S242147AbiDINbM (ORCPT ); Sat, 9 Apr 2022 09:31:12 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:56570 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S242111AbiDINbH (ORCPT ); Sat, 9 Apr 2022 09:31:07 -0400 Received: from cloudserver094114.home.pl (cloudserver094114.home.pl [79.96.170.134]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 1FA809AE6C; Sat, 9 Apr 2022 06:28:58 -0700 (PDT) Received: from localhost (127.0.0.1) (HELO v370.home.net.pl) by /usr/run/smtp (/usr/run/postfix/private/idea_relay_lmtp) via UNIX with SMTP (IdeaSmtpServer 5.0.0) id 2d06ce431da4cb50; Sat, 9 Apr 2022 15:28:57 +0200 Received: from kreacher.localnet (89-77-51-84.dynamic.chello.pl [89.77.51.84]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by v370.home.net.pl (Postfix) with ESMTPSA id D266366BCD0; Sat, 9 Apr 2022 15:28:56 +0200 (CEST) From: "Rafael J. Wysocki" To: Linux PCI Cc: Linux PM , LKML , Bjorn Helgaas , Mika Westerberg Subject: [PATCH v1 4/7] PCI/PM: Rework changing power states of PCI devices Date: Sat, 09 Apr 2022 15:22:54 +0200 Message-ID: <3689460.kQq0lBPeGt@kreacher> In-Reply-To: <4419002.LvFx2qVVIh@kreacher> References: <4419002.LvFx2qVVIh@kreacher> MIME-Version: 1.0 X-CLIENT-IP: 89.77.51.84 X-CLIENT-HOSTNAME: 89-77-51-84.dynamic.chello.pl X-VADE-SPAMSTATE: clean X-VADE-SPAMCAUSE: gggruggvucftvghtrhhoucdtuddrgedvvddrudekvddgfeelucetufdoteggodetrfdotffvucfrrhhofhhilhgvmecujffqoffgrffnpdggtffipffknecuuegrihhlohhuthemucduhedtnecusecvtfgvtghiphhivghnthhsucdlqddutddtmdenucfjughrpefhvffufffkjghfggfgtgesthfuredttddtjeenucfhrhhomhepfdftrghfrggvlhculfdrucghhihsohgtkhhifdcuoehrjhifsehrjhifhihsohgtkhhirdhnvghtqeenucggtffrrghtthgvrhhnpedvjeelgffhiedukedtleekkedvudfggefhgfegjefgueekjeelvefggfdvledutdenucfkphepkeelrdejjedrhedurdekgeenucevlhhushhtvghrufhiiigvpedtnecurfgrrhgrmhepihhnvghtpeekledrjeejrdehuddrkeegpdhhvghlohepkhhrvggrtghhvghrrdhlohgtrghlnhgvthdpmhgrihhlfhhrohhmpedftfgrfhgrvghlucflrdcuhgihshhotghkihdfuceorhhjfiesrhhjfiihshhotghkihdrnhgvtheqpdhnsggprhgtphhtthhopeehpdhrtghpthhtoheplhhinhhugidqphgtihesvhhgvghrrdhkvghrnhgvlhdrohhrghdprhgtphhtthhopehlihhnuhigqdhpmhesvhhgvghrrdhkvghrnhgvlhdrohhrghdprhgtphhtthhopehlihhnuhigqdhkvghrnhgvlhesvhhgvghrrdhkvghrnhgvlhdrohhrghdprhgtphhtthhopehhvghlghgrrghssehkvghrnhgvlhdrohhrghdprhgtphhtthhopehmihhkrgdrfigvshht vghrsggvrhhgsehlihhnuhigrdhinhhtvghlrdgtohhm X-DCC--Metrics: v370.home.net.pl 1024; Body=5 Fuz1=5 Fuz2=5 Precedence: bulk List-ID: X-Mailing-List: linux-pm@vger.kernel.org From: Rafael J. Wysocki There are some issues related to changing power states of PCI devices, mostly related to carrying out unnecessary actions in some places, and the code is generally hard to follow. 1. pci_power_up() has two callers, pci_set_power_state() and pci_pm_default_resume_early(). The latter updates the current power state of the device right after calling pci_power_up() and it restores the entire config space of the device right after that, so pci_power_up() itself need not read the PCI_PM_CTRL register or restore the BARs after programming the device into D0 in that case (which it does currently). 2. It is generally hard to get a clear view of the pci_power_up() code flow, especially in some corner cases, due to all of the involved PCI_PM_CTRL register reads and writes occurring in pci_platform_power_transition() and in pci_raw_set_power_state(), some of which are redundant. 3. The transitions from low-power states to D0 and the other way around are unnecessarily tangled in pci_raw_set_power_state() which causes it to use a redundant local variable and makes the code in it rather hard to follow. To address the above shortcomings, make the following changes: a. Remove the code handling transitions into D0 from pci_raw_set_power_state() and rename that function as pci_set_low_power_state(). b. Add the code handling transitions into D0 directly to pci_power_up() and to a new function pci_set_full_power_state() calling it internally that is only used in pci_set_power_state(). c. Make pci_power_up() avoid redundant PCI_PM_CTRL register accesses and make it work in the same way for transitions from any low- power states (transitions from D1 and D2 are handled slightly differently, which is not really necessary, before the change). d. Put the restoration of the BARs and the PCI_PM_CTRL register read confirming the power state change into pci_set_full_power_state() to avoid doing these things in pci_pm_default_resume_early() in vain. Signed-off-by: Rafael J. Wysocki --- drivers/pci/pci.c | 145 +++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 100 insertions(+), 45 deletions(-) Index: linux-pm/drivers/pci/pci.c =================================================================== --- linux-pm.orig/drivers/pci/pci.c +++ linux-pm/drivers/pci/pci.c @@ -1068,10 +1068,9 @@ static inline bool platform_pci_bridge_d } /** - * pci_raw_set_power_state - Use PCI PM registers to set the power state of - * given PCI device + * pci_set_low_power_state - Program the given device into a low-power state * @dev: PCI device to handle. - * @state: PCI power state (D0, D1, D2, D3hot) to put the device into. + * @state: PCI power state (D1, D2, D3hot) to put the device into. * * RETURN VALUE: * -EINVAL if the requested state is invalid. @@ -1080,10 +1079,9 @@ static inline bool platform_pci_bridge_d * 0 if device already is in the requested state. * 0 if device's power state has been successfully changed. */ -static int pci_raw_set_power_state(struct pci_dev *dev, pci_power_t state) +static int pci_set_low_power_state(struct pci_dev *dev, pci_power_t state) { u16 pmcsr; - bool need_restore = false; /* Check if we're already there */ if (dev->current_state == state) @@ -1092,7 +1090,7 @@ static int pci_raw_set_power_state(struc if (!dev->pm_cap) return -EIO; - if (state < PCI_D0 || state > PCI_D3hot) + if (state < PCI_D1 || state > PCI_D3hot) return -EINVAL; /* @@ -1101,8 +1099,7 @@ static int pci_raw_set_power_state(struc * we can go from D1 to D3, but we can't go directly from D3 to D1; * we'd have to go from D3 to D0, then to D1. */ - if (state != PCI_D0 && dev->current_state <= PCI_D3cold - && dev->current_state > state) { + if (dev->current_state <= PCI_D3cold && dev->current_state > state) { pci_err(dev, "invalid power transition (from %s to %s)\n", pci_power_name(dev->current_state), pci_power_name(state)); @@ -1127,23 +1124,9 @@ static int pci_raw_set_power_state(struc * This doesn't affect PME_Status, disables PME_En, and * sets PowerState to 0. */ - switch (dev->current_state) { - case PCI_D0: - case PCI_D1: - case PCI_D2: + if (dev->current_state <= PCI_D2) { pmcsr &= ~PCI_PM_CTRL_STATE_MASK; pmcsr |= state; - break; - case PCI_D3hot: - case PCI_D3cold: - case PCI_UNKNOWN: /* Boot-up */ - if ((pmcsr & PCI_PM_CTRL_STATE_MASK) == PCI_D3hot - && !(pmcsr & PCI_PM_CTRL_NO_SOFT_RESET)) - need_restore = true; - fallthrough; /* force to D0 */ - default: - pmcsr = 0; - break; } /* Enter specified state */ @@ -1153,9 +1136,9 @@ static int pci_raw_set_power_state(struc * Mandatory power management transition delays; see PCI PM 1.1 * 5.6.1 table 18 */ - if (state == PCI_D3hot || dev->current_state == PCI_D3hot) + if (state == PCI_D3hot) pci_dev_d3_sleep(dev); - else if (state == PCI_D2 || dev->current_state == PCI_D2) + else if (state == PCI_D2) udelay(PCI_PM_D2_DELAY); pci_read_config_word(dev, dev->pm_cap + PCI_PM_CTRL, &pmcsr); @@ -1165,22 +1148,6 @@ static int pci_raw_set_power_state(struc pci_power_name(dev->current_state), pci_power_name(state)); - /* - * According to section 5.4.1 of the "PCI BUS POWER MANAGEMENT - * INTERFACE SPECIFICATION, REV. 1.2", a device transitioning - * from D3hot to D0 _may_ perform an internal reset, thereby - * going to "D0 Uninitialized" rather than "D0 Initialized". - * For example, at least some versions of the 3c905B and the - * 3c556B exhibit this behaviour. - * - * At least some laptop BIOSen (e.g. the Thinkpad T21) leave - * devices in a D3hot state at boot. Consequently, we need to - * restore at least the BARs so that the device will be - * accessible to its driver. - */ - if (need_restore) - pci_restore_bars(dev); - if (dev->bus->self) pcie_aspm_pm_state_change(dev->bus->self); @@ -1312,8 +1279,54 @@ static int pci_dev_wait(struct pci_dev * */ int pci_power_up(struct pci_dev *dev) { - pci_platform_power_transition(dev, PCI_D0); - return pci_raw_set_power_state(dev, PCI_D0); + int ret; + + ret = pci_platform_power_transition(dev, PCI_D0); + if (ret) { + u16 pmcsr; + + /* + * The PCI_PM_CTRL register has not been read above, so read it + * now and bail out if that fails. + */ + pci_read_config_word(dev, dev->pm_cap + PCI_PM_CTRL, &pmcsr); + if (PCI_POSSIBLE_ERROR(pmcsr)) { + dev->current_state = PCI_D3cold; + goto fail; + } + dev->current_state = pmcsr & PCI_PM_CTRL_STATE_MASK; + } else if (dev->current_state == PCI_D3cold) { + /* + * Since current_state is still PCI_D3cold, the power state seen + * by the platform is still D3cold or the PCI_PM_CTRL register + * read in pci_update_current_state() has failed, so assume the + * device to be inaccessible. + */ + goto fail; + } + + /* There's nothing more to do if current_state is D0 at this point. */ + if (dev->current_state == PCI_D0) + return 0; + + /* + * Program the device into PCI_D0 by forcing the entire word to 0 (this + * doesn't affect PME_Status, disables PME_En, and sets PowerState to 0) + * and wait for the prescribed amount of time. Assume success. + */ + pci_write_config_word(dev, dev->pm_cap + PCI_PM_CTRL, 0); + + if (dev->current_state == PCI_D3hot) + pci_dev_d3_sleep(dev); + else if (dev->current_state == PCI_D2) + udelay(PCI_PM_D2_DELAY); + + dev->current_state = PCI_D0; + return 0; + +fail: + pci_err(dev, "Unable to change power state to D0, device inaccessible\n"); + return -ENODEV; } /** @@ -1340,6 +1353,48 @@ void pci_bus_set_current_state(struct pc pci_walk_bus(bus, __pci_dev_set_current_state, &state); } +static int pci_set_full_power_state(struct pci_dev *dev) +{ + pci_power_t old_state = dev->current_state; + u16 pmcsr; + int ret; + + ret = pci_power_up(dev); + if (ret) + return ret; + + if (!dev->pm_cap) + return 0; + + pci_read_config_word(dev, dev->pm_cap + PCI_PM_CTRL, &pmcsr); + + dev->current_state = pmcsr & PCI_PM_CTRL_STATE_MASK; + if (dev->current_state != PCI_D0) { + pci_info_ratelimited(dev, "Refused to change power state from %s to D0\n", + pci_power_name(dev->current_state)); + } else if (old_state >= PCI_D3hot && !(pmcsr & PCI_PM_CTRL_NO_SOFT_RESET)) { + /* + * According to section 5.4.1 of the "PCI BUS POWER MANAGEMENT + * INTERFACE SPECIFICATION, REV. 1.2", a device transitioning + * from D3hot to D0 _may_ perform an internal reset, thereby + * going to "D0 Uninitialized" rather than "D0 Initialized". For + * example, at least some versions of the 3c905B and the 3c556B + * exhibit this behaviour. + * + * At least some laptop BIOSen (e.g. the Thinkpad T21) leave + * devices in a D3hot state at boot. Consequently, we need to + * restore at least the BARs so that the device will be + * accessible to its driver. + */ + pci_restore_bars(dev); + } + + if (dev->bus->self) + pcie_aspm_pm_state_change(dev->bus->self); + + return 0; +} + /** * pci_set_power_state - Set the power state of a PCI device * @dev: PCI device to handle. @@ -1381,7 +1436,7 @@ int pci_set_power_state(struct pci_dev * return 0; if (state == PCI_D0) - return pci_power_up(dev); + return pci_set_full_power_state(dev); /* * This device is quirked not to be put into D3, so don't put it in @@ -1394,7 +1449,7 @@ int pci_set_power_state(struct pci_dev * * To put device in D3cold, we put device into D3hot in native * way, then put device into D3cold with platform ops */ - error = pci_raw_set_power_state(dev, state > PCI_D3hot ? + error = pci_set_low_power_state(dev, state > PCI_D3hot ? PCI_D3hot : state); if (pci_platform_power_transition(dev, state)) From patchwork Sat Apr 9 13:23:49 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Rafael J. Wysocki" X-Patchwork-Id: 559371 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 vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id C9BE1C43219 for ; Sat, 9 Apr 2022 13:29:01 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S242104AbiDINbF (ORCPT ); Sat, 9 Apr 2022 09:31:05 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:56412 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S242101AbiDINbE (ORCPT ); Sat, 9 Apr 2022 09:31:04 -0400 Received: from cloudserver094114.home.pl (cloudserver094114.home.pl [79.96.170.134]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 8B51BA9947; Sat, 9 Apr 2022 06:28:57 -0700 (PDT) Received: from localhost (127.0.0.1) (HELO v370.home.net.pl) by /usr/run/smtp (/usr/run/postfix/private/idea_relay_lmtp) via UNIX with SMTP (IdeaSmtpServer 5.0.0) id 6f83bd5860e6572f; Sat, 9 Apr 2022 15:28:56 +0200 Received: from kreacher.localnet (89-77-51-84.dynamic.chello.pl [89.77.51.84]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by v370.home.net.pl (Postfix) with ESMTPSA id 43C8F66BCD0; Sat, 9 Apr 2022 15:28:55 +0200 (CEST) From: "Rafael J. Wysocki" To: Linux PCI Cc: Linux PM , LKML , Bjorn Helgaas , Mika Westerberg Subject: [PATCH v1 5/7] PCI/PM: Move pci_set_low_power_state() next to its caller Date: Sat, 09 Apr 2022 15:23:49 +0200 Message-ID: <8948282.CDJkKcVGEf@kreacher> In-Reply-To: <4419002.LvFx2qVVIh@kreacher> References: <4419002.LvFx2qVVIh@kreacher> MIME-Version: 1.0 X-CLIENT-IP: 89.77.51.84 X-CLIENT-HOSTNAME: 89-77-51-84.dynamic.chello.pl X-VADE-SPAMSTATE: clean X-VADE-SPAMCAUSE: gggruggvucftvghtrhhoucdtuddrgedvvddrudekvddgfeelucetufdoteggodetrfdotffvucfrrhhofhhilhgvmecujffqoffgrffnpdggtffipffknecuuegrihhlohhuthemucduhedtnecusecvtfgvtghiphhivghnthhsucdlqddutddtmdenucfjughrpefhvffufffkjghfggfgtgesthfuredttddtjeenucfhrhhomhepfdftrghfrggvlhculfdrucghhihsohgtkhhifdcuoehrjhifsehrjhifhihsohgtkhhirdhnvghtqeenucggtffrrghtthgvrhhnpedvjeelgffhiedukedtleekkedvudfggefhgfegjefgueekjeelvefggfdvledutdenucfkphepkeelrdejjedrhedurdekgeenucevlhhushhtvghrufhiiigvpedtnecurfgrrhgrmhepihhnvghtpeekledrjeejrdehuddrkeegpdhhvghlohepkhhrvggrtghhvghrrdhlohgtrghlnhgvthdpmhgrihhlfhhrohhmpedftfgrfhgrvghlucflrdcuhgihshhotghkihdfuceorhhjfiesrhhjfiihshhotghkihdrnhgvtheqpdhnsggprhgtphhtthhopeehpdhrtghpthhtoheplhhinhhugidqphgtihesvhhgvghrrdhkvghrnhgvlhdrohhrghdprhgtphhtthhopehlihhnuhigqdhpmhesvhhgvghrrdhkvghrnhgvlhdrohhrghdprhgtphhtthhopehlihhnuhigqdhkvghrnhgvlhesvhhgvghrrdhkvghrnhgvlhdrohhrghdprhgtphhtthhopehhvghlghgrrghssehkvghrnhgvlhdrohhrghdprhgtphhtthhopehmihhkrgdrfigvshht vghrsggvrhhgsehlihhnuhigrdhinhhtvghlrdgtohhm X-DCC--Metrics: v370.home.net.pl 1024; Body=5 Fuz1=5 Fuz2=5 Precedence: bulk List-ID: X-Mailing-List: linux-pm@vger.kernel.org From: Rafael J. Wysocki Because pci_set_power_state() is the only caller of pci_set_low_power_state(), move the latter next to the former. No functional impact. Signed-off-by: Rafael J. Wysocki --- drivers/pci/pci.c | 174 +++++++++++++++++++++++++++--------------------------- 1 file changed, 87 insertions(+), 87 deletions(-) Index: linux-pm/drivers/pci/pci.c =================================================================== --- linux-pm.orig/drivers/pci/pci.c +++ linux-pm/drivers/pci/pci.c @@ -1068,93 +1068,6 @@ static inline bool platform_pci_bridge_d } /** - * pci_set_low_power_state - Program the given device into a low-power state - * @dev: PCI device to handle. - * @state: PCI power state (D1, D2, D3hot) to put the device into. - * - * RETURN VALUE: - * -EINVAL if the requested state is invalid. - * -EIO if device does not support PCI PM or its PM capabilities register has a - * wrong version, or device doesn't support the requested state. - * 0 if device already is in the requested state. - * 0 if device's power state has been successfully changed. - */ -static int pci_set_low_power_state(struct pci_dev *dev, pci_power_t state) -{ - u16 pmcsr; - - /* Check if we're already there */ - if (dev->current_state == state) - return 0; - - if (!dev->pm_cap) - return -EIO; - - if (state < PCI_D1 || state > PCI_D3hot) - return -EINVAL; - - /* - * Validate transition: We can enter D0 from any state, but if - * we're already in a low-power state, we can only go deeper. E.g., - * we can go from D1 to D3, but we can't go directly from D3 to D1; - * we'd have to go from D3 to D0, then to D1. - */ - if (dev->current_state <= PCI_D3cold && dev->current_state > state) { - pci_err(dev, "invalid power transition (from %s to %s)\n", - pci_power_name(dev->current_state), - pci_power_name(state)); - return -EINVAL; - } - - /* Check if this device supports the desired state */ - if ((state == PCI_D1 && !dev->d1_support) - || (state == PCI_D2 && !dev->d2_support)) - return -EIO; - - pci_read_config_word(dev, dev->pm_cap + PCI_PM_CTRL, &pmcsr); - if (PCI_POSSIBLE_ERROR(pmcsr)) { - pci_err(dev, "can't change power state from %s to %s (config space inaccessible)\n", - pci_power_name(dev->current_state), - pci_power_name(state)); - return -EIO; - } - - /* - * If we're (effectively) in D3, force entire word to 0. - * This doesn't affect PME_Status, disables PME_En, and - * sets PowerState to 0. - */ - if (dev->current_state <= PCI_D2) { - pmcsr &= ~PCI_PM_CTRL_STATE_MASK; - pmcsr |= state; - } - - /* Enter specified state */ - pci_write_config_word(dev, dev->pm_cap + PCI_PM_CTRL, pmcsr); - - /* - * Mandatory power management transition delays; see PCI PM 1.1 - * 5.6.1 table 18 - */ - if (state == PCI_D3hot) - pci_dev_d3_sleep(dev); - else if (state == PCI_D2) - udelay(PCI_PM_D2_DELAY); - - pci_read_config_word(dev, dev->pm_cap + PCI_PM_CTRL, &pmcsr); - dev->current_state = (pmcsr & PCI_PM_CTRL_STATE_MASK); - if (dev->current_state != state) - pci_info_ratelimited(dev, "refused to change power state from %s to %s\n", - pci_power_name(dev->current_state), - pci_power_name(state)); - - if (dev->bus->self) - pcie_aspm_pm_state_change(dev->bus->self); - - return 0; -} - -/** * pci_update_current_state - Read power state of given device and cache it * @dev: PCI device to handle. * @state: State to cache in case the device doesn't have the PM capability @@ -1391,6 +1304,93 @@ static int pci_set_full_power_state(stru if (dev->bus->self) pcie_aspm_pm_state_change(dev->bus->self); + + return 0; +} + +/** + * pci_set_low_power_state - Program the given device into a low-power state + * @dev: PCI device to handle. + * @state: PCI power state (D1, D2, D3hot) to put the device into. + * + * RETURN VALUE: + * -EINVAL if the requested state is invalid. + * -EIO if device does not support PCI PM or its PM capabilities register has a + * wrong version, or device doesn't support the requested state. + * 0 if device already is in the requested state. + * 0 if device's power state has been successfully changed. + */ +static int pci_set_low_power_state(struct pci_dev *dev, pci_power_t state) +{ + u16 pmcsr; + + /* Check if we're already there */ + if (dev->current_state == state) + return 0; + + if (!dev->pm_cap) + return -EIO; + + if (state < PCI_D1 || state > PCI_D3hot) + return -EINVAL; + + /* + * Validate transition: We can enter D0 from any state, but if + * we're already in a low-power state, we can only go deeper. E.g., + * we can go from D1 to D3, but we can't go directly from D3 to D1; + * we'd have to go from D3 to D0, then to D1. + */ + if (dev->current_state <= PCI_D3cold && dev->current_state > state) { + pci_err(dev, "invalid power transition (from %s to %s)\n", + pci_power_name(dev->current_state), + pci_power_name(state)); + return -EINVAL; + } + + /* Check if this device supports the desired state */ + if ((state == PCI_D1 && !dev->d1_support) + || (state == PCI_D2 && !dev->d2_support)) + return -EIO; + + pci_read_config_word(dev, dev->pm_cap + PCI_PM_CTRL, &pmcsr); + if (PCI_POSSIBLE_ERROR(pmcsr)) { + pci_err(dev, "can't change power state from %s to %s (config space inaccessible)\n", + pci_power_name(dev->current_state), + pci_power_name(state)); + return -EIO; + } + + /* + * If we're (effectively) in D3, force entire word to 0. + * This doesn't affect PME_Status, disables PME_En, and + * sets PowerState to 0. + */ + if (dev->current_state <= PCI_D2) { + pmcsr &= ~PCI_PM_CTRL_STATE_MASK; + pmcsr |= state; + } + + /* Enter specified state */ + pci_write_config_word(dev, dev->pm_cap + PCI_PM_CTRL, pmcsr); + + /* + * Mandatory power management transition delays; see PCI PM 1.1 + * 5.6.1 table 18 + */ + if (state == PCI_D3hot) + pci_dev_d3_sleep(dev); + else if (state == PCI_D2) + udelay(PCI_PM_D2_DELAY); + + pci_read_config_word(dev, dev->pm_cap + PCI_PM_CTRL, &pmcsr); + dev->current_state = (pmcsr & PCI_PM_CTRL_STATE_MASK); + if (dev->current_state != state) + pci_info_ratelimited(dev, "refused to change power state from %s to %s\n", + pci_power_name(dev->current_state), + pci_power_name(state)); + + if (dev->bus->self) + pcie_aspm_pm_state_change(dev->bus->self); return 0; } From patchwork Sat Apr 9 13:26:44 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Rafael J. Wysocki" X-Patchwork-Id: 559904 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 vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 82B82C433EF for ; Sat, 9 Apr 2022 13:28:59 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S242096AbiDINbE (ORCPT ); Sat, 9 Apr 2022 09:31:04 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:56290 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S242024AbiDINbD (ORCPT ); Sat, 9 Apr 2022 09:31:03 -0400 Received: from cloudserver094114.home.pl (cloudserver094114.home.pl [79.96.170.134]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 03C539AE6C; Sat, 9 Apr 2022 06:28:55 -0700 (PDT) Received: from localhost (127.0.0.1) (HELO v370.home.net.pl) by /usr/run/smtp (/usr/run/postfix/private/idea_relay_lmtp) via UNIX with SMTP (IdeaSmtpServer 5.0.0) id f7cabe0ba700f433; Sat, 9 Apr 2022 15:28:54 +0200 Received: from kreacher.localnet (89-77-51-84.dynamic.chello.pl [89.77.51.84]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by v370.home.net.pl (Postfix) with ESMTPSA id B7AED66BCD0; Sat, 9 Apr 2022 15:28:53 +0200 (CEST) From: "Rafael J. Wysocki" To: Linux PCI Cc: Linux PM , LKML , Bjorn Helgaas , Mika Westerberg Subject: [PATCH v1 6/7] PCI/PM: Clean up pci_set_low_power_state() Date: Sat, 09 Apr 2022 15:26:44 +0200 Message-ID: <1752041.VLH7GnMWUR@kreacher> In-Reply-To: <4419002.LvFx2qVVIh@kreacher> References: <4419002.LvFx2qVVIh@kreacher> MIME-Version: 1.0 X-CLIENT-IP: 89.77.51.84 X-CLIENT-HOSTNAME: 89-77-51-84.dynamic.chello.pl X-VADE-SPAMSTATE: clean X-VADE-SPAMCAUSE: gggruggvucftvghtrhhoucdtuddrgedvvddrudekvddgfeelucetufdoteggodetrfdotffvucfrrhhofhhilhgvmecujffqoffgrffnpdggtffipffknecuuegrihhlohhuthemucduhedtnecusecvtfgvtghiphhivghnthhsucdlqddutddtmdenucfjughrpefhvffufffkjghfggfgtgesthfuredttddtjeenucfhrhhomhepfdftrghfrggvlhculfdrucghhihsohgtkhhifdcuoehrjhifsehrjhifhihsohgtkhhirdhnvghtqeenucggtffrrghtthgvrhhnpedvjeelgffhiedukedtleekkedvudfggefhgfegjefgueekjeelvefggfdvledutdenucfkphepkeelrdejjedrhedurdekgeenucevlhhushhtvghrufhiiigvpedtnecurfgrrhgrmhepihhnvghtpeekledrjeejrdehuddrkeegpdhhvghlohepkhhrvggrtghhvghrrdhlohgtrghlnhgvthdpmhgrihhlfhhrohhmpedftfgrfhgrvghlucflrdcuhgihshhotghkihdfuceorhhjfiesrhhjfiihshhotghkihdrnhgvtheqpdhnsggprhgtphhtthhopeehpdhrtghpthhtoheplhhinhhugidqphgtihesvhhgvghrrdhkvghrnhgvlhdrohhrghdprhgtphhtthhopehlihhnuhigqdhpmhesvhhgvghrrdhkvghrnhgvlhdrohhrghdprhgtphhtthhopehlihhnuhigqdhkvghrnhgvlhesvhhgvghrrdhkvghrnhgvlhdrohhrghdprhgtphhtthhopehhvghlghgrrghssehkvghrnhgvlhdrohhrghdprhgtphhtthhopehmihhkrgdrfigvshht vghrsggvrhhgsehlihhnuhigrdhinhhtvghlrdgtohhm X-DCC--Metrics: v370.home.net.pl 1024; Body=5 Fuz1=5 Fuz2=5 Precedence: bulk List-ID: X-Mailing-List: linux-pm@vger.kernel.org From: Rafael J. Wysocki Make the following assorted non-essential changes in pci_set_low_power_state(): 1. Drop two redundant checks from it (the caller takes care of these conditions). 2. Modify error messages printed by it to make them more consistent with the messages printed by pci_power_up() and pci_set_full_power_state(). 3. Change the log level of one of the messages mentioned above to "debug", because it only indicates a programming mistake. 4. Make the function return -ENODEV (instead of -EIO) when the device is not accessible. Signed-off-by: Rafael J. Wysocki --- drivers/pci/pci.c | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) Index: linux-pm/drivers/pci/pci.c =================================================================== --- linux-pm.orig/drivers/pci/pci.c +++ linux-pm/drivers/pci/pci.c @@ -1324,16 +1324,9 @@ static int pci_set_low_power_state(struc { u16 pmcsr; - /* Check if we're already there */ - if (dev->current_state == state) - return 0; - if (!dev->pm_cap) return -EIO; - if (state < PCI_D1 || state > PCI_D3hot) - return -EINVAL; - /* * Validate transition: We can enter D0 from any state, but if * we're already in a low-power state, we can only go deeper. E.g., @@ -1341,7 +1334,7 @@ static int pci_set_low_power_state(struc * we'd have to go from D3 to D0, then to D1. */ if (dev->current_state <= PCI_D3cold && dev->current_state > state) { - pci_err(dev, "invalid power transition (from %s to %s)\n", + pci_dbg(dev, "Invalid power transition (from %s to %s)\n", pci_power_name(dev->current_state), pci_power_name(state)); return -EINVAL; @@ -1354,10 +1347,10 @@ static int pci_set_low_power_state(struc pci_read_config_word(dev, dev->pm_cap + PCI_PM_CTRL, &pmcsr); if (PCI_POSSIBLE_ERROR(pmcsr)) { - pci_err(dev, "can't change power state from %s to %s (config space inaccessible)\n", + pci_err(dev, "Unable to change power state from %s to %s, device inaccessible\n", pci_power_name(dev->current_state), pci_power_name(state)); - return -EIO; + return -ENODEV; } /* From patchwork Sat Apr 9 13:28:38 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Rafael J. Wysocki" X-Patchwork-Id: 559372 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 vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id E80FCC433F5 for ; Sat, 9 Apr 2022 13:28:58 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S242045AbiDINbE (ORCPT ); Sat, 9 Apr 2022 09:31:04 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:56280 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S241884AbiDINbD (ORCPT ); Sat, 9 Apr 2022 09:31:03 -0400 Received: from cloudserver094114.home.pl (cloudserver094114.home.pl [79.96.170.134]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id BA46BADD5F; Sat, 9 Apr 2022 06:28:54 -0700 (PDT) Received: from localhost (127.0.0.1) (HELO v370.home.net.pl) by /usr/run/smtp (/usr/run/postfix/private/idea_relay_lmtp) via UNIX with SMTP (IdeaSmtpServer 5.0.0) id 1352328eb26ee335; Sat, 9 Apr 2022 15:28:52 +0200 Received: from kreacher.localnet (89-77-51-84.dynamic.chello.pl [89.77.51.84]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by v370.home.net.pl (Postfix) with ESMTPSA id C220366BCD0; Sat, 9 Apr 2022 15:28:51 +0200 (CEST) From: "Rafael J. Wysocki" To: Linux PCI Cc: Linux PM , LKML , Bjorn Helgaas , Mika Westerberg Subject: [PATCH v1 7/7] PCI/PM: Rearrange pci_set_power_state() Date: Sat, 09 Apr 2022 15:28:38 +0200 Message-ID: <1938958.usQuhbGJ8B@kreacher> In-Reply-To: <4419002.LvFx2qVVIh@kreacher> References: <4419002.LvFx2qVVIh@kreacher> MIME-Version: 1.0 X-CLIENT-IP: 89.77.51.84 X-CLIENT-HOSTNAME: 89-77-51-84.dynamic.chello.pl X-VADE-SPAMSTATE: clean X-VADE-SPAMCAUSE: gggruggvucftvghtrhhoucdtuddrgedvvddrudekvddgfeelucetufdoteggodetrfdotffvucfrrhhofhhilhgvmecujffqoffgrffnpdggtffipffknecuuegrihhlohhuthemucduhedtnecusecvtfgvtghiphhivghnthhsucdlqddutddtmdenucfjughrpefhvffufffkjghfggfgtgesthfuredttddtjeenucfhrhhomhepfdftrghfrggvlhculfdrucghhihsohgtkhhifdcuoehrjhifsehrjhifhihsohgtkhhirdhnvghtqeenucggtffrrghtthgvrhhnpedvjeelgffhiedukedtleekkedvudfggefhgfegjefgueekjeelvefggfdvledutdenucfkphepkeelrdejjedrhedurdekgeenucevlhhushhtvghrufhiiigvpedtnecurfgrrhgrmhepihhnvghtpeekledrjeejrdehuddrkeegpdhhvghlohepkhhrvggrtghhvghrrdhlohgtrghlnhgvthdpmhgrihhlfhhrohhmpedftfgrfhgrvghlucflrdcuhgihshhotghkihdfuceorhhjfiesrhhjfiihshhotghkihdrnhgvtheqpdhnsggprhgtphhtthhopeehpdhrtghpthhtoheplhhinhhugidqphgtihesvhhgvghrrdhkvghrnhgvlhdrohhrghdprhgtphhtthhopehlihhnuhigqdhpmhesvhhgvghrrdhkvghrnhgvlhdrohhrghdprhgtphhtthhopehlihhnuhigqdhkvghrnhgvlhesvhhgvghrrdhkvghrnhgvlhdrohhrghdprhgtphhtthhopehhvghlghgrrghssehkvghrnhgvlhdrohhrghdprhgtphhtthhopehmihhkrgdrfigvshht vghrsggvrhhgsehlihhnuhigrdhinhhtvghlrdgtohhm X-DCC--Metrics: v370.home.net.pl 1024; Body=5 Fuz1=5 Fuz2=5 Precedence: bulk List-ID: X-Mailing-List: linux-pm@vger.kernel.org From: Rafael J. Wysocki The part of pci_set_power_state() related to transitions into low-power states is unnecessary convoluted, so clearly divide it into the D3cold special case and the general case covering all of the other states. Also fix a potential issue with calling pci_bus_set_current_state() to set the current state of all devices on the subordinate to D3cold without checking if the power state of the parent bridge has really changed to D3cold. Signed-off-by: Rafael J. Wysocki --- drivers/pci/pci.c | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) Index: linux-pm/drivers/pci/pci.c =================================================================== --- linux-pm.orig/drivers/pci/pci.c +++ linux-pm/drivers/pci/pci.c @@ -1438,19 +1438,25 @@ int pci_set_power_state(struct pci_dev * if (state >= PCI_D3hot && (dev->dev_flags & PCI_DEV_FLAGS_NO_D3)) return 0; - /* - * To put device in D3cold, we put device into D3hot in native - * way, then put device into D3cold with platform ops - */ - error = pci_set_low_power_state(dev, state > PCI_D3hot ? - PCI_D3hot : state); + if (state == PCI_D3cold) { + /* + * To put the device in D3cold, put it into D3hot in the native + * way, then put it into D3cold using platform ops. + */ + error = pci_set_low_power_state(dev, PCI_D3hot); - if (pci_platform_power_transition(dev, state)) - return error; + if (pci_platform_power_transition(dev, PCI_D3cold)) + return error; - /* Powering off a bridge may power off the whole hierarchy */ - if (state == PCI_D3cold) - pci_bus_set_current_state(dev->subordinate, PCI_D3cold); + /* Powering off a bridge may power off the whole hierarchy */ + if (dev->current_state == PCI_D3cold) + pci_bus_set_current_state(dev->subordinate, PCI_D3cold); + } else { + error = pci_set_low_power_state(dev, state); + + if (pci_platform_power_transition(dev, state)) + return error; + } return 0; }