From c7c3a6476e8340ae57e351887e5364b1cb913545 Mon Sep 17 00:00:00 2001 From: Gongwei Li Date: Fri, 24 Apr 2026 15:12:08 +0800 Subject: [PATCH 1/8] PM: tools: pm-graph: fix ValueError when parsing incomplete device properties When parsing device properties from ftrace data, the devprops() function assumes that each line has at least three fields and that the third field (f[2]) always contains a valid integer. However, due to incomplete or corrupted ftrace logs, f[2] may be missing, empty, or non-existent. This can lead to the following error: Traceback (most recent call last): File "../sleepgraph.py", line 7142, in stamp = rerunTest(sysvals.outdir) File "../sleepgraph.py", line 6255, in rerunTest testruns, stamp = processData() File "../sleepgraph.py", line 6181, in processData testruns, error = parseTraceLog(live) File "../sleepgraph.py", line 3470, in parseTraceLog tp, tf = loadTraceLog() File "../sleepgraph.py", line 3398, in loadTraceLog if tp.stampInfo(line, sysvals): File "../sleepgraph.py", line 3073, in stampInfo self.parsePlatformInfo(line, sv) File "../sleepgraph.py", line 3177, in parsePlatformInfo sv.devprops = self.devprops(sv.b64unzip(info)) File "../sleepgraph.py", line 3158, in devprops if int(f[2]): ValueError: invalid literal for int() with base 10: '' To prevent this crash, add proper validation before accessing. Signed-off-by: Gongwei Li Acked-by: Todd Brandt [ rjw: Subject tweak ] Link: https://patch.msgid.link/20260424071208.3610628-1-13875017792@163.com Signed-off-by: Rafael J. Wysocki --- tools/power/pm-graph/sleepgraph.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/power/pm-graph/sleepgraph.py b/tools/power/pm-graph/sleepgraph.py index 1555b51a7d55..f6d172254829 100755 --- a/tools/power/pm-graph/sleepgraph.py +++ b/tools/power/pm-graph/sleepgraph.py @@ -3155,7 +3155,7 @@ class TestProps: dev = f[0] props[dev] = DevProps() props[dev].altname = f[1] - if int(f[2]): + if len(f) > 2 and f[2] and int(f[2]): props[dev].isasync = True else: props[dev].isasync = False From 783c8109844503bd1c35dab41b6d5fd074a9f131 Mon Sep 17 00:00:00 2001 From: Matthew Leach Date: Fri, 3 Apr 2026 08:36:30 +0100 Subject: [PATCH 2/8] PM: hibernate: call preallocate_image() after freeze prepare Certain drivers release resources (pinned pages, etc.) into system memory during the prepare freeze PM op, making them swappable. Currently, hibernate_preallocate_memory() is called before prepare freeze, so those drivers have no opportunity to release resources first. If a driver is holding a large amount of unswappable system RAM, this can cause hibernate_preallocate_memory() to fail. Move the call to hibernate_preallocate_memory() after prepare freeze. According to the documentation for the prepare callback, devices should be left in a usable state, so storage drivers should still be able to service I/O requests. This allows drivers to release unswappable resources prior to preallocation, so they can be swapped out through hibernate_preallocate_memory()'s reclaim path. Also remove shrink_shmem_memory() since hibernate_preallocate_memory() will have reclaimed enough memory for the hibernation image. Signed-off-by: Matthew Leach Reviewed-by: Mario Limonciello (AMD) [ rjw: Subject and changelog tweaks ] Link: https://patch.msgid.link/20260403-hibernation-fixes-v3-1-31bc9fa3ba2d@collabora.com Signed-off-by: Rafael J. Wysocki --- kernel/power/hibernate.c | 46 ++++++++-------------------------------- 1 file changed, 9 insertions(+), 37 deletions(-) diff --git a/kernel/power/hibernate.c b/kernel/power/hibernate.c index af8d07bafe02..d2479c69d71a 100644 --- a/kernel/power/hibernate.c +++ b/kernel/power/hibernate.c @@ -392,23 +392,6 @@ static int create_image(int platform_mode) return error; } -static void shrink_shmem_memory(void) -{ - struct sysinfo info; - unsigned long nr_shmem_pages, nr_freed_pages; - - si_meminfo(&info); - nr_shmem_pages = info.sharedram; /* current page count used for shmem */ - /* - * The intent is to reclaim all shmem pages. Though shrink_all_memory() can - * only reclaim about half of them, it's enough for creating the hibernation - * image. - */ - nr_freed_pages = shrink_all_memory(nr_shmem_pages); - pr_debug("requested to reclaim %lu shmem pages, actually freed %lu pages\n", - nr_shmem_pages, nr_freed_pages); -} - /** * hibernation_snapshot - Quiesce devices and create a hibernation image. * @platform_mode: If set, use platform driver to prepare for the transition. @@ -425,14 +408,9 @@ int hibernation_snapshot(int platform_mode) if (error) goto Close; - /* Preallocate image memory before shutting down devices. */ - error = hibernate_preallocate_memory(); - if (error) - goto Close; - error = freeze_kernel_threads(); if (error) - goto Cleanup; + goto Close; if (hibernation_test(TEST_FREEZER)) { @@ -445,19 +423,13 @@ int hibernation_snapshot(int platform_mode) } error = dpm_prepare(PMSG_FREEZE); - if (error) { - dpm_complete(PMSG_RECOVER); - goto Thaw; - } + if (error) + goto Complete; - /* - * Device drivers may move lots of data to shmem in dpm_prepare(). The shmem - * pages will use lots of system memory, causing hibernation image creation - * fail due to insufficient free memory. - * This call is to force flush the shmem pages to swap disk and reclaim - * the system memory so that image creation can succeed. - */ - shrink_shmem_memory(); + /* Preallocate image memory before shutting down devices. */ + error = hibernate_preallocate_memory(); + if (error) + goto Complete; console_suspend_all(); pm_restrict_gfp_mask(); @@ -492,10 +464,10 @@ int hibernation_snapshot(int platform_mode) platform_end(platform_mode); return error; + Complete: + dpm_complete(PMSG_RECOVER); Thaw: thaw_kernel_threads(); - Cleanup: - swsusp_free(); goto Close; } From 3855941f1e4069182c895d5093c5fa589f5b38bd Mon Sep 17 00:00:00 2001 From: Jiakai Xu Date: Sat, 23 May 2026 02:23:14 +0000 Subject: [PATCH 3/8] PM: sleep: Use complete() in device_pm_sleep_init() Replace complete_all() with complete() in device_pm_sleep_init() to allow it to be called in atomic contexts without triggering a false-positive WARNING from lockdep_assert_RT_in_threaded_ctx() when CONFIG_PROVE_RAW_LOCK_NESTING is enabled. device_pm_sleep_init() may be called during device initialization while holding a raw_spinlock (e.g., from within device_initialize()), and complete_all() is unsafe in atomic contexts on PREEMPT_RT kernels. complete(), which is safe to call from any context, is sufficient here. complete_all() sets the completion count to UINT_MAX/2 (permanently signaled), while complete() increments it by 1. Since no threads can be waiting during device initialization, both are functionally equivalent. The completion is always reinitialized via reinit_completion() in dpm_clear_async_state() before each suspend/resume cycle. However, changing to complete() introduces a potential deadlock for devices with no PM support (dev->power.no_pm = true). Such devices are never added to the dpm_list and never go through dpm_clear_async_state(), so their completion is never reinitialized. A parent device waiting on a no_pm child across multiple suspend phases would consume the single-use token in the first phase and block forever in the second. Fix this by adding an early return in dpm_wait() when dev->power.no_pm is set, since no_pm devices do not participate in system suspend/resume. Fixes: 152e1d592071 ("PM: Prevent waiting forever on asynchronous resume after failing suspend") Signed-off-by: Jiakai Xu [ rjw: Subject adjustment ] Link: https://patch.msgid.link/20260523022314.2657232-1-xujiakai24@mails.ucas.ac.cn Signed-off-by: Rafael J. Wysocki --- drivers/base/power/main.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c index e1b550664bab..ed48c292f575 100644 --- a/drivers/base/power/main.c +++ b/drivers/base/power/main.c @@ -115,7 +115,7 @@ void device_pm_sleep_init(struct device *dev) dev->power.is_noirq_suspended = false; dev->power.is_late_suspended = false; init_completion(&dev->power.completion); - complete_all(&dev->power.completion); + complete(&dev->power.completion); dev->power.wakeup = NULL; INIT_LIST_HEAD(&dev->power.entry); } @@ -252,6 +252,10 @@ static void dpm_wait(struct device *dev, bool async) if (!dev) return; + /* Devices with no PM support don't use the completion. */ + if (dev->power.no_pm) + return; + if (async || (pm_async_enabled && dev->power.async_suspend)) wait_for_completion(&dev->power.completion); } From 2068d7715e947f0321bc676a44215d3983af4bbc Mon Sep 17 00:00:00 2001 From: l1rox3 Date: Wed, 20 May 2026 10:12:54 +0200 Subject: [PATCH 4/8] PM: hibernate: make LZ4 available for hibernation compression Without this, CRYPTO_LZ4 had to be manually enabled in the config to use LZ4 for hibernation compression. Add the select so it gets pulled in automatically when hibernation is enabled, just like CRYPTO_LZO already does. Tested-by: l1rox3 Signed-off-by: l1rox3 Link: https://patch.msgid.link/20260520081254.13493-1-l1rox3.developer@gmail.com Signed-off-by: Rafael J. Wysocki --- kernel/power/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/kernel/power/Kconfig b/kernel/power/Kconfig index 05337f437cca..530c897311d4 100644 --- a/kernel/power/Kconfig +++ b/kernel/power/Kconfig @@ -42,6 +42,7 @@ config HIBERNATION select CRC32 select CRYPTO select CRYPTO_LZO + select CRYPTO_LZ4 help Enable the suspend to disk (STD) functionality, which is usually called "hibernation" in user interfaces. STD checkpoints the From bfc7d93bc5e12288e5dc6bb54260f68cdf5a5c47 Mon Sep 17 00:00:00 2001 From: Sumeet Pawnikar Date: Fri, 15 May 2026 23:56:16 +0530 Subject: [PATCH 5/8] powercap: intel_rapl: Fix memory leak in rapl_add_package_cpuslocked() When topology_physical_package_id()/topology_logical_die_id() returns a negative value, rapl_add_package_cpuslocked() returns ERR_PTR(-EINVAL) directly without freeing the rapl_package structure that was just allocated by kzalloc_obj(), leaking memory on every failed package addition. Use the existing err_free_package label so that the allocation is released on the error path. Signed-off-by: Sumeet Pawnikar Link: https://patch.msgid.link/20260515182616.227707-1-sumeet4linux@gmail.com Signed-off-by: Rafael J. Wysocki --- drivers/powercap/intel_rapl_common.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/powercap/intel_rapl_common.c b/drivers/powercap/intel_rapl_common.c index a8dd02dff0a0..f8afb4461e45 100644 --- a/drivers/powercap/intel_rapl_common.c +++ b/drivers/powercap/intel_rapl_common.c @@ -1770,7 +1770,8 @@ struct rapl_package *rapl_add_package_cpuslocked(int id, struct rapl_if_priv *pr topology_physical_package_id(id) : topology_logical_die_id(id); if ((int)(rp->id) < 0) { pr_err("topology_logical_(package/die)_id() returned a negative value"); - return ERR_PTR(-EINVAL); + ret = -EINVAL; + goto err_free_package; } rp->lead_cpu = id; if (!rapl_msrs_are_pkg_scope() && topology_max_dies_per_package() > 1) From 3da1dbf936d2fb25ef9925550bb276861d803e57 Mon Sep 17 00:00:00 2001 From: Rosen Penev Date: Sun, 10 May 2026 14:39:48 -0700 Subject: [PATCH 6/8] PM: hibernate: Use flexible array for CRC uncompressed buffers The CRC uncompressed buffer pointer array has the same lifetime as struct crc_data, but it is currently allocated separately. That adds another allocation failure path and a matching cleanup branch without providing any extra flexibility. Store the pointer array as a flexible array member and allocate it together with the crc_data using kzalloc_flex(). The array remains zero-initialized, while the allocation and error handling become simpler. Assisted-by: Codex:GPT-5.5 Signed-off-by: Rosen Penev Link: https://patch.msgid.link/20260510213948.41750-1-rosenp@gmail.com Signed-off-by: Rafael J. Wysocki --- kernel/power/swap.c | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/kernel/power/swap.c b/kernel/power/swap.c index 2e64869bb5a0..b28233b8d00e 100644 --- a/kernel/power/swap.c +++ b/kernel/power/swap.c @@ -570,29 +570,23 @@ struct crc_data { wait_queue_head_t done; /* crc update done */ u32 *crc32; /* points to handle's crc32 */ size_t **unc_len; /* uncompressed lengths */ - unsigned char **unc; /* uncompressed data */ + unsigned char *unc[]; /* uncompressed data */ }; static struct crc_data *alloc_crc_data(int nr_threads) { struct crc_data *crc; - crc = kzalloc_obj(*crc); + crc = kzalloc_flex(*crc, unc, nr_threads); if (!crc) return NULL; - crc->unc = kcalloc(nr_threads, sizeof(*crc->unc), GFP_KERNEL); - if (!crc->unc) - goto err_free_crc; - crc->unc_len = kzalloc_objs(*crc->unc_len, nr_threads); if (!crc->unc_len) - goto err_free_unc; + goto err_free_crc; return crc; -err_free_unc: - kfree(crc->unc); err_free_crc: kfree(crc); return NULL; @@ -607,7 +601,6 @@ static void free_crc_data(struct crc_data *crc) kthread_stop(crc->thr); kfree(crc->unc_len); - kfree(crc->unc); kfree(crc); } From 497823b493145b650ccad56dd7cf5f8237136ae2 Mon Sep 17 00:00:00 2001 From: Yury Norov Date: Thu, 28 May 2026 14:36:21 -0400 Subject: [PATCH 7/8] powercap: intel_rapl: Use sysfs_emit() in cpumask_show() cpumask_show() is a sysfs show callback, so use sysfs_emit() and cpumask_pr_args() to emit the mask in it. This prepares for removing cpumap_print_to_pagebuf(). Signed-off-by: Yury Norov [ rjw: Subject and changelog tweaks ] Link: https://patch.msgid.link/20260528183625.870813-15-ynorov@nvidia.com Signed-off-by: Rafael J. Wysocki --- drivers/powercap/intel_rapl_common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/powercap/intel_rapl_common.c b/drivers/powercap/intel_rapl_common.c index f8afb4461e45..1006d183d508 100644 --- a/drivers/powercap/intel_rapl_common.c +++ b/drivers/powercap/intel_rapl_common.c @@ -1441,7 +1441,7 @@ static ssize_t cpumask_show(struct device *dev, } cpus_read_unlock(); - ret = cpumap_print_to_pagebuf(true, buf, cpu_mask); + ret = sysfs_emit(buf, "%*pbl\n", cpumask_pr_args(cpu_mask)); free_cpumask_var(cpu_mask); From 3edbf62df6c236ef51e9d733e3f6bd6d70ee59af Mon Sep 17 00:00:00 2001 From: Tzung-Bi Shih Date: Mon, 8 Jun 2026 02:15:26 +0000 Subject: [PATCH 8/8] PM: dpm_watchdog: Add sysctl interface for DPM watchdog timeouts Introduce sysctl knobs to allow configuring DPM watchdog timeouts at runtime. Currently, these timeouts are fixed at compile time via CONFIG_DPM_WATCHDOG_TIMEOUT and CONFIG_DPM_WATCHDOG_WARNING_TIMEOUT. This limits flexibility if the timeouts need to be adjusted for different testing scenarios or hardware behaviors without rebuilding the kernel. Add the following sysctl files under /proc/sys/kernel/: - dpm_watchdog_timeout_secs: The total timeout before panic. The maximum value is capped at CONFIG_DPM_WATCHDOG_TIMEOUT to prevent unreasonably large timeouts. - dpm_watchdog_warning_timeout_secs: The warning timeout. The maximum value is capped at the current dpm_watchdog_timeout_secs. Both sysctls have a minimum value of 1. Signed-off-by: Tzung-Bi Shih Link: https://patch.msgid.link/20260608021526.1023248-4-tzungbi@kernel.org Signed-off-by: Rafael J. Wysocki --- drivers/base/power/main.c | 61 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 57 insertions(+), 4 deletions(-) diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c index ed48c292f575..f71467f6ada4 100644 --- a/drivers/base/power/main.c +++ b/drivers/base/power/main.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -531,6 +532,58 @@ module_param(dpm_watchdog_all_cpu_backtrace, bool, 0644); MODULE_PARM_DESC(dpm_watchdog_all_cpu_backtrace, "Backtrace all CPUs on DPM watchdog timeout"); +static unsigned int __read_mostly dpm_watchdog_timeout = CONFIG_DPM_WATCHDOG_TIMEOUT; +static unsigned int __read_mostly dpm_watchdog_warning_timeout = + CONFIG_DPM_WATCHDOG_WARNING_TIMEOUT; +static const unsigned int dpm_watchdog_timeout_max = CONFIG_DPM_WATCHDOG_TIMEOUT; + +static int proc_dodpm_watchdog_timeout_secs(const struct ctl_table *table, + int write, void *buffer, + size_t *lenp, loff_t *ppos) +{ + struct ctl_table ctl = *table; + unsigned int val = dpm_watchdog_timeout; + int ret; + + ctl.data = &val; + ret = proc_douintvec_minmax(&ctl, write, buffer, lenp, ppos); + if (ret || !write) + return ret; + + if (val < dpm_watchdog_warning_timeout) + dpm_watchdog_warning_timeout = val; + dpm_watchdog_timeout = val; + + return 0; +} + +static const struct ctl_table dpm_watchdog_sysctls[] = { + { + .procname = "dpm_watchdog_timeout_secs", + .maxlen = sizeof(unsigned int), + .mode = 0644, + .proc_handler = proc_dodpm_watchdog_timeout_secs, + .extra1 = SYSCTL_ONE, + .extra2 = (void *)&dpm_watchdog_timeout_max, + }, + { + .procname = "dpm_watchdog_warning_timeout_secs", + .data = &dpm_watchdog_warning_timeout, + .maxlen = sizeof(unsigned int), + .mode = 0644, + .proc_handler = proc_douintvec_minmax, + .extra1 = SYSCTL_ONE, + .extra2 = (void *)&dpm_watchdog_timeout, + }, +}; + +static int __init dpm_watchdog_sysctl_init(void) +{ + register_sysctl_init("kernel", dpm_watchdog_sysctls); + return 0; +} +subsys_initcall(dpm_watchdog_sysctl_init); + /** * dpm_watchdog_handler - Driver suspend / resume watchdog handler. * @t: The timer that PM watchdog depends on. @@ -556,9 +609,9 @@ static void dpm_watchdog_handler(struct timer_list *t) dev_driver_string(wd->dev), dev_name(wd->dev)); } - time_left = CONFIG_DPM_WATCHDOG_TIMEOUT - CONFIG_DPM_WATCHDOG_WARNING_TIMEOUT; + time_left = dpm_watchdog_timeout - dpm_watchdog_warning_timeout; dev_warn(wd->dev, "**** DPM device timeout after %u seconds; %u seconds until panic ****\n", - CONFIG_DPM_WATCHDOG_WARNING_TIMEOUT, time_left); + dpm_watchdog_warning_timeout, time_left); show_stack(wd->tsk, NULL, KERN_WARNING); wd->fatal = true; @@ -576,11 +629,11 @@ static void dpm_watchdog_set(struct dpm_watchdog *wd, struct device *dev) wd->dev = dev; wd->tsk = current; - wd->fatal = CONFIG_DPM_WATCHDOG_TIMEOUT == CONFIG_DPM_WATCHDOG_WARNING_TIMEOUT; + wd->fatal = dpm_watchdog_timeout == dpm_watchdog_warning_timeout; timer_setup_on_stack(timer, dpm_watchdog_handler, 0); /* use same timeout value for both suspend and resume */ - timer->expires = jiffies + HZ * CONFIG_DPM_WATCHDOG_WARNING_TIMEOUT; + timer->expires = jiffies + HZ * dpm_watchdog_warning_timeout; add_timer(timer); }