Commit 017cf080 authored by Wim Van Sebroeck's avatar Wim Van Sebroeck

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: default avatarAlan Cox <alan@lxorguk.ukuu.org.uk>
Signed-off-by: default avatarWim Van Sebroeck <wim@iguana.be>
Acked-by: default avatarArnd Bergmann <arnd@arndb.de>
Acked-by: default avatarWolfram Sang <w.sang@pengutronix.de>
parent 014d694e
......@@ -127,6 +127,13 @@ bit-operations. The status bits that are defined are:
* WDOG_DEV_OPEN: this status bit shows whether or not the watchdog device
was opened via /dev/watchdog.
(This bit should only be used by the WatchDog Timer Driver Core).
* WDOG_ALLOW_RELEASE: this bit stores whether or not the magic close character
has been sent (so that we can support the magic close feature).
(This bit should only be used by the WatchDog Timer Driver Core).
Note: The WatchDog Timer Driver Core supports the magic close feature. To use
the magic close feature you must set the WDIOF_MAGICCLOSE bit in the options
field of the watchdog's info structure.
To get or set driver specific data the following two helper functions should be
used:
......
......@@ -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 @@ static int watchdog_open(struct inode *inode, struct file *file)
* @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);
......
......@@ -112,6 +112,7 @@ struct watchdog_device {
/* Bit numbers for status flags */
#define WDOG_ACTIVE 0 /* Is the watchdog running/active */
#define WDOG_DEV_OPEN 1 /* Opened via /dev/watchdog ? */
#define WDOG_ALLOW_RELEASE 2 /* Did we receive the magic char ? */
};
/* Use the following functions to manipulate watchdog driver specific data */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment