From: Tzung-Bi Shih Date: Mon, 8 Jun 2026 02:15:26 +0000 (+0000) Subject: PM: dpm_watchdog: Add sysctl interface for DPM watchdog timeouts X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=3edbf62df6c236ef51e9d733e3f6bd6d70ee59af;p=thirdparty%2Flinux.git 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 --- diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c index ed48c292f5757..f71467f6ada4e 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); }