Linux kernel -stable discussions
 help / color / mirror / Atom feed
From: Sasha Levin <sashal@kernel.org>
To: patches@lists.linux.dev, stable@vger.kernel.org
Cc: Charan Teja Kalla <quic_charante@quicinc.com>,
	Patrick Daly <quic_pdaly@quicinc.com>,
	"Rafael J . Wysocki" <rafael.j.wysocki@intel.com>,
	Sasha Levin <sashal@kernel.org>,
	rjw@rjwysocki.net, len.brown@intel.com, pavel@ucw.cz,
	gregkh@linuxfoundation.org, linux-pm@vger.kernel.org,
	linux-kernel@vger.kernel.org
Subject: [PATCH AUTOSEL 6.12 23/26] PM: runtime: fix denying of auto suspend in pm_suspend_timer_fn()
Date: Fri, 30 May 2025 08:40:09 -0400	[thread overview]
Message-ID: <20250530124012.2575409-23-sashal@kernel.org> (raw)
In-Reply-To: <20250530124012.2575409-1-sashal@kernel.org>

From: Charan Teja Kalla <quic_charante@quicinc.com>

[ Upstream commit 40d3b40dce375d6f1c1dbf08d79eed3aed6c691d ]

pm_runtime_put_autosuspend() schedules a hrtimer to expire
at "dev->power.timer_expires". If the hrtimer's callback,
pm_suspend_timer_fn(), observes that the current time equals
"dev->power.timer_expires", it unexpectedly bails out instead of
proceeding with runtime suspend.

pm_suspend_timer_fn():

 if (expires > 0 && expires < ktime_get_mono_fast_ns()) {
 	dev->power.timer_expires = 0;
 	rpm_suspend(..)
 }

Additionally, as ->timer_expires is not cleared, all the future auto
suspend requests will not schedule hrtimer to perform auto suspend.

rpm_suspend():

 if ((rpmflags & RPM_AUTO) &&...) {
 	if (!(dev->power.timer_expires && ...) { <-- this will fail.
 		hrtimer_start_range_ns(&dev->power.suspend_timer,...);
 	}
 }

Fix this by as well checking if current time reaches the set expiration.

Co-developed-by: Patrick Daly <quic_pdaly@quicinc.com>
Signed-off-by: Patrick Daly <quic_pdaly@quicinc.com>
Signed-off-by: Charan Teja Kalla <quic_charante@quicinc.com>
Link: https://patch.msgid.link/20250515064125.1211561-1-quic_charante@quicinc.com
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---

Now, based on my analysis, let me provide the decision: **YES** This
commit should be backported to stable kernel trees. Here's my extensive
analysis: ## Bug Analysis This is a clear **logical bug fix** in the PM
runtime autosuspend mechanism that affects device power management. The
issue is in the `pm_suspend_timer_fn()` function at
`drivers/base/power/runtime.c:1006`. ## The Problem The current code
uses a strict less-than comparison: ```c if (expires > 0 && expires <
ktime_get_mono_fast_ns()) { ``` However, this creates a race condition
where: 1. When `pm_runtime_put_autosuspend()` schedules an hrtimer to
expire at exactly `dev->power.timer_expires` 2. If the timer callback
`pm_suspend_timer_fn()` observes that the current time **equals**
`dev->power.timer_expires` (not less than), it incorrectly bails out 3.
The timer expires but the device is not suspended 4. Since
`timer_expires` is not cleared, all future auto-suspend requests fail
because the condition `if (!(dev->power.timer_expires && ...))` in
`rpm_suspend()` (line 596-597) will always be false ## The Fix The fix
correctly changes the comparison to `<=` (less than or equal): ```c if
(expires > 0 && expires <= ktime_get_mono_fast_ns()) { ``` This ensures
that the suspend is triggered when the current time equals or exceeds
the expiration time. ## Why This Should Be Backported 1. **Fixes a Real
User-Affecting Bug**: Devices may fail to auto-suspend, leading to
increased power consumption and potential battery drain on mobile
devices. 2. **Minimal Risk**: This is a one-character change (`<` to
`<=`) that fixes a clear logical error. The change is extremely
contained and low-risk. 3. **Critical Subsystem**: PM runtime is a
critical kernel subsystem affecting all device power management. A
failure here can impact system-wide power efficiency. 4. **No
Architectural Changes**: This doesn't introduce new features or change
architecture - it simply fixes incorrect logic. 5. **Small and
Contained**: The fix is confined to a single comparison operator in one
function. 6. **Clear Co-authors**: The commit shows collaboration
between Patrick Daly and Charan Teja Kalla from Qualcomm, indicating
this was found in real-world usage. ## Comparison with Similar Commits
Looking at the historical examples: - **Similar Commit #5 (Status:
YES)**: Also a PM runtime timer fix with data type correction - this had
similar characteristics and was backported - The current commit follows
the same pattern: critical PM runtime bug fix with minimal, contained
changes ## Stable Tree Criteria Met - ✅ Fixes important bug affecting
users - ✅ Relatively small and contained fix - ✅ No clear side effects
beyond fixing the issue - ✅ No major architectural changes - ✅ Touches
critical kernel subsystem (appropriately) - ✅ Follows stable tree rules
(important bugfix, minimal risk) - ✅ Has clear explanation of the
problem and solution This commit perfectly fits the stable backport
criteria and should be included in stable kernel trees to ensure proper
device power management functionality across all kernel versions.

 drivers/base/power/runtime.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c
index 04113adb092b5..99f25d6b2027a 100644
--- a/drivers/base/power/runtime.c
+++ b/drivers/base/power/runtime.c
@@ -1003,7 +1003,7 @@ static enum hrtimer_restart  pm_suspend_timer_fn(struct hrtimer *timer)
 	 * If 'expires' is after the current time, we've been called
 	 * too early.
 	 */
-	if (expires > 0 && expires < ktime_get_mono_fast_ns()) {
+	if (expires > 0 && expires <= ktime_get_mono_fast_ns()) {
 		dev->power.timer_expires = 0;
 		rpm_suspend(dev, dev->power.timer_autosuspends ?
 		    (RPM_ASYNC | RPM_AUTO) : RPM_ASYNC);
-- 
2.39.5


  parent reply	other threads:[~2025-05-30 12:40 UTC|newest]

Thread overview: 26+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-05-30 12:39 [PATCH AUTOSEL 6.12 01/26] ACPICA: fix acpi operand cache leak in dswstate.c Sasha Levin
2025-05-30 12:39 ` [PATCH AUTOSEL 6.12 02/26] ASoC: amd: yc: Add quirk for Lenovo Yoga Pro 7 14ASP9 Sasha Levin
2025-05-30 12:39 ` [PATCH AUTOSEL 6.12 03/26] clocksource: Fix the CPUs' choice in the watchdog per CPU verification Sasha Levin
2025-05-30 12:39 ` [PATCH AUTOSEL 6.12 04/26] tools/nolibc: use intmax definitions from compiler Sasha Levin
2025-05-30 12:39 ` [PATCH AUTOSEL 6.12 05/26] power: supply: collie: Fix wakeup source leaks on device unbind Sasha Levin
2025-05-30 12:39 ` [PATCH AUTOSEL 6.12 06/26] mmc: Add quirk to disable DDR50 tuning Sasha Levin
2025-05-30 12:39 ` [PATCH AUTOSEL 6.12 07/26] ACPICA: Avoid sequence overread in call to strncmp() Sasha Levin
2025-05-30 12:39 ` [PATCH AUTOSEL 6.12 08/26] mmc: sdhci-esdhc-imx: Save tuning value when card stays powered in suspend Sasha Levin
2025-05-30 12:39 ` [PATCH AUTOSEL 6.12 09/26] ASoC: tas2770: Power cycle amp on ISENSE/VSENSE change Sasha Levin
2025-05-30 12:39 ` [PATCH AUTOSEL 6.12 10/26] ASoC: intel/sdw_utils: Assign initial value in asoc_sdw_rt_amp_spk_rtd_init() Sasha Levin
2025-05-30 12:39 ` [PATCH AUTOSEL 6.12 11/26] ACPI: bus: Bail out if acpi_kobj registration fails Sasha Levin
2025-05-30 12:39 ` [PATCH AUTOSEL 6.12 12/26] ACPI: Add missing prototype for non CONFIG_SUSPEND/CONFIG_X86 case Sasha Levin
2025-05-30 12:39 ` [PATCH AUTOSEL 6.12 13/26] ACPICA: fix acpi parse and parseext cache leaks Sasha Levin
2025-05-30 12:40 ` [PATCH AUTOSEL 6.12 14/26] ACPICA: Apply pack(1) to union aml_resource Sasha Levin
2025-05-30 12:40 ` [PATCH AUTOSEL 6.12 15/26] ALSA: hda: cs35l41: Fix swapped l/r audio channels for Acer Helios laptops Sasha Levin
2025-05-30 12:40 ` [PATCH AUTOSEL 6.12 16/26] power: supply: bq27xxx: Retrieve again when busy Sasha Levin
2025-05-30 12:40 ` [PATCH AUTOSEL 6.12 17/26] pmdomain: core: Reset genpd->states to avoid freeing invalid data Sasha Levin
2025-05-30 12:40 ` [PATCH AUTOSEL 6.12 18/26] ACPICA: utilities: Fix overflow check in vsnprintf() Sasha Levin
2025-05-30 12:40 ` [PATCH AUTOSEL 6.12 19/26] platform-msi: Add msi_remove_device_irq_domain() in platform_device_msi_free_irqs_all() Sasha Levin
2025-05-30 12:40 ` [PATCH AUTOSEL 6.12 20/26] ASoC: tegra210_ahub: Add check to of_device_get_match_data() Sasha Levin
2025-05-30 12:40 ` [PATCH AUTOSEL 6.12 21/26] Make 'cc-option' work correctly for the -Wno-xyzzy pattern Sasha Levin
2025-05-30 12:40 ` [PATCH AUTOSEL 6.12 22/26] gpiolib: of: Add polarity quirk for s5m8767 Sasha Levin
2025-05-30 12:40 ` Sasha Levin [this message]
2025-05-30 12:40 ` [PATCH AUTOSEL 6.12 24/26] tools/nolibc: use pselect6_time64 if available Sasha Levin
2025-05-30 12:40 ` [PATCH AUTOSEL 6.12 25/26] power: supply: max17040: adjust thermal channel scaling Sasha Levin
2025-05-30 12:40 ` [PATCH AUTOSEL 6.12 26/26] ACPI: battery: negate current when discharging Sasha Levin

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=20250530124012.2575409-23-sashal@kernel.org \
    --to=sashal@kernel.org \
    --cc=gregkh@linuxfoundation.org \
    --cc=len.brown@intel.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-pm@vger.kernel.org \
    --cc=patches@lists.linux.dev \
    --cc=pavel@ucw.cz \
    --cc=quic_charante@quicinc.com \
    --cc=quic_pdaly@quicinc.com \
    --cc=rafael.j.wysocki@intel.com \
    --cc=rjw@rjwysocki.net \
    --cc=stable@vger.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