diff options
author | Wim Van Sebroeck <wim@iguana.be> | 2011-07-22 14:58:54 -0400 |
---|---|---|
committer | Wim Van Sebroeck <wim@iguana.be> | 2011-07-28 04:01:12 -0400 |
commit | 017cf0805105496ab1880e236cb3e4bf156fb915 (patch) | |
tree | f6889e009ddba78c5c5d1965d0dae77f4fb5edd8 /drivers/watchdog | |
parent | 014d694e5d59e4219803cd14deaae496d86e4910 (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.c | 27 |
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 | ||
127 | static ssize_t watchdog_write(struct file *file, const char __user *data, | 129 | 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, | |||
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 | ||
265 | static int watchdog_release(struct inode *inode, struct file *file) | 278 | static 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); |