Commit 950cda48 authored by Dave Jones's avatar Dave Jones

[WATCHDOG] Final 2.4 bits for eurotechwdt

parent 2ac7e7a9
...@@ -33,7 +33,6 @@ ...@@ -33,7 +33,6 @@
#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>
......
...@@ -3,27 +3,41 @@ ...@@ -3,27 +3,41 @@
* *
* (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>
...@@ -36,40 +50,35 @@ ...@@ -36,40 +50,35 @@
#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
*/ */
...@@ -110,7 +119,7 @@ str = get_options (str, ARRAY_SIZE(ints), ints); ...@@ -110,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 */
...@@ -119,22 +128,13 @@ MODULE_PARM_DESC(io, "Eurotech WDT io port (default=0x3f0)"); ...@@ -119,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);
...@@ -209,7 +209,7 @@ void eurwdt_interrupt(int irq, void *dev_id, struct pt_regs *regs) ...@@ -209,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);
} }
/** /**
...@@ -245,10 +245,9 @@ loff_t *ppos) ...@@ -245,10 +245,9 @@ loff_t *ppos)
} }
} }
eurwdt_ping(); /* the default timeout */ eurwdt_ping(); /* the default timeout */
return 1;
} }
return 0; return count;
} }
/** /**
...@@ -266,12 +265,13 @@ static int eurwdt_ioctl(struct inode *inode, struct file *file, ...@@ -266,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:
...@@ -281,6 +281,7 @@ static int eurwdt_ioctl(struct inode *inode, struct file *file, ...@@ -281,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);
...@@ -296,9 +297,26 @@ static int eurwdt_ioctl(struct inode *inode, struct file *file, ...@@ -296,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;
} }
} }
...@@ -313,32 +331,12 @@ static int eurwdt_ioctl(struct inode *inode, struct file *file, ...@@ -313,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;
}
} }
/** /**
...@@ -355,14 +353,14 @@ static int eurwdt_open(struct inode *inode, struct file *file) ...@@ -355,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;
} }
...@@ -451,7 +449,6 @@ static int __init eurwdt_init(void) ...@@ -451,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",
...@@ -484,8 +481,6 @@ static int __init eurwdt_init(void) ...@@ -484,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;
......
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