Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[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>

+92 -5
+9
Documentation/watchdog/watchdog-api.txt
··· 134 134 135 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 146 Environmental monitoring: 138 147 139 148 All watchdog drivers are required return more information about the system,
+27 -1
drivers/char/watchdog/i8xx_tco.c
··· 205 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 226 * /dev/watchdog handling 210 227 */ ··· 289 272 { 290 273 int new_options, retval = -EINVAL; 291 274 int new_heartbeat; 275 + int time_left; 292 276 void __user *argp = (void __user *)arg; 293 277 int __user *p = argp; 294 278 static struct watchdog_info ident = { ··· 338 320 return -EFAULT; 339 321 340 322 if (tco_timer_set_heartbeat(new_heartbeat)) 341 - return -EINVAL; 323 + return -EINVAL; 342 324 343 325 tco_timer_keepalive (); 344 326 /* Fall */ ··· 346 328 347 329 case WDIOC_GETTIMEOUT: 348 330 return put_user(heartbeat, p); 331 + 332 + case WDIOC_GETTIMELEFT: 333 + { 334 + if (tco_timer_get_timeleft(&time_left)) 335 + return -EINVAL; 336 + 337 + return put_user(time_left, p); 338 + } 349 339 350 340 default: 351 341 return -ENOIOCTLCMD;
+29 -1
drivers/char/watchdog/pcwd_pci.c
··· 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 25 * http://www.kernel.org/pub/linux/kernel/people/wim/pcwd/pcwd_pci/ 26 26 * 27 27 * More info available at http://www.berkprod.com/ or http://www.pcwatchdog.com/ ··· 390 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 412 * /dev/watchdog handling 395 413 */ ··· 529 511 530 512 case WDIOC_GETTIMEOUT: 531 513 return put_user(heartbeat, p); 514 + 515 + case WDIOC_GETTIMELEFT: 516 + { 517 + int time_left; 518 + 519 + if (pcipcwd_get_timeleft(&time_left)) 520 + return -EFAULT; 521 + 522 + return put_user(time_left, p); 523 + } 532 524 533 525 default: 534 526 return -ENOIOCTLCMD;
+23
drivers/char/watchdog/pcwd_usb.c
··· 317 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 334 * /dev/watchdog handling 322 335 */ ··· 434 421 435 422 case WDIOC_GETTIMEOUT: 436 423 return put_user(heartbeat, p); 424 + 425 + case WDIOC_GETTIMELEFT: 426 + { 427 + int time_left; 428 + 429 + if (usb_pcwd_get_timeleft(usb_pcwd_device, &time_left)) 430 + return -EFAULT; 431 + 432 + return put_user(time_left, p); 433 + } 437 434 438 435 default: 439 436 return -ENOIOCTLCMD;
+4 -3
include/linux/watchdog.h
··· 30 30 #define WDIOC_GETTIMEOUT _IOR(WATCHDOG_IOCTL_BASE, 7, int) 31 31 #define WDIOC_SETPRETIMEOUT _IOWR(WATCHDOG_IOCTL_BASE, 8, int) 32 32 #define WDIOC_GETPRETIMEOUT _IOR(WATCHDOG_IOCTL_BASE, 9, int) 33 + #define WDIOC_GETTIMELEFT _IOR(WATCHDOG_IOCTL_BASE, 10, int) 33 34 34 35 #define WDIOF_UNKNOWN -1 /* Unknown flag error */ 35 36 #define WDIOS_UNKNOWN -1 /* Unknown status error */ ··· 41 40 #define WDIOF_EXTERN2 0x0008 /* External relay 2 */ 42 41 #define WDIOF_POWERUNDER 0x0010 /* Power bad/power fault */ 43 42 #define WDIOF_CARDRESET 0x0020 /* Card previously reset the CPU */ 44 - #define WDIOF_POWEROVER 0x0040 /* Power over voltage */ 45 - #define WDIOF_SETTIMEOUT 0x0080 /* Set timeout (in seconds) */ 46 - #define WDIOF_MAGICCLOSE 0x0100 /* Supports magic close char */ 43 + #define WDIOF_POWEROVER 0x0040 /* Power over voltage */ 44 + #define WDIOF_SETTIMEOUT 0x0080 /* Set timeout (in seconds) */ 45 + #define WDIOF_MAGICCLOSE 0x0100 /* Supports magic close char */ 47 46 #define WDIOF_PRETIMEOUT 0x0200 /* Pretimeout (in seconds), get/set */ 48 47 #define WDIOF_KEEPALIVEPING 0x8000 /* Keep alive ping reply */ 49 48