mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Loic Poulain <loic.poulain@oss.qualcomm.com>
To: "Rafael J. Wysocki" <rafael@kernel.org>,
	Pavel Machek <pavel@kernel.org>, Len Brown <lenb@kernel.org>,
	Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
	Danilo Krummrich <dakr@kernel.org>,
	Johan Hovold <johan@kernel.org>
Cc: linux-pm@vger.kernel.org, driver-core@lists.linux.dev,
	linux-kernel@vger.kernel.org,
	Loic Poulain <loic.poulain@oss.qualcomm.com>,
	Nihal Kumar Gupta <nihal.gupta@oss.qualcomm.com>
Subject: [PATCH v2 2/2] PM: clk: Release the clock prepare reference across runtime suspend
Date: Tue, 10 Nov 2026 13:01:09 +0100	[thread overview]
Message-ID: <20261110-clk-leak-v2-2-d044cf0c3f1d@oss.qualcomm.com> (raw)
In-Reply-To: <20261110-clk-leak-v2-0-d044cf0c3f1d@oss.qualcomm.com>

The PM clock layer prepares a clock at acquire time and keeps that
reference until the entry is removed, pm_clk_suspend() only dropping
the enable reference. A prepare reference propagates to the parents
though, so a clock with enable/disable ops can keep an ancestor that
only implements prepare/unprepare running for as long as the device
exists. On Qualcomm platforms this keeps the RPM XO clock active
across runtime and system suspend even though all of its consumers
are suspended.

Unprepare on suspend for devices that are not IRQ-safe, as those
suspend in process context, and let the next pm_clk_resume() prepare
the clock again. This generalises the clk_is_enabled_when_prepared()
check in pm_clk_acquire(), which only considers the clock itself and
not its parents. Most drivers managing their own clocks already
unprepare in runtime suspend: 245 call sites under drivers/ against
27 that only disable.

Reported-by: Nihal Kumar Gupta <nihal.gupta@oss.qualcomm.com>
Signed-off-by: Loic Poulain <loic.poulain@oss.qualcomm.com>
---
 drivers/base/power/clock_ops.c | 10 ++++++----
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/drivers/base/power/clock_ops.c b/drivers/base/power/clock_ops.c
index 6f66e11a12428fb718abca197f5519b1ee21ff90..43150ecb58add7783d8602d525219c676fd808fe 100644
--- a/drivers/base/power/clock_ops.c
+++ b/drivers/base/power/clock_ops.c
@@ -33,7 +33,6 @@ struct pm_clock_entry {
 	char *con_id;
 	struct clk *clk;
 	enum pce_status status;
-	bool enabled_when_prepared;
 };
 
 /**
@@ -174,9 +173,11 @@ static void pm_clk_acquire(struct device *dev, struct pm_clock_entry *ce)
 		ce->status = PCE_STATUS_ERROR;
 		return;
 	} else if (clk_is_enabled_when_prepared(ce->clk)) {
-		/* we defer preparing the clock in that case */
+		/*
+		 * Preparing the clock would also start it, so defer that to
+		 * the first pm_clk_resume().
+		 */
 		ce->status = PCE_STATUS_ACQUIRED;
-		ce->enabled_when_prepared = true;
 	} else if (clk_prepare(ce->clk)) {
 		ce->status = PCE_STATUS_ERROR;
 		dev_err(dev, "clk_prepare() failed\n");
@@ -460,6 +461,7 @@ EXPORT_SYMBOL_GPL(devm_pm_clk_create);
 int pm_clk_suspend(struct device *dev)
 {
 	struct pm_subsys_data *psd = dev_to_psd(dev);
+	bool sleepable = !pm_runtime_is_irq_safe(dev);
 	struct pm_clock_entry *ce;
 	unsigned long flags;
 
@@ -472,7 +474,7 @@ int pm_clk_suspend(struct device *dev)
 
 	list_for_each_entry_reverse(ce, &psd->clock_list, node) {
 		if (ce->status == PCE_STATUS_ENABLED) {
-			if (ce->enabled_when_prepared) {
+			if (sleepable) {
 				clk_disable_unprepare(ce->clk);
 				ce->status = PCE_STATUS_ACQUIRED;
 			} else {

-- 
2.34.1


      parent reply	other threads:[~2026-11-10 12:01 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-11-10 12:01 [PATCH v2 0/2] PM: clk: Release clocks " Loic Poulain
2026-11-10 12:01 ` [PATCH v2 1/2] PM: clk: Derive PM clock locking from the device's IRQ safety Loic Poulain
2026-11-10 12:01 ` Loic Poulain [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20261110-clk-leak-v2-2-d044cf0c3f1d@oss.qualcomm.com \
    --to=loic.poulain@oss.qualcomm.com \
    --cc=dakr@kernel.org \
    --cc=driver-core@lists.linux.dev \
    --cc=gregkh@linuxfoundation.org \
    --cc=johan@kernel.org \
    --cc=lenb@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-pm@vger.kernel.org \
    --cc=nihal.gupta@oss.qualcomm.com \
    --cc=pavel@kernel.org \
    --cc=rafael@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®