I needed a way to set the software watchdog timer to use a runtime-set
"no way out" value instead of only CONFIG_WATCHDOG_NOWAYOUT. Rather
than modify only softdog.o, Alan Cox suggested I modify all the watchdog
drivers. Accordingly, the patch is below and posted to
http://domsch.com/linux/patches/linux-2.4.17-rc1-watchdog-nowayout-20011
217.patch. I'm cc:ing all the listed maintainers. Please respond to me
privately with your approval or suggested changes per driver. I don't
have any of this hardware to test with myself.
Most drivers were modified to add a 'nowayout=[01]' module parameter
which defaults to CONFIG_WATCHDOG_NOWAYOUT if not passed. wdt285.c
wasn't written to allow a way out at all, so it wasn't modified.
To the following drivers was also added a 'timeout=X' module parameter,
where timeout is specified in seconds. Only drivers for which no
similar parm was already present were modified:
advantechwdt.c ([email protected])
eurotechwdt.c ([email protected], [email protected])
ib700wdt.c ([email protected])
pcwd.c ([email protected])
wdt.c ([email protected])
wdt_pci.c ([email protected])
These already offer a timeout parm:
i810-tco.c ([email protected])
softdog.c ([email protected])
wdt285.o ([email protected])
These didn't get a timeout parm because it wasn't obvious if or how it
could be done:
machzwd.c ([email protected])
mixcomwd.c ([email protected], [email protected])
shwdt.c ([email protected])
wdt977.c ([email protected])
Thanks,
Matt
--
Matt Domsch
Sr. Software Engineer
Dell Linux Solutions http://www.dell.com/linux
#1 US Linux Server provider with 24% (IDC Sept 2001)
#2 Worldwide Linux Server provider with 17% (IDC Sept 2001)
#3 Unix provider with 18% in the US (Dataquest)!
diff -burNp --exclude-from=/home/mdomsch/excludes linux-2.4.17-rc1/drivers/char/acquirewdt.c linux/drivers/char/acquirewdt.c
--- linux-2.4.17-rc1/drivers/char/acquirewdt.c Thu Sep 13 17:21:32 2001
+++ linux/drivers/char/acquirewdt.c Mon Dec 17 11:39:51 2001
@@ -17,6 +17,9 @@
*
* (c) Copyright 1995 Alan Cox <[email protected]>
*
+ * 14-Dec-2001 Matt Domsch <[email protected]>
+ * Added nowayout module option to override CONFIG_WATCHDOG_NOWAYOUT
+ * Can't add timeout - driver doesn't allow changing value
*/
#include <linux/config.h>
@@ -50,8 +53,14 @@ static spinlock_t acq_lock;
#define WDT_STOP 0x43
#define WDT_START 0x443
-#define WD_TIMO (100*60) /* 1 minute */
+#ifdef CONFIG_WATCHDOG_NOWAYOUT
+static int nowayout = 1;
+#else
+static int nowayout = 0;
+#endif
+MODULE_PARM(nowayout,"i");
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
/*
* Kernel methods.
@@ -126,10 +135,12 @@ static int acq_open(struct inode *inode,
spin_unlock(&acq_lock);
return -EBUSY;
}
+ if (nowayout) {
+ MOD_INC_USE_COUNT;
+ }
/*
* Activate
*/
-
acq_is_open=1;
inb_p(WDT_START);
spin_unlock(&acq_lock);
@@ -145,9 +156,9 @@ static int acq_close(struct inode *inode
if(MINOR(inode->i_rdev)==WATCHDOG_MINOR)
{
spin_lock(&acq_lock);
-#ifndef CONFIG_WATCHDOG_NOWAYOUT
+ if (!nowayout) {
inb_p(WDT_STOP);
-#endif
+ }
acq_is_open=0;
spin_unlock(&acq_lock);
}
diff -burNp --exclude-from=/home/mdomsch/excludes linux-2.4.17-rc1/drivers/char/advantechwdt.c linux/drivers/char/advantechwdt.c
--- linux-2.4.17-rc1/drivers/char/advantechwdt.c Thu Sep 13 17:21:32 2001
+++ linux/drivers/char/advantechwdt.c Mon Dec 17 11:40:00 2001
@@ -20,6 +20,9 @@
*
* (c) Copyright 1995 Alan Cox <[email protected]>
*
+ * 14-Dec-2001 Matt Domsch <[email protected]>
+ * Added nowayout module option to override CONFIG_WATCHDOG_NOWAYOUT
+ * Added timeout module option to override default
*/
#include <linux/config.h>
@@ -56,8 +59,7 @@ static spinlock_t advwdt_lock;
* the manual says WDT_STOP is 0x43, not 0x443).
* (0x43 is also a write-only control register for the 8254 timer!)
*
- * TODO: module parameters to set the I/O port addresses and NOWAYOUT
- * option at load time.
+ * TODO: module parameters to set the I/O port addresses
*/
#define WDT_STOP 0x443
@@ -65,6 +67,19 @@ static spinlock_t advwdt_lock;
#define WD_TIMO 60 /* 1 minute */
+static int timeout = WD_TIMO; /* in seconds */
+MODULE_PARM(timeout,"i");
+MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds (default=60)");
+
+#ifdef CONFIG_WATCHDOG_NOWAYOUT
+static int nowayout = 1;
+#else
+static int nowayout = 0;
+#endif
+
+MODULE_PARM(nowayout,"i");
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
+
/*
* Kernel methods.
*/
@@ -73,7 +88,7 @@ static void
advwdt_ping(void)
{
/* Write a watchdog value */
- outb_p(WD_TIMO, WDT_START);
+ outb_p(timeout, WDT_START);
}
static ssize_t
@@ -135,6 +150,9 @@ advwdt_open(struct inode *inode, struct
spin_unlock(&advwdt_lock);
return -EBUSY;
}
+ if (nowayout) {
+ MOD_INC_USE_COUNT;
+ }
/*
* Activate
*/
@@ -154,9 +172,9 @@ advwdt_close(struct inode *inode, struct
lock_kernel();
if (MINOR(inode->i_rdev) == WATCHDOG_MINOR) {
spin_lock(&advwdt_lock);
-#ifndef CONFIG_WATCHDOG_NOWAYOUT
+ if (!nowayout) {
inb_p(WDT_STOP);
-#endif
+ }
advwdt_is_open = 0;
spin_unlock(&advwdt_lock);
}
@@ -209,11 +227,21 @@ static struct notifier_block advwdt_noti
0
};
+static void __init
+advwdt_validate_timeout(void)
+{
+ if (timeout < 1 || timeout > 63) {
+ timeout = WD_TIMO;
+ printk(KERN_INFO "advantechwdt: timeout value must be 1 <= x <= 63, using %d\n", timeout);
+ }
+}
+
static int __init
advwdt_init(void)
{
printk("WDT driver for Advantech single board computer initialising.\n");
+ advwdt_validate_timeout();
spin_lock_init(&advwdt_lock);
misc_register(&advwdt_miscdev);
#if WDT_START != WDT_STOP
diff -burNp --exclude-from=/home/mdomsch/excludes linux-2.4.17-rc1/drivers/char/eurotechwdt.c linux/drivers/char/eurotechwdt.c
--- linux-2.4.17-rc1/drivers/char/eurotechwdt.c Thu Oct 25 15:53:47 2001
+++ linux/drivers/char/eurotechwdt.c Mon Dec 17 11:41:11 2001
@@ -20,6 +20,10 @@
* "AS-IS" and at no charge.
*
* (c) Copyright 1995 Alan Cox <[email protected]>*
+ *
+ * 14-Dec-2001 Matt Domsch <[email protected]>
+ * Added nowayout module option to override CONFIG_WATCHDOG_NOWAYOUT
+ * Added timeout module option to override default
*/
#include <linux/config.h>
@@ -45,7 +49,6 @@
#include <linux/smp_lock.h>
static int eurwdt_is_open;
-static int eurwdt_timeout;
static spinlock_t eurwdt_lock;
/*
@@ -58,6 +61,18 @@ static int irq = 10;
static char *ev = "int";
#define WDT_TIMEOUT 60 /* 1 minute */
+static int timeout = WDT_TIMEOUT;
+
+MODULE_PARM(timeout,"i");
+MODULE_PARM_DESC(timeout, "Eurotech WDT timeout in seconds (default=60)");
+
+#ifdef CONFIG_WATCHDOG_NOWAYOUT
+static int nowayout = 1;
+#else
+static int nowayout = 0;
+#endif
+MODULE_PARM(nowayout,"i");
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
/*
@@ -116,6 +131,15 @@ MODULE_PARM_DESC(ev, "Eurotech WDT event
* Programming support
*/
+static void __init eurwdt_validate_timeout(void)
+{
+ if (timeout < 0 || timeout > 255) {
+ timeout = WDT_TIMEOUT;
+ printk(KERN_INFO "eurwdt: timeout must be 0 < x < 255, using %d\n",
+ timeout);
+ }
+}
+
static inline void eurwdt_write_reg(u8 index, u8 data)
{
outb(index, io);
@@ -189,7 +213,7 @@ void eurwdt_interrupt(int irq, void *dev
static void eurwdt_ping(void)
{
/* Write the watchdog default value */
- eurwdt_set_timeout(eurwdt_timeout);
+ eurwdt_set_timeout(timeout);
}
/**
@@ -263,7 +287,7 @@ static int eurwdt_ioctl(struct inode *in
if (time < 0 || time > 255)
return -EINVAL;
- eurwdt_timeout = time;
+ timeout = time;
eurwdt_set_timeout(time);
return 0;
}
@@ -287,9 +311,11 @@ static int eurwdt_open(struct inode *ino
spin_unlock(&eurwdt_lock);
return -EBUSY;
}
+ if (nowayout) {
+ MOD_INC_USE_COUNT;
+ }
eurwdt_is_open = 1;
- eurwdt_timeout = WDT_TIMEOUT; /* initial timeout */
/* Activate the WDT */
eurwdt_activate_timer();
@@ -323,14 +349,13 @@ static int eurwdt_open(struct inode *ino
static int eurwdt_release(struct inode *inode, struct file *file)
{
if (MINOR(inode->i_rdev) == WATCHDOG_MINOR) {
-#ifndef CONFIG_WATCHDOG_NOWAYOUT
+ if (!nowayout) {
eurwdt_disable_timer();
-#endif
+ }
eurwdt_is_open = 0;
MOD_DEC_USE_COUNT;
}
-
return 0;
}
@@ -423,6 +448,8 @@ static int __init eurwdt_init(void)
{
int ret;
+ eurwdt_validate_timeout();
+
ret = misc_register(&eurwdt_miscdev);
if (ret) {
printk(KERN_ERR "eurwdt: can't misc_register on minor=%d\n",
diff -burNp --exclude-from=/home/mdomsch/excludes linux-2.4.17-rc1/drivers/char/i810-tco.c linux/drivers/char/i810-tco.c
--- linux-2.4.17-rc1/drivers/char/i810-tco.c Thu Sep 13 17:21:32 2001
+++ linux/drivers/char/i810-tco.c Mon Dec 17 11:41:40 2001
@@ -1,5 +1,5 @@
/*
- * i810-tco 0.02: TCO timer driver for i810 chipsets
+ * i810-tco 0.03: TCO timer driver for i810 chipsets
*
* (c) Copyright 2000 kernel concepts <[email protected]>, All Rights Reserved.
* http://www.kernelconcepts.de
@@ -28,6 +28,9 @@
* Initial Version 0.01
* 20000728 Nils Faerber
* 0.02 Fix for SMI_EN->TCO_EN bit, some cleanups
+ * 20011214 Matt Domsch <[email protected]>
+ * 0.03 Added nowayout module option to override CONFIG_WATCHDOG_NOWAYOUT
+ * Didn't add timeout option as i810_margin already exists.
*/
#include <linux/module.h>
@@ -60,6 +63,18 @@ static spinlock_t tco_lock; /* Guards th
static int i810_margin = TIMER_MARGIN; /* steps of 0.6sec */
MODULE_PARM (i810_margin, "i");
+MODULE_PARM_DESC(i810_margin, "Watchdog timeout in steps of 0.6sec, 2<n<64. Default = 50 (30 seconds)");
+
+
+#ifdef CONFIG_WATCHDOG_NOWAYOUT
+static int nowayout = 1;
+#else
+static int nowayout = 0;
+#endif
+
+MODULE_PARM(nowayout,"i");
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
+
/*
* Timer active flag
@@ -167,6 +182,9 @@ static int i810tco_open (struct inode *i
if (timer_alive)
return -EBUSY;
+ if (nowayout) {
+ MOD_INC_USE_COUNT;
+ }
/*
* Reload and activate timer
*/
@@ -181,10 +199,10 @@ static int i810tco_release (struct inode
/*
* Shut off the timer.
*/
-#ifdef CONFIG_WATCHDOG_NOWAYOUT
+ if (nowayout) {
tco_timer_stop ();
timer_alive = 0;
-#endif
+ }
return 0;
}
@@ -342,8 +360,8 @@ static int __init watchdog_init (void)
tco_timer_reload ();
printk (KERN_INFO
- "i810 TCO timer: V0.02, timer margin: %d sec (0x%04x)\n",
- (int) (i810_margin * 6 / 10), TCOBASE);
+ "i810 TCO timer: V0.03, timer margin: %d sec (0x%04x), nowayout: %d\n",
+ (int) (i810_margin * 6 / 10), TCOBASE, nowayout);
return 0;
}
diff -burNp --exclude-from=/home/mdomsch/excludes linux-2.4.17-rc1/drivers/char/ib700wdt.c linux/drivers/char/ib700wdt.c
--- linux-2.4.17-rc1/drivers/char/ib700wdt.c Thu Oct 11 11:07:00 2001
+++ linux/drivers/char/ib700wdt.c Mon Dec 17 11:42:26 2001
@@ -25,6 +25,10 @@
*
* (c) Copyright 1995 Alan Cox <[email protected]>
*
+ * 14-Dec-2001 Matt Domsch <[email protected]>
+ * Added nowayout module option to override CONFIG_WATCHDOG_NOWAYOUT
+ * Added timeout module option to override default
+ *
*/
#include <linux/config.h>
@@ -92,15 +96,36 @@ static spinlock_t ibwdt_lock;
#define WD_TIMO 0 /* 30 seconds +/- 20%, from table */
+static int timeout_val = WD_TIMO; /* value in table */
+static int timeout = 30; /* in seconds */
+MODULE_PARM(timeout,"i");
+MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds, 0 < n < 30, must be even (default=30)");
+
+#ifdef CONFIG_WATCHDOG_NOWAYOUT
+static int nowayout = 1;
+#else
+static int nowayout = 0;
+#endif
+
+MODULE_PARM(nowayout,"i");
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
+
/*
* Kernel methods.
*/
+static void __init
+ibwdt_validate_timeout(void)
+{
+ timeout_val = (30 - timeout) / 2;
+ if (timeout_val < 0 || timeout_val > 0xF) timeout_val = WD_TIMO;
+}
+
static void
ibwdt_ping(void)
{
/* Write a watchdog value */
- outb_p(WD_TIMO, WDT_START);
+ outb_p(timeout_val, WDT_START);
}
static ssize_t
@@ -162,6 +187,9 @@ ibwdt_open(struct inode *inode, struct f
spin_unlock(&ibwdt_lock);
return -EBUSY;
}
+ if (nowayout) {
+ MOD_INC_USE_COUNT;
+ }
/*
* Activate
*/
@@ -181,9 +209,9 @@ ibwdt_close(struct inode *inode, struct
lock_kernel();
if (MINOR(inode->i_rdev) == WATCHDOG_MINOR) {
spin_lock(&ibwdt_lock);
-#ifndef CONFIG_WATCHDOG_NOWAYOUT
- outb_p(WD_TIMO, WDT_STOP);
-#endif
+ if (!nowayout) {
+ outb_p(timeout_val, WDT_STOP);
+ }
ibwdt_is_open = 0;
spin_unlock(&ibwdt_lock);
}
@@ -201,7 +229,7 @@ ibwdt_notify_sys(struct notifier_block *
{
if (code == SYS_DOWN || code == SYS_HALT) {
/* Turn the WDT off */
- outb_p(WD_TIMO, WDT_STOP);
+ outb_p(timeout_val, WDT_STOP);
}
return NOTIFY_DONE;
}
@@ -241,6 +269,7 @@ ibwdt_init(void)
{
printk("WDT driver for IB700 single board computer initialising.\n");
+ ibwdt_validate_timeout();
spin_lock_init(&ibwdt_lock);
misc_register(&ibwdt_miscdev);
#if WDT_START != WDT_STOP
diff -burNp --exclude-from=/home/mdomsch/excludes linux-2.4.17-rc1/drivers/char/machzwd.c linux/drivers/char/machzwd.c
--- linux-2.4.17-rc1/drivers/char/machzwd.c Thu Sep 13 17:21:32 2001
+++ linux/drivers/char/machzwd.c Mon Dec 17 11:23:31 2001
@@ -24,6 +24,8 @@
* a system RESET and it starts wd#2 that unconditionaly will RESET
* the system when the counter reaches zero.
*
+ * 14-Dec-2001 Matt Domsch <[email protected]>
+ * Added nowayout module option to override CONFIG_WATCHDOG_NOWAYOUT
*/
#include <linux/config.h>
@@ -103,6 +105,16 @@ MODULE_LICENSE("GPL");
MODULE_PARM(action, "i");
MODULE_PARM_DESC(action, "after watchdog resets, generate: 0 = RESET(*) 1 = SMI 2 = NMI 3 = SCI");
+#ifdef CONFIG_WATCHDOG_NOWAYOUT
+static int nowayout = 1;
+#else
+static int nowayout = 0;
+#endif
+
+MODULE_PARM(nowayout,"i");
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
+
+
#define PFX "machzwd"
static struct watchdog_info zf_info = {
@@ -307,7 +319,7 @@ static ssize_t zf_write(struct file *fil
* no need to check for close confirmation
* no way to disable watchdog ;)
*/
-#ifndef CONFIG_WATCHDOG_NOWAYOUT
+ if (!nowayout) {
size_t ofs;
/*
@@ -323,7 +335,7 @@ static ssize_t zf_write(struct file *fil
dprintk("zf_expect_close 1\n");
}
}
-#endif
+ }
/*
* Well, anyhow someone wrote to us,
* we should return that favour
@@ -386,9 +398,9 @@ static int zf_open(struct inode *inode,
return -EBUSY;
}
-#ifdef CONFIG_WATCHDOG_NOWAYOUT
+ if (nowayout) {
MOD_INC_USE_COUNT;
-#endif
+ }
zf_is_open = 1;
spin_unlock(&zf_lock);
diff -burNp --exclude-from=/home/mdomsch/excludes linux-2.4.17-rc1/drivers/char/mixcomwd.c linux/drivers/char/mixcomwd.c
--- linux-2.4.17-rc1/drivers/char/mixcomwd.c Thu Sep 13 17:21:32 2001
+++ linux/drivers/char/mixcomwd.c Mon Dec 17 11:44:09 2001
@@ -28,9 +28,12 @@
* Version 0.4 (99/11/15):
* - support for one more type board
*
+ * Version 0.5 (2001/12/14) Matt Domsch <[email protected]>
+ * - added nowayout module option to override CONFIG_WATCHDOG_NOWAYOUT
+ *
*/
-#define VERSION "0.4"
+#define VERSION "0.5"
#include <linux/module.h>
#include <linux/config.h>
@@ -57,26 +60,30 @@ static int mixcomwd_ioports[] = { 0x180,
static long mixcomwd_opened; /* long req'd for setbit --RR */
static int watchdog_port;
-
-#ifndef CONFIG_WATCHDOG_NOWAYOUT
static int mixcomwd_timer_alive;
static struct timer_list mixcomwd_timer;
+
+#ifdef CONFIG_WATCHDOG_NOWAYOUT
+static int nowayout = 1;
+#else
+static int nowayout = 0;
#endif
+MODULE_PARM(nowayout,"i");
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
+
static void mixcomwd_ping(void)
{
outb_p(55,watchdog_port);
return;
}
-#ifndef CONFIG_WATCHDOG_NOWAYOUT
static void mixcomwd_timerfun(unsigned long d)
{
mixcomwd_ping();
mod_timer(&mixcomwd_timer,jiffies+ 5*HZ);
}
-#endif
/*
* Allow only one person to hold it open
@@ -89,12 +96,14 @@ static int mixcomwd_open(struct inode *i
}
mixcomwd_ping();
-#ifndef CONFIG_WATCHDOG_NOWAYOUT
+ if (nowayout) {
+ MOD_INC_USE_COUNT;
+ } else {
if(mixcomwd_timer_alive) {
del_timer(&mixcomwd_timer);
mixcomwd_timer_alive=0;
}
-#endif
+ }
return 0;
}
@@ -102,7 +111,7 @@ static int mixcomwd_release(struct inode
{
lock_kernel();
-#ifndef CONFIG_WATCHDOG_NOWAYOUT
+ if (!nowayout) {
if(mixcomwd_timer_alive) {
printk(KERN_ERR "mixcomwd: release called while internal timer alive");
unlock_kernel();
@@ -114,7 +123,7 @@ static int mixcomwd_release(struct inode
mixcomwd_timer.data=0;
mixcomwd_timer_alive=1;
add_timer(&mixcomwd_timer);
-#endif
+ }
clear_bit(0,&mixcomwd_opened);
unlock_kernel();
@@ -148,9 +157,9 @@ static int mixcomwd_ioctl(struct inode *
{
case WDIOC_GETSTATUS:
status=mixcomwd_opened;
-#ifndef CONFIG_WATCHDOG_NOWAYOUT
+ if (!nowayout) {
status|=mixcomwd_timer_alive;
-#endif
+ }
if (copy_to_user((int *)arg, &status, sizeof(int))) {
return -EFAULT;
}
@@ -255,14 +264,14 @@ static int __init mixcomwd_init(void)
static void __exit mixcomwd_exit(void)
{
-#ifndef CONFIG_WATCHDOG_NOWAYOUT
+ if (!nowayout) {
if(mixcomwd_timer_alive) {
printk(KERN_WARNING "mixcomwd: I quit now, hardware will"
" probably reboot!\n");
del_timer(&mixcomwd_timer);
mixcomwd_timer_alive=0;
}
-#endif
+ }
release_region(watchdog_port,1);
misc_deregister(&mixcomwd_miscdev);
}
diff -burNp --exclude-from=/home/mdomsch/excludes linux-2.4.17-rc1/drivers/char/pcwd.c linux/drivers/char/pcwd.c
--- linux-2.4.17-rc1/drivers/char/pcwd.c Thu Sep 13 17:21:32 2001
+++ linux/drivers/char/pcwd.c Mon Dec 17 11:45:36 2001
@@ -40,6 +40,8 @@
* fairly useless proc entry.
* 990610 removed said useless proc code for the merge <alan>
* 000403 Removed last traces of proc code. <davej>
+ * 011214 Added nowayout module option to override CONFIG_WATCHDOG_NOWAYOUT <[email protected]>
+ * Added timeout module option to override default
*/
#include <linux/module.h>
@@ -76,7 +78,7 @@
*/
static int pcwd_ioports[] = { 0x270, 0x350, 0x370, 0x000 };
-#define WD_VER "1.10 (06/05/99)"
+#define WD_VER "1.12 (12/14/2001)"
/*
* It should be noted that PCWD_REVISION_B was removed because A and B
@@ -88,7 +90,22 @@ static int pcwd_ioports[] = { 0x270, 0x3
#define PCWD_REVISION_A 1
#define PCWD_REVISION_C 2
-#define WD_TIMEOUT 3 /* 1 1/2 seconds for a timeout */
+#define WD_TIMEOUT 4 /* 2 seconds for a timeout */
+static int timeout_val = WD_TIMEOUT;
+static int timeout = 2;
+
+MODULE_PARM(timeout,"i");
+MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds (default=2)");
+
+#ifdef CONFIG_WATCHDOG_NOWAYOUT
+static int nowayout = 1;
+#else
+static int nowayout = 0;
+#endif
+
+MODULE_PARM(nowayout,"i");
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
+
/*
* These are the defines for the PC Watchdog card, revision A.
@@ -126,7 +143,7 @@ static int __init pcwd_checkcard(void)
if (prev_card_dat == 0xFF)
return 0;
- while(count < WD_TIMEOUT) {
+ while(count < timeout_val) {
/* Read the raw card data from the port, and strip off the
first 4 bits */
@@ -454,7 +471,7 @@ static int pcwd_close(struct inode *ino,
{
lock_kernel();
is_open = 0;
-#ifndef CONFIG_WATCHDOG_NOWAYOUT
+ if (!nowayout) {
/* Disable the board */
if (revision == PCWD_REVISION_C) {
spin_lock(&io_lock);
@@ -462,7 +479,7 @@ static int pcwd_close(struct inode *ino,
outb_p(0xA5, current_readport + 3);
spin_unlock(&io_lock);
}
-#endif
+ }
unlock_kernel();
}
return 0;
@@ -564,9 +581,15 @@ static struct miscdevice temp_miscdev =
&pcwd_fops
};
+static void __init pcwd_validate_timeout(void)
+{
+ timeout_val = timeout * 2;
+}
+
static int __init pcwatchdog_init(void)
{
int i, found = 0;
+ pcwd_validate_timeout();
spin_lock_init(&io_lock);
revision = PCWD_REVISION_A;
diff -burNp --exclude-from=/home/mdomsch/excludes linux-2.4.17-rc1/drivers/char/sbc60xxwdt.c linux/drivers/char/sbc60xxwdt.c
--- linux-2.4.17-rc1/drivers/char/sbc60xxwdt.c Thu Sep 13 17:21:32 2001
+++ linux/drivers/char/sbc60xxwdt.c Mon Dec 17 11:45:54 2001
@@ -109,6 +109,15 @@ static unsigned long next_heartbeat;
static int wdt_is_open;
static int wdt_expect_close;
+#ifdef CONFIG_WATCHDOG_NOWAYOUT
+static int nowayout = 1;
+#else
+static int nowayout = 0;
+#endif
+
+MODULE_PARM(nowayout,"i");
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
+
/*
* Whack the dog
*/
@@ -202,6 +211,9 @@ static int fop_open(struct inode * inode
/* Just in case we're already talking to someone... */
if(wdt_is_open)
return -EBUSY;
+ if (nowayout) {
+ MOD_INC_USE_COUNT;
+ }
/* Good, fire up the show */
wdt_is_open = 1;
wdt_startup();
@@ -217,7 +229,7 @@ static int fop_close(struct inode * inod
lock_kernel();
if(MINOR(inode->i_rdev) == WATCHDOG_MINOR)
{
- if(wdt_expect_close)
+ if(wdt_expect_close && !nowayout)
wdt_turnoff();
else {
del_timer(&timer);
diff -burNp --exclude-from=/home/mdomsch/excludes linux-2.4.17-rc1/drivers/char/shwdt.c linux/drivers/char/shwdt.c
--- linux-2.4.17-rc1/drivers/char/shwdt.c Mon Oct 15 15:36:48 2001
+++ linux/drivers/char/shwdt.c Mon Dec 17 11:46:24 2001
@@ -9,6 +9,9 @@
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
+ *
+ * 14-Dec-2001 Matt Domsch <[email protected]>
+ * Added nowayout module option to override CONFIG_WATCHDOG_NOWAYOUT
*/
#include <linux/config.h>
@@ -61,6 +64,15 @@
static int sh_is_open = 0;
static struct watchdog_info sh_wdt_info;
+#ifdef CONFIG_WATCHDOG_NOWAYOUT
+static int nowayout = 1;
+#else
+static int nowayout = 0;
+#endif
+
+MODULE_PARM(nowayout,"i");
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
+
/**
* sh_wdt_write_cnt - Write to Counter
*
@@ -137,6 +149,9 @@ static int sh_wdt_open(struct inode *ino
if (sh_is_open) {
return -EBUSY;
}
+ if (nowayout) {
+ MOD_INC_USE_COUNT;
+ }
sh_is_open = 1;
sh_wdt_start();
@@ -162,9 +177,9 @@ static int sh_wdt_close(struct inode *in
lock_kernel();
if (MINOR(inode->i_rdev) == WATCHDOG_MINOR) {
-#ifndef CONFIG_WATCHDOG_NOWAYOUT
+ if (!nowayout) {
sh_wdt_stop();
-#endif
+ }
sh_is_open = 0;
}
diff -burNp --exclude-from=/home/mdomsch/excludes linux-2.4.17-rc1/drivers/char/softdog.c linux/drivers/char/softdog.c
--- linux-2.4.17-rc1/drivers/char/softdog.c Sun Sep 30 14:26:05 2001
+++ linux/drivers/char/softdog.c Mon Dec 17 10:12:29 2001
@@ -1,5 +1,5 @@
/*
- * SoftDog 0.05: A Software Watchdog Device
+ * SoftDog 0.06: A Software Watchdog Device
*
* (c) Copyright 1996 Alan Cox <[email protected]>, All Rights Reserved.
* http://www.redhat.com
@@ -26,6 +26,10 @@
*
* 19980911 Alan Cox
* Made SMP safe for 2.3.x
+ *
+ * 20011214 Matt Domsch <[email protected]>
+ * Added nowayout module option to override CONFIG_WATCHDOG_NOWAYOUT
+ * Didn't add timeout option, as soft_margin option already exists.
*/
#include <linux/module.h>
@@ -46,6 +50,15 @@
static int soft_margin = TIMER_MARGIN; /* in seconds */
MODULE_PARM(soft_margin,"i");
+
+#ifdef CONFIG_WATCHDOG_NOWAYOUT
+static int nowayout = 1;
+#else
+static int nowayout = 0;
+#endif
+
+MODULE_PARM(nowayout,"i");
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
MODULE_LICENSE("GPL");
/*
@@ -83,9 +96,9 @@ static int softdog_open(struct inode *in
{
if(timer_alive)
return -EBUSY;
-#ifdef CONFIG_WATCHDOG_NOWAYOUT
+ if (nowayout) {
MOD_INC_USE_COUNT;
-#endif
+ }
/*
* Activate timer
*/
@@ -98,12 +111,12 @@ static int softdog_release(struct inode
{
/*
* Shut off the timer.
- * Lock it in if it's a module and we defined ...NOWAYOUT
+ * Lock it in if it's a module and we set nowayout
*/
lock_kernel();
-#ifndef CONFIG_WATCHDOG_NOWAYOUT
+ if(!nowayout) {
del_timer(&watchdog_ticktock);
-#endif
+ }
timer_alive=0;
unlock_kernel();
return 0;
@@ -161,7 +174,7 @@ static struct miscdevice softdog_miscdev
fops: &softdog_fops,
};
-static char banner[] __initdata = KERN_INFO "Software Watchdog Timer: 0.05, timer margin: %d sec\n";
+static char banner[] __initdata = KERN_INFO "Software Watchdog Timer: 0.06, soft_margin: %d sec, nowayout: %d\n";
static int __init watchdog_init(void)
{
@@ -172,7 +185,7 @@ static int __init watchdog_init(void)
if (ret)
return ret;
- printk(banner, soft_margin);
+ printk(banner, soft_margin, nowayout);
return 0;
}
diff -burNp --exclude-from=/home/mdomsch/excludes linux-2.4.17-rc1/drivers/char/wdt.c linux/drivers/char/wdt.c
--- linux-2.4.17-rc1/drivers/char/wdt.c Fri Sep 7 11:28:38 2001
+++ linux/drivers/char/wdt.c Mon Dec 17 11:47:30 2001
@@ -15,7 +15,7 @@
*
* (c) Copyright 1995 Alan Cox <[email protected]>
*
- * Release 0.08.
+ * Release 0.09.
*
* Fixes
* Dave Gregorich : Modularisation and minor bugs
@@ -27,6 +27,7 @@
* Tim Hockin : Added insmod parameters, comment cleanup
* Parameterized timeout
* Tigran Aivazian : Restructured wdt_init() to handle failures
+ * Matt Domsch : added nowayout and timeout module options
*/
#include <linux/config.h>
@@ -62,6 +63,26 @@ static int irq=11;
#define WD_TIMO (100*60) /* 1 minute */
+static int timeout_val = WD_TIMO; /* value passed to card */
+static int timeout = 60; /* in seconds */
+MODULE_PARM(timeout,"i");
+MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds (default=60)");
+
+#ifdef CONFIG_WATCHDOG_NOWAYOUT
+static int nowayout = 1;
+#else
+static int nowayout = 0;
+#endif
+
+MODULE_PARM(nowayout,"i");
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
+
+static void __init
+wdt_validate_timeout(void)
+{
+ timeout_val = timeout * 100;
+}
+
#ifndef MODULE
/**
@@ -216,7 +237,7 @@ static void wdt_ping(void)
/* Write a watchdog value */
inb_p(WDT_DC);
wdt_ctr_mode(1,2);
- wdt_ctr_load(1,WD_TIMO); /* Timeout */
+ wdt_ctr_load(1,timeout_val); /* Timeout */
outb_p(0, WDT_DC);
}
@@ -339,6 +360,9 @@ static int wdt_open(struct inode *inode,
case WATCHDOG_MINOR:
if(wdt_is_open)
return -EBUSY;
+ if (nowayout) {
+ MOD_INC_USE_COUNT;
+ }
/*
* Activate
*/
@@ -349,7 +373,7 @@ static int wdt_open(struct inode *inode,
wdt_ctr_mode(1,2);
wdt_ctr_mode(2,0);
wdt_ctr_load(0, 8948); /* count at 100Hz */
- wdt_ctr_load(1,WD_TIMO); /* Timeout 120 seconds */
+ wdt_ctr_load(1,timeout_val); /* Timeout */
wdt_ctr_load(2,65535);
outb_p(0, WDT_DC); /* Enable */
return 0;
@@ -377,10 +401,10 @@ static int wdt_release(struct inode *ino
lock_kernel();
if(MINOR(inode->i_rdev)==WATCHDOG_MINOR)
{
-#ifndef CONFIG_WATCHDOG_NOWAYOUT
+ if (!nowayout) {
inb_p(WDT_DC); /* Disable counters */
wdt_ctr_load(2,0); /* 0 length reset pulses now */
-#endif
+ }
wdt_is_open=0;
}
unlock_kernel();
@@ -487,6 +511,7 @@ static int __init wdt_init(void)
{
int ret;
+ wdt_validate_timeout();
ret = misc_register(&wdt_miscdev);
if (ret) {
printk(KERN_ERR "wdt: can't misc_register on minor=%d\n", WATCHDOG_MINOR);
diff -burNp --exclude-from=/home/mdomsch/excludes linux-2.4.17-rc1/drivers/char/wdt977.c linux/drivers/char/wdt977.c
--- linux-2.4.17-rc1/drivers/char/wdt977.c Fri Sep 7 11:28:38 2001
+++ linux/drivers/char/wdt977.c Fri Dec 14 16:15:45 2001
@@ -1,5 +1,5 @@
/*
- * Wdt977 0.01: A Watchdog Device for Netwinder W83977AF chip
+ * Wdt977 0.02: A Watchdog Device for Netwinder W83977AF chip
*
* (c) Copyright 1998 Rebel.com (Woody Suwalski <[email protected]>)
*
@@ -11,6 +11,8 @@
* 2 of the License, or (at your option) any later version.
*
* -----------------------
+ * 14-Dec-2001 Matt Domsch <[email protected]>
+ * Added nowayout module option to override CONFIG_WATCHDOG_NOWAYOUT
*/
#include <linux/module.h>
@@ -32,6 +34,16 @@ static int timeout = 3;
static int timer_alive;
static int testmode;
+#ifdef CONFIG_WATCHDOG_NOWAYOUT
+static int nowayout = 1;
+#else
+static int nowayout = 0;
+#endif
+
+MODULE_PARM(nowayout,"i");
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
+
+
/*
* Allow only one person to hold it open
*/
@@ -40,9 +52,9 @@ static int wdt977_open(struct inode *ino
{
if(timer_alive)
return -EBUSY;
-#ifdef CONFIG_WATCHDOG_NOWAYOUT
+ if (nowayout) {
MOD_INC_USE_COUNT;
-#endif
+ }
timer_alive++;
//max timeout value = 255 minutes (0xFF). Write 0 to disable WatchDog.
@@ -89,9 +101,9 @@ static int wdt977_release(struct inode *
{
/*
* Shut off the timer.
- * Lock it in if it's a module and we defined ...NOWAYOUT
+ * Lock it in if it's a module and we set nowayout
*/
-#ifndef CONFIG_WATCHDOG_NOWAYOUT
+ if (!nowayout) {
lock_kernel();
// unlock the SuperIO chip
@@ -127,7 +139,7 @@ static int wdt977_release(struct inode *
unlock_kernel();
printk(KERN_INFO "Watchdog: shutdown.\n");
-#endif
+ }
return 0;
}
diff -burNp --exclude-from=/home/mdomsch/excludes linux-2.4.17-rc1/drivers/char/wdt_pci.c linux/drivers/char/wdt_pci.c
--- linux-2.4.17-rc1/drivers/char/wdt_pci.c Fri Sep 7 11:28:38 2001
+++ linux/drivers/char/wdt_pci.c Mon Dec 17 11:37:08 2001
@@ -15,7 +15,7 @@
*
* (c) Copyright 1995 Alan Cox <[email protected]>
*
- * Release 0.08.
+ * Release 0.09.
*
* Fixes
* Dave Gregorich : Modularisation and minor bugs
@@ -30,6 +30,7 @@
* Alan Cox : Split ISA and PCI cards into two drivers
* Jeff Garzik : PCI cleanups
* Tigran Aivazian : Restructured wdtpci_init_one() to handle failures
+ * Matt Domsch : added nowayout and timeout module options
*/
#include <linux/config.h>
@@ -83,6 +84,26 @@ static int irq=11;
#define WD_TIMO (100*60) /* 1 minute */
+static int timeout_val = WD_TIMO; /* value passed to card */
+static int timeout = 60; /* in seconds */
+MODULE_PARM(timeout,"i");
+MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds (default=60)");
+
+#ifdef CONFIG_WATCHDOG_NOWAYOUT
+static int nowayout = 1;
+#else
+static int nowayout = 0;
+#endif
+
+MODULE_PARM(nowayout,"i");
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
+
+static void __init
+wdtpci_validate_timeout(void)
+{
+ timeout_val = timeout * 100;
+}
+
#ifndef MODULE
/**
@@ -232,7 +253,7 @@ static void wdtpci_ping(void)
/* Write a watchdog value */
inb_p(WDT_DC);
wdtpci_ctr_mode(1,2);
- wdtpci_ctr_load(1,WD_TIMO); /* Timeout */
+ wdtpci_ctr_load(1,timeout_val); /* Timeout */
outb_p(0, WDT_DC);
}
@@ -355,9 +376,9 @@ static int wdtpci_open(struct inode *ino
case WATCHDOG_MINOR:
if(wdt_is_open)
return -EBUSY;
-#ifdef CONFIG_WATCHDOG_NOWAYOUT
+ if (nowayout) {
MOD_INC_USE_COUNT;
-#endif
+ }
/*
* Activate
*/
@@ -385,7 +406,7 @@ static int wdtpci_open(struct inode *ino
wdtpci_ctr_mode(1,2);
wdtpci_ctr_mode(2,1);
wdtpci_ctr_load(0,20833); /* count at 100Hz */
- wdtpci_ctr_load(1,WD_TIMO);/* Timeout 60 seconds */
+ wdtpci_ctr_load(1,timeout_val); /* Timeout */
/* DO NOT LOAD CTR2 on PCI card! -- JPN */
outb_p(0, WDT_DC); /* Enable */
return 0;
@@ -413,10 +434,10 @@ static int wdtpci_release(struct inode *
if(MINOR(inode->i_rdev)==WATCHDOG_MINOR)
{
lock_kernel();
-#ifndef CONFIG_WATCHDOG_NOWAYOUT
+ if (!nowayout) {
inb_p(WDT_DC); /* Disable counters */
wdtpci_ctr_load(2,0); /* 0 length reset pulses now */
-#endif
+ }
wdt_is_open=0;
unlock_kernel();
}
@@ -620,6 +641,8 @@ static int __init wdtpci_init(void)
if (rc < 1)
return -ENODEV;
+ wdtpci_validate_timeout();
+
return 0;
}
> To the following drivers was also added a 'timeout=X' module parameter,
> where timeout is specified in seconds. Only drivers for which no
> similar parm was already present were modified:
Timeout has been moved to an ioctl more by other diffs so Im not sure
timeout= is too important
Rest looks good
> Timeout has been moved to an ioctl more by other diffs so Im not sure
> timeout= is too important
Of the seven drivers I added this parm to, six do not offer such a method
via ioctl:
eurotechwdt.c provides WDIOC_SETTIMEOUT.
acquirewdt.c, advantechwdt.c, ib700wdt.c, pcwd.c, wdt.c, wdt_pci.c do not
provide a set timeout ioctl.
These already offer a timeout parm, but no set timeout ioctl:
i810-tco.c, softdog.c, wdt285.o
The other drivers I didn't add timeout parm to anyhow, but they don't have a
set timeout ioctl either:
machzwd.c, mixcomwd.c, shwdt.c, wdt977.c
Unless there are strong objections or a push to make it an ioctl everywhere
instead/also, I'd like to leave it in.
> Rest looks good
Thanks for reviewing and approving. 14 drivers modified, 5 drivers
approved, one investigating, two email addresses invalid, leaving 6 to hear
from.
-Matt
--
Matt Domsch
Sr. Software Engineer
Dell Linux Solutions http://www.dell.com/linux
#1 US Linux Server provider with 24.5% (IDC Dec 2001)
#2 Worldwide Linux Server provider with 18.2% (IDC Dec 2001)
No changes, just forward-ported the patches.
14 drivers modified, 5 drivers approved, one (wdt977) being handled by its
maintainer, two email addresses
invalid, leaving 6 to hear from.
Patch against 2.4.18-pre1 at
http://domsch.com/linux/patches/linux-2.4.18-pre1-nowayout-20020103.patch
acquirewdt.c | 21 ++++++++++++---
advantechwdt.c | 42 ++++++++++++++++++++++++++-----
eurotechwdt.c | 49 ++++++++++++++++++++++++++++---------
i810-tco.c | 32 +++++++++++++++++++-----
ib700wdt.c | 39 +++++++++++++++++++++++++----
machzwd.c | 48 ++++++++++++++++++++++--------------
mixcomwd.c | 75
+++++++++++++++++++++++++++++++--------------------------
pcwd.c | 45 +++++++++++++++++++++++++---------
sbc60xxwdt.c | 14 +++++++++-
shwdt.c | 21 +++++++++++++--
softdog.c | 33 +++++++++++++++++--------
wdt.c | 41 +++++++++++++++++++++++++------
wdt_pci.c | 43 +++++++++++++++++++++++++-------
13 files changed, 374 insertions(+), 129 deletions(-)
Patch against 2.5.2-pre6 at
http://domsch.com/linux/patches/linux-2.5.2-pre6-nowayout-20020103.patch
acquirewdt.c | 21 ++++++++++++----
advantechwdt.c | 42 ++++++++++++++++++++++++++------
eurotechwdt.c | 49 +++++++++++++++++++++++++++++--------
i810-tco.c | 32 +++++++++++++++++++-----
ib700wdt.c | 39 ++++++++++++++++++++++++++----
machzwd.c | 48 +++++++++++++++++++++++-------------
mixcomwd.c | 74
+++++++++++++++++++++++++++++++--------------------------
pcwd.c | 47 ++++++++++++++++++++++++++----------
sbc60xxwdt.c | 14 ++++++++++
shwdt.c | 21 +++++++++++++---
softdog.c | 33 +++++++++++++++++--------
wdt.c | 41 +++++++++++++++++++++++++------
wdt_pci.c | 43 +++++++++++++++++++++++++--------
13 files changed, 374 insertions(+), 130 deletions(-)
Thanks,
Matt
--
Matt Domsch
Sr. Software Engineer
Dell Linux Solutions http://www.dell.com/linux
#1 US Linux Server provider with 24.5% (IDC Dec 2001)
#2 Worldwide Linux Server provider with 18.2% (IDC Dec 2001)
[email protected] wrote:
>>Timeout has been moved to an ioctl more by other diffs so Im not sure
>>timeout= is too important
>>
>
> Of the seven drivers I added this parm to, six do not offer such a method
> via ioctl:
> eurotechwdt.c provides WDIOC_SETTIMEOUT.
And was the first to provide it:
http://marc.theaimsgroup.com/?l=linux-kernel&m=100619600900700&w=2
> acquirewdt.c, advantechwdt.c, ib700wdt.c, pcwd.c, wdt.c, wdt_pci.c do not
> provide a set timeout ioctl.
I think all should? As it would be nice/more consistent for all
>
> These already offer a timeout parm, but no set timeout ioctl:
> i810-tco.c, softdog.c, wdt285.o
>
> The other drivers I didn't add timeout parm to anyhow, but they don't have a
> set timeout ioctl either:
> machzwd.c, mixcomwd.c, shwdt.c, wdt977.c
new version of wdt977 in patch does provide WDIOC_SETTIMEOUT
>
> Unless there are strong objections or a push to make it an ioctl everywhere
> instead/also, I'd like to leave it in.
Personally I'm undecided whether param or ioctl is preferable.
I don't think many would need to change the timeout parameter
at runtime, but if you do it's a pain to reload the module,
so I vote for providing both interfaces?
>
>>Rest looks good
>>
>
> Thanks for reviewing and approving. 14 drivers modified, 5 drivers
> approved, one investigating, two email addresses invalid, leaving 6 to hear
> from.
>
> -Matt
What about the following though?
cpwatchdog.c
riowatchdog.c
sbc60xxwdt.c
Actually I think there should be a drivers/char/watchdog directory ?
(there are now around 18 seperate watchdog drivers).
Then the out of date watchdog.txt could be updated to point users
at this directory to see what's available, rather than the current
out of date list:
ICS WDT501-P
ICS WDT501-P (no fan tachometer)
ICS WDT500-P
Software Only
SA1100 Internal Watchdog
Berkshire Products PC Watchdog Revision A & C (by Ken Hollis)
ALso I've drivers here for {IBASE, Portwell} SBC watchdogs.
[Who] will I submit them to?
cheers,
Padraig.