aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWim Van Sebroeck <wim@iguana.be>2011-07-22 14:58:54 -0400
committerWim Van Sebroeck <wim@iguana.be>2011-07-28 04:01:12 -0400
commit017cf0805105496ab1880e236cb3e4bf156fb915 (patch)
treef6889e009ddba78c5c5d1965d0dae77f4fb5edd8
parent014d694e5d59e4219803cd14deaae496d86e4910 (diff)
watchdog: WatchDog Timer Driver Core - Add Magic Close feature
Add support for the Magic Close feature to the WatchDog Timer Driver Core framework. Signed-off-by: Alan Cox <alan@lxorguk.ukuu.org.uk> Signed-off-by: Wim Van Sebroeck <wim@iguana.be> Acked-by: Arnd Bergmann <arnd@arndb.de> Acked-by: Wolfram Sang <w.sang@pengutronix.de>
-rw-r--r--Documentation/watchdog/watchdog-kernel-api.txt7
-rw-r--r--drivers/watchdog/watchdog_dev.c27
-rw-r--r--include/linux/watchdog.h1
3 files changed, 32 insertions, 3 deletions
diff --git a/Documentation/watchdog/watchdog-kernel-api.txt b/Documentation/watchdog/watchdog-kernel-api.txt
index acdee39fb08a..41d552698ada 100644
--- a/Documentation/watchdog/watchdog-kernel-api.txt
+++ b/Documentation/watchdog/watchdog-kernel-api.txt
@@ -127,6 +127,13 @@ bit-operations. The status bits that are defined are:
127* WDOG_DEV_OPEN: this status bit shows whether or not the watchdog device 127* WDOG_DEV_OPEN: this status bit shows whether or not the watchdog device
128 was opened via /dev/watchdog. 128 was opened via /dev/watchdog.
129 (This bit should only be used by the WatchDog Timer Driver Core). 129 (This bit should only be used by the WatchDog Timer Driver Core).
130* WDOG_ALLOW_RELEASE: this bit stores whether or not the magic close character
131 has been sent (so that we can support the magic close feature).
132 (This bit should only be used by the WatchDog Timer Driver Core).
133
134Note: The WatchDog Timer Driver Core supports the magic close feature. To use
135the magic close feature you must set the WDIOF_MAGICCLOSE bit in the options
136field of the watchdog's info structure.
130 137
131To get or set driver specific data the following two helper functions should be 138To get or set driver specific data the following two helper functions should be
132used: 139used:
diff --git a/drivers/watchdog/watchdog_dev.c b/drivers/watchdog/watchdog_dev.c
index 2c0289deaadd..db40c6c79ef8 100644
--- a/drivers/watchdog/watchdog_dev.c
+++ b/drivers/watchdog/watchdog_dev.c
@@ -122,6 +122,8 @@ static int watchdog_stop(struct watchdog_device *wddev)
122 * @ppos: pointer to the file offset 122 * @ppos: pointer to the file offset
123 * 123 *
124 * A write to a watchdog device is defined as a keepalive ping. 124 * A write to a watchdog device is defined as a keepalive ping.
125 * Writing the magic 'V' sequence allows the next close to turn
126 * off the watchdog.
125 */ 127 */
126 128
127static ssize_t watchdog_write(struct file *file, const char __user *data, 129static ssize_t watchdog_write(struct file *file, const char __user *data,
@@ -133,9 +135,18 @@ static ssize_t watchdog_write(struct file *file, const char __user *data,
133 if (len == 0) 135 if (len == 0)
134 return 0; 136 return 0;
135 137
138 /*
139 * Note: just in case someone wrote the magic character
140 * five months ago...
141 */
142 clear_bit(WDOG_ALLOW_RELEASE, &wdd->status);
143
144 /* scan to see whether or not we got the magic character */
136 for (i = 0; i != len; i++) { 145 for (i = 0; i != len; i++) {
137 if (get_user(c, data + i)) 146 if (get_user(c, data + i))
138 return -EFAULT; 147 return -EFAULT;
148 if (c == 'V')
149 set_bit(WDOG_ALLOW_RELEASE, &wdd->status);
139 } 150 }
140 151
141 /* someone wrote to us, so we send the watchdog a keepalive ping */ 152 /* someone wrote to us, so we send the watchdog a keepalive ping */
@@ -259,14 +270,24 @@ out:
259 * @inode: inode of device 270 * @inode: inode of device
260 * @file: file handle to device 271 * @file: file handle to device
261 * 272 *
262 * This is the code for when /dev/watchdog gets closed. 273 * This is the code for when /dev/watchdog gets closed. We will only
274 * stop the watchdog when we have received the magic char, else the
275 * watchdog will keep running.
263 */ 276 */
264 277
265static int watchdog_release(struct inode *inode, struct file *file) 278static int watchdog_release(struct inode *inode, struct file *file)
266{ 279{
267 int err; 280 int err = -EBUSY;
281
282 /*
283 * We only stop the watchdog if we received the magic character
284 * or if WDIOF_MAGICCLOSE is not set
285 */
286 if (test_and_clear_bit(WDOG_ALLOW_RELEASE, &wdd->status) ||
287 !(wdd->info->options & WDIOF_MAGICCLOSE))
288 err = watchdog_stop(wdd);
268 289
269 err = watchdog_stop(wdd); 290 /* If the watchdog was not stopped, send a keepalive ping */
270 if (err < 0) { 291 if (err < 0) {
271 pr_crit("%s: watchdog did not stop!\n", wdd->info->identity); 292 pr_crit("%s: watchdog did not stop!\n", wdd->info->identity);
272 watchdog_ping(wdd); 293 watchdog_ping(wdd);
diff --git a/include/linux/watchdog.h b/include/linux/watchdog.h
index 9f33efe199d1..e9881ca2452b 100644
--- a/include/linux/watchdog.h
+++ b/include/linux/watchdog.h
@@ -112,6 +112,7 @@ struct watchdog_device {
112/* Bit numbers for status flags */ 112/* Bit numbers for status flags */
113#define WDOG_ACTIVE 0 /* Is the watchdog running/active */ 113#define WDOG_ACTIVE 0 /* Is the watchdog running/active */
114#define WDOG_DEV_OPEN 1 /* Opened via /dev/watchdog ? */ 114#define WDOG_DEV_OPEN 1 /* Opened via /dev/watchdog ? */
115#define WDOG_ALLOW_RELEASE 2 /* Did we receive the magic char ? */
115}; 116};
116 117
117/* Use the following functions to manipulate watchdog driver specific data */ 118/* Use the following functions to manipulate watchdog driver specific data */