aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/watchdog
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 /drivers/watchdog
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>
Diffstat (limited to 'drivers/watchdog')
-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)
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);