From ff84136cb6a4943f489ad037fe93f43be0573c23 Mon Sep 17 00:00:00 2001 From: Vladimir Zapolskiy Date: Fri, 7 Oct 2016 15:39:54 +0300 Subject: watchdog: add watchdog pretimeout governor framework The change adds a simple watchdog pretimeout framework infrastructure, its purpose is to allow users to select a desired handling of watchdog pretimeout events, which may be generated by some watchdog devices. A user selects a default watchdog pretimeout governor during compilation stage. Watchdogs with WDIOF_PRETIMEOUT capability now have one more device attribute in sysfs, pretimeout_governor attribute is intended to display the selected watchdog pretimeout governor. The framework has no impact at runtime on watchdog devices with no WDIOF_PRETIMEOUT capability set. Signed-off-by: Vladimir Zapolskiy Reviewed-by: Guenter Roeck Reviewed-by: Wolfram Sang Tested-by: Wolfram Sang Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/Kconfig | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers/watchdog/Kconfig') diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index 1bffe006ca9a..04d535ae497d 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -1831,4 +1831,11 @@ config USBPCWATCHDOG Most people will say N. +comment "Watchdog Pretimeout Governors" + +config WATCHDOG_PRETIMEOUT_GOV + bool "Enable watchdog pretimeout governors" + help + The option allows to select watchdog pretimeout governors. + endif # WATCHDOG -- cgit v1.2.3 From f77710c4cda01ad9c3672fb2f97bdea9a94da92a Mon Sep 17 00:00:00 2001 From: Vladimir Zapolskiy Date: Fri, 7 Oct 2016 15:39:55 +0300 Subject: watchdog: pretimeout: add noop pretimeout governor The change adds noop watchdog pretimeout governor, only an informational message is printed to the kernel log buffer when a watchdog triggers a pretimeout event. While introducing the first pretimeout governor the selected design assumes that the default pretimeout governor is selected by its name and it is always built-in, thus the default pretimeout governor can not be unregistered and the correspondent check can be removed from the watchdog_unregister_governor() function. Signed-off-by: Vladimir Zapolskiy Reviewed-by: Guenter Roeck Reviewed-by: Wolfram Sang Tested-by: Wolfram Sang Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/Kconfig | 28 ++++++++++++++++++++ drivers/watchdog/Makefile | 2 ++ drivers/watchdog/pretimeout_noop.c | 47 ++++++++++++++++++++++++++++++++++ drivers/watchdog/watchdog_pretimeout.h | 4 +++ 4 files changed, 81 insertions(+) create mode 100644 drivers/watchdog/pretimeout_noop.c (limited to 'drivers/watchdog/Kconfig') diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index 04d535ae497d..4aeb8f95beb4 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -1838,4 +1838,32 @@ config WATCHDOG_PRETIMEOUT_GOV help The option allows to select watchdog pretimeout governors. +if WATCHDOG_PRETIMEOUT_GOV + +choice + prompt "Default Watchdog Pretimeout Governor" + default WATCHDOG_PRETIMEOUT_DEFAULT_GOV_PANIC + help + This option selects a default watchdog pretimeout governor. + The governor takes its action, if a watchdog is capable + to report a pretimeout event. + +config WATCHDOG_PRETIMEOUT_DEFAULT_GOV_NOOP + bool "noop" + select WATCHDOG_PRETIMEOUT_GOV_NOOP + help + Use noop watchdog pretimeout governor by default. If noop + governor is selected by a user, write a short message to + the kernel log buffer and don't do any system changes. + +endchoice + +config WATCHDOG_PRETIMEOUT_GOV_NOOP + tristate "Noop watchdog pretimeout governor" + help + Noop watchdog pretimeout governor, only an informational + message is added to kernel log buffer. + +endif # WATCHDOG_PRETIMEOUT_GOV + endif # WATCHDOG diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile index 990c36ed4716..0502a21db1db 100644 --- a/drivers/watchdog/Makefile +++ b/drivers/watchdog/Makefile @@ -9,6 +9,8 @@ watchdog-objs += watchdog_core.o watchdog_dev.o watchdog-$(CONFIG_WATCHDOG_PRETIMEOUT_GOV) += watchdog_pretimeout.o +obj-$(CONFIG_WATCHDOG_PRETIMEOUT_GOV_NOOP) += pretimeout_noop.o + # Only one watchdog can succeed. We probe the ISA/PCI/USB based # watchdog-cards first, then the architecture specific watchdog # drivers and then the architecture independent "softdog" driver. diff --git a/drivers/watchdog/pretimeout_noop.c b/drivers/watchdog/pretimeout_noop.c new file mode 100644 index 000000000000..85f5299d197c --- /dev/null +++ b/drivers/watchdog/pretimeout_noop.c @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2015-2016 Mentor Graphics + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + */ + +#include +#include +#include + +#include "watchdog_pretimeout.h" + +/** + * pretimeout_noop - No operation on watchdog pretimeout event + * @wdd - watchdog_device + * + * This function prints a message about pretimeout to kernel log. + */ +static void pretimeout_noop(struct watchdog_device *wdd) +{ + pr_alert("watchdog%d: pretimeout event\n", wdd->id); +} + +static struct watchdog_governor watchdog_gov_noop = { + .name = "noop", + .pretimeout = pretimeout_noop, +}; + +static int __init watchdog_gov_noop_register(void) +{ + return watchdog_register_governor(&watchdog_gov_noop); +} + +static void __exit watchdog_gov_noop_unregister(void) +{ + watchdog_unregister_governor(&watchdog_gov_noop); +} +module_init(watchdog_gov_noop_register); +module_exit(watchdog_gov_noop_unregister); + +MODULE_AUTHOR("Vladimir Zapolskiy "); +MODULE_DESCRIPTION("Panic watchdog pretimeout governor"); +MODULE_LICENSE("GPL"); diff --git a/drivers/watchdog/watchdog_pretimeout.h b/drivers/watchdog/watchdog_pretimeout.h index c6cd9f80adb2..c4b6f88dc9c9 100644 --- a/drivers/watchdog/watchdog_pretimeout.h +++ b/drivers/watchdog/watchdog_pretimeout.h @@ -20,6 +20,10 @@ int watchdog_register_pretimeout(struct watchdog_device *wdd); void watchdog_unregister_pretimeout(struct watchdog_device *wdd); int watchdog_pretimeout_governor_get(struct watchdog_device *wdd, char *buf); +#if IS_ENABLED(CONFIG_WATCHDOG_PRETIMEOUT_DEFAULT_GOV_NOOP) +#define WATCHDOG_PRETIMEOUT_DEFAULT_GOV "noop" +#endif + #else static inline int watchdog_register_pretimeout(struct watchdog_device *wdd) { -- cgit v1.2.3 From da0d12ff2b829a35e9921918e925d79497b82bef Mon Sep 17 00:00:00 2001 From: Vladimir Zapolskiy Date: Fri, 7 Oct 2016 15:39:56 +0300 Subject: watchdog: pretimeout: add panic pretimeout governor The change adds panic watchdog pretimeout governor, on watchdog pretimeout event the kernel shall panic. In general watchdog pretimeout event means that something essentially bad is going on the system, for example a process scheduler stalls or watchdog feeder is killed due to OOM, so printing out information attendant to panic and before likely unavoidable reboot caused by a watchdog may help to determine a root cause of the issue. Signed-off-by: Vladimir Zapolskiy Reviewed-by: Guenter Roeck Reviewed-by: Wolfram Sang Tested-by: Wolfram Sang Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/Kconfig | 14 ++++++++++ drivers/watchdog/Makefile | 1 + drivers/watchdog/pretimeout_panic.c | 47 ++++++++++++++++++++++++++++++++++ drivers/watchdog/watchdog_pretimeout.c | 6 ++--- drivers/watchdog/watchdog_pretimeout.h | 2 ++ 5 files changed, 66 insertions(+), 4 deletions(-) create mode 100644 drivers/watchdog/pretimeout_panic.c (limited to 'drivers/watchdog/Kconfig') diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index 4aeb8f95beb4..cbd33321c0f8 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -1856,6 +1856,14 @@ config WATCHDOG_PRETIMEOUT_DEFAULT_GOV_NOOP governor is selected by a user, write a short message to the kernel log buffer and don't do any system changes. +config WATCHDOG_PRETIMEOUT_DEFAULT_GOV_PANIC + bool "panic" + select WATCHDOG_PRETIMEOUT_GOV_PANIC + help + Use panic watchdog pretimeout governor by default, if + a watchdog pretimeout event happens, consider that + a watchdog feeder is dead and reboot is unavoidable. + endchoice config WATCHDOG_PRETIMEOUT_GOV_NOOP @@ -1864,6 +1872,12 @@ config WATCHDOG_PRETIMEOUT_GOV_NOOP Noop watchdog pretimeout governor, only an informational message is added to kernel log buffer. +config WATCHDOG_PRETIMEOUT_GOV_PANIC + tristate "Panic watchdog pretimeout governor" + help + Panic watchdog pretimeout governor, on watchdog pretimeout + event put the kernel into panic. + endif # WATCHDOG_PRETIMEOUT_GOV endif # WATCHDOG diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile index 0502a21db1db..1a34c6a96988 100644 --- a/drivers/watchdog/Makefile +++ b/drivers/watchdog/Makefile @@ -10,6 +10,7 @@ watchdog-objs += watchdog_core.o watchdog_dev.o watchdog-$(CONFIG_WATCHDOG_PRETIMEOUT_GOV) += watchdog_pretimeout.o obj-$(CONFIG_WATCHDOG_PRETIMEOUT_GOV_NOOP) += pretimeout_noop.o +obj-$(CONFIG_WATCHDOG_PRETIMEOUT_GOV_PANIC) += pretimeout_panic.o # Only one watchdog can succeed. We probe the ISA/PCI/USB based # watchdog-cards first, then the architecture specific watchdog diff --git a/drivers/watchdog/pretimeout_panic.c b/drivers/watchdog/pretimeout_panic.c new file mode 100644 index 000000000000..0c197a1c97f4 --- /dev/null +++ b/drivers/watchdog/pretimeout_panic.c @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2015-2016 Mentor Graphics + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + */ + +#include +#include +#include + +#include "watchdog_pretimeout.h" + +/** + * pretimeout_panic - Panic on watchdog pretimeout event + * @wdd - watchdog_device + * + * Panic, watchdog has not been fed till pretimeout event. + */ +static void pretimeout_panic(struct watchdog_device *wdd) +{ + panic("watchdog pretimeout event\n"); +} + +static struct watchdog_governor watchdog_gov_panic = { + .name = "panic", + .pretimeout = pretimeout_panic, +}; + +static int __init watchdog_gov_panic_register(void) +{ + return watchdog_register_governor(&watchdog_gov_panic); +} + +static void __exit watchdog_gov_panic_unregister(void) +{ + watchdog_unregister_governor(&watchdog_gov_panic); +} +module_init(watchdog_gov_panic_register); +module_exit(watchdog_gov_panic_unregister); + +MODULE_AUTHOR("Vladimir Zapolskiy "); +MODULE_DESCRIPTION("Panic watchdog pretimeout governor"); +MODULE_LICENSE("GPL"); diff --git a/drivers/watchdog/watchdog_pretimeout.c b/drivers/watchdog/watchdog_pretimeout.c index 72612255fb55..098c965f6c78 100644 --- a/drivers/watchdog/watchdog_pretimeout.c +++ b/drivers/watchdog/watchdog_pretimeout.c @@ -60,7 +60,8 @@ int watchdog_register_governor(struct watchdog_governor *gov) { struct watchdog_pretimeout *p; - if (!default_gov) { + if (!strncmp(gov->name, WATCHDOG_PRETIMEOUT_DEFAULT_GOV, + WATCHDOG_GOV_NAME_MAXLEN)) { spin_lock_irq(&pretimeout_lock); default_gov = gov; @@ -79,9 +80,6 @@ void watchdog_unregister_governor(struct watchdog_governor *gov) struct watchdog_pretimeout *p; spin_lock_irq(&pretimeout_lock); - if (gov == default_gov) - default_gov = NULL; - list_for_each_entry(p, &pretimeout_list, entry) if (p->wdd->gov == gov) p->wdd->gov = default_gov; diff --git a/drivers/watchdog/watchdog_pretimeout.h b/drivers/watchdog/watchdog_pretimeout.h index c4b6f88dc9c9..867492aa7ea6 100644 --- a/drivers/watchdog/watchdog_pretimeout.h +++ b/drivers/watchdog/watchdog_pretimeout.h @@ -22,6 +22,8 @@ int watchdog_pretimeout_governor_get(struct watchdog_device *wdd, char *buf); #if 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" #endif #else -- cgit v1.2.3