aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@g5.osdl.org>2006-06-28 19:03:06 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2006-06-28 19:03:06 -0400
commitfffcb480e4224f25c965b93fa65541bfc7dd732e (patch)
treea48383b5487798cdcc0153e342d6d88abe71333d
parentb44597906e03d5e2b467c17a3b73585596c0d7be (diff)
parent56fb9e5346b99bc6b77def79b3739097bc13ea8a (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
-rw-r--r--Documentation/watchdog/pcwd-watchdog.txt75
-rw-r--r--Documentation/watchdog/src/watchdog-simple.c15
-rw-r--r--Documentation/watchdog/src/watchdog-test.c68
-rw-r--r--Documentation/watchdog/watchdog-api.txt56
-rw-r--r--Documentation/watchdog/watchdog.txt23
-rw-r--r--drivers/char/watchdog/at91_wdt.c82
-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.h10
10 files changed, 283 insertions, 127 deletions
diff --git a/Documentation/watchdog/pcwd-watchdog.txt b/Documentation/watchdog/pcwd-watchdog.txt
index 12187a33e310..d9ee6336c1d4 100644
--- a/Documentation/watchdog/pcwd-watchdog.txt
+++ b/Documentation/watchdog/pcwd-watchdog.txt
@@ -22,78 +22,9 @@
22 to run the program with an "&" to run it in the background!) 22 to run the program with an "&" to run it in the background!)
23 23
24 If you want to write a program to be compatible with the PC Watchdog 24 If you want to write a program to be compatible with the PC Watchdog
25 driver, simply do the following: 25 driver, simply use of modify the watchdog test program:
26 26 Documentation/watchdog/src/watchdog-test.c
27-- Snippet of code -- 27
28/*
29 * Watchdog Driver Test Program
30 */
31
32#include <stdio.h>
33#include <stdlib.h>
34#include <string.h>
35#include <unistd.h>
36#include <fcntl.h>
37#include <sys/ioctl.h>
38#include <linux/types.h>
39#include <linux/watchdog.h>
40
41int fd;
42
43/*
44 * This function simply sends an IOCTL to the driver, which in turn ticks
45 * the PC Watchdog card to reset its internal timer so it doesn't trigger
46 * a computer reset.
47 */
48void keep_alive(void)
49{
50 int dummy;
51
52 ioctl(fd, WDIOC_KEEPALIVE, &dummy);
53}
54
55/*
56 * The main program. Run the program with "-d" to disable the card,
57 * or "-e" to enable the card.
58 */
59int main(int argc, char *argv[])
60{
61 fd = open("/dev/watchdog", O_WRONLY);
62
63 if (fd == -1) {
64 fprintf(stderr, "Watchdog device not enabled.\n");
65 fflush(stderr);
66 exit(-1);
67 }
68
69 if (argc > 1) {
70 if (!strncasecmp(argv[1], "-d", 2)) {
71 ioctl(fd, WDIOC_SETOPTIONS, WDIOS_DISABLECARD);
72 fprintf(stderr, "Watchdog card disabled.\n");
73 fflush(stderr);
74 exit(0);
75 } else if (!strncasecmp(argv[1], "-e", 2)) {
76 ioctl(fd, WDIOC_SETOPTIONS, WDIOS_ENABLECARD);
77 fprintf(stderr, "Watchdog card enabled.\n");
78 fflush(stderr);
79 exit(0);
80 } else {
81 fprintf(stderr, "-d to disable, -e to enable.\n");
82 fprintf(stderr, "run by itself to tick the card.\n");
83 fflush(stderr);
84 exit(0);
85 }
86 } else {
87 fprintf(stderr, "Watchdog Ticking Away!\n");
88 fflush(stderr);
89 }
90
91 while(1) {
92 keep_alive();
93 sleep(1);
94 }
95}
96-- End snippet --
97 28
98 Other IOCTL functions include: 29 Other IOCTL functions include:
99 30
diff --git a/Documentation/watchdog/src/watchdog-simple.c b/Documentation/watchdog/src/watchdog-simple.c
new file mode 100644
index 000000000000..85cf17c48669
--- /dev/null
+++ b/Documentation/watchdog/src/watchdog-simple.c
@@ -0,0 +1,15 @@
1#include <stdlib.h>
2#include <fcntl.h>
3
4int main(int argc, const char *argv[]) {
5 int fd = open("/dev/watchdog", O_WRONLY);
6 if (fd == -1) {
7 perror("watchdog");
8 exit(1);
9 }
10 while (1) {
11 write(fd, "\0", 1);
12 fsync(fd);
13 sleep(10);
14 }
15}
diff --git a/Documentation/watchdog/src/watchdog-test.c b/Documentation/watchdog/src/watchdog-test.c
new file mode 100644
index 000000000000..65f6c19cb865
--- /dev/null
+++ b/Documentation/watchdog/src/watchdog-test.c
@@ -0,0 +1,68 @@
1/*
2 * Watchdog Driver Test Program
3 */
4
5#include <stdio.h>
6#include <stdlib.h>
7#include <string.h>
8#include <unistd.h>
9#include <fcntl.h>
10#include <sys/ioctl.h>
11#include <linux/types.h>
12#include <linux/watchdog.h>
13
14int fd;
15
16/*
17 * This function simply sends an IOCTL to the driver, which in turn ticks
18 * the PC Watchdog card to reset its internal timer so it doesn't trigger
19 * a computer reset.
20 */
21void keep_alive(void)
22{
23 int dummy;
24
25 ioctl(fd, WDIOC_KEEPALIVE, &dummy);
26}
27
28/*
29 * The main program. Run the program with "-d" to disable the card,
30 * or "-e" to enable the card.
31 */
32int main(int argc, char *argv[])
33{
34 fd = open("/dev/watchdog", O_WRONLY);
35
36 if (fd == -1) {
37 fprintf(stderr, "Watchdog device not enabled.\n");
38 fflush(stderr);
39 exit(-1);
40 }
41
42 if (argc > 1) {
43 if (!strncasecmp(argv[1], "-d", 2)) {
44 ioctl(fd, WDIOC_SETOPTIONS, WDIOS_DISABLECARD);
45 fprintf(stderr, "Watchdog card disabled.\n");
46 fflush(stderr);
47 exit(0);
48 } else if (!strncasecmp(argv[1], "-e", 2)) {
49 ioctl(fd, WDIOC_SETOPTIONS, WDIOS_ENABLECARD);
50 fprintf(stderr, "Watchdog card enabled.\n");
51 fflush(stderr);
52 exit(0);
53 } else {
54 fprintf(stderr, "-d to disable, -e to enable.\n");
55 fprintf(stderr, "run by itself to tick the card.\n");
56 fflush(stderr);
57 exit(0);
58 }
59 } else {
60 fprintf(stderr, "Watchdog Ticking Away!\n");
61 fflush(stderr);
62 }
63
64 while(1) {
65 keep_alive();
66 sleep(1);
67 }
68}
diff --git a/Documentation/watchdog/watchdog-api.txt b/Documentation/watchdog/watchdog-api.txt
index 21ed51173662..958ff3d48be3 100644
--- a/Documentation/watchdog/watchdog-api.txt
+++ b/Documentation/watchdog/watchdog-api.txt
@@ -34,22 +34,7 @@ activates as soon as /dev/watchdog is opened and will reboot unless
34the watchdog is pinged within a certain time, this time is called the 34the watchdog is pinged within a certain time, this time is called the
35timeout or margin. The simplest way to ping the watchdog is to write 35timeout or margin. The simplest way to ping the watchdog is to write
36some data to the device. So a very simple watchdog daemon would look 36some data to the device. So a very simple watchdog daemon would look
37like this: 37like this source file: see Documentation/watchdog/src/watchdog-simple.c
38
39#include <stdlib.h>
40#include <fcntl.h>
41
42int main(int argc, const char *argv[]) {
43 int fd=open("/dev/watchdog",O_WRONLY);
44 if (fd==-1) {
45 perror("watchdog");
46 exit(1);
47 }
48 while(1) {
49 write(fd, "\0", 1);
50 sleep(10);
51 }
52}
53 38
54A more advanced driver could for example check that a HTTP server is 39A more advanced driver could for example check that a HTTP server is
55still responding before doing the write call to ping the watchdog. 40still responding before doing the write call to ping the watchdog.
@@ -110,7 +95,40 @@ current timeout using the GETTIMEOUT ioctl.
110 ioctl(fd, WDIOC_GETTIMEOUT, &timeout); 95 ioctl(fd, WDIOC_GETTIMEOUT, &timeout);
111 printf("The timeout was is %d seconds\n", timeout); 96 printf("The timeout was is %d seconds\n", timeout);
112 97
113Envinronmental monitoring: 98Pretimeouts:
99
100Some watchdog timers can be set to have a trigger go off before the
101actual time they will reset the system. This can be done with an NMI,
102interrupt, or other mechanism. This allows Linux to record useful
103information (like panic information and kernel coredumps) before it
104resets.
105
106 pretimeout = 10;
107 ioctl(fd, WDIOC_SETPRETIMEOUT, &pretimeout);
108
109Note that the pretimeout is the number of seconds before the time
110when the timeout will go off. It is not the number of seconds until
111the pretimeout. So, for instance, if you set the timeout to 60 seconds
112and the pretimeout to 10 seconds, the pretimout will go of in 50
113seconds. Setting a pretimeout to zero disables it.
114
115There is also a get function for getting the pretimeout:
116
117 ioctl(fd, WDIOC_GETPRETIMEOUT, &timeout);
118 printf("The pretimeout was is %d seconds\n", timeout);
119
120Not all watchdog drivers will support a pretimeout.
121
122Get the number of seconds before reboot:
123
124Some watchdog drivers have the ability to report the remaining time
125before the system will reboot. The WDIOC_GETTIMELEFT is the ioctl
126that returns the number of seconds before reboot.
127
128 ioctl(fd, WDIOC_GETTIMELEFT, &timeleft);
129 printf("The timeout was is %d seconds\n", timeleft);
130
131Environmental monitoring:
114 132
115All watchdog drivers are required return more information about the system, 133All watchdog drivers are required return more information about the system,
116some do temperature, fan and power level monitoring, some can tell you 134some do temperature, fan and power level monitoring, some can tell you
@@ -169,6 +187,10 @@ The watchdog saw a keepalive ping since it was last queried.
169 187
170 WDIOF_SETTIMEOUT Can set/get the timeout 188 WDIOF_SETTIMEOUT Can set/get the timeout
171 189
190The watchdog can do pretimeouts.
191
192 WDIOF_PRETIMEOUT Pretimeout (in seconds), get/set
193
172 194
173For those drivers that return any bits set in the option field, the 195For those drivers that return any bits set in the option field, the
174GETSTATUS and GETBOOTSTATUS ioctls can be used to ask for the current 196GETSTATUS and GETBOOTSTATUS ioctls can be used to ask for the current
diff --git a/Documentation/watchdog/watchdog.txt b/Documentation/watchdog/watchdog.txt
index dffda29c8799..4b1ff69cc19a 100644
--- a/Documentation/watchdog/watchdog.txt
+++ b/Documentation/watchdog/watchdog.txt
@@ -65,28 +65,7 @@ The external event interfaces on the WDT boards are not currently supported.
65Minor numbers are however allocated for it. 65Minor numbers are however allocated for it.
66 66
67 67
68Example Watchdog Driver 68Example Watchdog Driver: see Documentation/watchdog/src/watchdog-simple.c
69-----------------------
70
71#include <stdio.h>
72#include <unistd.h>
73#include <fcntl.h>
74
75int main(int argc, const char *argv[])
76{
77 int fd=open("/dev/watchdog",O_WRONLY);
78 if(fd==-1)
79 {
80 perror("watchdog");
81 exit(1);
82 }
83 while(1)
84 {
85 write(fd,"\0",1);
86 fsync(fd);
87 sleep(10);
88 }
89}
90 69
91 70
92Contact Information 71Contact Information
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
29static int wdt_time = WDT_DEFAULT_TIME; 30static int wdt_time = WDT_DEFAULT_TIME;
30static int nowayout = WATCHDOG_NOWAYOUT; 31static int nowayout = WATCHDOG_NOWAYOUT;
@@ -32,8 +33,10 @@ static int nowayout = WATCHDOG_NOWAYOUT;
32module_param(wdt_time, int, 0); 33module_param(wdt_time, int, 0);
33MODULE_PARM_DESC(wdt_time, "Watchdog time in seconds. (default="__MODULE_STRING(WDT_DEFAULT_TIME) ")"); 34MODULE_PARM_DESC(wdt_time, "Watchdog time in seconds. (default="__MODULE_STRING(WDT_DEFAULT_TIME) ")");
34 35
36#ifdef CONFIG_WATCHDOG_NOWAYOUT
35module_param(nowayout, int, 0); 37module_param(nowayout, int, 0);
36MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); 38MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
39#endif
37 40
38 41
39static unsigned long at91wdt_busy; 42static 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
199static int __init at91_wdt_init(void) 202static 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
218static 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
229static void at91wdt_shutdown(struct platform_device *pdev)
230{
231 at91_wdt_stop();
232}
233
234#ifdef CONFIG_PM
235
236static int at91wdt_suspend(struct platform_device *pdev, pm_message_t message)
237{
238 at91_wdt_stop();
239 return 0;
240}
241
242static 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
254static 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
266static 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
217static void __exit at91_wdt_exit(void) 277static void __exit at91_wdt_exit(void)
218{ 278{
219 misc_deregister(&at91wdt_miscdev); 279 platform_driver_unregister(&at91wdt_driver);
220} 280}
221 281
222module_init(at91_wdt_init); 282module_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
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 1192ed8f4fe8..011bcfeb9f09 100644
--- a/include/linux/watchdog.h
+++ b/include/linux/watchdog.h
@@ -28,6 +28,9 @@ struct watchdog_info {
28#define WDIOC_KEEPALIVE _IOR(WATCHDOG_IOCTL_BASE, 5, int) 28#define WDIOC_KEEPALIVE _IOR(WATCHDOG_IOCTL_BASE, 5, int)
29#define WDIOC_SETTIMEOUT _IOWR(WATCHDOG_IOCTL_BASE, 6, int) 29#define WDIOC_SETTIMEOUT _IOWR(WATCHDOG_IOCTL_BASE, 6, int)
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)
32#define WDIOC_GETPRETIMEOUT _IOR(WATCHDOG_IOCTL_BASE, 9, int)
33#define WDIOC_GETTIMELEFT _IOR(WATCHDOG_IOCTL_BASE, 10, int)
31 34
32#define WDIOF_UNKNOWN -1 /* Unknown flag error */ 35#define WDIOF_UNKNOWN -1 /* Unknown flag error */
33#define WDIOS_UNKNOWN -1 /* Unknown status error */ 36#define WDIOS_UNKNOWN -1 /* Unknown status error */
@@ -38,9 +41,10 @@ struct watchdog_info {
38#define WDIOF_EXTERN2 0x0008 /* External relay 2 */ 41#define WDIOF_EXTERN2 0x0008 /* External relay 2 */
39#define WDIOF_POWERUNDER 0x0010 /* Power bad/power fault */ 42#define WDIOF_POWERUNDER 0x0010 /* Power bad/power fault */
40#define WDIOF_CARDRESET 0x0020 /* Card previously reset the CPU */ 43#define WDIOF_CARDRESET 0x0020 /* Card previously reset the CPU */
41#define WDIOF_POWEROVER 0x0040 /* Power over voltage */ 44#define WDIOF_POWEROVER 0x0040 /* Power over voltage */
42#define WDIOF_SETTIMEOUT 0x0080 /* Set timeout (in seconds) */ 45#define WDIOF_SETTIMEOUT 0x0080 /* Set timeout (in seconds) */
43#define WDIOF_MAGICCLOSE 0x0100 /* Supports magic close char */ 46#define WDIOF_MAGICCLOSE 0x0100 /* Supports magic close char */
47#define WDIOF_PRETIMEOUT 0x0200 /* Pretimeout (in seconds), get/set */
44#define WDIOF_KEEPALIVEPING 0x8000 /* Keep alive ping reply */ 48#define WDIOF_KEEPALIVEPING 0x8000 /* Keep alive ping reply */
45 49
46#define WDIOS_DISABLECARD 0x0001 /* Turn off the watchdog timer */ 50#define WDIOS_DISABLECARD 0x0001 /* Turn off the watchdog timer */