Commit 870c2c81 authored by Wim Van Sebroeck's avatar Wim Van Sebroeck

Merge http://linux.bkbits.net/linux-2.5

into hostme.bitkeeper.com:/repos/l/linux-watchdog/linux-2.5-watchdog
parents 21fbda93 4ad0c56a
/* /*
* Advantech Single Board Computer WDT driver for Linux 2.4.x * Advantech Single Board Computer WDT driver
* *
* (c) Copyright 2000-2001 Marek Michalkiewicz <marekm@linux.org.pl> * (c) Copyright 2000-2001 Marek Michalkiewicz <marekm@linux.org.pl>
* *
...@@ -22,10 +22,14 @@ ...@@ -22,10 +22,14 @@
* *
* 14-Dec-2001 Matt Domsch <Matt_Domsch@dell.com> * 14-Dec-2001 Matt Domsch <Matt_Domsch@dell.com>
* Added nowayout module option to override CONFIG_WATCHDOG_NOWAYOUT * Added nowayout module option to override CONFIG_WATCHDOG_NOWAYOUT
*
* 16-Oct-2002 Rob Radez <rob@osinvestor.com>
* Clean up ioctls, clean up init + exit, add expect close support,
* add wdt_start and wdt_stop as parameters.
*/ */
#include <linux/config.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/types.h> #include <linux/types.h>
#include <linux/miscdevice.h> #include <linux/miscdevice.h>
#include <linux/watchdog.h> #include <linux/watchdog.h>
...@@ -39,6 +43,9 @@ ...@@ -39,6 +43,9 @@
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <asm/system.h> #include <asm/system.h>
#define WATCHDOG_NAME "Advantech WDT"
#define WATCHDOG_TIMEOUT 60 /* 60 sec default timeout */
static unsigned long advwdt_is_open; static unsigned long advwdt_is_open;
static char adv_expect_close; static char adv_expect_close;
...@@ -54,9 +61,16 @@ static char adv_expect_close; ...@@ -54,9 +61,16 @@ static char adv_expect_close;
*/ */
static int wdt_stop = 0x443; static int wdt_stop = 0x443;
module_param(wdt_stop, int, 0);
MODULE_PARM_DESC(wdt_stop, "Advantech WDT 'stop' io port (default 0x443)");
static int wdt_start = 0x443; static int wdt_start = 0x443;
module_param(wdt_start, int, 0);
MODULE_PARM_DESC(wdt_start, "Advantech WDT 'start' io port (default 0x443)");
static int wd_margin = 60; /* 60 sec default timeout */ static int timeout = WATCHDOG_TIMEOUT; /* in seconds */
module_param(timeout, int, 0);
MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds. 1<= timeout <=63, default=60.");
#ifdef CONFIG_WATCHDOG_NOWAYOUT #ifdef CONFIG_WATCHDOG_NOWAYOUT
static int nowayout = 1; static int nowayout = 1;
...@@ -64,44 +78,18 @@ static int nowayout = 1; ...@@ -64,44 +78,18 @@ static int nowayout = 1;
static int nowayout = 0; static int nowayout = 0;
#endif #endif
MODULE_PARM(nowayout,"i"); module_param(nowayout, int, 0);
MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)"); MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
/* /*
* Kernel methods. * Kernel methods.
*/ */
#ifndef MODULE
static int __init adv_setup(char *str)
{
int ints[4];
str = get_options(str, ARRAY_SIZE(ints), ints);
if(ints[0] > 0){
wdt_stop = ints[1];
if(ints[0] > 1)
wdt_start = ints[2];
}
return 1;
}
__setup("advwdt=", adv_setup);
#endif /* !MODULE */
MODULE_PARM(wdt_stop, "i");
MODULE_PARM_DESC(wdt_stop, "Advantech WDT 'stop' io port (default 0x443)");
MODULE_PARM(wdt_start, "i");
MODULE_PARM_DESC(wdt_start, "Advantech WDT 'start' io port (default 0x443)");
static void static void
advwdt_ping(void) advwdt_ping(void)
{ {
/* Write a watchdog value */ /* Write a watchdog value */
outb_p(wd_margin, wdt_start); outb_p(timeout, wdt_start);
} }
static void static void
...@@ -140,7 +128,7 @@ static int ...@@ -140,7 +128,7 @@ static int
advwdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, advwdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
unsigned long arg) unsigned long arg)
{ {
int new_margin; int new_timeout;
static struct watchdog_info ident = { static struct watchdog_info ident = {
.options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE, .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE,
.firmware_version = 1, .firmware_version = 1,
...@@ -162,16 +150,16 @@ advwdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, ...@@ -162,16 +150,16 @@ advwdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
break; break;
case WDIOC_SETTIMEOUT: case WDIOC_SETTIMEOUT:
if (get_user(new_margin, (int *)arg)) if (get_user(new_timeout, (int *)arg))
return -EFAULT; return -EFAULT;
if ((new_margin < 1) || (new_margin > 63)) if ((new_timeout < 1) || (new_timeout > 63))
return -EINVAL; return -EINVAL;
wd_margin = new_margin; timeout = new_timeout;
advwdt_ping(); advwdt_ping();
/* Fall */ /* Fall */
case WDIOC_GETTIMEOUT: case WDIOC_GETTIMEOUT:
return put_user(wd_margin, (int *)arg); return put_user(timeout, (int *)arg);
case WDIOC_SETOPTIONS: case WDIOC_SETOPTIONS:
{ {
...@@ -218,7 +206,7 @@ advwdt_close(struct inode *inode, struct file *file) ...@@ -218,7 +206,7 @@ advwdt_close(struct inode *inode, struct file *file)
if (adv_expect_close == 42) { if (adv_expect_close == 42) {
advwdt_disable(); advwdt_disable();
} else { } else {
printk(KERN_CRIT "advancetechwdt: Unexpected close, not stopping watchdog!\n"); printk(KERN_CRIT WATCHDOG_NAME ": Unexpected close, not stopping watchdog!\n");
advwdt_ping(); advwdt_ping();
} }
clear_bit(0, &advwdt_is_open); clear_bit(0, &advwdt_is_open);
...@@ -247,6 +235,7 @@ advwdt_notify_sys(struct notifier_block *this, unsigned long code, ...@@ -247,6 +235,7 @@ advwdt_notify_sys(struct notifier_block *this, unsigned long code,
static struct file_operations advwdt_fops = { static struct file_operations advwdt_fops = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.llseek = no_llseek,
.write = advwdt_write, .write = advwdt_write,
.ioctl = advwdt_ioctl, .ioctl = advwdt_ioctl,
.open = advwdt_open, .open = advwdt_open,
...@@ -256,7 +245,7 @@ static struct file_operations advwdt_fops = { ...@@ -256,7 +245,7 @@ static struct file_operations advwdt_fops = {
static struct miscdevice advwdt_miscdev = { static struct miscdevice advwdt_miscdev = {
.minor = WATCHDOG_MINOR, .minor = WATCHDOG_MINOR,
.name = "watchdog", .name = "watchdog",
.fops = &advwdt_fops .fops = &advwdt_fops,
}; };
/* /*
...@@ -267,29 +256,65 @@ static struct miscdevice advwdt_miscdev = { ...@@ -267,29 +256,65 @@ static struct miscdevice advwdt_miscdev = {
static struct notifier_block advwdt_notifier = { static struct notifier_block advwdt_notifier = {
.notifier_call = advwdt_notify_sys, .notifier_call = advwdt_notify_sys,
.next = NULL, .next = NULL,
.priority = 0 .priority = 0,
}; };
static int __init static int __init
advwdt_init(void) advwdt_init(void)
{ {
int ret;
printk(KERN_INFO "WDT driver for Advantech single board computer initialising.\n"); printk(KERN_INFO "WDT driver for Advantech single board computer initialising.\n");
if (misc_register(&advwdt_miscdev)) if (timeout < 1 || timeout > 63) {
return -ENODEV; timeout = WATCHDOG_TIMEOUT;
if (wdt_stop != wdt_start) printk (KERN_INFO WATCHDOG_NAME ": timeout value must be 1<=x<=63, using %d\n",
if (!request_region(wdt_stop, 1, "Advantech WDT")) { timeout);
misc_deregister(&advwdt_miscdev);
return -EIO;
} }
if (!request_region(wdt_start, 1, "Advantech WDT")) {
misc_deregister(&advwdt_miscdev); if (wdt_stop != wdt_start) {
if (!request_region(wdt_stop, 1, WATCHDOG_NAME)) {
printk (KERN_ERR WATCHDOG_NAME ": I/O address 0x%04x already in use\n",
wdt_stop);
ret = -EIO;
goto out;
}
}
if (!request_region(wdt_start, 1, WATCHDOG_NAME)) {
printk (KERN_ERR WATCHDOG_NAME ": I/O address 0x%04x already in use\n",
wdt_start);
ret = -EIO;
goto unreg_stop;
}
ret = register_reboot_notifier(&advwdt_notifier);
if (ret != 0) {
printk (KERN_ERR WATCHDOG_NAME ": cannot register reboot notifier (err=%d)\n",
ret);
goto unreg_regions;
}
ret = misc_register(&advwdt_miscdev);
if (ret != 0) {
printk (KERN_ERR WATCHDOG_NAME ": cannot register miscdev on minor=%d (err=%d)\n",
WATCHDOG_MINOR, ret);
goto unreg_reboot;
}
printk (KERN_INFO WATCHDOG_NAME ": initialized. timeout=%d sec (nowayout=%d)\n",
timeout, nowayout);
out:
return ret;
unreg_reboot:
unregister_reboot_notifier(&advwdt_notifier);
unreg_regions:
release_region(wdt_start, 1);
unreg_stop:
if (wdt_stop != wdt_start) if (wdt_stop != wdt_start)
release_region(wdt_stop, 1); release_region(wdt_stop, 1);
return -EIO; goto out;
}
register_reboot_notifier(&advwdt_notifier);
return 0;
} }
static void __exit static void __exit
......
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