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 | |
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>
-rw-r--r-- | Documentation/watchdog/watchdog-kernel-api.txt | 7 | ||||
-rw-r--r-- | drivers/watchdog/watchdog_dev.c | 27 | ||||
-rw-r--r-- | include/linux/watchdog.h | 1 |
3 files changed, 32 insertions, 3 deletions
diff --git a/Documentation/watchdog/watchdog-kernel-api.txt b/Documentation/watchdog/watchdog-kernel-api.txt index acdee39fb08a..41d552698ada 100644 --- a/Documentation/watchdog/watchdog-kernel-api.txt +++ b/Documentation/watchdog/watchdog-kernel-api.txt | |||
@@ -127,6 +127,13 @@ bit-operations. The status bits that are defined are: | |||
127 | * WDOG_DEV_OPEN: this status bit shows whether or not the watchdog device | 127 | * WDOG_DEV_OPEN: this status bit shows whether or not the watchdog device |
128 | was opened via /dev/watchdog. | 128 | was opened via /dev/watchdog. |
129 | (This bit should only be used by the WatchDog Timer Driver Core). | 129 | (This bit should only be used by the WatchDog Timer Driver Core). |
130 | * WDOG_ALLOW_RELEASE: this bit stores whether or not the magic close character | ||
131 | has been sent (so that we can support the magic close feature). | ||
132 | (This bit should only be used by the WatchDog Timer Driver Core). | ||
133 | |||
134 | Note: The WatchDog Timer Driver Core supports the magic close feature. To use | ||
135 | the magic close feature you must set the WDIOF_MAGICCLOSE bit in the options | ||
136 | field of the watchdog's info structure. | ||
130 | 137 | ||
131 | To get or set driver specific data the following two helper functions should be | 138 | To get or set driver specific data the following two helper functions should be |
132 | used: | 139 | used: |
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); |
diff --git a/include/linux/watchdog.h b/include/linux/watchdog.h index 9f33efe199d1..e9881ca2452b 100644 --- a/include/linux/watchdog.h +++ b/include/linux/watchdog.h | |||
@@ -112,6 +112,7 @@ struct watchdog_device { | |||
112 | /* Bit numbers for status flags */ | 112 | /* Bit numbers for status flags */ |
113 | #define WDOG_ACTIVE 0 /* Is the watchdog running/active */ | 113 | #define WDOG_ACTIVE 0 /* Is the watchdog running/active */ |
114 | #define WDOG_DEV_OPEN 1 /* Opened via /dev/watchdog ? */ | 114 | #define WDOG_DEV_OPEN 1 /* Opened via /dev/watchdog ? */ |
115 | #define WDOG_ALLOW_RELEASE 2 /* Did we receive the magic char ? */ | ||
115 | }; | 116 | }; |
116 | 117 | ||
117 | /* Use the following functions to manipulate watchdog driver specific data */ | 118 | /* Use the following functions to manipulate watchdog driver specific data */ |