Commit 51a43a9a authored by Linus Torvalds's avatar Linus Torvalds

Merge bk://linux-dj.bkbits.net/watchdog

into penguin.transmeta.com:/home/penguin/torvalds/repositories/kernel/linux
parents b615f582 bd5490e4
...@@ -24,24 +24,18 @@ ...@@ -24,24 +24,18 @@
#include <linux/config.h> #include <linux/config.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/version.h>
#include <linux/types.h> #include <linux/types.h>
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/miscdevice.h> #include <linux/miscdevice.h>
#include <linux/watchdog.h> #include <linux/watchdog.h>
#include <linux/slab.h>
#include <linux/ioport.h> #include <linux/ioport.h>
#include <linux/fcntl.h>
#include <asm/io.h>
#include <asm/uaccess.h>
#include <asm/system.h>
#include <linux/notifier.h> #include <linux/notifier.h>
#include <linux/reboot.h> #include <linux/reboot.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/smp_lock.h>
#include <asm/io.h>
#include <asm/uaccess.h>
#include <asm/system.h>
static int acq_is_open; static int acq_is_open;
static spinlock_t acq_lock; static spinlock_t acq_lock;
......
...@@ -13,64 +13,49 @@ ...@@ -13,64 +13,49 @@
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version * as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version. * 2 of the License, or (at your option) any later version.
* *
* Neither Alan Cox nor CymruNet Ltd. admit liability nor provide * Neither Alan Cox nor CymruNet Ltd. admit liability nor provide
* warranty for any of this software. This material is provided * warranty for any of this software. This material is provided
* "AS-IS" and at no charge. * "AS-IS" and at no charge.
* *
* (c) Copyright 1995 Alan Cox <alan@redhat.com> * (c) Copyright 1995 Alan Cox <alan@redhat.com>
* *
* 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
* Added timeout module option to override default
*/ */
#include <linux/config.h> #include <linux/config.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/version.h>
#include <linux/types.h> #include <linux/types.h>
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/miscdevice.h> #include <linux/miscdevice.h>
#include <linux/watchdog.h> #include <linux/watchdog.h>
#include <linux/slab.h>
#include <linux/ioport.h> #include <linux/ioport.h>
#include <linux/fcntl.h>
#include <asm/io.h>
#include <asm/uaccess.h>
#include <asm/system.h>
#include <linux/notifier.h> #include <linux/notifier.h>
#include <linux/reboot.h> #include <linux/reboot.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/spinlock.h>
#include <linux/smp_lock.h>
static int advwdt_is_open; #include <asm/io.h>
#include <asm/uaccess.h>
#include <asm/system.h>
static unsigned long advwdt_is_open;
static char adv_expect_close; static char adv_expect_close;
static spinlock_t advwdt_lock;
/* /*
* You must set these - there is no sane way to probe for this board. * You must set these - there is no sane way to probe for this board.
* *
* To enable or restart, write the timeout value in seconds (1 to 63) * To enable or restart, write the timeout value in seconds (1 to 63)
* to I/O port WDT_START. To disable, read I/O port WDT_STOP. * to I/O port wdt_start. To disable, read I/O port wdt_stop.
* Both are 0x443 for most boards (tested on a PCA-6276VE-00B1), but * Both are 0x443 for most boards (tested on a PCA-6276VE-00B1), but
* check your manual (at least the PCA-6159 seems to be different - * check your manual (at least the PCA-6159 seems to be different -
* the manual says WDT_STOP is 0x43, not 0x443). * the manual says wdt_stop is 0x43, not 0x443).
* (0x43 is also a write-only control register for the 8254 timer!) * (0x43 is also a write-only control register for the 8254 timer!)
*
* TODO: module parameters to set the I/O port addresses
*/ */
#define WDT_STOP 0x443 static int wdt_stop = 0x443;
#define WDT_START 0x443 static int wdt_start = 0x443;
#define WD_TIMO 60 /* 1 minute */
static int timeout = WD_TIMO; /* in seconds */ static int wd_margin = 60; /* 60 sec default timeout */
MODULE_PARM(timeout,"i");
MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds (default=60)");
#ifdef CONFIG_WATCHDOG_NOWAYOUT #ifdef CONFIG_WATCHDOG_NOWAYOUT
static int nowayout = 1; static int nowayout = 1;
...@@ -84,12 +69,44 @@ MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CON ...@@ -84,12 +69,44 @@ MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CON
/* /*
* 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(timeout, WDT_START); outb_p(wd_margin, wdt_start);
}
static void
advwdt_disable(void)
{
inb_p(wdt_stop);
} }
static ssize_t static ssize_t
...@@ -118,16 +135,11 @@ advwdt_write(struct file *file, const char *buf, size_t count, loff_t *ppos) ...@@ -118,16 +135,11 @@ advwdt_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
return count; return count;
} }
static ssize_t
advwdt_read(struct file *file, char *buf, size_t count, loff_t *ppos)
{
return -EINVAL;
}
static int 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;
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,
...@@ -139,16 +151,47 @@ advwdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, ...@@ -139,16 +151,47 @@ advwdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
if (copy_to_user((struct watchdog_info *)arg, &ident, sizeof(ident))) if (copy_to_user((struct watchdog_info *)arg, &ident, sizeof(ident)))
return -EFAULT; return -EFAULT;
break; break;
case WDIOC_GETSTATUS: case WDIOC_GETSTATUS:
if (copy_to_user((int *)arg, &advwdt_is_open, sizeof(int))) case WDIOC_GETBOOTSTATUS:
return -EFAULT; return put_user(0, (int *)arg);
break;
case WDIOC_KEEPALIVE: case WDIOC_KEEPALIVE:
advwdt_ping(); advwdt_ping();
break; break;
case WDIOC_SETTIMEOUT:
if (get_user(new_margin, (int *)arg))
return -EFAULT;
if ((new_margin < 1) || (new_margin > 63))
return -EINVAL;
wd_margin = new_margin;
advwdt_ping();
/* Fall */
case WDIOC_GETTIMEOUT:
return put_user(wd_margin, (int *)arg);
case WDIOC_SETOPTIONS:
{
int options, retval = -EINVAL;
if (get_user(options, (int *)arg))
return -EFAULT;
if (options & WDIOS_DISABLECARD) {
advwdt_disable();
retval = 0;
}
if (options & WDIOS_ENABLECARD) {
advwdt_ping();
retval = 0;
}
return retval;
}
default: default:
return -ENOTTY; return -ENOTTY;
} }
...@@ -158,37 +201,27 @@ advwdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, ...@@ -158,37 +201,27 @@ advwdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
static int static int
advwdt_open(struct inode *inode, struct file *file) advwdt_open(struct inode *inode, struct file *file)
{ {
if (minor(inode->i_rdev) == WATCHDOG_MINOR) { if (test_and_set_bit(0, &advwdt_is_open))
spin_lock(&advwdt_lock); return -EBUSY;
if (advwdt_is_open) { /*
spin_unlock(&advwdt_lock); * Activate
return -EBUSY; */
}
if (nowayout)
MOD_INC_USE_COUNT;
/* Activate */ advwdt_ping();
advwdt_is_open = 1; return 0;
advwdt_ping();
spin_unlock(&advwdt_lock);
return 0;
} else {
return -ENODEV;
}
} }
static int static int
advwdt_close(struct inode *inode, struct file *file) advwdt_close(struct inode *inode, struct file *file)
{ {
if (minor(inode->i_rdev) == WATCHDOG_MINOR) { if (adv_expect_close == 42) {
spin_lock(&advwdt_lock); advwdt_disable();
if (!nowayout) } else {
inb_p(WDT_STOP); printk(KERN_CRIT "advancetechwdt: Unexpected close, not stopping watchdog!\n");
advwdt_ping();
advwdt_is_open = 0;
spin_unlock(&advwdt_lock);
} }
clear_bit(0, &advwdt_is_open);
adv_expect_close = 0;
return 0; return 0;
} }
...@@ -200,10 +233,10 @@ static int ...@@ -200,10 +233,10 @@ static int
advwdt_notify_sys(struct notifier_block *this, unsigned long code, advwdt_notify_sys(struct notifier_block *this, unsigned long code,
void *unused) void *unused)
{ {
if (code == SYS_DOWN || code == SYS_HALT) if (code == SYS_DOWN || code == SYS_HALT) {
/* Turn the WDT off */ /* Turn the WDT off */
inb_p(WDT_STOP); advwdt_disable();
}
return NOTIFY_DONE; return NOTIFY_DONE;
} }
...@@ -213,7 +246,6 @@ advwdt_notify_sys(struct notifier_block *this, unsigned long code, ...@@ -213,7 +246,6 @@ 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,
.read = advwdt_read,
.write = advwdt_write, .write = advwdt_write,
.ioctl = advwdt_ioctl, .ioctl = advwdt_ioctl,
.open = advwdt_open, .open = advwdt_open,
...@@ -237,35 +269,22 @@ static struct notifier_block advwdt_notifier = { ...@@ -237,35 +269,22 @@ static struct notifier_block advwdt_notifier = {
.priority = 0 .priority = 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 static int __init
advwdt_init(void) advwdt_init(void)
{ {
printk("WDT driver for Advantech single board computer initialising.\n"); printk(KERN_INFO "WDT driver for Advantech single board computer initialising.\n");
advwdt_validate_timeout();
spin_lock_init(&advwdt_lock);
if (misc_register(&advwdt_miscdev)) if (misc_register(&advwdt_miscdev))
return -ENODEV; return -ENODEV;
#if WDT_START != WDT_STOP if (wdt_stop != wdt_start)
if (!request_region(WDT_STOP, 1, "Advantech WDT")) { if (!request_region(wdt_stop, 1, "Advantech WDT")) {
misc_deregister(&advwdt_miscdev); misc_deregister(&advwdt_miscdev);
return -EIO; return -EIO;
} }
#endif if (!request_region(wdt_start, 1, "Advantech WDT")) {
if (!request_region(WDT_START, 1, "Advantech WDT")) {
misc_deregister(&advwdt_miscdev); misc_deregister(&advwdt_miscdev);
#if WDT_START != WDT_STOP if (wdt_stop != wdt_start)
release_region(WDT_STOP, 1); release_region(wdt_stop, 1);
#endif
return -EIO; return -EIO;
} }
register_reboot_notifier(&advwdt_notifier); register_reboot_notifier(&advwdt_notifier);
...@@ -277,14 +296,15 @@ advwdt_exit(void) ...@@ -277,14 +296,15 @@ advwdt_exit(void)
{ {
misc_deregister(&advwdt_miscdev); misc_deregister(&advwdt_miscdev);
unregister_reboot_notifier(&advwdt_notifier); unregister_reboot_notifier(&advwdt_notifier);
#if WDT_START != WDT_STOP if(wdt_stop != wdt_start)
release_region(WDT_STOP,1); release_region(wdt_stop,1);
#endif release_region(wdt_start,1);
release_region(WDT_START,1);
} }
module_init(advwdt_init); module_init(advwdt_init);
module_exit(advwdt_exit); module_exit(advwdt_exit);
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
MODULE_AUTHOR("Marek Michalkiewicz <marekm@linux.org.pl>");
MODULE_DESCRIPTION("Advantech Single Board Computer WDT driver");
...@@ -30,26 +30,20 @@ ...@@ -30,26 +30,20 @@
*/ */
#include <linux/module.h> #include <linux/module.h>
#include <linux/version.h>
#include <linux/types.h> #include <linux/types.h>
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/timer.h> #include <linux/timer.h>
#include <linux/sched.h>
#include <linux/miscdevice.h> #include <linux/miscdevice.h>
#include <linux/watchdog.h> #include <linux/watchdog.h>
#include <linux/slab.h>
#include <linux/ioport.h> #include <linux/ioport.h>
#include <linux/fcntl.h>
#include <linux/smp_lock.h>
#include <asm/io.h>
#include <asm/uaccess.h>
#include <asm/system.h>
#include <linux/notifier.h> #include <linux/notifier.h>
#include <linux/reboot.h> #include <linux/reboot.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/pci.h> #include <linux/pci.h>
#include <asm/io.h>
#include <asm/uaccess.h>
#include <asm/system.h>
#define OUR_NAME "alim7101_wdt" #define OUR_NAME "alim7101_wdt"
#define WDT_ENABLE 0x9C #define WDT_ENABLE 0x9C
......
...@@ -3,78 +3,82 @@ ...@@ -3,78 +3,82 @@
* *
* (c) Copyright 2001 Ascensit <support@ascensit.com> * (c) Copyright 2001 Ascensit <support@ascensit.com>
* (c) Copyright 2001 Rodolfo Giometti <giometti@ascensit.com> * (c) Copyright 2001 Rodolfo Giometti <giometti@ascensit.com>
* (c) Copyright 2002 Rob Radez <rob@osinvestor.com>
* *
* Based on wdt.c. * Based on wdt.c.
* Original copyright messages: * Original copyright messages:
* *
* (c) Copyright 1996-1997 Alan Cox <alan@redhat.com>, All Rights Reserved. * (c) Copyright 1996-1997 Alan Cox <alan@redhat.com>, All Rights Reserved.
* http://www.redhat.com * http://www.redhat.com
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version * as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version. * 2 of the License, or (at your option) any later version.
* *
* Neither Alan Cox nor CymruNet Ltd. admit liability nor provide * Neither Alan Cox nor CymruNet Ltd. admit liability nor provide
* warranty for any of this software. This material is provided * warranty for any of this software. This material is provided
* "AS-IS" and at no charge. * "AS-IS" and at no charge.
* *
* (c) Copyright 1995 Alan Cox <alan@lxorguk.ukuu.org.uk> * (c) Copyright 1995 Alan Cox <alan@lxorguk.ukuu.org.uk>*
*/
/* Changelog:
*
* 2002/04/25 - Rob Radez
* clean up #includes
* clean up locking
* make __setup param unique
* proper options in watchdog_info
* add WDIOC_GETSTATUS and WDIOC_SETOPTIONS ioctls
* add expect_close support
* *
* 14-Dec-2001 Matt Domsch <Matt_Domsch@dell.com> * 2001 - Rodolfo Giometti
* Added nowayout module option to override CONFIG_WATCHDOG_NOWAYOUT * Initial release
* Added timeout module option to override default *
* 2002.05.30 - Joel Becker <joel.becker@oracle.com>
* Added Matt Domsch's nowayout module option.
*/ */
#include <linux/config.h> #include <linux/config.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/version.h>
#include <linux/types.h> #include <linux/types.h>
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/miscdevice.h> #include <linux/miscdevice.h>
#include <linux/watchdog.h> #include <linux/watchdog.h>
#include <linux/slab.h>
#include <linux/ioport.h> #include <linux/ioport.h>
#include <linux/fcntl.h>
#include <linux/notifier.h> #include <linux/notifier.h>
#include <linux/reboot.h> #include <linux/reboot.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/spinlock.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <asm/system.h> #include <asm/system.h>
static int eurwdt_is_open; static unsigned long eurwdt_is_open;
static spinlock_t eurwdt_lock; static int eurwdt_timeout;
static char eur_expect_close; static char eur_expect_close;
/* /*
* You must set these - there is no sane way to probe for this board. * You must set these - there is no sane way to probe for this board.
* You can use wdt=x,y to set these now. * You can use eurwdt=x,y to set these now.
*/ */
static int io = 0x3f0; static int io = 0x3f0;
static int irq = 10; static int irq = 10;
static char *ev = "int"; static char *ev = "int";
#define WDT_TIMEOUT 60 /* 1 minute */ #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 #ifdef CONFIG_WATCHDOG_NOWAYOUT
static int nowayout = 1; static int nowayout = 1;
#else #else
static int nowayout = 0; static int nowayout = 0;
#endif #endif
MODULE_PARM(nowayout,"i"); MODULE_PARM(nowayout,"i");
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)");
/* /*
* Some symbolic names * Some symbolic names
*/ */
...@@ -115,7 +119,7 @@ str = get_options (str, ARRAY_SIZE(ints), ints); ...@@ -115,7 +119,7 @@ str = get_options (str, ARRAY_SIZE(ints), ints);
return 1; return 1;
} }
__setup("wdt=", eurwdt_setup); __setup("eurwdt=", eurwdt_setup);
#endif /* !MODULE */ #endif /* !MODULE */
...@@ -124,22 +128,13 @@ MODULE_PARM_DESC(io, "Eurotech WDT io port (default=0x3f0)"); ...@@ -124,22 +128,13 @@ MODULE_PARM_DESC(io, "Eurotech WDT io port (default=0x3f0)");
MODULE_PARM(irq, "i"); MODULE_PARM(irq, "i");
MODULE_PARM_DESC(irq, "Eurotech WDT irq (default=10)"); MODULE_PARM_DESC(irq, "Eurotech WDT irq (default=10)");
MODULE_PARM(ev, "s"); MODULE_PARM(ev, "s");
MODULE_PARM_DESC(ev, "Eurotech WDT event type (default is `reboot')"); MODULE_PARM_DESC(ev, "Eurotech WDT event type (default is `int')");
/* /*
* Programming support * 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) static inline void eurwdt_write_reg(u8 index, u8 data)
{ {
outb(index, io); outb(index, io);
...@@ -214,7 +209,7 @@ void eurwdt_interrupt(int irq, void *dev_id, struct pt_regs *regs) ...@@ -214,7 +209,7 @@ void eurwdt_interrupt(int irq, void *dev_id, struct pt_regs *regs)
static void eurwdt_ping(void) static void eurwdt_ping(void)
{ {
/* Write the watchdog default value */ /* Write the watchdog default value */
eurwdt_set_timeout(timeout); eurwdt_set_timeout(eurwdt_timeout);
} }
/** /**
...@@ -250,10 +245,9 @@ loff_t *ppos) ...@@ -250,10 +245,9 @@ loff_t *ppos)
} }
} }
eurwdt_ping(); /* the default timeout */ eurwdt_ping(); /* the default timeout */
return 1;
} }
return 0; return count;
} }
/** /**
...@@ -271,12 +265,13 @@ static int eurwdt_ioctl(struct inode *inode, struct file *file, ...@@ -271,12 +265,13 @@ static int eurwdt_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg) unsigned int cmd, unsigned long arg)
{ {
static struct watchdog_info ident = { static struct watchdog_info ident = {
.options = WDIOF_CARDRESET, .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE,
.firmware_version = 1, .firmware_version = 1,
.identity = "WDT Eurotech CPU-1220/1410", .identity = "WDT Eurotech CPU-1220/1410",
}; };
int time; int time;
int options, retval = -EINVAL;
switch(cmd) { switch(cmd) {
default: default:
...@@ -286,6 +281,7 @@ static int eurwdt_ioctl(struct inode *inode, struct file *file, ...@@ -286,6 +281,7 @@ static int eurwdt_ioctl(struct inode *inode, struct file *file,
return copy_to_user((struct watchdog_info *)arg, &ident, return copy_to_user((struct watchdog_info *)arg, &ident,
sizeof(ident)) ? -EFAULT : 0; sizeof(ident)) ? -EFAULT : 0;
case WDIOC_GETSTATUS:
case WDIOC_GETBOOTSTATUS: case WDIOC_GETBOOTSTATUS:
return put_user(0, (int *) arg); return put_user(0, (int *) arg);
...@@ -301,9 +297,26 @@ static int eurwdt_ioctl(struct inode *inode, struct file *file, ...@@ -301,9 +297,26 @@ static int eurwdt_ioctl(struct inode *inode, struct file *file,
if (time < 0 || time > 255) if (time < 0 || time > 255)
return -EINVAL; return -EINVAL;
timeout = time; eurwdt_timeout = time;
eurwdt_set_timeout(time); eurwdt_set_timeout(time);
return 0; /* Fall */
case WDIOC_GETTIMEOUT:
return put_user(eurwdt_timeout, (int *)arg);
case WDIOC_SETOPTIONS:
if (get_user(options, (int *)arg))
return -EFAULT;
if (options & WDIOS_DISABLECARD) {
eurwdt_disable_timer();
retval = 0;
}
if (options & WDIOS_ENABLECARD) {
eurwdt_activate_timer();
eurwdt_ping();
retval = 0;
}
return retval;
} }
} }
...@@ -318,32 +331,12 @@ static int eurwdt_ioctl(struct inode *inode, struct file *file, ...@@ -318,32 +331,12 @@ static int eurwdt_ioctl(struct inode *inode, struct file *file,
static int eurwdt_open(struct inode *inode, struct file *file) static int eurwdt_open(struct inode *inode, struct file *file)
{ {
switch (minor(inode->i_rdev)) { if (test_and_set_bit(0, &eurwdt_is_open))
case WATCHDOG_MINOR: return -EBUSY;
spin_lock(&eurwdt_lock); eurwdt_timeout = WDT_TIMEOUT; /* initial timeout */
if (eurwdt_is_open) { /* Activate the WDT */
spin_unlock(&eurwdt_lock); eurwdt_activate_timer();
return -EBUSY; return 0;
}
if (nowayout)
MOD_INC_USE_COUNT;
eurwdt_is_open = 1;
/* Activate the WDT */
eurwdt_activate_timer();
spin_unlock(&eurwdt_lock);
MOD_INC_USE_COUNT;
return 0;
case TEMP_MINOR:
return 0;
default:
return -ENODEV;
}
} }
/** /**
...@@ -360,14 +353,14 @@ static int eurwdt_open(struct inode *inode, struct file *file) ...@@ -360,14 +353,14 @@ static int eurwdt_open(struct inode *inode, struct file *file)
static int eurwdt_release(struct inode *inode, struct file *file) static int eurwdt_release(struct inode *inode, struct file *file)
{ {
if (minor(inode->i_rdev) == WATCHDOG_MINOR) { if (eur_expect_close == 42) {
if (!nowayout) eurwdt_disable_timer();
eurwdt_disable_timer(); } else {
printk(KERN_CRIT "eurwdt: Unexpected close, not stopping watchdog!\n");
eurwdt_is_open = 0; eurwdt_ping();
MOD_DEC_USE_COUNT; }
} clear_bit(0, &eurwdt_is_open);
eur_expect_close = 0;
return 0; return 0;
} }
...@@ -456,7 +449,6 @@ static int __init eurwdt_init(void) ...@@ -456,7 +449,6 @@ static int __init eurwdt_init(void)
{ {
int ret; int ret;
eurwdt_validate_timeout();
ret = misc_register(&eurwdt_miscdev); ret = misc_register(&eurwdt_miscdev);
if (ret) { if (ret) {
printk(KERN_ERR "eurwdt: can't misc_register on minor=%d\n", printk(KERN_ERR "eurwdt: can't misc_register on minor=%d\n",
...@@ -489,8 +481,6 @@ static int __init eurwdt_init(void) ...@@ -489,8 +481,6 @@ static int __init eurwdt_init(void)
" - timeout event: %s\n", " - timeout event: %s\n",
io, irq, (!strcmp("int", ev) ? "int" : "reboot")); io, irq, (!strcmp("int", ev) ? "int" : "reboot"));
spin_lock_init(&eurwdt_lock);
out: out:
return ret; return ret;
......
...@@ -47,9 +47,6 @@ ...@@ -47,9 +47,6 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/types.h> #include <linux/types.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/mm.h>
#include <linux/miscdevice.h> #include <linux/miscdevice.h>
#include <linux/watchdog.h> #include <linux/watchdog.h>
#include <linux/reboot.h> #include <linux/reboot.h>
......
...@@ -33,24 +33,18 @@ ...@@ -33,24 +33,18 @@
#include <linux/config.h> #include <linux/config.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/version.h>
#include <linux/types.h> #include <linux/types.h>
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/miscdevice.h> #include <linux/miscdevice.h>
#include <linux/watchdog.h> #include <linux/watchdog.h>
#include <linux/slab.h>
#include <linux/ioport.h> #include <linux/ioport.h>
#include <linux/fcntl.h>
#include <asm/io.h>
#include <asm/uaccess.h>
#include <asm/system.h>
#include <linux/notifier.h> #include <linux/notifier.h>
#include <linux/reboot.h> #include <linux/reboot.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/smp_lock.h>
#include <asm/io.h>
#include <asm/uaccess.h>
#include <asm/system.h>
static int ibwdt_is_open; static int ibwdt_is_open;
static spinlock_t ibwdt_lock; static spinlock_t ibwdt_lock;
...@@ -92,15 +86,32 @@ static int expect_close = 0; ...@@ -92,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_STOP 0x441
#define WDT_START 0x443 #define WDT_START 0x443
/* Default timeout */
#define WD_TIMO 0 /* 30 seconds +/- 20%, from table */ #define WD_TIMO 0 /* 30 seconds +/- 20%, from table */
static int timeout_val = WD_TIMO; /* value in table */ static int wd_margin = WD_TIMO;
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 #ifdef CONFIG_WATCHDOG_NOWAYOUT
static int nowayout = 1; static int nowayout = 1;
...@@ -111,22 +122,16 @@ static int nowayout = 0; ...@@ -111,22 +122,16 @@ static int nowayout = 0;
MODULE_PARM(nowayout,"i"); MODULE_PARM(nowayout,"i");
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.
*/ */
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 static void
ibwdt_ping(void) ibwdt_ping(void)
{ {
/* Write a watchdog value */ /* Write a watchdog value */
outb_p(timeout_val, WDT_START); outb_p(wd_times[wd_margin], WDT_START);
} }
static ssize_t static ssize_t
...@@ -145,7 +150,6 @@ ibwdt_write(struct file *file, const char *buf, size_t count, loff_t *ppos) ...@@ -145,7 +150,6 @@ ibwdt_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
for (i = 0; i != count; i++) { for (i = 0; i != count; i++) {
char c; char c;
if (get_user(c, buf + i)) if (get_user(c, buf + i))
return -EFAULT; return -EFAULT;
if (c == 'V') if (c == 'V')
...@@ -168,6 +172,8 @@ static int ...@@ -168,6 +172,8 @@ static int
ibwdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, ibwdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
unsigned long arg) unsigned long arg)
{ {
int i, new_margin;
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,
...@@ -189,6 +195,22 @@ ibwdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, ...@@ -189,6 +195,22 @@ ibwdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
ibwdt_ping(); ibwdt_ping();
break; 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: default:
return -ENOTTY; return -ENOTTY;
} }
...@@ -223,7 +245,7 @@ ibwdt_close(struct inode *inode, struct file *file) ...@@ -223,7 +245,7 @@ ibwdt_close(struct inode *inode, struct file *file)
if (minor(inode->i_rdev) == WATCHDOG_MINOR) { if (minor(inode->i_rdev) == WATCHDOG_MINOR) {
spin_lock(&ibwdt_lock); spin_lock(&ibwdt_lock);
if (expect_close) if (expect_close)
outb_p(timeout_val, WDT_STOP); outb_p(wd_times[wd_margin], WDT_STOP);
else else
printk(KERN_CRIT "WDT device closed unexpectedly. WDT will not stop!\n"); printk(KERN_CRIT "WDT device closed unexpectedly. WDT will not stop!\n");
...@@ -243,7 +265,7 @@ ibwdt_notify_sys(struct notifier_block *this, unsigned long code, ...@@ -243,7 +265,7 @@ ibwdt_notify_sys(struct notifier_block *this, unsigned long code,
{ {
if (code == SYS_DOWN || code == SYS_HALT) { if (code == SYS_DOWN || code == SYS_HALT) {
/* Turn the WDT off */ /* Turn the WDT off */
outb_p(timeout_val, WDT_STOP); outb_p(wd_times[wd_margin], WDT_STOP);
} }
return NOTIFY_DONE; return NOTIFY_DONE;
} }
...@@ -283,7 +305,6 @@ ibwdt_init(void) ...@@ -283,7 +305,6 @@ ibwdt_init(void)
{ {
printk("WDT driver for IB700 single board computer initialising.\n"); printk("WDT driver for IB700 single board computer initialising.\n");
ibwdt_validate_timeout();
spin_lock_init(&ibwdt_lock); spin_lock_init(&ibwdt_lock);
if (misc_register(&ibwdt_miscdev)) if (misc_register(&ibwdt_miscdev))
return -ENODEV; return -ENODEV;
......
...@@ -19,7 +19,6 @@ ...@@ -19,7 +19,6 @@
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/miscdevice.h> #include <linux/miscdevice.h>
#include <linux/watchdog.h> #include <linux/watchdog.h>
#include <linux/smp_lock.h>
#include <linux/init.h> #include <linux/init.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <asm/sgi/sgimc.h> #include <asm/sgi/sgimc.h>
......
...@@ -30,25 +30,19 @@ ...@@ -30,25 +30,19 @@
#include <linux/config.h> #include <linux/config.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/version.h>
#include <linux/types.h> #include <linux/types.h>
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/timer.h> #include <linux/timer.h>
#include <linux/jiffies.h> #include <linux/jiffies.h>
#include <linux/miscdevice.h> #include <linux/miscdevice.h>
#include <linux/watchdog.h> #include <linux/watchdog.h>
#include <linux/slab.h>
#include <linux/ioport.h> #include <linux/ioport.h>
#include <linux/fcntl.h>
#include <linux/smp_lock.h>
#include <asm/io.h>
#include <asm/uaccess.h>
#include <asm/system.h>
#include <linux/notifier.h> #include <linux/notifier.h>
#include <linux/reboot.h> #include <linux/reboot.h>
#include <linux/init.h> #include <linux/init.h>
#include <asm/io.h>
#include <asm/uaccess.h>
#include <asm/system.h>
/* ports */ /* ports */
#define ZF_IOBASE 0x218 #define ZF_IOBASE 0x218
......
...@@ -38,15 +38,11 @@ ...@@ -38,15 +38,11 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/config.h> #include <linux/config.h>
#include <linux/types.h> #include <linux/types.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/mm.h>
#include <linux/miscdevice.h> #include <linux/miscdevice.h>
#include <linux/ioport.h> #include <linux/ioport.h>
#include <linux/watchdog.h> #include <linux/watchdog.h>
#include <linux/reboot.h> #include <linux/reboot.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/smp_lock.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <asm/io.h> #include <asm/io.h>
......
...@@ -45,27 +45,17 @@ ...@@ -45,27 +45,17 @@
*/ */
#include <linux/module.h> #include <linux/module.h>
#include <linux/types.h> #include <linux/types.h>
#include <linux/errno.h>
#include <linux/sched.h>
#include <linux/tty.h>
#include <linux/timer.h> #include <linux/timer.h>
#include <linux/config.h> #include <linux/config.h>
#include <linux/kernel.h>
#include <linux/wait.h> #include <linux/wait.h>
#include <linux/string.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/ioport.h> #include <linux/ioport.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/miscdevice.h> #include <linux/miscdevice.h>
#include <linux/fs.h>
#include <linux/mm.h>
#include <linux/watchdog.h> #include <linux/watchdog.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/proc_fs.h>
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/smp_lock.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <asm/io.h> #include <asm/io.h>
......
...@@ -24,7 +24,6 @@ ...@@ -24,7 +24,6 @@
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/miscdevice.h> #include <linux/miscdevice.h>
#include <linux/watchdog.h> #include <linux/watchdog.h>
#include <linux/smp_lock.h>
#include <linux/init.h> #include <linux/init.h>
#include <asm/hardware.h> #include <asm/hardware.h>
......
...@@ -56,25 +56,20 @@ ...@@ -56,25 +56,20 @@
*/ */
#include <linux/module.h> #include <linux/module.h>
#include <linux/version.h>
#include <linux/types.h> #include <linux/types.h>
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/timer.h> #include <linux/timer.h>
#include <linux/jiffies.h> #include <linux/jiffies.h>
#include <linux/miscdevice.h> #include <linux/miscdevice.h>
#include <linux/watchdog.h> #include <linux/watchdog.h>
#include <linux/slab.h>
#include <linux/ioport.h> #include <linux/ioport.h>
#include <linux/fcntl.h>
#include <linux/smp_lock.h>
#include <asm/io.h>
#include <asm/uaccess.h>
#include <asm/system.h>
#include <linux/notifier.h> #include <linux/notifier.h>
#include <linux/reboot.h> #include <linux/reboot.h>
#include <linux/init.h> #include <linux/init.h>
#include <asm/io.h>
#include <asm/uaccess.h>
#include <asm/system.h>
#define OUR_NAME "sbc60xxwdt" #define OUR_NAME "sbc60xxwdt"
/* /*
......
...@@ -28,21 +28,20 @@ ...@@ -28,21 +28,20 @@
#include <linux/config.h> #include <linux/config.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/kernel.h>
#include <linux/miscdevice.h> #include <linux/miscdevice.h>
#include <linux/watchdog.h> #include <linux/watchdog.h>
#include <linux/ioport.h> #include <linux/ioport.h>
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/ioport.h>
#include <asm/semaphore.h>
#include <asm/io.h>
#include <asm/uaccess.h>
#include <linux/notifier.h> #include <linux/notifier.h>
#include <linux/reboot.h> #include <linux/reboot.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/isapnp.h> #include <linux/isapnp.h>
#include <linux/pci.h> #include <linux/pci.h>
#include <asm/semaphore.h>
#include <asm/io.h>
#include <asm/uaccess.h>
#define SC1200_MODULE_VER "build 20020303" #define SC1200_MODULE_VER "build 20020303"
#define SC1200_MODULE_NAME "sc1200wdt" #define SC1200_MODULE_NAME "sc1200wdt"
#define PFX SC1200_MODULE_NAME ": " #define PFX SC1200_MODULE_NAME ": "
......
...@@ -49,25 +49,19 @@ ...@@ -49,25 +49,19 @@
*/ */
#include <linux/module.h> #include <linux/module.h>
#include <linux/version.h>
#include <linux/types.h> #include <linux/types.h>
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/timer.h> #include <linux/timer.h>
#include <linux/sched.h>
#include <linux/miscdevice.h> #include <linux/miscdevice.h>
#include <linux/watchdog.h> #include <linux/watchdog.h>
#include <linux/slab.h>
#include <linux/ioport.h> #include <linux/ioport.h>
#include <linux/fcntl.h>
#include <linux/smp_lock.h>
#include <asm/io.h>
#include <asm/uaccess.h>
#include <asm/system.h>
#include <linux/notifier.h> #include <linux/notifier.h>
#include <linux/reboot.h> #include <linux/reboot.h>
#include <linux/init.h> #include <linux/init.h>
#include <asm/io.h>
#include <asm/uaccess.h>
#include <asm/system.h>
/* /*
* The SC520 can timeout anywhere from 492us to 32.21s. * The SC520 can timeout anywhere from 492us to 32.21s.
* If we reset the watchdog every ~250ms we should be safe. * If we reset the watchdog every ~250ms we should be safe.
......
...@@ -19,19 +19,17 @@ ...@@ -19,19 +19,17 @@
#include <linux/config.h> #include <linux/config.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/miscdevice.h> #include <linux/miscdevice.h>
#include <linux/watchdog.h> #include <linux/watchdog.h>
#include <linux/notifier.h> #include <linux/notifier.h>
#include <linux/reboot.h> #include <linux/reboot.h>
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/scx200.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <asm/io.h> #include <asm/io.h>
#include <linux/scx200.h>
#define NAME "scx200_wdt" #define NAME "scx200_wdt"
MODULE_AUTHOR("Christer Weinigel <wingel@nano-system.com>"); MODULE_AUTHOR("Christer Weinigel <wingel@nano-system.com>");
......
...@@ -16,7 +16,6 @@ ...@@ -16,7 +16,6 @@
#include <linux/config.h> #include <linux/config.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/kernel.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>
......
...@@ -27,21 +27,21 @@ ...@@ -27,21 +27,21 @@
* 19980911 Alan Cox * 19980911 Alan Cox
* Made SMP safe for 2.3.x * Made SMP safe for 2.3.x
* *
* 20011214 Matt Domsch <Matt_Domsch@dell.com> * 20011127 Joel Becker (jlbec@evilplan.org>
* Added nowayout module option to override CONFIG_WATCHDOG_NOWAYOUT * Added soft_noboot; Allows testing the softdog trigger without
* Didn't add timeout option, as soft_margin option already exists. * requiring a recompile.
* Added WDIOC_GETTIMEOUT and WDIOC_SETTIMOUT.
*
* 20020530 Joel Becker <joel.becker@oracle.com>
* Added Matt Domsch's nowayout module option.
*/ */
#include <linux/module.h> #include <linux/module.h>
#include <linux/config.h> #include <linux/config.h>
#include <linux/types.h> #include <linux/types.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/mm.h>
#include <linux/miscdevice.h> #include <linux/miscdevice.h>
#include <linux/watchdog.h> #include <linux/watchdog.h>
#include <linux/reboot.h> #include <linux/reboot.h>
#include <linux/smp_lock.h>
#include <linux/init.h> #include <linux/init.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
...@@ -49,8 +49,15 @@ ...@@ -49,8 +49,15 @@
static int expect_close = 0; static int expect_close = 0;
static int soft_margin = TIMER_MARGIN; /* in seconds */ static int soft_margin = TIMER_MARGIN; /* in seconds */
#ifdef ONLY_TESTING
static int soft_noboot = 1;
#else
static int soft_noboot = 0;
#endif /* ONLY_TESTING */
MODULE_PARM(soft_margin,"i"); MODULE_PARM(soft_margin,"i");
MODULE_PARM(soft_noboot,"i");
MODULE_LICENSE("GPL");
#ifdef CONFIG_WATCHDOG_NOWAYOUT #ifdef CONFIG_WATCHDOG_NOWAYOUT
static int nowayout = 1; static int nowayout = 1;
...@@ -60,7 +67,6 @@ static int nowayout = 0; ...@@ -60,7 +67,6 @@ static int nowayout = 0;
MODULE_PARM(nowayout,"i"); MODULE_PARM(nowayout,"i");
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)");
MODULE_LICENSE("GPL");
/* /*
* Our timer * Our timer
...@@ -70,7 +76,7 @@ static void watchdog_fire(unsigned long); ...@@ -70,7 +76,7 @@ static void watchdog_fire(unsigned long);
static struct timer_list watchdog_ticktock = static struct timer_list watchdog_ticktock =
TIMER_INITIALIZER(watchdog_fire, 0, 0); TIMER_INITIALIZER(watchdog_fire, 0, 0);
static int timer_alive; static unsigned long timer_alive;
/* /*
...@@ -79,13 +85,14 @@ static int timer_alive; ...@@ -79,13 +85,14 @@ static int timer_alive;
static void watchdog_fire(unsigned long data) static void watchdog_fire(unsigned long data)
{ {
#ifdef ONLY_TESTING if (soft_noboot)
printk(KERN_CRIT "SOFTDOG: Would Reboot.\n"); printk(KERN_CRIT "SOFTDOG: Triggered - Reboot ignored.\n");
#else else
printk(KERN_CRIT "SOFTDOG: Initiating system reboot.\n"); {
machine_restart(NULL); printk(KERN_CRIT "SOFTDOG: Initiating system reboot.\n");
printk("WATCHDOG: Reboot didn't ?????\n"); machine_restart(NULL);
#endif printk("SOFTDOG: Reboot didn't ?????\n");
}
} }
/* /*
...@@ -94,7 +101,7 @@ static void watchdog_fire(unsigned long data) ...@@ -94,7 +101,7 @@ static void watchdog_fire(unsigned long data)
static int softdog_open(struct inode *inode, struct file *file) static int softdog_open(struct inode *inode, struct file *file)
{ {
if(timer_alive) if(test_and_set_bit(0, &timer_alive))
return -EBUSY; return -EBUSY;
if (nowayout) { if (nowayout) {
MOD_INC_USE_COUNT; MOD_INC_USE_COUNT;
...@@ -103,7 +110,6 @@ static int softdog_open(struct inode *inode, struct file *file) ...@@ -103,7 +110,6 @@ static int softdog_open(struct inode *inode, struct file *file)
* Activate timer * Activate timer
*/ */
mod_timer(&watchdog_ticktock, jiffies+(soft_margin*HZ)); mod_timer(&watchdog_ticktock, jiffies+(soft_margin*HZ));
timer_alive=1;
return 0; return 0;
} }
...@@ -113,12 +119,12 @@ static int softdog_release(struct inode *inode, struct file *file) ...@@ -113,12 +119,12 @@ static int softdog_release(struct inode *inode, struct file *file)
* Shut off the timer. * Shut off the timer.
* Lock it in if it's a module and we set nowayout * Lock it in if it's a module and we set nowayout
*/ */
if(!nowayout) { if (expect_close) {
del_timer(&watchdog_ticktock); del_timer(&watchdog_ticktock);
} else { } else {
printk(KERN_CRIT "SOFTDOG: WDT device closed unexpectedly. WDT will not stop!\n"); printk(KERN_CRIT "SOFTDOG: WDT device closed unexpectedly. WDT will not stop!\n");
} }
timer_alive=0; clear_bit(0, &timer_alive);
return 0; return 0;
} }
...@@ -156,6 +162,7 @@ static ssize_t softdog_write(struct file *file, const char *data, size_t len, lo ...@@ -156,6 +162,7 @@ static ssize_t softdog_write(struct file *file, const char *data, size_t len, lo
static int softdog_ioctl(struct inode *inode, struct file *file, static int softdog_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg) unsigned int cmd, unsigned long arg)
{ {
int new_margin;
static struct watchdog_info ident = { static struct watchdog_info ident = {
.options = WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE, .options = WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE,
.identity = "Software Watchdog", .identity = "Software Watchdog",
...@@ -173,6 +180,16 @@ static int softdog_ioctl(struct inode *inode, struct file *file, ...@@ -173,6 +180,16 @@ static int softdog_ioctl(struct inode *inode, struct file *file,
case WDIOC_KEEPALIVE: case WDIOC_KEEPALIVE:
mod_timer(&watchdog_ticktock, jiffies+(soft_margin*HZ)); mod_timer(&watchdog_ticktock, jiffies+(soft_margin*HZ));
return 0; return 0;
case WDIOC_SETTIMEOUT:
if (get_user(new_margin, (int *)arg))
return -EFAULT;
if (new_margin < 1)
return -EINVAL;
soft_margin = new_margin;
mod_timer(&watchdog_ticktock, jiffies+(soft_margin*HZ));
/* Fall */
case WDIOC_GETTIMEOUT:
return put_user(soft_margin, (int *)arg);
} }
} }
......
...@@ -42,24 +42,18 @@ ...@@ -42,24 +42,18 @@
*/ */
#include <linux/module.h> #include <linux/module.h>
#include <linux/version.h>
#include <linux/types.h> #include <linux/types.h>
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/timer.h> #include <linux/timer.h>
#include <linux/jiffies.h> #include <linux/jiffies.h>
#include <linux/miscdevice.h> #include <linux/miscdevice.h>
#include <linux/watchdog.h> #include <linux/watchdog.h>
#include <linux/slab.h>
#include <linux/ioport.h> #include <linux/ioport.h>
#include <linux/fcntl.h>
#include <linux/smp_lock.h>
#include <asm/io.h>
#include <asm/uaccess.h>
#include <asm/system.h>
#include <linux/notifier.h> #include <linux/notifier.h>
#include <linux/reboot.h> #include <linux/reboot.h>
#include <linux/init.h> #include <linux/init.h>
#include <asm/io.h>
#include <asm/uaccess.h>
#include <asm/system.h>
#define OUR_NAME "w83877f_wdt" #define OUR_NAME "w83877f_wdt"
...@@ -220,6 +214,8 @@ static int fop_open(struct inode * inode, struct file * file) ...@@ -220,6 +214,8 @@ static int fop_open(struct inode * inode, struct file * file)
case WATCHDOG_MINOR: case WATCHDOG_MINOR:
/* Just in case we're already talking to someone... */ /* Just in case we're already talking to someone... */
if(test_and_set_bit(0, &wdt_is_open)) { if(test_and_set_bit(0, &wdt_is_open)) {
/* Davej: Is this unlock bogus? */
spin_unlock(&wdt_spinlock);
return -EBUSY; return -EBUSY;
} }
/* Good, fire up the show */ /* Good, fire up the show */
...@@ -242,7 +238,7 @@ static int fop_close(struct inode * inode, struct file * file) ...@@ -242,7 +238,7 @@ static int fop_close(struct inode * inode, struct file * file)
printk(OUR_NAME ": device file closed unexpectedly. Will not stop the WDT!\n"); printk(OUR_NAME ": device file closed unexpectedly. Will not stop the WDT!\n");
} }
} }
wdt_is_open = 0; clear_bit(0, &wdt_is_open);
return 0; return 0;
} }
......
...@@ -27,16 +27,15 @@ ...@@ -27,16 +27,15 @@
*/ */
#include <linux/module.h> #include <linux/module.h>
#include <linux/kernel.h>
#include <linux/miscdevice.h> #include <linux/miscdevice.h>
#include <linux/watchdog.h> #include <linux/watchdog.h>
#include <linux/ioport.h> #include <linux/ioport.h>
#include <asm/io.h>
#include <asm/uaccess.h>
#include <linux/notifier.h> #include <linux/notifier.h>
#include <linux/reboot.h> #include <linux/reboot.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <asm/io.h>
#include <asm/uaccess.h>
static unsigned long wafwdt_is_open; static unsigned long wafwdt_is_open;
static spinlock_t wafwdt_lock; static spinlock_t wafwdt_lock;
......
...@@ -27,22 +27,17 @@ ...@@ -27,22 +27,17 @@
* Tim Hockin : Added insmod parameters, comment cleanup * Tim Hockin : Added insmod parameters, comment cleanup
* Parameterized timeout * Parameterized timeout
* Tigran Aivazian : Restructured wdt_init() to handle failures * Tigran Aivazian : Restructured wdt_init() to handle failures
* Matt Domsch : added nowayout and timeout module options * Joel Becker : Added WDIOC_GET/SETTIMEOUT
* Matt Domsch : Added nowayout module option
*/ */
#include <linux/config.h> #include <linux/config.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/version.h>
#include <linux/types.h> #include <linux/types.h>
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/miscdevice.h> #include <linux/miscdevice.h>
#include <linux/watchdog.h> #include <linux/watchdog.h>
#include "wd501p.h"
#include <linux/slab.h>
#include <linux/ioport.h> #include <linux/ioport.h>
#include <linux/fcntl.h>
#include <linux/notifier.h> #include <linux/notifier.h>
#include <linux/reboot.h> #include <linux/reboot.h>
#include <linux/init.h> #include <linux/init.h>
...@@ -50,6 +45,7 @@ ...@@ -50,6 +45,7 @@
#include <asm/io.h> #include <asm/io.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <asm/system.h> #include <asm/system.h>
#include "wd501p.h"
static unsigned long wdt_is_open; static unsigned long wdt_is_open;
static int expect_close; static int expect_close;
...@@ -62,12 +58,10 @@ static int expect_close; ...@@ -62,12 +58,10 @@ static int expect_close;
static int io=0x240; static int io=0x240;
static int irq=11; static int irq=11;
/* Default margin */
#define WD_TIMO (100*60) /* 1 minute */ #define WD_TIMO (100*60) /* 1 minute */
static int timeout_val = WD_TIMO; /* value passed to card */ static int wd_margin = WD_TIMO;
static int timeout = 60; /* in seconds */
MODULE_PARM(timeout,"i");
MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds (default=60)");
#ifdef CONFIG_WATCHDOG_NOWAYOUT #ifdef CONFIG_WATCHDOG_NOWAYOUT
static int nowayout = 1; static int nowayout = 1;
...@@ -78,12 +72,6 @@ static int nowayout = 0; ...@@ -78,12 +72,6 @@ static int nowayout = 0;
MODULE_PARM(nowayout,"i"); MODULE_PARM(nowayout,"i");
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)");
static void __init
wdt_validate_timeout(void)
{
timeout_val = timeout * 100;
}
#ifndef MODULE #ifndef MODULE
/** /**
...@@ -238,7 +226,7 @@ static void wdt_ping(void) ...@@ -238,7 +226,7 @@ static void wdt_ping(void)
/* Write a watchdog value */ /* Write a watchdog value */
inb_p(WDT_DC); inb_p(WDT_DC);
wdt_ctr_mode(1,2); wdt_ctr_mode(1,2);
wdt_ctr_load(1,timeout_val); /* Timeout */ wdt_ctr_load(1,wd_margin); /* Timeout */
outb_p(0, WDT_DC); outb_p(0, WDT_DC);
} }
...@@ -329,6 +317,8 @@ static ssize_t wdt_read(struct file *file, char *buf, size_t count, loff_t *ptr) ...@@ -329,6 +317,8 @@ static ssize_t wdt_read(struct file *file, char *buf, size_t count, loff_t *ptr)
static int wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, static int wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
unsigned long arg) unsigned long arg)
{ {
int new_margin;
static struct watchdog_info ident= static struct watchdog_info ident=
{ {
.options = WDIOF_OVERHEAT|WDIOF_POWERUNDER|WDIOF_POWEROVER .options = WDIOF_OVERHEAT|WDIOF_POWERUNDER|WDIOF_POWEROVER
...@@ -353,6 +343,17 @@ static int wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, ...@@ -353,6 +343,17 @@ static int wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
case WDIOC_KEEPALIVE: case WDIOC_KEEPALIVE:
wdt_ping(); wdt_ping();
return 0; return 0;
case WDIOC_SETTIMEOUT:
if (get_user(new_margin, (int *)arg))
return -EFAULT;
/* Arbitrary, can't find the card's limits */
if ((new_margin < 0) || (new_margin > 60))
return -EINVAL;
wd_margin = new_margin * 100;
wdt_ping();
/* Fall */
case WDIOC_GETTIMEOUT:
return put_user(wd_margin / 100, (int *)arg);
} }
} }
...@@ -375,19 +376,17 @@ static int wdt_open(struct inode *inode, struct file *file) ...@@ -375,19 +376,17 @@ static int wdt_open(struct inode *inode, struct file *file)
case WATCHDOG_MINOR: case WATCHDOG_MINOR:
if(test_and_set_bit(0, &wdt_is_open)) if(test_and_set_bit(0, &wdt_is_open))
return -EBUSY; return -EBUSY;
if (nowayout) {
MOD_INC_USE_COUNT;
}
/* /*
* Activate * Activate
*/ */
wdt_is_open=1;
inb_p(WDT_DC); /* Disable */ inb_p(WDT_DC); /* Disable */
wdt_ctr_mode(0,3); wdt_ctr_mode(0,3);
wdt_ctr_mode(1,2); wdt_ctr_mode(1,2);
wdt_ctr_mode(2,0); wdt_ctr_mode(2,0);
wdt_ctr_load(0, 8948); /* count at 100Hz */ wdt_ctr_load(0, 8948); /* count at 100Hz */
wdt_ctr_load(1,timeout_val); /* Timeout */ wdt_ctr_load(1,wd_margin); /* Timeout 120 seconds */
wdt_ctr_load(2,65535); wdt_ctr_load(2,65535);
outb_p(0, WDT_DC); /* Enable */ outb_p(0, WDT_DC); /* Enable */
return 0; return 0;
...@@ -525,7 +524,6 @@ static int __init wdt_init(void) ...@@ -525,7 +524,6 @@ static int __init wdt_init(void)
{ {
int ret; int ret;
wdt_validate_timeout();
ret = misc_register(&wdt_miscdev); ret = misc_register(&wdt_miscdev);
if (ret) { if (ret) {
printk(KERN_ERR "wdt: can't misc_register on minor=%d\n", WATCHDOG_MINOR); printk(KERN_ERR "wdt: can't misc_register on minor=%d\n", WATCHDOG_MINOR);
......
...@@ -25,7 +25,6 @@ ...@@ -25,7 +25,6 @@
#include <linux/reboot.h> #include <linux/reboot.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/smp_lock.h>
#include <asm/irq.h> #include <asm/irq.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
...@@ -124,10 +123,10 @@ static ssize_t watchdog_write(struct file *file, const char *data, size_t len, l ...@@ -124,10 +123,10 @@ static ssize_t watchdog_write(struct file *file, const char *data, size_t len, l
static int watchdog_ioctl(struct inode *inode, struct file *file, static int watchdog_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg) unsigned int cmd, unsigned long arg)
{ {
int i; int i, new_margin;
static struct watchdog_info ident= static struct watchdog_info ident=
{ {
0, WDIOF_SETTIMEOUT,
0, 0,
"Footbridge Watchdog" "Footbridge Watchdog"
}; };
...@@ -145,6 +144,17 @@ static int watchdog_ioctl(struct inode *inode, struct file *file, ...@@ -145,6 +144,17 @@ static int watchdog_ioctl(struct inode *inode, struct file *file,
case WDIOC_KEEPALIVE: case WDIOC_KEEPALIVE:
watchdog_ping(); watchdog_ping();
return 0; return 0;
case WDIOC_SETTIMEOUT:
if (get_user(new_margin, (int *)arg))
return -EFAULT;
/* Arbitrary, can't find the card's limits */
if ((new_marg < 0) || (new_margin > 60))
return -EINVAL;
soft_margin = new_margin;
watchdog_ping();
/* Fall */
case WDIOC_GETTIMEOUT:
return put_user(soft_margin, (int *)arg);
} }
} }
...@@ -166,10 +176,15 @@ static struct miscdevice watchdog_miscdev= ...@@ -166,10 +176,15 @@ static struct miscdevice watchdog_miscdev=
static int __init footbridge_watchdog_init(void) static int __init footbridge_watchdog_init(void)
{ {
int retval;
if (machine_is_netwinder()) if (machine_is_netwinder())
return -ENODEV; return -ENODEV;
misc_register(&watchdog_miscdev); retval = misc_register(&watchdog_miscdev);
if(retval < 0)
return retval;
printk("Footbridge Watchdog Timer: 0.01, timer margin: %d sec\n", printk("Footbridge Watchdog Timer: 0.01, timer margin: %d sec\n",
soft_margin); soft_margin);
if (machine_is_cats()) if (machine_is_cats())
......
...@@ -25,7 +25,6 @@ ...@@ -25,7 +25,6 @@
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/miscdevice.h> #include <linux/miscdevice.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/smp_lock.h>
#include <linux/watchdog.h> #include <linux/watchdog.h>
#include <asm/io.h> #include <asm/io.h>
......
...@@ -30,21 +30,18 @@ ...@@ -30,21 +30,18 @@
* Alan Cox : Split ISA and PCI cards into two drivers * Alan Cox : Split ISA and PCI cards into two drivers
* Jeff Garzik : PCI cleanups * Jeff Garzik : PCI cleanups
* Tigran Aivazian : Restructured wdtpci_init_one() to handle failures * Tigran Aivazian : Restructured wdtpci_init_one() to handle failures
* Matt Domsch : added nowayout and timeout module options * Joel Becker : Added WDIOC_GET/SETTIMEOUT
* Zwane Mwaikambo : Magic char closing, locking changes, cleanups
* Matt Domsch : nowayout module option
*/ */
#include <linux/config.h> #include <linux/config.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/version.h>
#include <linux/types.h> #include <linux/types.h>
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/miscdevice.h> #include <linux/miscdevice.h>
#include <linux/watchdog.h> #include <linux/watchdog.h>
#include <linux/slab.h>
#include <linux/ioport.h> #include <linux/ioport.h>
#include <linux/fcntl.h>
#include <linux/notifier.h> #include <linux/notifier.h>
#include <linux/reboot.h> #include <linux/reboot.h>
#include <linux/init.h> #include <linux/init.h>
...@@ -72,23 +69,18 @@ ...@@ -72,23 +69,18 @@
#define PCI_DEVICE_ID_WDG_CSM 0x22c0 #define PCI_DEVICE_ID_WDG_CSM 0x22c0
#endif #endif
static unsigned long wdt_is_open; static struct semaphore open_sem;
static spinlock_t wdtpci_lock;
static int expect_close = 0; static int expect_close = 0;
/* static int io;
* You must set these - there is no sane way to probe for this board. static int irq;
* You can use wdt=x,y to set these now.
*/
static int io=0x240;
static int irq=11;
/* Default timeout */
#define WD_TIMO (100*60) /* 1 minute */ #define WD_TIMO (100*60) /* 1 minute */
#define WD_TIMO_MAX (WD_TIMO*60) /* 1 hour(?) */
static int timeout_val = WD_TIMO; /* value passed to card */ static int wd_margin = WD_TIMO;
static int timeout = 60; /* in seconds */
MODULE_PARM(timeout,"i");
MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds (default=60)");
#ifdef CONFIG_WATCHDOG_NOWAYOUT #ifdef CONFIG_WATCHDOG_NOWAYOUT
static int nowayout = 1; static int nowayout = 1;
...@@ -99,43 +91,6 @@ static int nowayout = 0; ...@@ -99,43 +91,6 @@ static int nowayout = 0;
MODULE_PARM(nowayout,"i"); MODULE_PARM(nowayout,"i");
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)");
static void __init
wdtpci_validate_timeout(void)
{
timeout_val = timeout * 100;
}
#ifndef MODULE
/**
* wdtpci_setup:
* @str: command line string
*
* Setup options. The board isn't really probe-able so we have to
* get the user to tell us the configuration. Sane people build it
* modular but the others come here.
*/
static int __init wdtpci_setup(char *str)
{
int ints[4];
str = get_options (str, ARRAY_SIZE(ints), ints);
if (ints[0] > 0)
{
io = ints[1];
if(ints[0] > 1)
irq = ints[2];
}
return 1;
}
__setup("wdt=", wdtpci_setup);
#endif /* !MODULE */
/* /*
* Programming support * Programming support
*/ */
...@@ -251,11 +206,15 @@ static void wdtpci_interrupt(int irq, void *dev_id, struct pt_regs *regs) ...@@ -251,11 +206,15 @@ static void wdtpci_interrupt(int irq, void *dev_id, struct pt_regs *regs)
static void wdtpci_ping(void) static void wdtpci_ping(void)
{ {
unsigned long flags;
/* Write a watchdog value */ /* Write a watchdog value */
spin_lock_irqsave(&wdtpci_lock, flags);
inb_p(WDT_DC); inb_p(WDT_DC);
wdtpci_ctr_mode(1,2); wdtpci_ctr_mode(1,2);
wdtpci_ctr_load(1,timeout_val); /* Timeout */ wdtpci_ctr_load(1,wd_margin); /* Timeout */
outb_p(0, WDT_DC); outb_p(0, WDT_DC);
spin_unlock_irqrestore(&wdtpci_lock, flags);
} }
/** /**
...@@ -275,10 +234,12 @@ static ssize_t wdtpci_write(struct file *file, const char *buf, size_t count, lo ...@@ -275,10 +234,12 @@ static ssize_t wdtpci_write(struct file *file, const char *buf, size_t count, lo
if (ppos != &file->f_pos) if (ppos != &file->f_pos)
return -ESPIPE; return -ESPIPE;
if(count) if (count) {
{
if (!nowayout) { if (!nowayout) {
size_t i; size_t i;
expect_close = 0;
for (i = 0; i != count; i++) { for (i = 0; i != count; i++) {
char c; char c;
if(get_user(c, buf+i)) if(get_user(c, buf+i))
...@@ -288,9 +249,9 @@ static ssize_t wdtpci_write(struct file *file, const char *buf, size_t count, lo ...@@ -288,9 +249,9 @@ static ssize_t wdtpci_write(struct file *file, const char *buf, size_t count, lo
} }
} }
wdtpci_ping(); wdtpci_ping();
return 1;
} }
return 0;
return count;
} }
/** /**
...@@ -342,6 +303,7 @@ static ssize_t wdtpci_read(struct file *file, char *buf, size_t count, loff_t *p ...@@ -342,6 +303,7 @@ static ssize_t wdtpci_read(struct file *file, char *buf, size_t count, loff_t *p
static int wdtpci_ioctl(struct inode *inode, struct file *file, unsigned int cmd, static int wdtpci_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
unsigned long arg) unsigned long arg)
{ {
int new_margin;
static struct watchdog_info ident = { static struct watchdog_info ident = {
.options = WDIOF_OVERHEAT | WDIOF_POWERUNDER | .options = WDIOF_OVERHEAT | WDIOF_POWERUNDER |
WDIOF_POWEROVER | WDIOF_EXTERN1 | WDIOF_POWEROVER | WDIOF_EXTERN1 |
...@@ -366,6 +328,18 @@ static int wdtpci_ioctl(struct inode *inode, struct file *file, unsigned int cmd ...@@ -366,6 +328,18 @@ static int wdtpci_ioctl(struct inode *inode, struct file *file, unsigned int cmd
case WDIOC_KEEPALIVE: case WDIOC_KEEPALIVE:
wdtpci_ping(); wdtpci_ping();
return 0; return 0;
case WDIOC_SETTIMEOUT:
if (get_user(new_margin, (int *)arg))
return -EFAULT;
/* Arbitrary, can't find the card's limits */
new_margin *= 100;
if ((new_margin < 0) || (new_margin > WD_TIMO_MAX))
return -EINVAL;
wd_margin = new_margin;
wdtpci_ping();
/* Fall */
case WDIOC_GETTIMEOUT:
return put_user(wd_margin / 100, (int *)arg);
} }
} }
...@@ -383,20 +357,22 @@ static int wdtpci_ioctl(struct inode *inode, struct file *file, unsigned int cmd ...@@ -383,20 +357,22 @@ static int wdtpci_ioctl(struct inode *inode, struct file *file, unsigned int cmd
static int wdtpci_open(struct inode *inode, struct file *file) static int wdtpci_open(struct inode *inode, struct file *file)
{ {
unsigned long flags;
switch(minor(inode->i_rdev)) switch(minor(inode->i_rdev))
{ {
case WATCHDOG_MINOR: case WATCHDOG_MINOR:
if( test_and_set_bit(0,&wdt_is_open) ) if (down_trylock(&open_sem))
{
return -EBUSY; return -EBUSY;
}
if (nowayout) { if (nowayout) {
MOD_INC_USE_COUNT; MOD_INC_USE_COUNT;
} }
/* /*
* Activate * Activate
*/ */
spin_lock_irqsave(&wdtpci_lock, flags);
inb_p(WDT_DC); /* Disable */ inb_p(WDT_DC); /* Disable */
/* /*
...@@ -418,9 +394,10 @@ static int wdtpci_open(struct inode *inode, struct file *file) ...@@ -418,9 +394,10 @@ static int wdtpci_open(struct inode *inode, struct file *file)
wdtpci_ctr_mode(1,2); wdtpci_ctr_mode(1,2);
wdtpci_ctr_mode(2,1); wdtpci_ctr_mode(2,1);
wdtpci_ctr_load(0,20833); /* count at 100Hz */ wdtpci_ctr_load(0,20833); /* count at 100Hz */
wdtpci_ctr_load(1,timeout_val); /* Timeout */ wdtpci_ctr_load(1,wd_margin);/* Timeout 60 seconds */
/* DO NOT LOAD CTR2 on PCI card! -- JPN */ /* DO NOT LOAD CTR2 on PCI card! -- JPN */
outb_p(0, WDT_DC); /* Enable */ outb_p(0, WDT_DC); /* Enable */
spin_unlock_irqrestore(&wdtpci_lock, flags);
return 0; return 0;
case TEMP_MINOR: case TEMP_MINOR:
return 0; return 0;
...@@ -443,13 +420,19 @@ static int wdtpci_open(struct inode *inode, struct file *file) ...@@ -443,13 +420,19 @@ static int wdtpci_open(struct inode *inode, struct file *file)
static int wdtpci_release(struct inode *inode, struct file *file) static int wdtpci_release(struct inode *inode, struct file *file)
{ {
if(minor(inode->i_rdev)==WATCHDOG_MINOR)
{ if (minor(inode->i_rdev)==WATCHDOG_MINOR) {
if (!nowayout) { unsigned long flags;
if (expect_close) {
spin_lock_irqsave(&wdtpci_lock, flags);
inb_p(WDT_DC); /* Disable counters */ inb_p(WDT_DC); /* Disable counters */
wdtpci_ctr_load(2,0); /* 0 length reset pulses now */ wdtpci_ctr_load(2,0); /* 0 length reset pulses now */
spin_unlock_irqrestore(&wdtpci_lock, flags);
} else {
printk(KERN_CRIT PFX "Unexpected close, not stopping timer!");
wdtpci_ping();
} }
clear_bit(0, &wdt_is_open ); up(&open_sem);
} }
return 0; return 0;
} }
...@@ -469,11 +452,14 @@ static int wdtpci_release(struct inode *inode, struct file *file) ...@@ -469,11 +452,14 @@ static int wdtpci_release(struct inode *inode, struct file *file)
static int wdtpci_notify_sys(struct notifier_block *this, unsigned long code, static int wdtpci_notify_sys(struct notifier_block *this, unsigned long code,
void *unused) void *unused)
{ {
if(code==SYS_DOWN || code==SYS_HALT) unsigned long flags;
{
if (code==SYS_DOWN || code==SYS_HALT) {
/* Turn the card off */ /* Turn the card off */
spin_lock_irqsave(&wdtpci_lock, flags);
inb_p(WDT_DC); inb_p(WDT_DC);
wdtpci_ctr_load(2,0); wdtpci_ctr_load(2,0);
spin_unlock_irqrestore(&wdtpci_lock, flags);
} }
return NOTIFY_DONE; return NOTIFY_DONE;
} }
...@@ -533,6 +519,9 @@ static int __init wdtpci_init_one (struct pci_dev *dev, ...@@ -533,6 +519,9 @@ static int __init wdtpci_init_one (struct pci_dev *dev,
if (pci_enable_device (dev)) if (pci_enable_device (dev))
goto out; goto out;
sema_init(&open_sem, 1);
spin_lock_init(&wdtpci_lock);
irq = dev->irq; irq = dev->irq;
io = pci_resource_start (dev, 2); io = pci_resource_start (dev, 2);
printk ("WDT501-P(PCI-WDG-CSM) driver 0.07 at %X " printk ("WDT501-P(PCI-WDG-CSM) driver 0.07 at %X "
...@@ -650,8 +639,6 @@ static int __init wdtpci_init(void) ...@@ -650,8 +639,6 @@ static int __init wdtpci_init(void)
if (rc < 1) if (rc < 1)
return -ENODEV; return -ENODEV;
wdtpci_validate_timeout();
return 0; return 0;
} }
......
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