Commit d87b6141 authored by Dave Jones's avatar Dave Jones

[WATCHDOG] Final 2.4 bits for ib700wdt

parent 950cda48
......@@ -86,15 +86,32 @@ static int expect_close = 0;
*
*/
static int wd_times[] = {
30, /* 0x0 */
28, /* 0x1 */
26, /* 0x2 */
24, /* 0x3 */
22, /* 0x4 */
20, /* 0x5 */
18, /* 0x6 */
16, /* 0x7 */
14, /* 0x8 */
12, /* 0x9 */
10, /* 0xA */
8, /* 0xB */
6, /* 0xC */
4, /* 0xD */
2, /* 0xE */
0, /* 0xF */
};
#define WDT_STOP 0x441
#define WDT_START 0x443
/* Default timeout */
#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)");
static int wd_margin = WD_TIMO;
#ifdef CONFIG_WATCHDOG_NOWAYOUT
static int nowayout = 1;
......@@ -105,22 +122,16 @@ static int nowayout = 0;
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(timeout_val, WDT_START);
outb_p(wd_times[wd_margin], WDT_START);
}
static ssize_t
......@@ -139,7 +150,6 @@ ibwdt_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
for (i = 0; i != count; i++) {
char c;
if (get_user(c, buf + i))
return -EFAULT;
if (c == 'V')
......@@ -162,6 +172,8 @@ static int
ibwdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
unsigned long arg)
{
int i, new_margin;
static struct watchdog_info ident = {
.options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE,
.firmware_version = 1,
......@@ -183,6 +195,22 @@ ibwdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
ibwdt_ping();
break;
case WDIOC_SETTIMEOUT:
if (get_user(new_margin, (int *)arg))
return -EFAULT;
if ((new_margin < 0) || (new_margin > 30))
return -EINVAL;
for (i = 0x0F; i > -1; i--)
if (wd_times[i] > new_margin)
break;
wd_margin = i;
ibwdt_ping();
/* Fall */
case WDIOC_GETTIMEOUT:
return put_user(wd_times[wd_margin], (int *)arg);
break;
default:
return -ENOTTY;
}
......@@ -217,7 +245,7 @@ ibwdt_close(struct inode *inode, struct file *file)
if (minor(inode->i_rdev) == WATCHDOG_MINOR) {
spin_lock(&ibwdt_lock);
if (expect_close)
outb_p(timeout_val, WDT_STOP);
outb_p(wd_times[wd_margin], WDT_STOP);
else
printk(KERN_CRIT "WDT device closed unexpectedly. WDT will not stop!\n");
......@@ -237,7 +265,7 @@ ibwdt_notify_sys(struct notifier_block *this, unsigned long code,
{
if (code == SYS_DOWN || code == SYS_HALT) {
/* Turn the WDT off */
outb_p(timeout_val, WDT_STOP);
outb_p(wd_times[wd_margin], WDT_STOP);
}
return NOTIFY_DONE;
}
......@@ -277,7 +305,6 @@ ibwdt_init(void)
{
printk("WDT driver for IB700 single board computer initialising.\n");
ibwdt_validate_timeout();
spin_lock_init(&ibwdt_lock);
if (misc_register(&ibwdt_miscdev))
return -ENODEV;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment