From patchwork Tue Feb 18 20:11:42 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Rafael J. Wysocki" X-Patchwork-Id: 866143 Received: from cloudserver094114.home.pl (cloudserver094114.home.pl [79.96.170.134]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B8ACD1B87F2; Tue, 18 Feb 2025 20:21:02 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=79.96.170.134 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739910065; cv=none; b=FWSV8Cd1L3PduFs01d5ig2iL75cR7gTcKVtGpkuCMMtPkPH9pUdci8SRLLvx2jA1ktbCqpMSq85eUOcBa9NMzeJw/EGKp/0WQXSSyrky8oSBfCvWCJJ9elKYTWcAcNO85beM9BBLTwqpyv7/T/UZe1qLpYyE7bzcFgs1/tknY3s= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739910065; c=relaxed/simple; bh=IAYZ73oZUjA3Og3NA7vq+SF9k6/cmTVsArqXa/W4RBg=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=sw/XK1A+puLyERqjt3M4eGFqzmuUjhCRw92kQXxprHwy2Wbkik60eiGsBkijHu7AqbRbUoScQZzvmEf+JORAqdeBYrHLSgFBd+odYRazbIZifn1xKzpuyjhm+ZySS+fwHnSsJhIY3jektrDCzse2cYzWe+SUbt0oZvAwZkDAKGE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=rjwysocki.net; spf=pass smtp.mailfrom=rjwysocki.net; dkim=pass (2048-bit key) header.d=rjwysocki.net header.i=@rjwysocki.net header.b=g7OzTkKK; arc=none smtp.client-ip=79.96.170.134 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=rjwysocki.net Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=rjwysocki.net Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=rjwysocki.net header.i=@rjwysocki.net header.b="g7OzTkKK" 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 6.2.1) id b4a096f98544a87d; Tue, 18 Feb 2025 21:20:54 +0100 Received: from kreacher.localnet (unknown [195.136.19.94]) (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 cloudserver094114.home.pl (Postfix) with ESMTPSA id 4AEB396554D; Tue, 18 Feb 2025 21:20:54 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=rjwysocki.net; s=dkim; t=1739910054; bh=IAYZ73oZUjA3Og3NA7vq+SF9k6/cmTVsArqXa/W4RBg=; h=From:Subject:Date; b=g7OzTkKKczDQpO+8x7rcbb2mDSPy8F6kHTree/aSre+R1fS3zi6ozwz2OEtVp2ZBH z0PC7t6hgKQHcvaT4jYEvCAtk5oV/RIEjM59bLMFg5IIOyDQTzn58+5BTJV5E5fxmp Hr2xYJQukpzRuuUjJMQPj5059I+ysSIzin+bXE6VsbINYA0FEcL9ijyHnIVOjbPSxk MPXirI7tSq7k9ib/MNw/OQD7wbSU2g89GKYqnVYMM5TQQeVzDu7Fl0pqpaJy3RsKXE RfldoFTZcTb54KYu2f7LHOy/LDRo3ZusanLxV5RQS2b9hmWxNynXT4SJa7AU9TSNxL IZBrFSh6R8C6A== From: "Rafael J. Wysocki" To: Linux PM Cc: LKML , Alan Stern , Bjorn Helgaas , Linux PCI , Ulf Hansson , Johan Hovold , Manivannan Sadhasivam , Jon Hunter , Linux ACPI , Mika Westerberg , Andy Shevchenko Subject: [PATCH v2 1/4] PM: Block enabling of runtime PM during system suspend Date: Tue, 18 Feb 2025 21:11:42 +0100 Message-ID: <6131109.lOV4Wx5bFT@rjwysocki.net> In-Reply-To: <12612706.O9o76ZdvQC@rjwysocki.net> References: <12612706.O9o76ZdvQC@rjwysocki.net> Precedence: bulk X-Mailing-List: linux-acpi@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-CLIENT-IP: 195.136.19.94 X-CLIENT-HOSTNAME: 195.136.19.94 X-VADE-SPAMSTATE: clean X-VADE-SPAMCAUSE: gggruggvucftvghtrhhoucdtuddrgeefvddrtddtgdeivddviecutefuodetggdotefrodftvfcurfhrohhfihhlvgemucfjqffogffrnfdpggftiffpkfenuceurghilhhouhhtmecuudehtdenucesvcftvggtihhpihgvnhhtshculddquddttddmnecujfgurhephffvvefufffkjghfggfgtgesthfuredttddtjeenucfhrhhomhepfdftrghfrggvlhculfdrucghhihsohgtkhhifdcuoehrjhifsehrjhifhihsohgtkhhirdhnvghtqeenucggtffrrghtthgvrhhnpedvffeuiedtgfdvtddugeeujedtffetteegfeekffdvfedttddtuefhgeefvdejhfenucfkphepudelhedrudefiedrudelrdelgeenucevlhhushhtvghrufhiiigvpedtnecurfgrrhgrmhepihhnvghtpeduleehrddufeeirdduledrleegpdhhvghlohepkhhrvggrtghhvghrrdhlohgtrghlnhgvthdpmhgrihhlfhhrohhmpehrjhifsehrjhifhihsohgtkhhirdhnvghtpdhnsggprhgtphhtthhopeduvddprhgtphhtthhopehlihhnuhigqdhpmhesvhhgvghrrdhkvghrnhgvlhdrohhrghdprhgtphhtthhopehlihhnuhigqdhkvghrnhgvlhesvhhgvghrrdhkvghrnhgvlhdrohhrghdprhgtphhtthhopehsthgvrhhnsehrohiflhgrnhgurdhhrghrvhgrrhgurdgvughupdhrtghpthhtohephhgvlhhgrggrsheskhgvrhhnvghlrdhorhhgpdhrtghpthhtoheplhhinhhugidqphgtihesvhhgvghrrdhkvghrnhgvlhdrohh X-DCC--Metrics: v370.home.net.pl 1024; Body=12 Fuz1=12 Fuz2=12 From: Rafael J. Wysocki If device_prepare() runs on a device that has never had runtime PM enabled so far, it may reasonably assume that runtime PM will not be enabled for that device during the system suspend-resume cycle currently in progress, but this has never been guaranteed. To verify this assumption, make device_prepare() arrange for triggering a device warning accompanied by a call trace dump if runtime PM is enabled for such a device after it has returned. Signed-off-by: Rafael J. Wysocki Reviewed-by: Ulf Hansson --- v1 -> v2: Fix a typo in a message and remove an unrelated change (Ulf). --- drivers/base/power/main.c | 9 +++++++++ drivers/base/power/runtime.c | 24 ++++++++++++++++++++++++ include/linux/pm.h | 1 + include/linux/pm_runtime.h | 4 ++++ 4 files changed, 38 insertions(+) --- a/drivers/base/power/main.c +++ b/drivers/base/power/main.c @@ -1109,6 +1109,8 @@ device_unlock(dev); out: + /* If enabling runtime PM for the device is blocked, unblock it. */ + pm_runtime_unblock(dev); pm_runtime_put(dev); } @@ -1815,6 +1817,13 @@ * it again during the complete phase. */ pm_runtime_get_noresume(dev); + /* + * If runtime PM is disabled for the device at this point and it has + * never been enabled so far, it should not be enabled until this system + * suspend-resume cycle is complete, so prepare to trigger a warning on + * subsequent attempts to enable it. + */ + pm_runtime_block_if_disabled(dev); if (dev->power.syscore) return 0; --- a/drivers/base/power/runtime.c +++ b/drivers/base/power/runtime.c @@ -1460,6 +1460,26 @@ } EXPORT_SYMBOL_GPL(pm_runtime_barrier); +void pm_runtime_block_if_disabled(struct device *dev) +{ + spin_lock_irq(&dev->power.lock); + + if (dev->power.disable_depth && dev->power.last_status == RPM_INVALID) + dev->power.last_status = RPM_BLOCKED; + + spin_unlock_irq(&dev->power.lock); +} + +void pm_runtime_unblock(struct device *dev) +{ + spin_lock_irq(&dev->power.lock); + + if (dev->power.last_status == RPM_BLOCKED) + dev->power.last_status = RPM_INVALID; + + spin_unlock_irq(&dev->power.lock); +} + void __pm_runtime_disable(struct device *dev, bool check_resume) { spin_lock_irq(&dev->power.lock); @@ -1518,6 +1538,10 @@ if (--dev->power.disable_depth > 0) goto out; + if (dev->power.last_status == RPM_BLOCKED) { + dev_warn(dev, "Attempt to enable runtime PM when it is blocked\n"); + dump_stack(); + } dev->power.last_status = RPM_INVALID; dev->power.accounting_timestamp = ktime_get_mono_fast_ns(); --- a/include/linux/pm.h +++ b/include/linux/pm.h @@ -597,6 +597,7 @@ RPM_RESUMING, RPM_SUSPENDED, RPM_SUSPENDING, + RPM_BLOCKED, }; /* --- a/include/linux/pm_runtime.h +++ b/include/linux/pm_runtime.h @@ -77,6 +77,8 @@ extern int pm_schedule_suspend(struct device *dev, unsigned int delay); extern int __pm_runtime_set_status(struct device *dev, unsigned int status); extern int pm_runtime_barrier(struct device *dev); +extern void pm_runtime_block_if_disabled(struct device *dev); +extern void pm_runtime_unblock(struct device *dev); extern void pm_runtime_enable(struct device *dev); extern void __pm_runtime_disable(struct device *dev, bool check_resume); extern void pm_runtime_allow(struct device *dev); @@ -271,6 +273,8 @@ static inline int __pm_runtime_set_status(struct device *dev, unsigned int status) { return 0; } static inline int pm_runtime_barrier(struct device *dev) { return 0; } +static inline void pm_runtime_block_if_disabled(struct device *dev) {} +static inline void pm_runtime_unblock(struct device *dev) {} static inline void pm_runtime_enable(struct device *dev) {} static inline void __pm_runtime_disable(struct device *dev, bool c) {} static inline void pm_runtime_allow(struct device *dev) {} From patchwork Tue Feb 18 20:13:09 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Rafael J. Wysocki" X-Patchwork-Id: 866478 Received: from cloudserver094114.home.pl (cloudserver094114.home.pl [79.96.170.134]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 326E121B9E1; Tue, 18 Feb 2025 20:21:01 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=79.96.170.134 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739910064; cv=none; b=WJz2HvZl4cYclZOERrAbtdTd21DviXYn0aASDM4k3LKshiyMF3JFe6HN7V/ntxWnSDDxr6NAkW41cYCjNgRzXeQKtelMLep9u4gWQD32lq//b9+znb1t0QWizHhxUXfgZci2V+jDkcRa0KeMrqOUgNzLiRmaFkEP4oxKP+vh1vY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739910064; c=relaxed/simple; bh=ehbbhur3xJOIzDNh17ILpSUkzLXRzagOxKu96FYhXDg=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=j5Oj4EGWDwO0uZysP1tqQIf1J9ovnDmFNObjYHZLs6PIuvLcAJEE0Dwnnjd+mlABKVt/Ur/yyhzi/xbRG+JdO//vUinuff/G82CnJo3A+d73SRnOKk4MnKzQrTfqq+JgDYBR1VGqD4/vFn2vcSICzWnCroo7LFoJPJpE4tZjtI4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=rjwysocki.net; spf=pass smtp.mailfrom=rjwysocki.net; dkim=pass (2048-bit key) header.d=rjwysocki.net header.i=@rjwysocki.net header.b=GYhb5TsL; arc=none smtp.client-ip=79.96.170.134 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=rjwysocki.net Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=rjwysocki.net Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=rjwysocki.net header.i=@rjwysocki.net header.b="GYhb5TsL" 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 6.2.1) id dd35bb12e63d55d5; Tue, 18 Feb 2025 21:20:54 +0100 Received: from kreacher.localnet (unknown [195.136.19.94]) (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 cloudserver094114.home.pl (Postfix) with ESMTPSA id 70AD496554D; Tue, 18 Feb 2025 21:20:53 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=rjwysocki.net; s=dkim; t=1739910054; bh=ehbbhur3xJOIzDNh17ILpSUkzLXRzagOxKu96FYhXDg=; h=From:Subject:Date; b=GYhb5TsLajwqp67HlS8mIaGrrupbIWs8tFGXBXvjlVFMolipIubG11CsMR10QjRSH mD49f38fo80Hek1yrCqQ/+k6f+FSg4hcW2ThalqiuuJcIHCRep0csnRCBh4Dg2knk1 X7NM/NG9cYkWvR2HsAZRfrOzytExNfLPTzcr/dPOfheZkPe4gpkj1IWeC+z5z30Bxp J99Ps+YdXfeSkshj+dogNYfLkF7+DC9p/l9/FFG1tdBMdmaiepyuF0Ddmy+297La58 kQ58qvjfje+2D3jCnYaKDXmtymfJJhJhSpPlhd/rtoAOroLiXpbsLZNTR+3NtYkQcA A+xr7OKHvqK1A== From: "Rafael J. Wysocki" To: Linux PM Cc: LKML , Alan Stern , Bjorn Helgaas , Linux PCI , Ulf Hansson , Johan Hovold , Manivannan Sadhasivam , Jon Hunter , Linux ACPI , Mika Westerberg , Andy Shevchenko Subject: [PATCH v2 2/4] PM: runtime: Introduce pm_runtime_blocked() Date: Tue, 18 Feb 2025 21:13:09 +0100 Message-ID: <4632087.LvFx2qVVIh@rjwysocki.net> In-Reply-To: <12612706.O9o76ZdvQC@rjwysocki.net> References: <12612706.O9o76ZdvQC@rjwysocki.net> Precedence: bulk X-Mailing-List: linux-acpi@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-CLIENT-IP: 195.136.19.94 X-CLIENT-HOSTNAME: 195.136.19.94 X-VADE-SPAMSTATE: clean X-VADE-SPAMCAUSE: gggruggvucftvghtrhhoucdtuddrgeefvddrtddtgdeivddviecutefuodetggdotefrodftvfcurfhrohhfihhlvgemucfjqffogffrnfdpggftiffpkfenuceurghilhhouhhtmecuudehtdenucesvcftvggtihhpihgvnhhtshculddquddttddmnecujfgurhephffvvefufffkjghfggfgtgesthfuredttddtjeenucfhrhhomhepfdftrghfrggvlhculfdrucghhihsohgtkhhifdcuoehrjhifsehrjhifhihsohgtkhhirdhnvghtqeenucggtffrrghtthgvrhhnpedvffeuiedtgfdvtddugeeujedtffetteegfeekffdvfedttddtuefhgeefvdejhfenucfkphepudelhedrudefiedrudelrdelgeenucevlhhushhtvghrufhiiigvpedtnecurfgrrhgrmhepihhnvghtpeduleehrddufeeirdduledrleegpdhhvghlohepkhhrvggrtghhvghrrdhlohgtrghlnhgvthdpmhgrihhlfhhrohhmpehrjhifsehrjhifhihsohgtkhhirdhnvghtpdhnsggprhgtphhtthhopeduvddprhgtphhtthhopehlihhnuhigqdhpmhesvhhgvghrrdhkvghrnhgvlhdrohhrghdprhgtphhtthhopehlihhnuhigqdhkvghrnhgvlhesvhhgvghrrdhkvghrnhgvlhdrohhrghdprhgtphhtthhopehsthgvrhhnsehrohiflhgrnhgurdhhrghrvhgrrhgurdgvughupdhrtghpthhtohephhgvlhhgrggrsheskhgvrhhnvghlrdhorhhgpdhrtghpthhtoheplhhinhhugidqphgtihesvhhgvghrrdhkvghrnhgvlhdrohh X-DCC--Metrics: v370.home.net.pl 1024; Body=12 Fuz1=12 Fuz2=12 From: Rafael J. Wysocki Introduce a new helper function called pm_runtime_blocked() for checking the power.last_status value indicating whether or not enabling runtime PM for the given device has been blocked (which happens in the "prepare" phase of system-wide suspend if runtime PM is disabled for the given device at that point). Signed-off-by: Rafael J. Wysocki Reviewed-by: Ulf Hansson --- v1 -> v2: Add the R-by, no other changes. --- drivers/base/power/runtime.c | 17 +++++++++++++++++ include/linux/pm_runtime.h | 2 ++ 2 files changed, 19 insertions(+) --- a/drivers/base/power/runtime.c +++ b/drivers/base/power/runtime.c @@ -1555,6 +1555,23 @@ } EXPORT_SYMBOL_GPL(pm_runtime_enable); +bool pm_runtime_blocked(struct device *dev) +{ + bool ret; + + /* + * dev->power.last_status is a bit field, so in case it is updated via + * RMW, read it under the spin lock. + */ + spin_lock_irq(&dev->power.lock); + + ret = dev->power.last_status == RPM_BLOCKED; + + spin_unlock_irq(&dev->power.lock); + + return ret; +} + static void pm_runtime_disable_action(void *data) { pm_runtime_dont_use_autosuspend(data); --- a/include/linux/pm_runtime.h +++ b/include/linux/pm_runtime.h @@ -81,6 +81,7 @@ extern void pm_runtime_unblock(struct device *dev); extern void pm_runtime_enable(struct device *dev); extern void __pm_runtime_disable(struct device *dev, bool check_resume); +extern bool pm_runtime_blocked(struct device *dev); extern void pm_runtime_allow(struct device *dev); extern void pm_runtime_forbid(struct device *dev); extern void pm_runtime_no_callbacks(struct device *dev); @@ -277,6 +278,7 @@ static inline void pm_runtime_unblock(struct device *dev) {} static inline void pm_runtime_enable(struct device *dev) {} static inline void __pm_runtime_disable(struct device *dev, bool c) {} +static inline bool pm_runtime_blocked(struct device *dev) { return true; } static inline void pm_runtime_allow(struct device *dev) {} static inline void pm_runtime_forbid(struct device *dev) {} From patchwork Tue Feb 18 20:16:48 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Rafael J. Wysocki" X-Patchwork-Id: 866144 Received: from cloudserver094114.home.pl (cloudserver094114.home.pl [79.96.170.134]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 0DE8A1B87EB; Tue, 18 Feb 2025 20:21:00 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=79.96.170.134 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739910064; cv=none; b=DIbrHWJb7kP4UJzt+uukzfiy9SO9w7hraSQhtDJ73PCckGXeTx8Nq0YdPTUHyBYzLNqV+pUfAM7hyXPs6OGmLZc9r4IlbUBR4JrURt+X8gSkQAqPXl8qEWww8/chaggc2lc3g081Mp28rpvYVlvgtX2/Q8G4jFArFqbTme49P70= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739910064; c=relaxed/simple; bh=UWFsr3S0ZAgFS9MM5N1gmI7f6CQaZdj255B5JhS38vA=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=O/ZSlCxYOV1gsN7q29lKa1IMZzYxUYUokbAvmPXLO/OCjblSQ1Hd/KsqmU/nJyoutaSNSLRiHVfe8lwgfcwcOrRyi60BLYKqS2ZVmmL4rvrKObjEM37SNKfya9Z//OUk2N4UejyB10cc+bBHQwmIDVe63YlIqt23n3SjzB4EXc4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=rjwysocki.net; spf=pass smtp.mailfrom=rjwysocki.net; dkim=pass (2048-bit key) header.d=rjwysocki.net header.i=@rjwysocki.net header.b=DPriTzos; arc=none smtp.client-ip=79.96.170.134 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=rjwysocki.net Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=rjwysocki.net Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=rjwysocki.net header.i=@rjwysocki.net header.b="DPriTzos" 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 6.2.1) id 94f45c07a1466cf7; Tue, 18 Feb 2025 21:20:53 +0100 Received: from kreacher.localnet (unknown [195.136.19.94]) (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 cloudserver094114.home.pl (Postfix) with ESMTPSA id 8243996554D; Tue, 18 Feb 2025 21:20:52 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=rjwysocki.net; s=dkim; t=1739910053; bh=UWFsr3S0ZAgFS9MM5N1gmI7f6CQaZdj255B5JhS38vA=; h=From:Subject:Date; b=DPriTzosChgGQHpRb1su/rfJv5R61RicnUG8ClheZYbArXGTpjFeT8ywm+IVaFnRj I2p/ErygndMJU9uaTMOiZcCfUrLVl9hCfm5DUG1btOOjeHyCSrX3wneDCfyvF77Got gzarq64qOawW9tUrgedIseETMdCirsM6UcnJkqvWAHfTwtDVS9eRTp1xqvhj2XJRgt imToXamddZfpulfOOBXcW1PTje3B92yy3fQehWea2IO0MTJQUPr39FAQq+Gi7u1/HV spp8BQVUrobjF/mOPZK7vmFxnMd7KDeaLz8aOvY8zfKLl1x/A9yGe3xBmANVLDzctF QT2hj3igMOLUQ== From: "Rafael J. Wysocki" To: Linux PM Cc: LKML , Alan Stern , Bjorn Helgaas , Linux PCI , Ulf Hansson , Johan Hovold , Manivannan Sadhasivam , Jon Hunter , Linux ACPI , Mika Westerberg , Andy Shevchenko Subject: [PATCH v2 3/4] PM: sleep: Use DPM_FLAG_SMART_SUSPEND conditionally Date: Tue, 18 Feb 2025 21:16:48 +0100 Message-ID: <1914558.tdWV9SEqCh@rjwysocki.net> In-Reply-To: <12612706.O9o76ZdvQC@rjwysocki.net> References: <12612706.O9o76ZdvQC@rjwysocki.net> Precedence: bulk X-Mailing-List: linux-acpi@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-CLIENT-IP: 195.136.19.94 X-CLIENT-HOSTNAME: 195.136.19.94 X-VADE-SPAMSTATE: clean X-VADE-SPAMCAUSE: gggruggvucftvghtrhhoucdtuddrgeefvddrtddtgdeivddviecutefuodetggdotefrodftvfcurfhrohhfihhlvgemucfjqffogffrnfdpggftiffpkfenuceurghilhhouhhtmecuudehtdenucesvcftvggtihhpihgvnhhtshculddquddttddmnecujfgurhephffvvefufffkjghfggfgtgesthfuredttddtjeenucfhrhhomhepfdftrghfrggvlhculfdrucghhihsohgtkhhifdcuoehrjhifsehrjhifhihsohgtkhhirdhnvghtqeenucggtffrrghtthgvrhhnpeefudduuedtuefgleffudeigeeitdeufeelvdejgefftdethffhhfethfeljefgteenucffohhmrghinhepkhgvrhhnvghlrdhorhhgnecukfhppeduleehrddufeeirdduledrleegnecuvehluhhsthgvrhfuihiivgeptdenucfrrghrrghmpehinhgvthepudelhedrudefiedrudelrdelgedphhgvlhhopehkrhgvrggthhgvrhdrlhhotggrlhhnvghtpdhmrghilhhfrhhomheprhhjfiesrhhjfiihshhotghkihdrnhgvthdpnhgspghrtghpthhtohepuddvpdhrtghpthhtoheplhhinhhugidqphhmsehvghgvrhdrkhgvrhhnvghlrdhorhhgpdhrtghpthhtoheplhhinhhugidqkhgvrhhnvghlsehvghgvrhdrkhgvrhhnvghlrdhorhhgpdhrtghpthhtohepshhtvghrnhesrhhofihlrghnugdrhhgrrhhvrghrugdrvgguuhdprhgtphhtthhopehhvghlghgrrghssehkvghrnhgvlhdrohhrghdprhgtphhtthhopehlihhnuhi X-DCC--Metrics: v370.home.net.pl 1024; Body=12 Fuz1=12 Fuz2=12 From: Rafael J. Wysocki A recent discussion has revealed that using DPM_FLAG_SMART_SUSPEND unconditionally is generally problematic because it may lead to situations in which the device's runtime PM information is internally inconsistent or does not reflect its real state [1]. For this reason, change the handling of DPM_FLAG_SMART_SUSPEND so that it is only taken into account if it is consistently set by the drivers of all devices having any PM callbacks throughout dependency graphs in accordance with the following rules: - The "smart suspend" feature is only enabled for devices whose drivers ask for it (that is, set DPM_FLAG_SMART_SUSPEND) and for devices without PM callbacks unless they have never had runtime PM enabled. - The "smart suspend" feature is not enabled for a device if it has not been enabled for the device's parent unless the parent does not take children into account or it has never had runtime PM enabled. - The "smart suspend" feature is not enabled for a device if it has not been enabled for one of the device's suppliers taking runtime PM into account unless that supplier has never had runtime PM enabled. Namely, introduce a new device PM flag called smart_suspend that is only set if the above conditions are met and update all DPM_FLAG_SMART_SUSPEND users to check power.smart_suspend instead of directly checking the latter. At the same time, drop the power.set_active flage introduced recently in commit 3775fc538f53 ("PM: sleep: core: Synchronize runtime PM status of parents and children") because it is now sufficient to check power.smart_suspend along with the dev_pm_skip_resume() return value to decide whether or not pm_runtime_set_active() needs to be called for the device. Link: https://lore.kernel.org/linux-pm/CAPDyKFroyU3YDSfw_Y6k3giVfajg3NQGwNWeteJWqpW29BojhQ@mail.gmail.com/ [1] Fixes: 7585946243d6 ("PM: sleep: core: Restrict power.set_active propagation") Signed-off-by: Rafael J. Wysocki Reviewed-by: Ulf Hansson --- v1 -> v2: * Add helper function for reading power.smart_suspend() (Ulf), add the R-by. * Rearrange conditionals in device_prepare_smart_suspend() so that the checks involving locking are done last. --- drivers/acpi/device_pm.c | 4 +- drivers/base/power/main.c | 63 +++++++++++++++++++++++++++++++++++----------- drivers/mfd/intel-lpss.c | 2 - drivers/pci/pci-driver.c | 6 +--- include/linux/device.h | 5 +++ include/linux/pm.h | 2 - 6 files changed, 60 insertions(+), 22 deletions(-) --- a/drivers/acpi/device_pm.c +++ b/drivers/acpi/device_pm.c @@ -1161,7 +1161,7 @@ */ int acpi_subsys_suspend(struct device *dev) { - if (!dev_pm_test_driver_flags(dev, DPM_FLAG_SMART_SUSPEND) || + if (!dev_pm_smart_suspend(dev) || acpi_dev_needs_resume(dev, ACPI_COMPANION(dev))) pm_runtime_resume(dev); @@ -1320,7 +1320,7 @@ */ int acpi_subsys_poweroff(struct device *dev) { - if (!dev_pm_test_driver_flags(dev, DPM_FLAG_SMART_SUSPEND) || + if (!dev_pm_smart_suspend(dev) || acpi_dev_needs_resume(dev, ACPI_COMPANION(dev))) pm_runtime_resume(dev); --- a/drivers/base/power/main.c +++ b/drivers/base/power/main.c @@ -656,15 +656,13 @@ * so change its status accordingly. * * Otherwise, the device is going to be resumed, so set its PM-runtime - * status to "active" unless its power.set_active flag is clear, in + * status to "active" unless its power.smart_suspend flag is clear, in * which case it is not necessary to update its PM-runtime status. */ - if (skip_resume) { + if (skip_resume) pm_runtime_set_suspended(dev); - } else if (dev->power.set_active) { + else if (dev_pm_smart_suspend(dev)) pm_runtime_set_active(dev); - dev->power.set_active = false; - } if (dev->pm_domain) { info = "noirq power domain "; @@ -1282,14 +1280,8 @@ dev->power.may_skip_resume)) dev->power.must_resume = true; - if (dev->power.must_resume) { - if (dev_pm_test_driver_flags(dev, DPM_FLAG_SMART_SUSPEND)) { - dev->power.set_active = true; - if (dev->parent && !dev->parent->power.ignore_children) - dev->parent->power.set_active = true; - } + if (dev->power.must_resume) dpm_superior_set_must_resume(dev); - } Complete: complete_all(&dev->power.completion); @@ -1797,6 +1789,49 @@ return error; } +static void device_prepare_smart_suspend(struct device *dev) +{ + struct device_link *link; + int idx; + + /* + * The "smart suspend" feature is enabled for devices whose drivers ask + * for it and for devices without PM callbacks unless runtime PM is + * disabled and enabling it is blocked for them. + * + * However, if "smart suspend" is not enabled for the device's parent + * or any of its suppliers that take runtime PM into account, it cannot + * be enabled for the device either. + */ + dev->power.smart_suspend = (dev->power.no_pm_callbacks || + dev_pm_test_driver_flags(dev, DPM_FLAG_SMART_SUSPEND)) && + !pm_runtime_blocked(dev); + + if (!dev_pm_smart_suspend(dev)) + return; + + if (dev->parent && !dev_pm_smart_suspend(dev->parent) && + !dev->parent->power.ignore_children && !pm_runtime_blocked(dev->parent)) { + dev->power.smart_suspend = false; + return; + } + + idx = device_links_read_lock(); + + list_for_each_entry_rcu_locked(link, &dev->links.suppliers, c_node) { + if (!(link->flags | DL_FLAG_PM_RUNTIME)) + continue; + + if (!dev_pm_smart_suspend(link->supplier) && + !pm_runtime_blocked(link->supplier)) { + dev->power.smart_suspend = false; + break; + } + } + + device_links_read_unlock(idx); +} + /** * device_prepare - Prepare a device for system power transition. * @dev: Device to handle. @@ -1858,6 +1893,7 @@ pm_runtime_put(dev); return ret; } + device_prepare_smart_suspend(dev); /* * A positive return value from ->prepare() means "this device appears * to be runtime-suspended and its state is fine, so if it really is @@ -2033,6 +2069,5 @@ bool dev_pm_skip_suspend(struct device *dev) { - return dev_pm_test_driver_flags(dev, DPM_FLAG_SMART_SUSPEND) && - pm_runtime_status_suspended(dev); + return dev_pm_smart_suspend(dev) && pm_runtime_status_suspended(dev); } --- a/drivers/mfd/intel-lpss.c +++ b/drivers/mfd/intel-lpss.c @@ -480,7 +480,7 @@ static int resume_lpss_device(struct device *dev, void *data) { - if (!dev_pm_test_driver_flags(dev, DPM_FLAG_SMART_SUSPEND)) + if (!dev_pm_smart_suspend(dev)) pm_runtime_resume(dev); return 0; --- a/drivers/pci/pci-driver.c +++ b/drivers/pci/pci-driver.c @@ -812,8 +812,7 @@ * suspend callbacks can cope with runtime-suspended devices, it is * better to resume the device from runtime suspend here. */ - if (!dev_pm_test_driver_flags(dev, DPM_FLAG_SMART_SUSPEND) || - pci_dev_need_resume(pci_dev)) { + if (!dev_pm_smart_suspend(dev) || pci_dev_need_resume(pci_dev)) { pm_runtime_resume(dev); pci_dev->state_saved = false; } else { @@ -1151,8 +1150,7 @@ } /* The reason to do that is the same as in pci_pm_suspend(). */ - if (!dev_pm_test_driver_flags(dev, DPM_FLAG_SMART_SUSPEND) || - pci_dev_need_resume(pci_dev)) { + if (!dev_pm_smart_suspend(dev) || pci_dev_need_resume(pci_dev)) { pm_runtime_resume(dev); pci_dev->state_saved = false; } else { --- a/include/linux/device.h +++ b/include/linux/device.h @@ -1025,6 +1025,11 @@ return !!(dev->power.driver_flags & flags); } +static inline bool dev_pm_smart_suspend(struct device *dev) +{ + return dev->power.smart_suspend; +} + static inline void device_lock(struct device *dev) { mutex_lock(&dev->mutex); --- a/include/linux/pm.h +++ b/include/linux/pm.h @@ -680,8 +680,8 @@ bool syscore:1; bool no_pm_callbacks:1; /* Owned by the PM core */ bool async_in_progress:1; /* Owned by the PM core */ + bool smart_suspend:1; /* Owned by the PM core */ bool must_resume:1; /* Owned by the PM core */ - bool set_active:1; /* Owned by the PM core */ bool may_skip_resume:1; /* Set by subsystems */ #else bool should_wakeup:1; From patchwork Tue Feb 18 20:20:46 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Rafael J. Wysocki" X-Patchwork-Id: 866479 Received: from cloudserver094114.home.pl (cloudserver094114.home.pl [79.96.170.134]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 049BB21B9E0; Tue, 18 Feb 2025 20:20:59 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=79.96.170.134 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739910064; cv=none; b=Zu5p1FXzXPL1ITlUbynDzFV4OmZn+fE64pqD2AWYgn3x3TvbaC8yD4S/Uo99ho9SO74GN5zRNyqSXTAzsqR5YMovmxAijbNBxZnIUVP771P3ohEeXnJdTDaMAkN32BGxEEhThQrEK7gbpxhfYMnv5Uy1L1DCkiLxScFKdqaJaAc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739910064; c=relaxed/simple; bh=Mi0yeJ0NG7Wggqky6pV4DEQsB94EDemrjJ+/gmx9XZY=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=s+BC+pqoZLUA4Pdwh9vW0b5ZBuHO8racwE/PaegqrhhVEu3a2VOLqxt3gkkBwVdKZV67WnSxn0qosY7bxjj+oHm9KIR/Ua180A+KfFRjK9BODVD3FiX6y0jvjDqXr7/cPKlnuVQ4CVUhhdah7e2Bx/svfsbk7ptp8pdsF9H1GmI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=rjwysocki.net; spf=pass smtp.mailfrom=rjwysocki.net; dkim=pass (2048-bit key) header.d=rjwysocki.net header.i=@rjwysocki.net header.b=H4334Tr1; arc=none smtp.client-ip=79.96.170.134 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=rjwysocki.net Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=rjwysocki.net Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=rjwysocki.net header.i=@rjwysocki.net header.b="H4334Tr1" 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 6.2.1) id 4976fd652ffeded7; Tue, 18 Feb 2025 21:20:52 +0100 Received: from kreacher.localnet (unknown [195.136.19.94]) (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 cloudserver094114.home.pl (Postfix) with ESMTPSA id 8283696554D; Tue, 18 Feb 2025 21:20:51 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=rjwysocki.net; s=dkim; t=1739910052; bh=Mi0yeJ0NG7Wggqky6pV4DEQsB94EDemrjJ+/gmx9XZY=; h=From:Subject:Date; b=H4334Tr1mb6uz+bPzXNEwdkp3mwIlrK0St12WEBqEIygqXylgoeXIPeGgmQBfDTE1 EIS/mbwrd8cfnzaJZcYvA8SBCluludgvAZxPJoB/JH3MMGPmvvfOejxysg8aB0Ri8G jRhnCQorZkjzZ99NFmNsXPEiLXomoQvkXkKJMNmjVP4ISlohMA0zlxvagtt+6BLv36 vVfL9j3w4mE88vBnXjmYnkYwYekEfAaGGCQm0pjcTMysZATXWwM7Bs1AvsXsYLwyPd bMLRp9Bj6+y53eZFT0iR6lscDgwB3BkdkPIURxU8uat1J9c665xMhscsFBOnGtsHN4 gQwlJjmucMJJg== From: "Rafael J. Wysocki" To: Linux PM Cc: LKML , Alan Stern , Bjorn Helgaas , Linux PCI , Ulf Hansson , Johan Hovold , Manivannan Sadhasivam , Jon Hunter , Linux ACPI , Mika Westerberg , Andy Shevchenko Subject: [PATCH v2 4/4] PM: sleep: Avoid unnecessary checks in device_prepare_smart_suspend() Date: Tue, 18 Feb 2025 21:20:46 +0100 Message-ID: <2978873.e9J7NaK4W3@rjwysocki.net> In-Reply-To: <12612706.O9o76ZdvQC@rjwysocki.net> References: <12612706.O9o76ZdvQC@rjwysocki.net> Precedence: bulk X-Mailing-List: linux-acpi@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-CLIENT-IP: 195.136.19.94 X-CLIENT-HOSTNAME: 195.136.19.94 X-VADE-SPAMSTATE: clean X-VADE-SPAMCAUSE: gggruggvucftvghtrhhoucdtuddrgeefvddrtddtgdeivddviecutefuodetggdotefrodftvfcurfhrohhfihhlvgemucfjqffogffrnfdpggftiffpkfenuceurghilhhouhhtmecuudehtdenucesvcftvggtihhpihgvnhhtshculddquddttddmnecujfgurhephffvvefufffkjghfggfgtgesthfuredttddtjeenucfhrhhomhepfdftrghfrggvlhculfdrucghhihsohgtkhhifdcuoehrjhifsehrjhifhihsohgtkhhirdhnvghtqeenucggtffrrghtthgvrhhnpedvffeuiedtgfdvtddugeeujedtffetteegfeekffdvfedttddtuefhgeefvdejhfenucfkphepudelhedrudefiedrudelrdelgeenucevlhhushhtvghrufhiiigvpedtnecurfgrrhgrmhepihhnvghtpeduleehrddufeeirdduledrleegpdhhvghlohepkhhrvggrtghhvghrrdhlohgtrghlnhgvthdpmhgrihhlfhhrohhmpehrjhifsehrjhifhihsohgtkhhirdhnvghtpdhnsggprhgtphhtthhopeduvddprhgtphhtthhopehlihhnuhigqdhpmhesvhhgvghrrdhkvghrnhgvlhdrohhrghdprhgtphhtthhopehlihhnuhigqdhkvghrnhgvlhesvhhgvghrrdhkvghrnhgvlhdrohhrghdprhgtphhtthhopehsthgvrhhnsehrohiflhgrnhgurdhhrghrvhgrrhgurdgvughupdhrtghpthhtohephhgvlhhgrggrsheskhgvrhhnvghlrdhorhhgpdhrtghpthhtoheplhhinhhugidqphgtihesvhhgvghrrdhkvghrnhgvlhdrohh X-DCC--Metrics: v370.home.net.pl 1024; Body=12 Fuz1=12 Fuz2=12 From: Rafael J. Wysocki Add an optimization (on top of previous changes) to avoid calling pm_runtime_blocked(), which involves acquiring the device's PM spinlock, for devices with no PM callbacks and runtime PM "blocked". Signed-off-by: Rafael J. Wysocki --- drivers/base/power/main.c | 16 +++++++++------- drivers/base/power/runtime.c | 9 +++++++-- include/linux/pm_runtime.h | 4 ++-- 3 files changed, 18 insertions(+), 11 deletions(-) --- a/drivers/base/power/main.c +++ b/drivers/base/power/main.c @@ -1796,16 +1796,14 @@ /* * The "smart suspend" feature is enabled for devices whose drivers ask - * for it and for devices without PM callbacks unless runtime PM is - * disabled and enabling it is blocked for them. + * for it and for devices without PM callbacks. * * However, if "smart suspend" is not enabled for the device's parent * or any of its suppliers that take runtime PM into account, it cannot * be enabled for the device either. */ - dev->power.smart_suspend = (dev->power.no_pm_callbacks || - dev_pm_test_driver_flags(dev, DPM_FLAG_SMART_SUSPEND)) && - !pm_runtime_blocked(dev); + dev->power.smart_suspend = dev->power.no_pm_callbacks || + dev_pm_test_driver_flags(dev, DPM_FLAG_SMART_SUSPEND); if (!dev_pm_smart_suspend(dev)) return; @@ -1843,6 +1841,7 @@ static int device_prepare(struct device *dev, pm_message_t state) { int (*callback)(struct device *) = NULL; + bool no_runtime_pm; int ret = 0; /* @@ -1858,7 +1857,7 @@ * suspend-resume cycle is complete, so prepare to trigger a warning on * subsequent attempts to enable it. */ - pm_runtime_block_if_disabled(dev); + no_runtime_pm = pm_runtime_block_if_disabled(dev); if (dev->power.syscore) return 0; @@ -1893,7 +1892,10 @@ pm_runtime_put(dev); return ret; } - device_prepare_smart_suspend(dev); + /* Do not enable "smart suspend" for devices without runtime PM. */ + if (!no_runtime_pm) + device_prepare_smart_suspend(dev); + /* * A positive return value from ->prepare() means "this device appears * to be runtime-suspended and its state is fine, so if it really is --- a/drivers/base/power/runtime.c +++ b/drivers/base/power/runtime.c @@ -1460,14 +1460,19 @@ } EXPORT_SYMBOL_GPL(pm_runtime_barrier); -void pm_runtime_block_if_disabled(struct device *dev) +bool pm_runtime_block_if_disabled(struct device *dev) { + bool ret; + spin_lock_irq(&dev->power.lock); - if (dev->power.disable_depth && dev->power.last_status == RPM_INVALID) + ret = dev->power.disable_depth && dev->power.last_status == RPM_INVALID; + if (ret) dev->power.last_status = RPM_BLOCKED; spin_unlock_irq(&dev->power.lock); + + return ret; } void pm_runtime_unblock(struct device *dev) --- a/include/linux/pm_runtime.h +++ b/include/linux/pm_runtime.h @@ -77,7 +77,7 @@ extern int pm_schedule_suspend(struct device *dev, unsigned int delay); extern int __pm_runtime_set_status(struct device *dev, unsigned int status); extern int pm_runtime_barrier(struct device *dev); -extern void pm_runtime_block_if_disabled(struct device *dev); +extern bool pm_runtime_block_if_disabled(struct device *dev); extern void pm_runtime_unblock(struct device *dev); extern void pm_runtime_enable(struct device *dev); extern void __pm_runtime_disable(struct device *dev, bool check_resume); @@ -274,7 +274,7 @@ static inline int __pm_runtime_set_status(struct device *dev, unsigned int status) { return 0; } static inline int pm_runtime_barrier(struct device *dev) { return 0; } -static inline void pm_runtime_block_if_disabled(struct device *dev) {} +static inline bool pm_runtime_block_if_disabled(struct device *dev) { return true; } static inline void pm_runtime_unblock(struct device *dev) {} static inline void pm_runtime_enable(struct device *dev) {} static inline void __pm_runtime_disable(struct device *dev, bool c) {}