From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (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 E8BD427D776; Fri, 30 May 2025 12:42:01 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1748608922; cv=none; b=kclc2QqdShljXl5V2l1HpasfoP/JnZgyJIRdg9r9LhqQXYxqki/w6uwJ05o69O22yAV6rv0jsm96Aq4VrDg3qSOr+UfqeBXzuSkN5Fn/Lr0WUVPr0jo0ptEYSvsnjvFk2tjrDWNC1zRHnhF0683yg6Pudl6Xc0m3hhTanZXrwOg= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1748608922; c=relaxed/simple; bh=AKfo+7glg+p/2bvTAM1UHlzqEE6AaThHbvYEzeCCWWo=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version:Content-Type; b=DjOcIgzThnpFPjEB6w2cLo1Dln/xhYLyEzSU+aZiY8mbNeumSkHUB08X5E/wTt7gxNN9OJY8l5eXtLXon5Y3/7xp28J9ej+tPjCVhiyTnXBgcErH34AP0MPcsJCwiyhLmxJ8DgqcBQ6lqQOBeZBZtzZH5hRUHaHGYK744s9PTvw= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=EAfWXqjt; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="EAfWXqjt" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 4B84CC4CEEF; Fri, 30 May 2025 12:42:00 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1748608921; bh=AKfo+7glg+p/2bvTAM1UHlzqEE6AaThHbvYEzeCCWWo=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=EAfWXqjt22CkMsS9VZZ7ZLp/E6ogWOLAOMT/N440AFtaJ9m/0EvIhSNCpnYtQ6Oqw gO8yPJrocS1Bjo2EKsETDVJLdQhiDKSbSgT1IT1xGbbFoP5mCoLz+y4Yk5HhxmJ+jV l4jnHjB0HuWcd3QGZHqj9/LHvg63yfH/9/NDM1SqPP9kqY+DIhOVfKHmzV+Fz98C6H Y33xzB7PTdp95DQ4VwyO8eVjt2uazCGOm7oRZ1293Mkl/KgLOtW2tngk9v9eS05aV4 2rINsOK+pUQfVanPG0114y88JHzL1N+MjTErharZlW0XkD27kON6mpbfVZ4zMimr30 d95F8TrOis9Dg== From: Sasha Levin To: patches@lists.linux.dev, stable@vger.kernel.org Cc: Charan Teja Kalla , Patrick Daly , "Rafael J . Wysocki" , Sasha Levin , 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 5.10 09/10] PM: runtime: fix denying of auto suspend in pm_suspend_timer_fn() Date: Fri, 30 May 2025 08:41:47 -0400 Message-Id: <20250530124148.2576913-9-sashal@kernel.org> X-Mailer: git-send-email 2.39.5 In-Reply-To: <20250530124148.2576913-1-sashal@kernel.org> References: <20250530124148.2576913-1-sashal@kernel.org> Precedence: bulk X-Mailing-List: patches@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-stable: review X-Patchwork-Hint: Ignore X-stable-base: Linux 5.10.237 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Charan Teja Kalla [ 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 Signed-off-by: Patrick Daly Signed-off-by: Charan Teja Kalla Link: https://patch.msgid.link/20250515064125.1211561-1-quic_charante@quicinc.com Signed-off-by: Rafael J. Wysocki Signed-off-by: Sasha Levin --- 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 4950864d3ea50..58d376b1cd680 100644 --- a/drivers/base/power/runtime.c +++ b/drivers/base/power/runtime.c @@ -998,7 +998,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