[PATCH v2] watchdog: pretimeout: Add "dump" pretimeout governor
Tzung-Bi Shih <[email protected]> Tue, 7 Jul 2026 10:21:05 +0000
| Newsgroups | org.kernel.vger.linux-watchdog,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <[email protected]> |
Add a new "dump" pretimeout governor that triggers a backtrace of all CPUs (via trigger_all_cpu_backtrace()) to the kernel log buffer. This provides diagnostic information right before the hardware watchdog fires. In addition, update the WATCHDOG_PRETIMEOUT_GOV_SEL Kconfig logic to fall back to the "panic" governor only when both "noop" and "dump" governors are disabled. Signed-off-by: Tzung-Bi Shih <[email protected]> --- Alternatives considered: We can also introduce some options and put trigger_all_cpu_backtrace() into the existing "noop" governor. --- v2: - Change "tristate" -> "bool" for WATCHDOG_PRETIMEOUT_GOV_DUMP. v1: https://lore.kernel.org/all/[email protected] --- drivers/watchdog/Kconfig | 19 ++++++++++- drivers/watchdog/Makefile | 1 + drivers/watchdog/pretimeout_dump.c | 45 ++++++++++++++++++++++++++ drivers/watchdog/watchdog_pretimeout.h | 4 ++- 4 files changed, 67 insertions(+), 2 deletions(-) create mode 100644 drivers/watchdog/pretimeout_dump.c diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index 08cb8612d41f..c93bc0d285f0 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -93,10 +93,19 @@ config WATCHDOG_PRETIMEOUT_GOV_SEL tristate depends on WATCHDOG_PRETIMEOUT_GOV default m - select WATCHDOG_PRETIMEOUT_GOV_PANIC if WATCHDOG_PRETIMEOUT_GOV_NOOP=n + select WATCHDOG_PRETIMEOUT_GOV_PANIC if \ + WATCHDOG_PRETIMEOUT_GOV_NOOP=n && WATCHDOG_PRETIMEOUT_GOV_DUMP=n if WATCHDOG_PRETIMEOUT_GOV +config WATCHDOG_PRETIMEOUT_GOV_DUMP + bool "Dump watchdog pretimeout governor" + depends on WATCHDOG_CORE=y + default WATCHDOG_CORE + help + Dump watchdog pretimeout governor, all cpu backtrace is + added to kernel log buffer. + config WATCHDOG_PRETIMEOUT_GOV_NOOP tristate "Noop watchdog pretimeout governor" depends on WATCHDOG_CORE @@ -121,6 +130,14 @@ choice The governor takes its action, if a watchdog is capable to report a pretimeout event. +config WATCHDOG_PRETIMEOUT_DEFAULT_GOV_DUMP + bool "dump" + depends on WATCHDOG_PRETIMEOUT_GOV_DUMP + help + Use dump watchdog pretimeout governor by default. If dump + governor is selected by a user, dump all cpu backtrace to + the kernel log buffer and don't do any system changes. + config WATCHDOG_PRETIMEOUT_DEFAULT_GOV_NOOP bool "noop" depends on WATCHDOG_PRETIMEOUT_GOV_NOOP diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile index bc1d52220f22..598556f03bc3 100644 --- a/drivers/watchdog/Makefile +++ b/drivers/watchdog/Makefile @@ -11,6 +11,7 @@ watchdog-objs += watchdog_core.o watchdog_dev.o watchdog-$(CONFIG_WATCHDOG_PRETIMEOUT_GOV) += watchdog_pretimeout.o watchdog-$(CONFIG_WATCHDOG_HRTIMER_PRETIMEOUT) += watchdog_hrtimer_pretimeout.o +obj-$(CONFIG_WATCHDOG_PRETIMEOUT_GOV_DUMP) += pretimeout_dump.o obj-$(CONFIG_WATCHDOG_PRETIMEOUT_GOV_NOOP) += pretimeout_noop.o obj-$(CONFIG_WATCHDOG_PRETIMEOUT_GOV_PANIC) += pretimeout_panic.o diff --git a/drivers/watchdog/pretimeout_dump.c b/drivers/watchdog/pretimeout_dump.c new file mode 100644 index 000000000000..c5d3dac2606c --- /dev/null +++ b/drivers/watchdog/pretimeout_dump.c @@ -0,0 +1,45 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright 2026 Google LLC + */ + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/nmi.h> +#include <linux/watchdog.h> + +#include "watchdog_pretimeout.h" + +/** + * pretimeout_dump - Dump on watchdog pretimeout event + * @wdd: watchdog_device + * + * Dump all cpu backtrace on pretimeout event. + */ +static void pretimeout_dump(struct watchdog_device *wdd) +{ + pr_alert("watchdog%d: pretimeout event\n", wdd->id); + if (!trigger_all_cpu_backtrace()) + pr_alert("trigger_all_cpu_backtrace() isn't available\n"); +} + +static struct watchdog_governor watchdog_gov_dump = { + .name = "dump", + .pretimeout = pretimeout_dump, +}; + +static int __init watchdog_gov_dump_register(void) +{ + return watchdog_register_governor(&watchdog_gov_dump); +} + +static void __exit watchdog_gov_dump_unregister(void) +{ + watchdog_unregister_governor(&watchdog_gov_dump); +} +module_init(watchdog_gov_dump_register); +module_exit(watchdog_gov_dump_unregister); + +MODULE_AUTHOR("Tzung-Bi Shih <[email protected]>"); +MODULE_DESCRIPTION("Dump watchdog pretimeout governor"); +MODULE_LICENSE("GPL"); diff --git a/drivers/watchdog/watchdog_pretimeout.h b/drivers/watchdog/watchdog_pretimeout.h index a3f1abc68839..57aa790e2669 100644 --- a/drivers/watchdog/watchdog_pretimeout.h +++ b/drivers/watchdog/watchdog_pretimeout.h @@ -24,7 +24,9 @@ int watchdog_pretimeout_governor_get(struct watchdog_device *wdd, char *buf); int watchdog_pretimeout_governor_set(struct watchdog_device *wdd, const char *buf); -#if IS_ENABLED(CONFIG_WATCHDOG_PRETIMEOUT_DEFAULT_GOV_NOOP) +#if IS_ENABLED(CONFIG_WATCHDOG_PRETIMEOUT_DEFAULT_GOV_DUMP) +#define WATCHDOG_PRETIMEOUT_DEFAULT_GOV "dump" +#elif IS_ENABLED(CONFIG_WATCHDOG_PRETIMEOUT_DEFAULT_GOV_NOOP) #define WATCHDOG_PRETIMEOUT_DEFAULT_GOV "noop" #elif IS_ENABLED(CONFIG_WATCHDOG_PRETIMEOUT_DEFAULT_GOV_PANIC) #define WATCHDOG_PRETIMEOUT_DEFAULT_GOV "panic" -- 2.55.0.rc2.803.g1fd1e6609c-goog