Skip to content

Commit

Permalink
[WATCHDOG] add WDIOC_GETTIMELEFT ioctl
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Wim Van Sebroeck committed Jun 20, 2006
1 parent e05b59f commit 58b519f
Show file tree
Hide file tree
Showing 5 changed files with 92 additions and 5 deletions.
9 changes: 9 additions & 0 deletions Documentation/watchdog/watchdog-api.txt
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,15 @@ There is also a get function for getting the pretimeout:

Not all watchdog drivers will support a pretimeout.

Get the number of seconds before reboot:

Some watchdog drivers have the ability to report the remaining time
before the system will reboot. The WDIOC_GETTIMELEFT is the ioctl
that returns the number of seconds before reboot.

ioctl(fd, WDIOC_GETTIMELEFT, &timeleft);
printf("The timeout was is %d seconds\n", timeleft);

Environmental monitoring:

All watchdog drivers are required return more information about the system,
Expand Down
28 changes: 27 additions & 1 deletion drivers/char/watchdog/i8xx_tco.c
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,23 @@ static int tco_timer_set_heartbeat (int t)
return 0;
}

static int tco_timer_get_timeleft (int *time_left)
{
unsigned char val;

spin_lock(&tco_lock);

/* read the TCO Timer */
val = inb (TCO1_RLD);
val &= 0x3f;

spin_unlock(&tco_lock);

*time_left = (int)((val * 6) / 10);

return 0;
}

/*
* /dev/watchdog handling
*/
Expand Down Expand Up @@ -272,6 +289,7 @@ static int i8xx_tco_ioctl (struct inode *inode, struct file *file,
{
int new_options, retval = -EINVAL;
int new_heartbeat;
int time_left;
void __user *argp = (void __user *)arg;
int __user *p = argp;
static struct watchdog_info ident = {
Expand Down Expand Up @@ -320,7 +338,7 @@ static int i8xx_tco_ioctl (struct inode *inode, struct file *file,
return -EFAULT;

if (tco_timer_set_heartbeat(new_heartbeat))
return -EINVAL;
return -EINVAL;

tco_timer_keepalive ();
/* Fall */
Expand All @@ -329,6 +347,14 @@ static int i8xx_tco_ioctl (struct inode *inode, struct file *file,
case WDIOC_GETTIMEOUT:
return put_user(heartbeat, p);

case WDIOC_GETTIMELEFT:
{
if (tco_timer_get_timeleft(&time_left))
return -EINVAL;

return put_user(time_left, p);
}

default:
return -ENOIOCTLCMD;
}
Expand Down
30 changes: 29 additions & 1 deletion drivers/char/watchdog/pcwd_pci.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
*/

/*
* A bells and whistles driver is available from:
* A bells and whistles driver is available from:
* http://www.kernel.org/pub/linux/kernel/people/wim/pcwd/pcwd_pci/
*
* More info available at http://www.berkprod.com/ or http://www.pcwatchdog.com/
Expand Down Expand Up @@ -390,6 +390,24 @@ static int pcipcwd_get_temperature(int *temperature)
return 0;
}

static int pcipcwd_get_timeleft(int *time_left)
{
int msb;
int lsb;

/* Read the time that's left before rebooting */
/* Note: if the board is not yet armed then we will read 0xFFFF */
send_command(CMD_READ_WATCHDOG_TIMEOUT, &msb, &lsb);

*time_left = (msb << 8) + lsb;

if (debug >= VERBOSE)
printk(KERN_DEBUG PFX "Time left before next reboot: %d\n",
*time_left);

return 0;
}

/*
* /dev/watchdog handling
*/
Expand Down Expand Up @@ -512,6 +530,16 @@ static int pcipcwd_ioctl(struct inode *inode, struct file *file,
case WDIOC_GETTIMEOUT:
return put_user(heartbeat, p);

case WDIOC_GETTIMELEFT:
{
int time_left;

if (pcipcwd_get_timeleft(&time_left))
return -EFAULT;

return put_user(time_left, p);
}

default:
return -ENOIOCTLCMD;
}
Expand Down
23 changes: 23 additions & 0 deletions drivers/char/watchdog/pcwd_usb.c
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,19 @@ static int usb_pcwd_get_temperature(struct usb_pcwd_private *usb_pcwd, int *temp
return 0;
}

static int usb_pcwd_get_timeleft(struct usb_pcwd_private *usb_pcwd, int *time_left)
{
unsigned char msb, lsb;

/* Read the time that's left before rebooting */
/* Note: if the board is not yet armed then we will read 0xFFFF */
usb_pcwd_send_command(usb_pcwd, CMD_READ_WATCHDOG_TIMEOUT, &msb, &lsb);

*time_left = (msb << 8) + lsb;

return 0;
}

/*
* /dev/watchdog handling
*/
Expand Down Expand Up @@ -422,6 +435,16 @@ static int usb_pcwd_ioctl(struct inode *inode, struct file *file,
case WDIOC_GETTIMEOUT:
return put_user(heartbeat, p);

case WDIOC_GETTIMELEFT:
{
int time_left;

if (usb_pcwd_get_timeleft(usb_pcwd_device, &time_left))
return -EFAULT;

return put_user(time_left, p);
}

default:
return -ENOIOCTLCMD;
}
Expand Down
7 changes: 4 additions & 3 deletions include/linux/watchdog.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ struct watchdog_info {
#define WDIOC_GETTIMEOUT _IOR(WATCHDOG_IOCTL_BASE, 7, int)
#define WDIOC_SETPRETIMEOUT _IOWR(WATCHDOG_IOCTL_BASE, 8, int)
#define WDIOC_GETPRETIMEOUT _IOR(WATCHDOG_IOCTL_BASE, 9, int)
#define WDIOC_GETTIMELEFT _IOR(WATCHDOG_IOCTL_BASE, 10, int)

#define WDIOF_UNKNOWN -1 /* Unknown flag error */
#define WDIOS_UNKNOWN -1 /* Unknown status error */
Expand All @@ -40,9 +41,9 @@ struct watchdog_info {
#define WDIOF_EXTERN2 0x0008 /* External relay 2 */
#define WDIOF_POWERUNDER 0x0010 /* Power bad/power fault */
#define WDIOF_CARDRESET 0x0020 /* Card previously reset the CPU */
#define WDIOF_POWEROVER 0x0040 /* Power over voltage */
#define WDIOF_SETTIMEOUT 0x0080 /* Set timeout (in seconds) */
#define WDIOF_MAGICCLOSE 0x0100 /* Supports magic close char */
#define WDIOF_POWEROVER 0x0040 /* Power over voltage */
#define WDIOF_SETTIMEOUT 0x0080 /* Set timeout (in seconds) */
#define WDIOF_MAGICCLOSE 0x0100 /* Supports magic close char */
#define WDIOF_PRETIMEOUT 0x0200 /* Pretimeout (in seconds), get/set */
#define WDIOF_KEEPALIVEPING 0x8000 /* Keep alive ping reply */

Expand Down

0 comments on commit 58b519f

Please sign in to comment.