summaryrefslogtreecommitdiffstats
path: root/drivers/watchdog/watchdog_dev.c
diff options
context:
space:
mode:
authorWim Van Sebroeck <wim@iguana.be>2011-07-22 18:58:54 +0000
committerWim Van Sebroeck <wim@iguana.be>2011-07-28 08:01:12 +0000
commit017cf0805105496ab1880e236cb3e4bf156fb915 (patch)
treef6889e009ddba78c5c5d1965d0dae77f4fb5edd8 /drivers/watchdog/watchdog_dev.c
parent014d694e5d59e4219803cd14deaae496d86e4910 (diff)
downloadlinux-017cf0805105496ab1880e236cb3e4bf156fb915.tar.bz2
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>
Diffstat (limited to 'drivers/watchdog/watchdog_dev.c')
-rw-r--r--drivers/watchdog/watchdog_dev.c27
1 files changed, 24 insertions, 3 deletions
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)
* @ppos: pointer to the file offset
*
* A write to a watchdog device is defined as a keepalive ping.
+ * Writing the magic 'V' sequence allows the next close to turn
+ * off the watchdog.
*/
static 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,
if (len == 0)
return 0;
+ /*
+ * Note: just in case someone wrote the magic character
+ * five months ago...
+ */
+ clear_bit(WDOG_ALLOW_RELEASE, &wdd->status);
+
+ /* scan to see whether or not we got the magic character */
for (i = 0; i != len; i++) {
if (get_user(c, data + i))
return -EFAULT;
+ if (c == 'V')
+ set_bit(WDOG_ALLOW_RELEASE, &wdd->status);
}
/* someone wrote to us, so we send the watchdog a keepalive ping */
@@ -259,14 +270,24 @@ out:
* @inode: inode of device
* @file: file handle to device
*
- * This is the code for when /dev/watchdog gets closed.
+ * This is the code for when /dev/watchdog gets closed. We will only
+ * stop the watchdog when we have received the magic char, else the
+ * watchdog will keep running.
*/
static int watchdog_release(struct inode *inode, struct file *file)
{
- int err;
+ int err = -EBUSY;
+
+ /*
+ * We only stop the watchdog if we received the magic character
+ * or if WDIOF_MAGICCLOSE is not set
+ */
+ if (test_and_clear_bit(WDOG_ALLOW_RELEASE, &wdd->status) ||
+ !(wdd->info->options & WDIOF_MAGICCLOSE))
+ err = watchdog_stop(wdd);
- err = watchdog_stop(wdd);
+ /* If the watchdog was not stopped, send a keepalive ping */
if (err < 0) {
pr_crit("%s: watchdog did not stop!\n", wdd->info->identity);
watchdog_ping(wdd);