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>
This commit is contained in:
Wim Van Sebroeck 2011-07-22 18:58:54 +00:00
parent 014d694e5d
commit 017cf08051
3 changed files with 32 additions and 3 deletions

View File

@ -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:

View File

@ -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;
err = watchdog_stop(wdd);
/*
* 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);
/* 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);

View File

@ -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 */