diff options
| author | Wim Van Sebroeck <wim@iguana.be> | 2006-05-21 06:48:44 -0400 |
|---|---|---|
| committer | Wim Van Sebroeck <wim@iguana.be> | 2006-06-20 13:00:30 -0400 |
| commit | 58b519f3e5e491d5a3e320dc525f58ac439bdde4 (patch) | |
| tree | efff3a0bd308effbbedce1a50fbb40d71e5b5d96 | |
| parent | e05b59fe7927bc648ac3af3d59dc64a7ee6b22e2 (diff) | |
[WATCHDOG] add WDIOC_GETTIMELEFT ioctl
Some watchdog drivers have the ability to report the remaining time
before the system will reboot. With the WDIOC_GETTIMELEFT ioctl
you can now read the time left before the watchdog would reboot
your system.
The following drivers support this new IOCTL:
i8xx_tco.c, pcwd_pci.c and pcwd_usb.c .
Signed-off-by: Wim Van Sebroeck <wim@iguana.be>
Signed-off-by: Andrew Morton <akpm@osdl.org>
| -rw-r--r-- | Documentation/watchdog/watchdog-api.txt | 9 | ||||
| -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 | ||||
| -rw-r--r-- | include/linux/watchdog.h | 7 |
5 files changed, 92 insertions, 5 deletions
diff --git a/Documentation/watchdog/watchdog-api.txt b/Documentation/watchdog/watchdog-api.txt index 7dc2c1c6f779..d738ec25eaa4 100644 --- a/Documentation/watchdog/watchdog-api.txt +++ b/Documentation/watchdog/watchdog-api.txt | |||
| @@ -134,6 +134,15 @@ There is also a get function for getting the pretimeout: | |||
| 134 | 134 | ||
| 135 | Not all watchdog drivers will support a pretimeout. | 135 | Not all watchdog drivers will support a pretimeout. |
| 136 | 136 | ||
| 137 | Get the number of seconds before reboot: | ||
| 138 | |||
| 139 | Some watchdog drivers have the ability to report the remaining time | ||
| 140 | before the system will reboot. The WDIOC_GETTIMELEFT is the ioctl | ||
| 141 | that returns the number of seconds before reboot. | ||
| 142 | |||
| 143 | ioctl(fd, WDIOC_GETTIMELEFT, &timeleft); | ||
| 144 | printf("The timeout was is %d seconds\n", timeleft); | ||
| 145 | |||
| 137 | Environmental monitoring: | 146 | Environmental monitoring: |
| 138 | 147 | ||
| 139 | All watchdog drivers are required return more information about the system, | 148 | All watchdog drivers are required return more information about the system, |
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 | } |
diff --git a/include/linux/watchdog.h b/include/linux/watchdog.h index a99c937f665e..011bcfeb9f09 100644 --- a/include/linux/watchdog.h +++ b/include/linux/watchdog.h | |||
| @@ -30,6 +30,7 @@ struct watchdog_info { | |||
| 30 | #define WDIOC_GETTIMEOUT _IOR(WATCHDOG_IOCTL_BASE, 7, int) | 30 | #define WDIOC_GETTIMEOUT _IOR(WATCHDOG_IOCTL_BASE, 7, int) |
| 31 | #define WDIOC_SETPRETIMEOUT _IOWR(WATCHDOG_IOCTL_BASE, 8, int) | 31 | #define WDIOC_SETPRETIMEOUT _IOWR(WATCHDOG_IOCTL_BASE, 8, int) |
| 32 | #define WDIOC_GETPRETIMEOUT _IOR(WATCHDOG_IOCTL_BASE, 9, int) | 32 | #define WDIOC_GETPRETIMEOUT _IOR(WATCHDOG_IOCTL_BASE, 9, int) |
| 33 | #define WDIOC_GETTIMELEFT _IOR(WATCHDOG_IOCTL_BASE, 10, int) | ||
| 33 | 34 | ||
| 34 | #define WDIOF_UNKNOWN -1 /* Unknown flag error */ | 35 | #define WDIOF_UNKNOWN -1 /* Unknown flag error */ |
| 35 | #define WDIOS_UNKNOWN -1 /* Unknown status error */ | 36 | #define WDIOS_UNKNOWN -1 /* Unknown status error */ |
| @@ -40,9 +41,9 @@ struct watchdog_info { | |||
| 40 | #define WDIOF_EXTERN2 0x0008 /* External relay 2 */ | 41 | #define WDIOF_EXTERN2 0x0008 /* External relay 2 */ |
| 41 | #define WDIOF_POWERUNDER 0x0010 /* Power bad/power fault */ | 42 | #define WDIOF_POWERUNDER 0x0010 /* Power bad/power fault */ |
| 42 | #define WDIOF_CARDRESET 0x0020 /* Card previously reset the CPU */ | 43 | #define WDIOF_CARDRESET 0x0020 /* Card previously reset the CPU */ |
| 43 | #define WDIOF_POWEROVER 0x0040 /* Power over voltage */ | 44 | #define WDIOF_POWEROVER 0x0040 /* Power over voltage */ |
| 44 | #define WDIOF_SETTIMEOUT 0x0080 /* Set timeout (in seconds) */ | 45 | #define WDIOF_SETTIMEOUT 0x0080 /* Set timeout (in seconds) */ |
| 45 | #define WDIOF_MAGICCLOSE 0x0100 /* Supports magic close char */ | 46 | #define WDIOF_MAGICCLOSE 0x0100 /* Supports magic close char */ |
| 46 | #define WDIOF_PRETIMEOUT 0x0200 /* Pretimeout (in seconds), get/set */ | 47 | #define WDIOF_PRETIMEOUT 0x0200 /* Pretimeout (in seconds), get/set */ |
| 47 | #define WDIOF_KEEPALIVEPING 0x8000 /* Keep alive ping reply */ | 48 | #define WDIOF_KEEPALIVEPING 0x8000 /* Keep alive ping reply */ |
| 48 | 49 | ||
