diff options
author | Linus Torvalds <torvalds@g5.osdl.org> | 2006-06-28 19:03:06 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-06-28 19:03:06 -0400 |
commit | fffcb480e4224f25c965b93fa65541bfc7dd732e (patch) | |
tree | a48383b5487798cdcc0153e342d6d88abe71333d /drivers/char | |
parent | b44597906e03d5e2b467c17a3b73585596c0d7be (diff) | |
parent | 56fb9e5346b99bc6b77def79b3739097bc13ea8a (diff) |
Merge master.kernel.org:/pub/scm/linux/kernel/git/wim/linux-2.6-watchdog
* master.kernel.org:/pub/scm/linux/kernel/git/wim/linux-2.6-watchdog:
[WATCHDOG] Documentation/watchdog update
[WATCHDOG] convert AT91RM9200 watchdog to platform driver
[WATCHDOG] add WDIOC_GETTIMELEFT ioctl
[WATCHDOG] Pre-Timeout flags
Diffstat (limited to 'drivers/char')
-rw-r--r-- | drivers/char/watchdog/at91_wdt.c | 82 | ||||
-rw-r--r-- | drivers/char/watchdog/i8xx_tco.c | 28 | ||||
-rw-r--r-- | drivers/char/watchdog/pcwd_pci.c | 30 | ||||
-rw-r--r-- | drivers/char/watchdog/pcwd_usb.c | 23 |
4 files changed, 150 insertions, 13 deletions
diff --git a/drivers/char/watchdog/at91_wdt.c b/drivers/char/watchdog/at91_wdt.c index ac83bc4b019a..00080655533d 100644 --- a/drivers/char/watchdog/at91_wdt.c +++ b/drivers/char/watchdog/at91_wdt.c | |||
@@ -17,14 +17,15 @@ | |||
17 | #include <linux/miscdevice.h> | 17 | #include <linux/miscdevice.h> |
18 | #include <linux/module.h> | 18 | #include <linux/module.h> |
19 | #include <linux/moduleparam.h> | 19 | #include <linux/moduleparam.h> |
20 | #include <linux/platform_device.h> | ||
20 | #include <linux/types.h> | 21 | #include <linux/types.h> |
21 | #include <linux/watchdog.h> | 22 | #include <linux/watchdog.h> |
22 | #include <asm/bitops.h> | 23 | #include <asm/bitops.h> |
23 | #include <asm/uaccess.h> | 24 | #include <asm/uaccess.h> |
24 | 25 | ||
25 | 26 | ||
26 | #define WDT_DEFAULT_TIME 5 /* 5 seconds */ | 27 | #define WDT_DEFAULT_TIME 5 /* seconds */ |
27 | #define WDT_MAX_TIME 256 /* 256 seconds */ | 28 | #define WDT_MAX_TIME 256 /* seconds */ |
28 | 29 | ||
29 | static int wdt_time = WDT_DEFAULT_TIME; | 30 | static int wdt_time = WDT_DEFAULT_TIME; |
30 | static int nowayout = WATCHDOG_NOWAYOUT; | 31 | static int nowayout = WATCHDOG_NOWAYOUT; |
@@ -32,8 +33,10 @@ static int nowayout = WATCHDOG_NOWAYOUT; | |||
32 | module_param(wdt_time, int, 0); | 33 | module_param(wdt_time, int, 0); |
33 | MODULE_PARM_DESC(wdt_time, "Watchdog time in seconds. (default="__MODULE_STRING(WDT_DEFAULT_TIME) ")"); | 34 | MODULE_PARM_DESC(wdt_time, "Watchdog time in seconds. (default="__MODULE_STRING(WDT_DEFAULT_TIME) ")"); |
34 | 35 | ||
36 | #ifdef CONFIG_WATCHDOG_NOWAYOUT | ||
35 | module_param(nowayout, int, 0); | 37 | module_param(nowayout, int, 0); |
36 | MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); | 38 | MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); |
39 | #endif | ||
37 | 40 | ||
38 | 41 | ||
39 | static unsigned long at91wdt_busy; | 42 | static unsigned long at91wdt_busy; |
@@ -138,7 +141,7 @@ static int at91_wdt_ioctl(struct inode *inode, struct file *file, | |||
138 | case WDIOC_SETTIMEOUT: | 141 | case WDIOC_SETTIMEOUT: |
139 | if (get_user(new_value, p)) | 142 | if (get_user(new_value, p)) |
140 | return -EFAULT; | 143 | return -EFAULT; |
141 | 144 | ||
142 | if (at91_wdt_settimeout(new_value)) | 145 | if (at91_wdt_settimeout(new_value)) |
143 | return -EINVAL; | 146 | return -EINVAL; |
144 | 147 | ||
@@ -196,27 +199,84 @@ static struct miscdevice at91wdt_miscdev = { | |||
196 | .fops = &at91wdt_fops, | 199 | .fops = &at91wdt_fops, |
197 | }; | 200 | }; |
198 | 201 | ||
199 | static int __init at91_wdt_init(void) | 202 | static int __init at91wdt_probe(struct platform_device *pdev) |
200 | { | 203 | { |
201 | int res; | 204 | int res; |
202 | 205 | ||
203 | /* Check that the heartbeat value is within range; if not reset to the default */ | 206 | if (at91wdt_miscdev.dev) |
204 | if (at91_wdt_settimeout(wdt_time)) { | 207 | return -EBUSY; |
205 | at91_wdt_settimeout(WDT_DEFAULT_TIME); | 208 | at91wdt_miscdev.dev = &pdev->dev; |
206 | printk(KERN_INFO "at91_wdt: wdt_time value must be 1 <= wdt_time <= 256, using %d\n", wdt_time); | ||
207 | } | ||
208 | 209 | ||
209 | res = misc_register(&at91wdt_miscdev); | 210 | res = misc_register(&at91wdt_miscdev); |
210 | if (res) | 211 | if (res) |
211 | return res; | 212 | return res; |
212 | 213 | ||
213 | printk("AT91 Watchdog Timer enabled (%d seconds, nowayout=%d)\n", wdt_time, nowayout); | 214 | printk("AT91 Watchdog Timer enabled (%d seconds%s)\n", wdt_time, nowayout ? ", nowayout" : ""); |
214 | return 0; | 215 | return 0; |
215 | } | 216 | } |
216 | 217 | ||
218 | static int __exit at91wdt_remove(struct platform_device *pdev) | ||
219 | { | ||
220 | int res; | ||
221 | |||
222 | res = misc_deregister(&at91wdt_miscdev); | ||
223 | if (!res) | ||
224 | at91wdt_miscdev.dev = NULL; | ||
225 | |||
226 | return res; | ||
227 | } | ||
228 | |||
229 | static void at91wdt_shutdown(struct platform_device *pdev) | ||
230 | { | ||
231 | at91_wdt_stop(); | ||
232 | } | ||
233 | |||
234 | #ifdef CONFIG_PM | ||
235 | |||
236 | static int at91wdt_suspend(struct platform_device *pdev, pm_message_t message) | ||
237 | { | ||
238 | at91_wdt_stop(); | ||
239 | return 0; | ||
240 | } | ||
241 | |||
242 | static int at91wdt_resume(struct platform_device *pdev) | ||
243 | { | ||
244 | if (at91wdt_busy) | ||
245 | at91_wdt_start(); | ||
246 | return 0; | ||
247 | } | ||
248 | |||
249 | #else | ||
250 | #define at91wdt_suspend NULL | ||
251 | #define at91wdt_resume NULL | ||
252 | #endif | ||
253 | |||
254 | static struct platform_driver at91wdt_driver = { | ||
255 | .probe = at91wdt_probe, | ||
256 | .remove = __exit_p(at91wdt_remove), | ||
257 | .shutdown = at91wdt_shutdown, | ||
258 | .suspend = at91wdt_suspend, | ||
259 | .resume = at91wdt_resume, | ||
260 | .driver = { | ||
261 | .name = "at91_wdt", | ||
262 | .owner = THIS_MODULE, | ||
263 | }, | ||
264 | }; | ||
265 | |||
266 | static int __init at91_wdt_init(void) | ||
267 | { | ||
268 | /* Check that the heartbeat value is within range; if not reset to the default */ | ||
269 | if (at91_wdt_settimeout(wdt_time)) { | ||
270 | at91_wdt_settimeout(WDT_DEFAULT_TIME); | ||
271 | pr_info("at91_wdt: wdt_time value must be 1 <= wdt_time <= 256, using %d\n", wdt_time); | ||
272 | } | ||
273 | |||
274 | return platform_driver_register(&at91wdt_driver); | ||
275 | } | ||
276 | |||
217 | static void __exit at91_wdt_exit(void) | 277 | static void __exit at91_wdt_exit(void) |
218 | { | 278 | { |
219 | misc_deregister(&at91wdt_miscdev); | 279 | platform_driver_unregister(&at91wdt_driver); |
220 | } | 280 | } |
221 | 281 | ||
222 | module_init(at91_wdt_init); | 282 | module_init(at91_wdt_init); |
diff --git a/drivers/char/watchdog/i8xx_tco.c b/drivers/char/watchdog/i8xx_tco.c index fa2ba9ebe42a..bfbdbbf3c2f2 100644 --- a/drivers/char/watchdog/i8xx_tco.c +++ b/drivers/char/watchdog/i8xx_tco.c | |||
@@ -205,6 +205,23 @@ static int tco_timer_set_heartbeat (int t) | |||
205 | return 0; | 205 | return 0; |
206 | } | 206 | } |
207 | 207 | ||
208 | static int tco_timer_get_timeleft (int *time_left) | ||
209 | { | ||
210 | unsigned char val; | ||
211 | |||
212 | spin_lock(&tco_lock); | ||
213 | |||
214 | /* read the TCO Timer */ | ||
215 | val = inb (TCO1_RLD); | ||
216 | val &= 0x3f; | ||
217 | |||
218 | spin_unlock(&tco_lock); | ||
219 | |||
220 | *time_left = (int)((val * 6) / 10); | ||
221 | |||
222 | return 0; | ||
223 | } | ||
224 | |||
208 | /* | 225 | /* |
209 | * /dev/watchdog handling | 226 | * /dev/watchdog handling |
210 | */ | 227 | */ |
@@ -272,6 +289,7 @@ static int i8xx_tco_ioctl (struct inode *inode, struct file *file, | |||
272 | { | 289 | { |
273 | int new_options, retval = -EINVAL; | 290 | int new_options, retval = -EINVAL; |
274 | int new_heartbeat; | 291 | int new_heartbeat; |
292 | int time_left; | ||
275 | void __user *argp = (void __user *)arg; | 293 | void __user *argp = (void __user *)arg; |
276 | int __user *p = argp; | 294 | int __user *p = argp; |
277 | static struct watchdog_info ident = { | 295 | static struct watchdog_info ident = { |
@@ -320,7 +338,7 @@ static int i8xx_tco_ioctl (struct inode *inode, struct file *file, | |||
320 | return -EFAULT; | 338 | return -EFAULT; |
321 | 339 | ||
322 | if (tco_timer_set_heartbeat(new_heartbeat)) | 340 | if (tco_timer_set_heartbeat(new_heartbeat)) |
323 | return -EINVAL; | 341 | return -EINVAL; |
324 | 342 | ||
325 | tco_timer_keepalive (); | 343 | tco_timer_keepalive (); |
326 | /* Fall */ | 344 | /* Fall */ |
@@ -329,6 +347,14 @@ static int i8xx_tco_ioctl (struct inode *inode, struct file *file, | |||
329 | case WDIOC_GETTIMEOUT: | 347 | case WDIOC_GETTIMEOUT: |
330 | return put_user(heartbeat, p); | 348 | return put_user(heartbeat, p); |
331 | 349 | ||
350 | case WDIOC_GETTIMELEFT: | ||
351 | { | ||
352 | if (tco_timer_get_timeleft(&time_left)) | ||
353 | return -EINVAL; | ||
354 | |||
355 | return put_user(time_left, p); | ||
356 | } | ||
357 | |||
332 | default: | 358 | default: |
333 | return -ENOIOCTLCMD; | 359 | return -ENOIOCTLCMD; |
334 | } | 360 | } |
diff --git a/drivers/char/watchdog/pcwd_pci.c b/drivers/char/watchdog/pcwd_pci.c index 2451edbefece..1f40ecefbf72 100644 --- a/drivers/char/watchdog/pcwd_pci.c +++ b/drivers/char/watchdog/pcwd_pci.c | |||
@@ -21,7 +21,7 @@ | |||
21 | */ | 21 | */ |
22 | 22 | ||
23 | /* | 23 | /* |
24 | * A bells and whistles driver is available from: | 24 | * A bells and whistles driver is available from: |
25 | * http://www.kernel.org/pub/linux/kernel/people/wim/pcwd/pcwd_pci/ | 25 | * http://www.kernel.org/pub/linux/kernel/people/wim/pcwd/pcwd_pci/ |
26 | * | 26 | * |
27 | * More info available at http://www.berkprod.com/ or http://www.pcwatchdog.com/ | 27 | * More info available at http://www.berkprod.com/ or http://www.pcwatchdog.com/ |
@@ -390,6 +390,24 @@ static int pcipcwd_get_temperature(int *temperature) | |||
390 | return 0; | 390 | return 0; |
391 | } | 391 | } |
392 | 392 | ||
393 | static int pcipcwd_get_timeleft(int *time_left) | ||
394 | { | ||
395 | int msb; | ||
396 | int lsb; | ||
397 | |||
398 | /* Read the time that's left before rebooting */ | ||
399 | /* Note: if the board is not yet armed then we will read 0xFFFF */ | ||
400 | send_command(CMD_READ_WATCHDOG_TIMEOUT, &msb, &lsb); | ||
401 | |||
402 | *time_left = (msb << 8) + lsb; | ||
403 | |||
404 | if (debug >= VERBOSE) | ||
405 | printk(KERN_DEBUG PFX "Time left before next reboot: %d\n", | ||
406 | *time_left); | ||
407 | |||
408 | return 0; | ||
409 | } | ||
410 | |||
393 | /* | 411 | /* |
394 | * /dev/watchdog handling | 412 | * /dev/watchdog handling |
395 | */ | 413 | */ |
@@ -512,6 +530,16 @@ static int pcipcwd_ioctl(struct inode *inode, struct file *file, | |||
512 | case WDIOC_GETTIMEOUT: | 530 | case WDIOC_GETTIMEOUT: |
513 | return put_user(heartbeat, p); | 531 | return put_user(heartbeat, p); |
514 | 532 | ||
533 | case WDIOC_GETTIMELEFT: | ||
534 | { | ||
535 | int time_left; | ||
536 | |||
537 | if (pcipcwd_get_timeleft(&time_left)) | ||
538 | return -EFAULT; | ||
539 | |||
540 | return put_user(time_left, p); | ||
541 | } | ||
542 | |||
515 | default: | 543 | default: |
516 | return -ENOIOCTLCMD; | 544 | return -ENOIOCTLCMD; |
517 | } | 545 | } |
diff --git a/drivers/char/watchdog/pcwd_usb.c b/drivers/char/watchdog/pcwd_usb.c index 3fdfda9324fa..0d072bed501d 100644 --- a/drivers/char/watchdog/pcwd_usb.c +++ b/drivers/char/watchdog/pcwd_usb.c | |||
@@ -317,6 +317,19 @@ static int usb_pcwd_get_temperature(struct usb_pcwd_private *usb_pcwd, int *temp | |||
317 | return 0; | 317 | return 0; |
318 | } | 318 | } |
319 | 319 | ||
320 | static int usb_pcwd_get_timeleft(struct usb_pcwd_private *usb_pcwd, int *time_left) | ||
321 | { | ||
322 | unsigned char msb, lsb; | ||
323 | |||
324 | /* Read the time that's left before rebooting */ | ||
325 | /* Note: if the board is not yet armed then we will read 0xFFFF */ | ||
326 | usb_pcwd_send_command(usb_pcwd, CMD_READ_WATCHDOG_TIMEOUT, &msb, &lsb); | ||
327 | |||
328 | *time_left = (msb << 8) + lsb; | ||
329 | |||
330 | return 0; | ||
331 | } | ||
332 | |||
320 | /* | 333 | /* |
321 | * /dev/watchdog handling | 334 | * /dev/watchdog handling |
322 | */ | 335 | */ |
@@ -422,6 +435,16 @@ static int usb_pcwd_ioctl(struct inode *inode, struct file *file, | |||
422 | case WDIOC_GETTIMEOUT: | 435 | case WDIOC_GETTIMEOUT: |
423 | return put_user(heartbeat, p); | 436 | return put_user(heartbeat, p); |
424 | 437 | ||
438 | case WDIOC_GETTIMELEFT: | ||
439 | { | ||
440 | int time_left; | ||
441 | |||
442 | if (usb_pcwd_get_timeleft(usb_pcwd_device, &time_left)) | ||
443 | return -EFAULT; | ||
444 | |||
445 | return put_user(time_left, p); | ||
446 | } | ||
447 | |||
425 | default: | 448 | default: |
426 | return -ENOIOCTLCMD; | 449 | return -ENOIOCTLCMD; |
427 | } | 450 | } |