aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWim Van Sebroeck <wim@iguana.be>2006-05-21 06:48:44 -0400
committerWim Van Sebroeck <wim@iguana.be>2006-06-20 13:00:30 -0400
commit58b519f3e5e491d5a3e320dc525f58ac439bdde4 (patch)
treeefff3a0bd308effbbedce1a50fbb40d71e5b5d96
parente05b59fe7927bc648ac3af3d59dc64a7ee6b22e2 (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.txt9
-rw-r--r--drivers/char/watchdog/i8xx_tco.c28
-rw-r--r--drivers/char/watchdog/pcwd_pci.c30
-rw-r--r--drivers/char/watchdog/pcwd_usb.c23
-rw-r--r--include/linux/watchdog.h7
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
135Not all watchdog drivers will support a pretimeout. 135Not all watchdog drivers will support a pretimeout.
136 136
137Get the number of seconds before reboot:
138
139Some watchdog drivers have the ability to report the remaining time
140before the system will reboot. The WDIOC_GETTIMELEFT is the ioctl
141that 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
137Environmental monitoring: 146Environmental monitoring:
138 147
139All watchdog drivers are required return more information about the system, 148All 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
208static 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
393static 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
320static 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