184 lines
6.8 KiB
Diff
184 lines
6.8 KiB
Diff
|
From 25fa3156526d2e4e1a9bc84a160bf7850107bf27 Mon Sep 17 00:00:00 2001
|
||
|
From: Paul Crawford <psc@sat.dundee.ac.uk>
|
||
|
Date: Fri, 30 Dec 2016 16:39:16 +0000
|
||
|
Subject: [PATCH 06/10] Make IT87 fix-up automatic by default
|
||
|
|
||
|
- Update 00cf0b0 from Maciej S. Szmigiero proposed making the IT87
|
||
|
style of fix something that is set only by the configuration file,
|
||
|
however, for many users with the buggy IT87 driver this will cause
|
||
|
problems.
|
||
|
|
||
|
- This change make the choice a 3 state one:
|
||
|
|
||
|
NO = never use ioctl-based refresh (old way, and in keeping
|
||
|
with the kernel API guidelines for watchdog use).
|
||
|
|
||
|
YES = always use the ioctl-based refresh (i.e set timer every
|
||
|
time, instead of writing to /dev/watchdog). Might be
|
||
|
useful if another driver module is found to share same
|
||
|
sort of bug as the IT87 module.
|
||
|
|
||
|
AUTO = check for IT87 and use ioctl-based method if found. This
|
||
|
is the same basec behaviour as before update 00cf0b0 but
|
||
|
the choice for yes/no now supported.
|
||
|
---
|
||
|
include/extern.h | 4 ++++
|
||
|
src/configfile.c | 12 ++++++++++--
|
||
|
src/keep_alive.c | 43 ++++++++++++++++++++++++++++++++-----------
|
||
|
watchdog.conf.5 | 8 ++++----
|
||
|
4 files changed, 50 insertions(+), 17 deletions(-)
|
||
|
|
||
|
diff --git a/include/extern.h b/include/extern.h
|
||
|
index cbf97fd..6d4ba5e 100644
|
||
|
--- a/include/extern.h
|
||
|
+++ b/include/extern.h
|
||
|
@@ -59,6 +59,10 @@ struct list {
|
||
|
#define FALSE 0
|
||
|
#endif
|
||
|
|
||
|
+#define ENUM_NO 0
|
||
|
+#define ENUM_YES 1
|
||
|
+#define ENUM_AUTO 2
|
||
|
+
|
||
|
#define TS_SIZE 12
|
||
|
|
||
|
/* === External variables === */
|
||
|
diff --git a/src/configfile.c b/src/configfile.c
|
||
|
index 809e39a..29e3464 100644
|
||
|
--- a/src/configfile.c
|
||
|
+++ b/src/configfile.c
|
||
|
@@ -96,7 +96,7 @@ char *logdir = "/var/log/watchdog";
|
||
|
char *heartbeat = NULL;
|
||
|
int hbstamps = 300;
|
||
|
|
||
|
-int refresh_use_settimeout = FALSE;
|
||
|
+int refresh_use_settimeout = ENUM_AUTO;
|
||
|
int realtime = FALSE;
|
||
|
|
||
|
/* Self-repairing binaries list */
|
||
|
@@ -120,6 +120,13 @@ READ_LIST_ADD("yes", 1)
|
||
|
READ_LIST_END()
|
||
|
};
|
||
|
|
||
|
+static const read_list_t YN_Auto_list[] = {
|
||
|
+READ_LIST_ADD("no", ENUM_NO)
|
||
|
+READ_LIST_ADD("yes", ENUM_YES)
|
||
|
+READ_LIST_ADD("auto", ENUM_AUTO)
|
||
|
+READ_LIST_END()
|
||
|
+};
|
||
|
+
|
||
|
/* Use the macros below to simplify the parsing function. For now we don't use the
|
||
|
* integer range checking (0=0 so not checked), and assume all strings can be blank and
|
||
|
* enumerated choices are Yes/No, but in future we could add such settings to the #define'd
|
||
|
@@ -129,6 +136,7 @@ READ_LIST_END()
|
||
|
#define READ_INT(name, iv) read_int_func( arg, val, name, 0, 0, iv)
|
||
|
#define READ_STRING(name, str) read_string_func( arg, val, name, Read_allow_blank, str)
|
||
|
#define READ_YESNO(name, iv) read_enumerated_func(arg, val, name, Yes_No_list, iv)
|
||
|
+#define READ_YN_AUTO(name, iv) read_enumerated_func(arg, val, name, YN_Auto_list, iv)
|
||
|
#define READ_LIST(name, list) read_list_func( arg, val, name, 0, list)
|
||
|
|
||
|
/*
|
||
|
@@ -208,7 +216,7 @@ void read_config(char *configfile)
|
||
|
} else if (READ_INT(LOGTICK, &logtick) == 0) {
|
||
|
ticker = logtick;
|
||
|
} else if (READ_STRING(DEVICE, &devname) == 0) {
|
||
|
- } else if (READ_YESNO(DEVICE_USE_SETTIMEOUT, &refresh_use_settimeout) == 0) {
|
||
|
+ } else if (READ_YN_AUTO(DEVICE_USE_SETTIMEOUT, &refresh_use_settimeout) == 0) {
|
||
|
} else if (READ_INT(DEVICE_TIMEOUT, &dev_timeout) == 0) {
|
||
|
} else if (READ_LIST(TEMP, &temp_list) == 0) {
|
||
|
} else if (READ_INT(MAXTEMP, &maxtemp) == 0) {
|
||
|
diff --git a/src/keep_alive.c b/src/keep_alive.c
|
||
|
index a57b0b5..6e721d9 100644
|
||
|
--- a/src/keep_alive.c
|
||
|
+++ b/src/keep_alive.c
|
||
|
@@ -29,6 +29,7 @@
|
||
|
|
||
|
static int watchdog_fd = -1;
|
||
|
static int timeout_used = TIMER_MARGIN;
|
||
|
+static int Refresh_using_ioctl = FALSE;
|
||
|
|
||
|
/*
|
||
|
* Open the watchdog timer (if name non-NULL) and set the time-out value (if non-zero).
|
||
|
@@ -67,19 +68,39 @@ int open_watchdog(char *name, int timeout)
|
||
|
/* The IT8728 on Gigabyte motherboard (and similar) would trip due to the normal
|
||
|
* refresh in the device driver failing to reset the timer for no obvious reason
|
||
|
* (though the normal operation used the Consumer IR sender to refresh via an
|
||
|
- * interrupt - also a non-obvious method!) so let's warn users of these
|
||
|
- * watchdogs and direct them to a workaround option.
|
||
|
+ * interrupt - also a non-obvious method!) so this work-around simply sets the
|
||
|
+ * time-out every refresh operation.
|
||
|
*
|
||
|
- * See https://bugs.launchpad.net/ubuntu/+source/linux/+bug/932381 and
|
||
|
- * https://bugzilla.kernel.org/show_bug.cgi?id=42801
|
||
|
+ * See https://bugs.launchpad.net/ubuntu/+source/linux/+bug/932381
|
||
|
+ * Also https://bugzilla.kernel.org/show_bug.cgi?id=42801
|
||
|
*
|
||
|
*/
|
||
|
- if (!refresh_use_settimeout && strcmp("IT87 WDT", (char *)ident.identity) == 0) {
|
||
|
- log_message(LOG_INFO,
|
||
|
- "IT87 watchdog detected, if watchdog trips by itself when the first timeout interval elapses "
|
||
|
- "try updating to the latest kernel");
|
||
|
- log_message(LOG_INFO, "if this does not help please report a kernel bug (not this package bug!) "
|
||
|
- "and try using watchdog-refresh-use-settimeout=yes config option as a workaround");
|
||
|
+
|
||
|
+ Refresh_using_ioctl = FALSE;
|
||
|
+
|
||
|
+ switch (refresh_use_settimeout) {
|
||
|
+ case ENUM_NO:
|
||
|
+ /* Set to "no" so never use ioctl mode. */
|
||
|
+ break;
|
||
|
+
|
||
|
+ case ENUM_YES:
|
||
|
+ /* Set to "yes" so always use ioctl mode. */
|
||
|
+ Refresh_using_ioctl = TRUE;
|
||
|
+ log_message(LOG_INFO, "Running ioctl-based refresh");
|
||
|
+ break;
|
||
|
+
|
||
|
+ case ENUM_AUTO:
|
||
|
+ /* Set to "auto" to decide based on driver identity. */
|
||
|
+ Refresh_using_ioctl = FALSE;
|
||
|
+ if (strcmp("IT87 WDT", (char *)ident.identity) == 0) {
|
||
|
+ Refresh_using_ioctl = TRUE;
|
||
|
+ log_message(LOG_INFO, "Running IT87 module fix-up");
|
||
|
+ }
|
||
|
+ break;
|
||
|
+
|
||
|
+ default:
|
||
|
+ log_message(LOG_ERR, "Unknown ioctl selection mode (%d)", refresh_use_settimeout);
|
||
|
+ break;
|
||
|
}
|
||
|
|
||
|
return rv;
|
||
|
@@ -165,7 +186,7 @@ int keep_alive(void)
|
||
|
if (watchdog_fd == -1)
|
||
|
return (ENOERR);
|
||
|
|
||
|
- if (refresh_use_settimeout) {
|
||
|
+ if (Refresh_using_ioctl) {
|
||
|
int timeout = timeout_used;
|
||
|
if (ioctl(watchdog_fd, WDIOC_SETTIMEOUT, &timeout) < 0) {
|
||
|
err = errno;
|
||
|
diff --git a/watchdog.conf.5 b/watchdog.conf.5
|
||
|
index 4e5155a..709c36e 100644
|
||
|
--- a/watchdog.conf.5
|
||
|
+++ b/watchdog.conf.5
|
||
|
@@ -64,11 +64,11 @@ Set the watchdog device name, typically /dev/watchdog. Default is to disable
|
||
|
keep alive support. This should be tested by running the daemon from the
|
||
|
command line before configuring it to start automatically on booting.
|
||
|
.TP
|
||
|
-watchdog-refresh-use-settimeout = <yes|no>
|
||
|
+watchdog-refresh-use-settimeout = <auto|yes|no>
|
||
|
Refresh watchdog timer by setting its timeout instead of using a normal watchdog
|
||
|
-refresh operation.
|
||
|
-Might help if your watchdog trips by itself when the first timeout interval
|
||
|
-elapses.
|
||
|
+refresh operation. Might help if your watchdog trips by itself when the first
|
||
|
+timeout interval elapses. Default is 'auto' for IT87 fix-up but this can be
|
||
|
+disabled with 'no' or forced for other modules with 'yes'.
|
||
|
.TP
|
||
|
watchdog-timeout = <timeout>
|
||
|
Set the watchdog device timeout during startup. If not set, a default is used
|
||
|
--
|
||
|
2.20.1
|
||
|
|