Commit b588e2bb authored by Linus Torvalds's avatar Linus Torvalds

Merge git://git.kernel.org/pub/scm/linux/kernel/git/wim/linux-2.6-watchdog

* git://git.kernel.org/pub/scm/linux/kernel/git/wim/linux-2.6-watchdog: (70 commits)
  [WATCHDOG] more coding style clean-up's
  [WATCHDOG] sbc8360.c - move stop code into a function
  [WATCHDOG] Coding style - Indentation - part 2
  [WATCHDOG] Coding style - Indentation - part 1
  [WATCHDOG] mpc8xxx_wdt: add support for MPC8xx watchdogs
  [WATCHDOG] mpc8xxx_wdt: fix build
  [WATCHDOG] mpc8xxx_wdt: various renames, mostly s/mpc83xx/mpc8xxx/g
  [WATCHDOG] mpc83xx_wdt: rename to mpc8xxx_wdt
  [WATCHDOG] mpc83xx_wdt: add support for MPC86xx CPUs
  [WATCHDOG] mpc83xx_wdt: convert to the OF platform driver
  [WATCHDOG] pcwd: a couple of watchdogs escaped conversion
  [WATCHDOG] Clean-up includes
  [WATCHDOG] hpwdt.c - fix double includes
  [WATCHDOG 57/57] wdt501/pci: Clean up, coding style and switch to unlocked_ioctl
  [WATCHDOG 56/57] wdt977: clean up, coding style and switch to unlocked_ioctl
  [WATCHDOG 55/57] wdt285: switch to unlocked_ioctl and tidy up oddments of coding style
  [WATCHDOG 54/57] wdrtas: clean up, coding style, switch to unlocked_ioctl
  [WATCHDOG 53/57] wafer5823wdt: Clean up, coding style, switch to unlocked_ioctl
  [WATCHDOG 52/57] w83977f_wdt: clean up, coding style and switch to unlocked_ioctl
  [WATCHDOG 51/57] w83877f_wdt: clean up code, coding style, switch to unlocked_ioctl
  ...
parents 3df302ff 7944d3a5
...@@ -463,7 +463,7 @@ config PC87413_WDT ...@@ -463,7 +463,7 @@ config PC87413_WDT
module will be called pc87413_wdt. module will be called pc87413_wdt.
Most people will say N. Most people will say N.
config 60XX_WDT config 60XX_WDT
tristate "SBC-60XX Watchdog Timer" tristate "SBC-60XX Watchdog Timer"
depends on X86 depends on X86
...@@ -695,9 +695,17 @@ config 8xx_WDT ...@@ -695,9 +695,17 @@ config 8xx_WDT
tristate "MPC8xx Watchdog Timer" tristate "MPC8xx Watchdog Timer"
depends on 8xx depends on 8xx
config 83xx_WDT config 8xxx_WDT
tristate "MPC83xx Watchdog Timer" tristate "MPC8xxx Platform Watchdog Timer"
depends on PPC_83xx depends on PPC_8xx || PPC_83xx || PPC_86xx
help
This driver is for a SoC level watchdog that exists on some
Freescale PowerPC processors. So far this driver supports:
- MPC8xx watchdogs
- MPC83xx watchdogs
- MPC86xx watchdogs
For BookE processors (MPC85xx) use the BOOKE_WDT driver instead.
config MV64X60_WDT config MV64X60_WDT
tristate "MV64X60 (Marvell Discovery) Watchdog Timer" tristate "MV64X60 (Marvell Discovery) Watchdog Timer"
......
...@@ -92,7 +92,7 @@ obj-$(CONFIG_SBC_EPX_C3_WATCHDOG) += sbc_epx_c3.o ...@@ -92,7 +92,7 @@ obj-$(CONFIG_SBC_EPX_C3_WATCHDOG) += sbc_epx_c3.o
# MIPS Architecture # MIPS Architecture
obj-$(CONFIG_INDYDOG) += indydog.o obj-$(CONFIG_INDYDOG) += indydog.o
obj-$(CONFIG_WDT_MTX1) += mtx-1_wdt.o obj-$(CONFIG_WDT_MTX1) += mtx-1_wdt.o
obj-$(CONFIG_WDT_RM9K_GPI) += rm9k_wdt.o obj-$(CONFIG_WDT_RM9K_GPI) += rm9k_wdt.o
obj-$(CONFIG_SIBYTE_WDOG) += sb_wdog.o obj-$(CONFIG_SIBYTE_WDOG) += sb_wdog.o
obj-$(CONFIG_AR7_WDT) += ar7_wdt.o obj-$(CONFIG_AR7_WDT) += ar7_wdt.o
...@@ -103,7 +103,7 @@ obj-$(CONFIG_TXX9_WDT) += txx9wdt.o ...@@ -103,7 +103,7 @@ obj-$(CONFIG_TXX9_WDT) += txx9wdt.o
# POWERPC Architecture # POWERPC Architecture
obj-$(CONFIG_8xx_WDT) += mpc8xx_wdt.o obj-$(CONFIG_8xx_WDT) += mpc8xx_wdt.o
obj-$(CONFIG_MPC5200_WDT) += mpc5200_wdt.o obj-$(CONFIG_MPC5200_WDT) += mpc5200_wdt.o
obj-$(CONFIG_83xx_WDT) += mpc83xx_wdt.o obj-$(CONFIG_8xxx_WDT) += mpc8xxx_wdt.o
obj-$(CONFIG_MV64X60_WDT) += mv64x60_wdt.o obj-$(CONFIG_MV64X60_WDT) += mv64x60_wdt.o
obj-$(CONFIG_BOOKE_WDT) += booke_wdt.o obj-$(CONFIG_BOOKE_WDT) += booke_wdt.o
......
...@@ -58,39 +58,45 @@ ...@@ -58,39 +58,45 @@
#include <linux/types.h> /* For standard types (like size_t) */ #include <linux/types.h> /* For standard types (like size_t) */
#include <linux/errno.h> /* For the -ENODEV/... values */ #include <linux/errno.h> /* For the -ENODEV/... values */
#include <linux/kernel.h> /* For printk/panic/... */ #include <linux/kernel.h> /* For printk/panic/... */
#include <linux/miscdevice.h> /* For MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR) */ #include <linux/miscdevice.h> /* For MODULE_ALIAS_MISCDEV
(WATCHDOG_MINOR) */
#include <linux/watchdog.h> /* For the watchdog specific items */ #include <linux/watchdog.h> /* For the watchdog specific items */
#include <linux/fs.h> /* For file operations */ #include <linux/fs.h> /* For file operations */
#include <linux/ioport.h> /* For io-port access */ #include <linux/ioport.h> /* For io-port access */
#include <linux/platform_device.h> /* For platform_driver framework */ #include <linux/platform_device.h> /* For platform_driver framework */
#include <linux/init.h> /* For __init/__exit/... */ #include <linux/init.h> /* For __init/__exit/... */
#include <linux/uaccess.h> /* For copy_to_user/put_user/... */
#include <asm/uaccess.h> /* For copy_to_user/put_user/... */ #include <linux/io.h> /* For inb/outb/... */
#include <asm/io.h> /* For inb/outb/... */
/* Module information */ /* Module information */
#define DRV_NAME "acquirewdt" #define DRV_NAME "acquirewdt"
#define PFX DRV_NAME ": " #define PFX DRV_NAME ": "
#define WATCHDOG_NAME "Acquire WDT" #define WATCHDOG_NAME "Acquire WDT"
#define WATCHDOG_HEARTBEAT 0 /* There is no way to see what the correct time-out period is */ /* There is no way to see what the correct time-out period is */
#define WATCHDOG_HEARTBEAT 0
/* internal variables */ /* internal variables */
static struct platform_device *acq_platform_device; /* the watchdog platform device */ /* the watchdog platform device */
static struct platform_device *acq_platform_device;
static unsigned long acq_is_open; static unsigned long acq_is_open;
static char expect_close; static char expect_close;
/* module parameters */ /* module parameters */
static int wdt_stop = 0x43; /* You must set this - there is no sane way to probe for this board. */ /* You must set this - there is no sane way to probe for this board. */
static int wdt_stop = 0x43;
module_param(wdt_stop, int, 0); module_param(wdt_stop, int, 0);
MODULE_PARM_DESC(wdt_stop, "Acquire WDT 'stop' io port (default 0x43)"); MODULE_PARM_DESC(wdt_stop, "Acquire WDT 'stop' io port (default 0x43)");
static int wdt_start = 0x443; /* You must set this - there is no sane way to probe for this board. */ /* You must set this - there is no sane way to probe for this board. */
static int wdt_start = 0x443;
module_param(wdt_start, int, 0); module_param(wdt_start, int, 0);
MODULE_PARM_DESC(wdt_start, "Acquire WDT 'start' io port (default 0x443)"); MODULE_PARM_DESC(wdt_start, "Acquire WDT 'start' io port (default 0x443)");
static int nowayout = WATCHDOG_NOWAYOUT; static int nowayout = WATCHDOG_NOWAYOUT;
module_param(nowayout, int, 0); module_param(nowayout, int, 0);
MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); MODULE_PARM_DESC(nowayout,
"Watchdog cannot be stopped once started (default="
__MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
/* /*
* Watchdog Operations * Watchdog Operations
...@@ -112,18 +118,18 @@ static void acq_stop(void) ...@@ -112,18 +118,18 @@ static void acq_stop(void)
* /dev/watchdog handling * /dev/watchdog handling
*/ */
static ssize_t acq_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) static ssize_t acq_write(struct file *file, const char __user *buf,
size_t count, loff_t *ppos)
{ {
/* See if we got the magic character 'V' and reload the timer */ /* See if we got the magic character 'V' and reload the timer */
if(count) { if (count) {
if (!nowayout) { if (!nowayout) {
size_t i; size_t i;
/* note: just in case someone wrote the magic character /* note: just in case someone wrote the magic character
* five months ago... */ five months ago... */
expect_close = 0; expect_close = 0;
/* scan to see whether or not we got the
/* scan to see whether or not we got the magic character */ magic character */
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))
...@@ -132,64 +138,55 @@ static ssize_t acq_write(struct file *file, const char __user *buf, size_t count ...@@ -132,64 +138,55 @@ static ssize_t acq_write(struct file *file, const char __user *buf, size_t count
expect_close = 42; expect_close = 42;
} }
} }
/* Well, anyhow someone wrote to us, we should
/* Well, anyhow someone wrote to us, we should return that favour */ return that favour */
acq_keepalive(); acq_keepalive();
} }
return count; return count;
} }
static int acq_ioctl(struct inode *inode, struct file *file, unsigned int cmd, static long acq_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
unsigned long arg)
{ {
int options, retval = -EINVAL; int options, retval = -EINVAL;
void __user *argp = (void __user *)arg; void __user *argp = (void __user *)arg;
int __user *p = argp; int __user *p = argp;
static struct watchdog_info ident = static struct watchdog_info ident = {
{
.options = WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE, .options = WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE,
.firmware_version = 1, .firmware_version = 1,
.identity = WATCHDOG_NAME, .identity = WATCHDOG_NAME,
}; };
switch(cmd) switch (cmd) {
{
case WDIOC_GETSUPPORT: case WDIOC_GETSUPPORT:
return copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0; return copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0;
case WDIOC_GETSTATUS: case WDIOC_GETSTATUS:
case WDIOC_GETBOOTSTATUS: case WDIOC_GETBOOTSTATUS:
return put_user(0, p); return put_user(0, p);
case WDIOC_KEEPALIVE:
acq_keepalive();
return 0;
case WDIOC_GETTIMEOUT:
return put_user(WATCHDOG_HEARTBEAT, p);
case WDIOC_SETOPTIONS: case WDIOC_SETOPTIONS:
{ {
if (get_user(options, p)) if (get_user(options, p))
return -EFAULT; return -EFAULT;
if (options & WDIOS_DISABLECARD) {
if (options & WDIOS_DISABLECARD) acq_stop();
{ retval = 0;
acq_stop(); }
retval = 0; if (options & WDIOS_ENABLECARD) {
} acq_keepalive();
retval = 0;
if (options & WDIOS_ENABLECARD) }
{ return retval;
acq_keepalive();
retval = 0;
}
return retval;
} }
case WDIOC_KEEPALIVE:
acq_keepalive();
return 0;
case WDIOC_GETTIMEOUT:
return put_user(WATCHDOG_HEARTBEAT, p);
default: default:
return -ENOTTY; return -ENOTTY;
} }
} }
...@@ -211,7 +208,8 @@ static int acq_close(struct inode *inode, struct file *file) ...@@ -211,7 +208,8 @@ static int acq_close(struct inode *inode, struct file *file)
if (expect_close == 42) { if (expect_close == 42) {
acq_stop(); acq_stop();
} else { } else {
printk(KERN_CRIT PFX "Unexpected close, not stopping watchdog!\n"); printk(KERN_CRIT PFX
"Unexpected close, not stopping watchdog!\n");
acq_keepalive(); acq_keepalive();
} }
clear_bit(0, &acq_is_open); clear_bit(0, &acq_is_open);
...@@ -227,7 +225,7 @@ static const struct file_operations acq_fops = { ...@@ -227,7 +225,7 @@ static const struct file_operations acq_fops = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.llseek = no_llseek, .llseek = no_llseek,
.write = acq_write, .write = acq_write,
.ioctl = acq_ioctl, .unlocked_ioctl = acq_ioctl,
.open = acq_open, .open = acq_open,
.release = acq_close, .release = acq_close,
}; };
...@@ -248,32 +246,29 @@ static int __devinit acq_probe(struct platform_device *dev) ...@@ -248,32 +246,29 @@ static int __devinit acq_probe(struct platform_device *dev)
if (wdt_stop != wdt_start) { if (wdt_stop != wdt_start) {
if (!request_region(wdt_stop, 1, WATCHDOG_NAME)) { if (!request_region(wdt_stop, 1, WATCHDOG_NAME)) {
printk (KERN_ERR PFX "I/O address 0x%04x already in use\n", printk(KERN_ERR PFX
wdt_stop); "I/O address 0x%04x already in use\n", wdt_stop);
ret = -EIO; ret = -EIO;
goto out; goto out;
} }
} }
if (!request_region(wdt_start, 1, WATCHDOG_NAME)) { if (!request_region(wdt_start, 1, WATCHDOG_NAME)) {
printk (KERN_ERR PFX "I/O address 0x%04x already in use\n", printk(KERN_ERR PFX "I/O address 0x%04x already in use\n",
wdt_start); wdt_start);
ret = -EIO; ret = -EIO;
goto unreg_stop; goto unreg_stop;
} }
ret = misc_register(&acq_miscdev); ret = misc_register(&acq_miscdev);
if (ret != 0) { if (ret != 0) {
printk (KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n", printk(KERN_ERR PFX
WATCHDOG_MINOR, ret); "cannot register miscdev on minor=%d (err=%d)\n",
WATCHDOG_MINOR, ret);
goto unreg_regions; goto unreg_regions;
} }
printk(KERN_INFO PFX "initialized. (nowayout=%d)\n", nowayout);
printk (KERN_INFO PFX "initialized. (nowayout=%d)\n",
nowayout);
return 0; return 0;
unreg_regions: unreg_regions:
release_region(wdt_start, 1); release_region(wdt_start, 1);
unreg_stop: unreg_stop:
...@@ -286,9 +281,9 @@ static int __devinit acq_probe(struct platform_device *dev) ...@@ -286,9 +281,9 @@ static int __devinit acq_probe(struct platform_device *dev)
static int __devexit acq_remove(struct platform_device *dev) static int __devexit acq_remove(struct platform_device *dev)
{ {
misc_deregister(&acq_miscdev); misc_deregister(&acq_miscdev);
release_region(wdt_start,1); release_region(wdt_start, 1);
if(wdt_stop != wdt_start) if (wdt_stop != wdt_start)
release_region(wdt_stop,1); release_region(wdt_stop, 1);
return 0; return 0;
} }
...@@ -313,18 +308,19 @@ static int __init acq_init(void) ...@@ -313,18 +308,19 @@ static int __init acq_init(void)
{ {
int err; int err;
printk(KERN_INFO "WDT driver for Acquire single board computer initialising.\n"); printk(KERN_INFO
"WDT driver for Acquire single board computer initialising.\n");
err = platform_driver_register(&acquirewdt_driver); err = platform_driver_register(&acquirewdt_driver);
if (err) if (err)
return err; return err;
acq_platform_device = platform_device_register_simple(DRV_NAME, -1, NULL, 0); acq_platform_device = platform_device_register_simple(DRV_NAME,
-1, NULL, 0);
if (IS_ERR(acq_platform_device)) { if (IS_ERR(acq_platform_device)) {
err = PTR_ERR(acq_platform_device); err = PTR_ERR(acq_platform_device);
goto unreg_platform_driver; goto unreg_platform_driver;
} }
return 0; return 0;
unreg_platform_driver: unreg_platform_driver:
......
...@@ -37,9 +37,9 @@ ...@@ -37,9 +37,9 @@
#include <linux/ioport.h> #include <linux/ioport.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/io.h>
#include <linux/uaccess.h>
#include <asm/io.h>
#include <asm/uaccess.h>
#include <asm/system.h> #include <asm/system.h>
#define DRV_NAME "advantechwdt" #define DRV_NAME "advantechwdt"
...@@ -47,7 +47,8 @@ ...@@ -47,7 +47,8 @@
#define WATCHDOG_NAME "Advantech WDT" #define WATCHDOG_NAME "Advantech WDT"
#define WATCHDOG_TIMEOUT 60 /* 60 sec default timeout */ #define WATCHDOG_TIMEOUT 60 /* 60 sec default timeout */
static struct platform_device *advwdt_platform_device; /* the watchdog platform device */ /* the watchdog platform device */
static struct platform_device *advwdt_platform_device;
static unsigned long advwdt_is_open; static unsigned long advwdt_is_open;
static char adv_expect_close; static char adv_expect_close;
...@@ -72,35 +73,35 @@ MODULE_PARM_DESC(wdt_start, "Advantech WDT 'start' io port (default 0x443)"); ...@@ -72,35 +73,35 @@ MODULE_PARM_DESC(wdt_start, "Advantech WDT 'start' io port (default 0x443)");
static int timeout = WATCHDOG_TIMEOUT; /* in seconds */ static int timeout = WATCHDOG_TIMEOUT; /* in seconds */
module_param(timeout, int, 0); module_param(timeout, int, 0);
MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds. 1<= timeout <=63, default=" __MODULE_STRING(WATCHDOG_TIMEOUT) "."); MODULE_PARM_DESC(timeout,
"Watchdog timeout in seconds. 1<= timeout <=63, default="
__MODULE_STRING(WATCHDOG_TIMEOUT) ".");
static int nowayout = WATCHDOG_NOWAYOUT; static int nowayout = WATCHDOG_NOWAYOUT;
module_param(nowayout, int, 0); module_param(nowayout, int, 0);
MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); MODULE_PARM_DESC(nowayout,
"Watchdog cannot be stopped once started (default="
__MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
/* /*
* Watchdog Operations * Watchdog Operations
*/ */
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(timeout, wdt_start);
} }
static void static void advwdt_disable(void)
advwdt_disable(void)
{ {
inb_p(wdt_stop); inb_p(wdt_stop);
} }
static int static int advwdt_set_heartbeat(int t)
advwdt_set_heartbeat(int t)
{ {
if ((t < 1) || (t > 63)) if (t < 1 || t > 63)
return -EINVAL; return -EINVAL;
timeout = t; timeout = t;
return 0; return 0;
} }
...@@ -109,8 +110,8 @@ advwdt_set_heartbeat(int t) ...@@ -109,8 +110,8 @@ advwdt_set_heartbeat(int t)
* /dev/watchdog handling * /dev/watchdog handling
*/ */
static ssize_t static ssize_t advwdt_write(struct file *file, const char __user *buf,
advwdt_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) size_t count, loff_t *ppos)
{ {
if (count) { if (count) {
if (!nowayout) { if (!nowayout) {
...@@ -120,7 +121,7 @@ advwdt_write(struct file *file, const char __user *buf, size_t count, loff_t *pp ...@@ -120,7 +121,7 @@ advwdt_write(struct file *file, const char __user *buf, size_t count, loff_t *pp
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')
adv_expect_close = 42; adv_expect_close = 42;
...@@ -131,9 +132,7 @@ advwdt_write(struct file *file, const char __user *buf, size_t count, loff_t *pp ...@@ -131,9 +132,7 @@ advwdt_write(struct file *file, const char __user *buf, size_t count, loff_t *pp
return count; return count;
} }
static int static long advwdt_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
advwdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
unsigned long arg)
{ {
int new_timeout; int new_timeout;
void __user *argp = (void __user *)arg; void __user *argp = (void __user *)arg;
...@@ -146,57 +145,50 @@ advwdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, ...@@ -146,57 +145,50 @@ advwdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
switch (cmd) { switch (cmd) {
case WDIOC_GETSUPPORT: case WDIOC_GETSUPPORT:
if (copy_to_user(argp, &ident, sizeof(ident))) if (copy_to_user(argp, &ident, sizeof(ident)))
return -EFAULT; return -EFAULT;
break; break;
case WDIOC_GETSTATUS: case WDIOC_GETSTATUS:
case WDIOC_GETBOOTSTATUS: case WDIOC_GETBOOTSTATUS:
return put_user(0, p); return put_user(0, p);
case WDIOC_KEEPALIVE:
advwdt_ping();
break;
case WDIOC_SETTIMEOUT:
if (get_user(new_timeout, p))
return -EFAULT;
if (advwdt_set_heartbeat(new_timeout))
return -EINVAL;
advwdt_ping();
/* Fall */
case WDIOC_GETTIMEOUT:
return put_user(timeout, p);
case WDIOC_SETOPTIONS: case WDIOC_SETOPTIONS:
{ {
int options, retval = -EINVAL; int options, retval = -EINVAL;
if (get_user(options, p))
return -EFAULT;
if (options & WDIOS_DISABLECARD) {
advwdt_disable();
retval = 0;
}
if (options & WDIOS_ENABLECARD) { if (get_user(options, p))
advwdt_ping(); return -EFAULT;
retval = 0; if (options & WDIOS_DISABLECARD) {
} advwdt_disable();
retval = 0;
return retval; }
if (options & WDIOS_ENABLECARD) {
advwdt_ping();
retval = 0;
}
return retval;
} }
case WDIOC_KEEPALIVE:
advwdt_ping();
break;
case WDIOC_SETTIMEOUT:
if (get_user(new_timeout, p))
return -EFAULT;
if (advwdt_set_heartbeat(new_timeout))
return -EINVAL;
advwdt_ping();
/* Fall */
case WDIOC_GETTIMEOUT:
return put_user(timeout, p);
default: default:
return -ENOTTY; return -ENOTTY;
} }
return 0; return 0;
} }
static int static int advwdt_open(struct inode *inode, struct file *file)
advwdt_open(struct inode *inode, struct file *file)
{ {
if (test_and_set_bit(0, &advwdt_is_open)) if (test_and_set_bit(0, &advwdt_is_open))
return -EBUSY; return -EBUSY;
...@@ -208,13 +200,13 @@ advwdt_open(struct inode *inode, struct file *file) ...@@ -208,13 +200,13 @@ advwdt_open(struct inode *inode, struct file *file)
return nonseekable_open(inode, file); return nonseekable_open(inode, file);
} }
static int static int advwdt_close(struct inode *inode, struct file *file)
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 PFX "Unexpected close, not stopping watchdog!\n"); printk(KERN_CRIT PFX
"Unexpected close, not stopping watchdog!\n");
advwdt_ping(); advwdt_ping();
} }
clear_bit(0, &advwdt_is_open); clear_bit(0, &advwdt_is_open);
...@@ -230,7 +222,7 @@ static const struct file_operations advwdt_fops = { ...@@ -230,7 +222,7 @@ static const struct file_operations advwdt_fops = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.llseek = no_llseek, .llseek = no_llseek,
.write = advwdt_write, .write = advwdt_write,
.ioctl = advwdt_ioctl, .unlocked_ioctl = advwdt_ioctl,
.open = advwdt_open, .open = advwdt_open,
.release = advwdt_close, .release = advwdt_close,
}; };
...@@ -245,23 +237,24 @@ static struct miscdevice advwdt_miscdev = { ...@@ -245,23 +237,24 @@ static struct miscdevice advwdt_miscdev = {
* Init & exit routines * Init & exit routines
*/ */
static int __devinit static int __devinit advwdt_probe(struct platform_device *dev)
advwdt_probe(struct platform_device *dev)
{ {
int ret; int ret;
if (wdt_stop != wdt_start) { if (wdt_stop != wdt_start) {
if (!request_region(wdt_stop, 1, WATCHDOG_NAME)) { if (!request_region(wdt_stop, 1, WATCHDOG_NAME)) {
printk (KERN_ERR PFX "I/O address 0x%04x already in use\n", printk(KERN_ERR PFX
wdt_stop); "I/O address 0x%04x already in use\n",
wdt_stop);
ret = -EIO; ret = -EIO;
goto out; goto out;
} }
} }
if (!request_region(wdt_start, 1, WATCHDOG_NAME)) { if (!request_region(wdt_start, 1, WATCHDOG_NAME)) {
printk (KERN_ERR PFX "I/O address 0x%04x already in use\n", printk(KERN_ERR PFX
wdt_start); "I/O address 0x%04x already in use\n",
wdt_start);
ret = -EIO; ret = -EIO;
goto unreg_stop; goto unreg_stop;
} }
...@@ -269,20 +262,19 @@ advwdt_probe(struct platform_device *dev) ...@@ -269,20 +262,19 @@ advwdt_probe(struct platform_device *dev)
/* Check that the heartbeat value is within it's range ; if not reset to the default */ /* Check that the heartbeat value is within it's range ; if not reset to the default */
if (advwdt_set_heartbeat(timeout)) { if (advwdt_set_heartbeat(timeout)) {
advwdt_set_heartbeat(WATCHDOG_TIMEOUT); advwdt_set_heartbeat(WATCHDOG_TIMEOUT);
printk (KERN_INFO PFX "timeout value must be 1<=x<=63, using %d\n", printk(KERN_INFO PFX
timeout); "timeout value must be 1<=x<=63, using %d\n", timeout);
} }
ret = misc_register(&advwdt_miscdev); ret = misc_register(&advwdt_miscdev);
if (ret != 0) { if (ret != 0) {
printk (KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n", printk(KERN_ERR PFX
WATCHDOG_MINOR, ret); "cannot register miscdev on minor=%d (err=%d)\n",
WATCHDOG_MINOR, ret);
goto unreg_regions; goto unreg_regions;
} }
printk(KERN_INFO PFX "initialized. timeout=%d sec (nowayout=%d)\n",
printk (KERN_INFO PFX "initialized. timeout=%d sec (nowayout=%d)\n",
timeout, nowayout); timeout, nowayout);
out: out:
return ret; return ret;
unreg_regions: unreg_regions:
...@@ -293,19 +285,17 @@ advwdt_probe(struct platform_device *dev) ...@@ -293,19 +285,17 @@ advwdt_probe(struct platform_device *dev)
goto out; goto out;
} }
static int __devexit static int __devexit advwdt_remove(struct platform_device *dev)
advwdt_remove(struct platform_device *dev)
{ {
misc_deregister(&advwdt_miscdev); misc_deregister(&advwdt_miscdev);
release_region(wdt_start,1); release_region(wdt_start, 1);
if(wdt_stop != wdt_start) if (wdt_stop != wdt_start)
release_region(wdt_stop,1); release_region(wdt_stop, 1);
return 0; return 0;
} }
static void static void advwdt_shutdown(struct platform_device *dev)
advwdt_shutdown(struct platform_device *dev)
{ {
/* Turn the WDT off if we have a soft shutdown */ /* Turn the WDT off if we have a soft shutdown */
advwdt_disable(); advwdt_disable();
...@@ -321,18 +311,19 @@ static struct platform_driver advwdt_driver = { ...@@ -321,18 +311,19 @@ static struct platform_driver advwdt_driver = {
}, },
}; };
static int __init static int __init advwdt_init(void)
advwdt_init(void)
{ {
int err; int err;
printk(KERN_INFO "WDT driver for Advantech single board computer initialising.\n"); printk(KERN_INFO
"WDT driver for Advantech single board computer initialising.\n");
err = platform_driver_register(&advwdt_driver); err = platform_driver_register(&advwdt_driver);
if (err) if (err)
return err; return err;
advwdt_platform_device = platform_device_register_simple(DRV_NAME, -1, NULL, 0); advwdt_platform_device = platform_device_register_simple(DRV_NAME,
-1, NULL, 0);
if (IS_ERR(advwdt_platform_device)) { if (IS_ERR(advwdt_platform_device)) {
err = PTR_ERR(advwdt_platform_device); err = PTR_ERR(advwdt_platform_device);
goto unreg_platform_driver; goto unreg_platform_driver;
...@@ -345,8 +336,7 @@ advwdt_init(void) ...@@ -345,8 +336,7 @@ advwdt_init(void)
return err; return err;
} }
static void __exit static void __exit advwdt_exit(void)
advwdt_exit(void)
{ {
platform_device_unregister(advwdt_platform_device); platform_device_unregister(advwdt_platform_device);
platform_driver_unregister(&advwdt_driver); platform_driver_unregister(&advwdt_driver);
......
...@@ -18,9 +18,8 @@ ...@@ -18,9 +18,8 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/uaccess.h>
#include <asm/uaccess.h> #include <linux/io.h>
#include <asm/io.h>
#define WATCHDOG_NAME "ALi_M1535" #define WATCHDOG_NAME "ALi_M1535"
#define PFX WATCHDOG_NAME ": " #define PFX WATCHDOG_NAME ": "
...@@ -30,17 +29,21 @@ ...@@ -30,17 +29,21 @@
static unsigned long ali_is_open; static unsigned long ali_is_open;
static char ali_expect_release; static char ali_expect_release;
static struct pci_dev *ali_pci; static struct pci_dev *ali_pci;
static u32 ali_timeout_bits; /* stores the computed timeout */ static u32 ali_timeout_bits; /* stores the computed timeout */
static DEFINE_SPINLOCK(ali_lock); /* Guards the hardware */ static DEFINE_SPINLOCK(ali_lock); /* Guards the hardware */
/* module parameters */ /* module parameters */
static int timeout = WATCHDOG_TIMEOUT; static int timeout = WATCHDOG_TIMEOUT;
module_param(timeout, int, 0); module_param(timeout, int, 0);
MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds. (0<timeout<18000, default=" __MODULE_STRING(WATCHDOG_TIMEOUT) ")"); MODULE_PARM_DESC(timeout,
"Watchdog timeout in seconds. (0 < timeout < 18000, default="
__MODULE_STRING(WATCHDOG_TIMEOUT) ")");
static int nowayout = WATCHDOG_NOWAYOUT; static int nowayout = WATCHDOG_NOWAYOUT;
module_param(nowayout, int, 0); module_param(nowayout, int, 0);
MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); MODULE_PARM_DESC(nowayout,
"Watchdog cannot be stopped once started (default="
__MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
/* /*
* ali_start - start watchdog countdown * ali_start - start watchdog countdown
...@@ -103,15 +106,16 @@ static void ali_keepalive(void) ...@@ -103,15 +106,16 @@ static void ali_keepalive(void)
static int ali_settimer(int t) static int ali_settimer(int t)
{ {
if(t < 0) if (t < 0)
return -EINVAL; return -EINVAL;
else if(t < 60) else if (t < 60)
ali_timeout_bits = t|(1<<6); ali_timeout_bits = t|(1<<6);
else if(t < 3600) else if (t < 3600)
ali_timeout_bits = (t/60)|(1<<7); ali_timeout_bits = (t/60)|(1<<7);
else if(t < 18000) else if (t < 18000)
ali_timeout_bits = (t/300)|(1<<6)|(1<<7); ali_timeout_bits = (t/300)|(1<<6)|(1<<7);
else return -EINVAL; else
return -EINVAL;
timeout = t; timeout = t;
return 0; return 0;
...@@ -134,21 +138,22 @@ static int ali_settimer(int t) ...@@ -134,21 +138,22 @@ static int ali_settimer(int t)
*/ */
static ssize_t ali_write(struct file *file, const char __user *data, static ssize_t ali_write(struct file *file, const char __user *data,
size_t len, loff_t * ppos) size_t len, loff_t *ppos)
{ {
/* See if we got the magic character 'V' and reload the timer */ /* See if we got the magic character 'V' and reload the timer */
if (len) { if (len) {
if (!nowayout) { if (!nowayout) {
size_t i; size_t i;
/* note: just in case someone wrote the magic character /* note: just in case someone wrote the
* five months ago... */ magic character five months ago... */
ali_expect_release = 0; ali_expect_release = 0;
/* scan to see whether or not we got the magic character */ /* scan to see whether or not we got
the magic character */
for (i = 0; i != len; i++) { for (i = 0; i != len; i++) {
char c; char c;
if(get_user(c, data+i)) if (get_user(c, data + i))
return -EFAULT; return -EFAULT;
if (c == 'V') if (c == 'V')
ali_expect_release = 42; ali_expect_release = 42;
...@@ -163,7 +168,6 @@ static ssize_t ali_write(struct file *file, const char __user *data, ...@@ -163,7 +168,6 @@ static ssize_t ali_write(struct file *file, const char __user *data,
/* /*
* ali_ioctl - handle watchdog ioctls * ali_ioctl - handle watchdog ioctls
* @inode: VFS inode
* @file: VFS file pointer * @file: VFS file pointer
* @cmd: ioctl number * @cmd: ioctl number
* @arg: arguments to the ioctl * @arg: arguments to the ioctl
...@@ -172,8 +176,7 @@ static ssize_t ali_write(struct file *file, const char __user *data, ...@@ -172,8 +176,7 @@ static ssize_t ali_write(struct file *file, const char __user *data,
* we want an extension to enable irq ack monitoring and the like * we want an extension to enable irq ack monitoring and the like
*/ */
static int ali_ioctl(struct inode *inode, struct file *file, static long ali_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
unsigned int cmd, unsigned long arg)
{ {
void __user *argp = (void __user *)arg; void __user *argp = (void __user *)arg;
int __user *p = argp; int __user *p = argp;
...@@ -186,57 +189,45 @@ static int ali_ioctl(struct inode *inode, struct file *file, ...@@ -186,57 +189,45 @@ static int ali_ioctl(struct inode *inode, struct file *file,
}; };
switch (cmd) { switch (cmd) {
case WDIOC_GETSUPPORT: case WDIOC_GETSUPPORT:
return copy_to_user(argp, &ident, return copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0;
sizeof (ident)) ? -EFAULT : 0;
case WDIOC_GETSTATUS:
case WDIOC_GETSTATUS: case WDIOC_GETBOOTSTATUS:
case WDIOC_GETBOOTSTATUS: return put_user(0, p);
return put_user(0, p); case WDIOC_SETOPTIONS:
{
case WDIOC_KEEPALIVE: int new_options, retval = -EINVAL;
ali_keepalive();
return 0; if (get_user(new_options, p))
return -EFAULT;
case WDIOC_SETOPTIONS: if (new_options & WDIOS_DISABLECARD) {
{ ali_stop();
int new_options, retval = -EINVAL; retval = 0;
if (get_user (new_options, p))
return -EFAULT;
if (new_options & WDIOS_DISABLECARD) {
ali_stop();
retval = 0;
}
if (new_options & WDIOS_ENABLECARD) {
ali_start();
retval = 0;
}
return retval;
} }
if (new_options & WDIOS_ENABLECARD) {
case WDIOC_SETTIMEOUT: ali_start();
{ retval = 0;
int new_timeout;
if (get_user(new_timeout, p))
return -EFAULT;
if (ali_settimer(new_timeout))
return -EINVAL;
ali_keepalive();
/* Fall */
} }
return retval;
case WDIOC_GETTIMEOUT: }
return put_user(timeout, p); case WDIOC_KEEPALIVE:
ali_keepalive();
default: return 0;
return -ENOTTY; case WDIOC_SETTIMEOUT:
{
int new_timeout;
if (get_user(new_timeout, p))
return -EFAULT;
if (ali_settimer(new_timeout))
return -EINVAL;
ali_keepalive();
/* Fall */
}
case WDIOC_GETTIMEOUT:
return put_user(timeout, p);
default:
return -ENOTTY;
} }
} }
...@@ -274,10 +265,11 @@ static int ali_release(struct inode *inode, struct file *file) ...@@ -274,10 +265,11 @@ static int ali_release(struct inode *inode, struct file *file)
/* /*
* Shut off the timer. * Shut off the timer.
*/ */
if (ali_expect_release == 42) { if (ali_expect_release == 42)
ali_stop(); ali_stop();
} else { else {
printk(KERN_CRIT PFX "Unexpected close, not stopping watchdog!\n"); printk(KERN_CRIT PFX
"Unexpected close, not stopping watchdog!\n");
ali_keepalive(); ali_keepalive();
} }
clear_bit(0, &ali_is_open); clear_bit(0, &ali_is_open);
...@@ -292,13 +284,11 @@ static int ali_release(struct inode *inode, struct file *file) ...@@ -292,13 +284,11 @@ static int ali_release(struct inode *inode, struct file *file)
*/ */
static int ali_notify_sys(struct notifier_block *this, unsigned long code, void *unused) static int ali_notify_sys(struct notifier_block *this,
unsigned long code, void *unused)
{ {
if (code==SYS_DOWN || code==SYS_HALT) { if (code == SYS_DOWN || code == SYS_HALT)
/* Turn the WDT off */ ali_stop(); /* Turn the WDT off */
ali_stop();
}
return NOTIFY_DONE; return NOTIFY_DONE;
} }
...@@ -340,10 +330,10 @@ static int __init ali_find_watchdog(void) ...@@ -340,10 +330,10 @@ static int __init ali_find_watchdog(void)
/* Check for the a 7101 PMU */ /* Check for the a 7101 PMU */
pdev = pci_get_device(PCI_VENDOR_ID_AL, 0x7101, NULL); pdev = pci_get_device(PCI_VENDOR_ID_AL, 0x7101, NULL);
if(pdev == NULL) if (pdev == NULL)
return -ENODEV; return -ENODEV;
if(pci_enable_device(pdev)) { if (pci_enable_device(pdev)) {
pci_dev_put(pdev); pci_dev_put(pdev);
return -EIO; return -EIO;
} }
...@@ -355,9 +345,12 @@ static int __init ali_find_watchdog(void) ...@@ -355,9 +345,12 @@ static int __init ali_find_watchdog(void)
*/ */
pci_read_config_dword(pdev, 0xCC, &wdog); pci_read_config_dword(pdev, 0xCC, &wdog);
wdog &= ~0x3F; /* Timer bits */ /* Timer bits */
wdog &= ~((1<<27)|(1<<26)|(1<<25)|(1<<24)); /* Issued events */ wdog &= ~0x3F;
wdog &= ~((1<<16)|(1<<13)|(1<<12)|(1<<11)|(1<<10)|(1<<9)); /* No monitor bits */ /* Issued events */
wdog &= ~((1<<27)|(1<<26)|(1<<25)|(1<<24));
/* No monitor bits */
wdog &= ~((1<<16)|(1<<13)|(1<<12)|(1<<11)|(1<<10)|(1<<9));
pci_write_config_dword(pdev, 0xCC, wdog); pci_write_config_dword(pdev, 0xCC, wdog);
...@@ -369,12 +362,12 @@ static int __init ali_find_watchdog(void) ...@@ -369,12 +362,12 @@ static int __init ali_find_watchdog(void)
*/ */
static const struct file_operations ali_fops = { static const struct file_operations ali_fops = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.llseek = no_llseek, .llseek = no_llseek,
.write = ali_write, .write = ali_write,
.ioctl = ali_ioctl, .unlocked_ioctl = ali_ioctl,
.open = ali_open, .open = ali_open,
.release = ali_release, .release = ali_release,
}; };
static struct miscdevice ali_miscdev = { static struct miscdevice ali_miscdev = {
...@@ -399,15 +392,16 @@ static int __init watchdog_init(void) ...@@ -399,15 +392,16 @@ static int __init watchdog_init(void)
int ret; int ret;
/* Check whether or not the hardware watchdog is there */ /* Check whether or not the hardware watchdog is there */
if (ali_find_watchdog() != 0) { if (ali_find_watchdog() != 0)
return -ENODEV; return -ENODEV;
}
/* Check that the timeout value is within it's range ; if not reset to the default */ /* Check that the timeout value is within it's range;
if not reset to the default */
if (timeout < 1 || timeout >= 18000) { if (timeout < 1 || timeout >= 18000) {
timeout = WATCHDOG_TIMEOUT; timeout = WATCHDOG_TIMEOUT;
printk(KERN_INFO PFX "timeout value must be 0<timeout<18000, using %d\n", printk(KERN_INFO PFX
timeout); "timeout value must be 0 < timeout < 18000, using %d\n",
timeout);
} }
/* Calculate the watchdog's timeout */ /* Calculate the watchdog's timeout */
...@@ -415,15 +409,16 @@ static int __init watchdog_init(void) ...@@ -415,15 +409,16 @@ static int __init watchdog_init(void)
ret = register_reboot_notifier(&ali_notifier); ret = register_reboot_notifier(&ali_notifier);
if (ret != 0) { if (ret != 0) {
printk(KERN_ERR PFX "cannot register reboot notifier (err=%d)\n", printk(KERN_ERR PFX
ret); "cannot register reboot notifier (err=%d)\n", ret);
goto out; goto out;
} }
ret = misc_register(&ali_miscdev); ret = misc_register(&ali_miscdev);
if (ret != 0) { if (ret != 0) {
printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n", printk(KERN_ERR PFX
WATCHDOG_MINOR, ret); "cannot register miscdev on minor=%d (err=%d)\n",
WATCHDOG_MINOR, ret);
goto unreg_reboot; goto unreg_reboot;
} }
......
This diff is collapsed.
...@@ -213,7 +213,7 @@ static int ar7_wdt_notify_sys(struct notifier_block *this, ...@@ -213,7 +213,7 @@ static int ar7_wdt_notify_sys(struct notifier_block *this,
} }
static struct notifier_block ar7_wdt_notifier = { static struct notifier_block ar7_wdt_notifier = {
.notifier_call = ar7_wdt_notify_sys .notifier_call = ar7_wdt_notify_sys,
}; };
static ssize_t ar7_wdt_write(struct file *file, const char *data, static ssize_t ar7_wdt_write(struct file *file, const char *data,
...@@ -230,7 +230,7 @@ static ssize_t ar7_wdt_write(struct file *file, const char *data, ...@@ -230,7 +230,7 @@ static ssize_t ar7_wdt_write(struct file *file, const char *data,
expect_close = 0; expect_close = 0;
for (i = 0; i < len; ++i) { for (i = 0; i < len; ++i) {
char c; char c;
if (get_user(c, data+i)) if (get_user(c, data + i))
return -EFAULT; return -EFAULT;
if (c == 'V') if (c == 'V')
expect_close = 1; expect_close = 1;
...@@ -251,8 +251,6 @@ static long ar7_wdt_ioctl(struct file *file, ...@@ -251,8 +251,6 @@ static long ar7_wdt_ioctl(struct file *file,
int new_margin; int new_margin;
switch (cmd) { switch (cmd) {
default:
return -ENOTTY;
case WDIOC_GETSUPPORT: case WDIOC_GETSUPPORT:
if (copy_to_user((struct watchdog_info *)arg, &ident, if (copy_to_user((struct watchdog_info *)arg, &ident,
sizeof(ident))) sizeof(ident)))
...@@ -281,6 +279,8 @@ static long ar7_wdt_ioctl(struct file *file, ...@@ -281,6 +279,8 @@ static long ar7_wdt_ioctl(struct file *file,
if (put_user(margin, (int *)arg)) if (put_user(margin, (int *)arg))
return -EFAULT; return -EFAULT;
return 0; return 0;
default:
return -ENOTTY;
} }
} }
......
...@@ -212,8 +212,8 @@ static struct watchdog_info at32_wdt_info = { ...@@ -212,8 +212,8 @@ static struct watchdog_info at32_wdt_info = {
/* /*
* Handle commands from user-space. * Handle commands from user-space.
*/ */
static int at32_wdt_ioctl(struct inode *inode, struct file *file, static long at32_wdt_ioctl(struct file *file,
unsigned int cmd, unsigned long arg) unsigned int cmd, unsigned long arg)
{ {
int ret = -ENOTTY; int ret = -ENOTTY;
int time; int time;
...@@ -221,27 +221,10 @@ static int at32_wdt_ioctl(struct inode *inode, struct file *file, ...@@ -221,27 +221,10 @@ static int at32_wdt_ioctl(struct inode *inode, struct file *file,
int __user *p = argp; int __user *p = argp;
switch (cmd) { switch (cmd) {
case WDIOC_KEEPALIVE:
at32_wdt_pat();
ret = 0;
break;
case WDIOC_GETSUPPORT: case WDIOC_GETSUPPORT:
ret = copy_to_user(argp, &at32_wdt_info, ret = copy_to_user(argp, &at32_wdt_info,
sizeof(at32_wdt_info)) ? -EFAULT : 0; sizeof(at32_wdt_info)) ? -EFAULT : 0;
break; break;
case WDIOC_SETTIMEOUT:
ret = get_user(time, p);
if (ret)
break;
ret = at32_wdt_settimeout(time);
if (ret)
break;
/* Enable new time value */
at32_wdt_start();
/* fall through */
case WDIOC_GETTIMEOUT:
ret = put_user(wdt->timeout, p);
break;
case WDIOC_GETSTATUS: case WDIOC_GETSTATUS:
ret = put_user(0, p); ret = put_user(0, p);
break; break;
...@@ -258,6 +241,23 @@ static int at32_wdt_ioctl(struct inode *inode, struct file *file, ...@@ -258,6 +241,23 @@ static int at32_wdt_ioctl(struct inode *inode, struct file *file,
at32_wdt_start(); at32_wdt_start();
ret = 0; ret = 0;
break; break;
case WDIOC_KEEPALIVE:
at32_wdt_pat();
ret = 0;
break;
case WDIOC_SETTIMEOUT:
ret = get_user(time, p);
if (ret)
break;
ret = at32_wdt_settimeout(time);
if (ret)
break;
/* Enable new time value */
at32_wdt_start();
/* fall through */
case WDIOC_GETTIMEOUT:
ret = put_user(wdt->timeout, p);
break;
} }
return ret; return ret;
...@@ -283,7 +283,7 @@ static ssize_t at32_wdt_write(struct file *file, const char __user *data, ...@@ -283,7 +283,7 @@ static ssize_t at32_wdt_write(struct file *file, const char __user *data,
*/ */
for (i = 0; i != len; i++) { for (i = 0; i != len; i++) {
char c; char c;
if (get_user(c, data+i)) if (get_user(c, data + i))
return -EFAULT; return -EFAULT;
if (c == 'V') if (c == 'V')
expect_release = 42; expect_release = 42;
...@@ -298,7 +298,7 @@ static ssize_t at32_wdt_write(struct file *file, const char __user *data, ...@@ -298,7 +298,7 @@ static ssize_t at32_wdt_write(struct file *file, const char __user *data,
static const struct file_operations at32_wdt_fops = { static const struct file_operations at32_wdt_fops = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.llseek = no_llseek, .llseek = no_llseek,
.ioctl = at32_wdt_ioctl, .unlocked_ioctl = at32_wdt_ioctl,
.open = at32_wdt_open, .open = at32_wdt_open,
.release = at32_wdt_close, .release = at32_wdt_close,
.write = at32_wdt_write, .write = at32_wdt_write,
...@@ -391,7 +391,6 @@ static int __exit at32_wdt_remove(struct platform_device *pdev) ...@@ -391,7 +391,6 @@ static int __exit at32_wdt_remove(struct platform_device *pdev)
wdt = NULL; wdt = NULL;
platform_set_drvdata(pdev, NULL); platform_set_drvdata(pdev, NULL);
} }
return 0; return 0;
} }
......
...@@ -20,7 +20,7 @@ ...@@ -20,7 +20,7 @@
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/types.h> #include <linux/types.h>
#include <linux/watchdog.h> #include <linux/watchdog.h>
#include <asm/uaccess.h> #include <linux/uaccess.h>
#include <asm/arch/at91_st.h> #include <asm/arch/at91_st.h>
...@@ -31,11 +31,14 @@ static int wdt_time = WDT_DEFAULT_TIME; ...@@ -31,11 +31,14 @@ static int wdt_time = WDT_DEFAULT_TIME;
static int nowayout = WATCHDOG_NOWAYOUT; static int nowayout = WATCHDOG_NOWAYOUT;
module_param(wdt_time, int, 0); module_param(wdt_time, int, 0);
MODULE_PARM_DESC(wdt_time, "Watchdog time in seconds. (default="__MODULE_STRING(WDT_DEFAULT_TIME) ")"); MODULE_PARM_DESC(wdt_time, "Watchdog time in seconds. (default="
__MODULE_STRING(WDT_DEFAULT_TIME) ")");
#ifdef CONFIG_WATCHDOG_NOWAYOUT #ifdef CONFIG_WATCHDOG_NOWAYOUT
module_param(nowayout, int, 0); module_param(nowayout, int, 0);
MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); MODULE_PARM_DESC(nowayout,
"Watchdog cannot be stopped once started (default="
__MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
#endif #endif
...@@ -46,7 +49,7 @@ static unsigned long at91wdt_busy; ...@@ -46,7 +49,7 @@ static unsigned long at91wdt_busy;
/* /*
* Disable the watchdog. * Disable the watchdog.
*/ */
static void inline at91_wdt_stop(void) static inline void at91_wdt_stop(void)
{ {
at91_sys_write(AT91_ST_WDMR, AT91_ST_EXTEN); at91_sys_write(AT91_ST_WDMR, AT91_ST_EXTEN);
} }
...@@ -54,16 +57,17 @@ static void inline at91_wdt_stop(void) ...@@ -54,16 +57,17 @@ static void inline at91_wdt_stop(void)
/* /*
* Enable and reset the watchdog. * Enable and reset the watchdog.
*/ */
static void inline at91_wdt_start(void) static inline void at91_wdt_start(void)
{ {
at91_sys_write(AT91_ST_WDMR, AT91_ST_EXTEN | AT91_ST_RSTEN | (((65536 * wdt_time) >> 8) & AT91_ST_WDV)); at91_sys_write(AT91_ST_WDMR, AT91_ST_EXTEN | AT91_ST_RSTEN |
(((65536 * wdt_time) >> 8) & AT91_ST_WDV));
at91_sys_write(AT91_ST_CR, AT91_ST_WDRST); at91_sys_write(AT91_ST_CR, AT91_ST_WDRST);
} }
/* /*
* Reload the watchdog timer. (ie, pat the watchdog) * Reload the watchdog timer. (ie, pat the watchdog)
*/ */
static void inline at91_wdt_reload(void) static inline void at91_wdt_reload(void)
{ {
at91_sys_write(AT91_ST_CR, AT91_ST_WDRST); at91_sys_write(AT91_ST_CR, AT91_ST_WDRST);
} }
...@@ -89,8 +93,9 @@ static int at91_wdt_open(struct inode *inode, struct file *file) ...@@ -89,8 +93,9 @@ static int at91_wdt_open(struct inode *inode, struct file *file)
*/ */
static int at91_wdt_close(struct inode *inode, struct file *file) static int at91_wdt_close(struct inode *inode, struct file *file)
{ {
/* Disable the watchdog when file is closed */
if (!nowayout) if (!nowayout)
at91_wdt_stop(); /* Disable the watchdog when file is closed */ at91_wdt_stop();
clear_bit(0, &at91wdt_busy); clear_bit(0, &at91wdt_busy);
return 0; return 0;
...@@ -110,7 +115,8 @@ static int at91_wdt_settimeout(int new_time) ...@@ -110,7 +115,8 @@ static int at91_wdt_settimeout(int new_time)
if ((new_time <= 0) || (new_time > WDT_MAX_TIME)) if ((new_time <= 0) || (new_time > WDT_MAX_TIME))
return -EINVAL; return -EINVAL;
/* Set new watchdog time. It will be used when at91_wdt_start() is called. */ /* Set new watchdog time. It will be used when
at91_wdt_start() is called. */
wdt_time = new_time; wdt_time = new_time;
return 0; return 0;
} }
...@@ -123,60 +129,52 @@ static struct watchdog_info at91_wdt_info = { ...@@ -123,60 +129,52 @@ static struct watchdog_info at91_wdt_info = {
/* /*
* Handle commands from user-space. * Handle commands from user-space.
*/ */
static int at91_wdt_ioctl(struct inode *inode, struct file *file, static long at91_wdt_ioct(struct file *file,
unsigned int cmd, unsigned long arg) unsigned int cmd, unsigned long arg)
{ {
void __user *argp = (void __user *)arg; void __user *argp = (void __user *)arg;
int __user *p = argp; int __user *p = argp;
int new_value; int new_value;
switch(cmd) { switch (cmd) {
case WDIOC_KEEPALIVE: case WDIOC_GETSUPPORT:
at91_wdt_reload(); /* pat the watchdog */ return copy_to_user(argp, &at91_wdt_info,
return 0; sizeof(at91_wdt_info)) ? -EFAULT : 0;
case WDIOC_GETSTATUS:
case WDIOC_GETSUPPORT: case WDIOC_GETBOOTSTATUS:
return copy_to_user(argp, &at91_wdt_info, sizeof(at91_wdt_info)) ? -EFAULT : 0; return put_user(0, p);
case WDIOC_SETOPTIONS:
case WDIOC_SETTIMEOUT: if (get_user(new_value, p))
if (get_user(new_value, p)) return -EFAULT;
return -EFAULT; if (new_value & WDIOS_DISABLECARD)
at91_wdt_stop();
if (at91_wdt_settimeout(new_value)) if (new_value & WDIOS_ENABLECARD)
return -EINVAL;
/* Enable new time value */
at91_wdt_start(); at91_wdt_start();
return 0;
/* Return current value */ case WDIOC_KEEPALIVE:
return put_user(wdt_time, p); at91_wdt_reload(); /* pat the watchdog */
return 0;
case WDIOC_GETTIMEOUT: case WDIOC_SETTIMEOUT:
return put_user(wdt_time, p); if (get_user(new_value, p))
return -EFAULT;
case WDIOC_GETSTATUS: if (at91_wdt_settimeout(new_value))
case WDIOC_GETBOOTSTATUS: return -EINVAL;
return put_user(0, p); /* Enable new time value */
at91_wdt_start();
case WDIOC_SETOPTIONS: /* Return current value */
if (get_user(new_value, p)) return put_user(wdt_time, p);
return -EFAULT; case WDIOC_GETTIMEOUT:
return put_user(wdt_time, p);
if (new_value & WDIOS_DISABLECARD) default:
at91_wdt_stop(); return -ENOTTY;
if (new_value & WDIOS_ENABLECARD)
at91_wdt_start();
return 0;
default:
return -ENOTTY;
} }
} }
/* /*
* Pat the watchdog whenever device is written to. * Pat the watchdog whenever device is written to.
*/ */
static ssize_t at91_wdt_write(struct file *file, const char *data, size_t len, loff_t *ppos) static ssize_t at91_wdt_write(struct file *file, const char *data,
size_t len, loff_t *ppos)
{ {
at91_wdt_reload(); /* pat the watchdog */ at91_wdt_reload(); /* pat the watchdog */
return len; return len;
...@@ -187,7 +185,7 @@ static ssize_t at91_wdt_write(struct file *file, const char *data, size_t len, l ...@@ -187,7 +185,7 @@ static ssize_t at91_wdt_write(struct file *file, const char *data, size_t len, l
static const struct file_operations at91wdt_fops = { static const struct file_operations at91wdt_fops = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.llseek = no_llseek, .llseek = no_llseek,
.ioctl = at91_wdt_ioctl, .unlocked_ioctl = at91_wdt_ioctl,
.open = at91_wdt_open, .open = at91_wdt_open,
.release = at91_wdt_close, .release = at91_wdt_close,
.write = at91_wdt_write, .write = at91_wdt_write,
...@@ -211,7 +209,8 @@ static int __init at91wdt_probe(struct platform_device *pdev) ...@@ -211,7 +209,8 @@ static int __init at91wdt_probe(struct platform_device *pdev)
if (res) if (res)
return res; return res;
printk("AT91 Watchdog Timer enabled (%d seconds%s)\n", wdt_time, nowayout ? ", nowayout" : ""); printk(KERN_INFO "AT91 Watchdog Timer enabled (%d seconds%s)\n",
wdt_time, nowayout ? ", nowayout" : "");
return 0; return 0;
} }
...@@ -265,7 +264,8 @@ static struct platform_driver at91wdt_driver = { ...@@ -265,7 +264,8 @@ static struct platform_driver at91wdt_driver = {
static int __init at91_wdt_init(void) static int __init at91_wdt_init(void)
{ {
/* Check that the heartbeat value is within range; if not reset to the default */ /* Check that the heartbeat value is within range;
if not reset to the default */
if (at91_wdt_settimeout(wdt_time)) { if (at91_wdt_settimeout(wdt_time)) {
at91_wdt_settimeout(WDT_DEFAULT_TIME); at91_wdt_settimeout(WDT_DEFAULT_TIME);
pr_info("at91_wdt: wdt_time value must be 1 <= wdt_time <= 256, using %d\n", wdt_time); pr_info("at91_wdt: wdt_time value must be 1 <= wdt_time <= 256, using %d\n", wdt_time);
......
...@@ -24,8 +24,8 @@ ...@@ -24,8 +24,8 @@
#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/uaccess.h>
#include <asm/blackfin.h> #include <asm/blackfin.h>
#include <asm/uaccess.h>
#define stamp(fmt, args...) pr_debug("%s:%i: " fmt "\n", __func__, __LINE__, ## args) #define stamp(fmt, args...) pr_debug("%s:%i: " fmt "\n", __func__, __LINE__, ## args)
#define stampit() stamp("here i am") #define stampit() stamp("here i am")
...@@ -148,7 +148,8 @@ static int bfin_wdt_set_timeout(unsigned long t) ...@@ -148,7 +148,8 @@ static int bfin_wdt_set_timeout(unsigned long t)
int run = bfin_wdt_running(); int run = bfin_wdt_running();
bfin_wdt_stop(); bfin_wdt_stop();
bfin_write_WDOG_CNT(cnt); bfin_write_WDOG_CNT(cnt);
if (run) bfin_wdt_start(); if (run)
bfin_wdt_start();
} }
spin_unlock_irqrestore(&bfin_wdt_spinlock, flags); spin_unlock_irqrestore(&bfin_wdt_spinlock, flags);
...@@ -191,16 +192,15 @@ static int bfin_wdt_release(struct inode *inode, struct file *file) ...@@ -191,16 +192,15 @@ static int bfin_wdt_release(struct inode *inode, struct file *file)
{ {
stampit(); stampit();
if (expect_close == 42) { if (expect_close == 42)
bfin_wdt_stop(); bfin_wdt_stop();
} else { else {
printk(KERN_CRIT PFX "Unexpected close, not stopping watchdog!\n"); printk(KERN_CRIT PFX
"Unexpected close, not stopping watchdog!\n");
bfin_wdt_keepalive(); bfin_wdt_keepalive();
} }
expect_close = 0; expect_close = 0;
clear_bit(0, &open_check); clear_bit(0, &open_check);
return 0; return 0;
} }
...@@ -214,7 +214,7 @@ static int bfin_wdt_release(struct inode *inode, struct file *file) ...@@ -214,7 +214,7 @@ static int bfin_wdt_release(struct inode *inode, struct file *file)
* Pings the watchdog on write. * Pings the watchdog on write.
*/ */
static ssize_t bfin_wdt_write(struct file *file, const char __user *data, static ssize_t bfin_wdt_write(struct file *file, const char __user *data,
size_t len, loff_t *ppos) size_t len, loff_t *ppos)
{ {
stampit(); stampit();
...@@ -241,7 +241,6 @@ static ssize_t bfin_wdt_write(struct file *file, const char __user *data, ...@@ -241,7 +241,6 @@ static ssize_t bfin_wdt_write(struct file *file, const char __user *data,
/** /**
* bfin_wdt_ioctl - Query Device * bfin_wdt_ioctl - Query Device
* @inode: inode of device
* @file: file handle of device * @file: file handle of device
* @cmd: watchdog command * @cmd: watchdog command
* @arg: argument * @arg: argument
...@@ -249,8 +248,8 @@ static ssize_t bfin_wdt_write(struct file *file, const char __user *data, ...@@ -249,8 +248,8 @@ static ssize_t bfin_wdt_write(struct file *file, const char __user *data,
* Query basic information from the device or ping it, as outlined by the * Query basic information from the device or ping it, as outlined by the
* watchdog API. * watchdog API.
*/ */
static int bfin_wdt_ioctl(struct inode *inode, struct file *file, static long bfin_wdt_ioctl(struct file *file,
unsigned int cmd, unsigned long arg) unsigned int cmd, unsigned long arg)
{ {
void __user *argp = (void __user *)arg; void __user *argp = (void __user *)arg;
int __user *p = argp; int __user *p = argp;
...@@ -258,59 +257,49 @@ static int bfin_wdt_ioctl(struct inode *inode, struct file *file, ...@@ -258,59 +257,49 @@ static int bfin_wdt_ioctl(struct inode *inode, struct file *file,
stampit(); stampit();
switch (cmd) { switch (cmd) {
default: case WDIOC_GETSUPPORT:
return -ENOTTY; if (copy_to_user(argp, &bfin_wdt_info, sizeof(bfin_wdt_info)))
return -EFAULT;
case WDIOC_GETSUPPORT: else
if (copy_to_user(argp, &bfin_wdt_info, sizeof(bfin_wdt_info)))
return -EFAULT;
else
return 0;
case WDIOC_GETSTATUS:
case WDIOC_GETBOOTSTATUS:
return put_user(!!(_bfin_swrst & SWRST_RESET_WDOG), p);
case WDIOC_KEEPALIVE:
bfin_wdt_keepalive();
return 0; return 0;
case WDIOC_GETSTATUS:
case WDIOC_SETTIMEOUT: { case WDIOC_GETBOOTSTATUS:
int new_timeout; return put_user(!!(_bfin_swrst & SWRST_RESET_WDOG), p);
case WDIOC_SETOPTIONS: {
if (get_user(new_timeout, p)) unsigned long flags;
return -EFAULT; int options, ret = -EINVAL;
if (bfin_wdt_set_timeout(new_timeout)) if (get_user(options, p))
return -EINVAL; return -EFAULT;
spin_lock_irqsave(&bfin_wdt_spinlock, flags);
if (options & WDIOS_DISABLECARD) {
bfin_wdt_stop();
ret = 0;
} }
/* Fall */ if (options & WDIOS_ENABLECARD) {
case WDIOC_GETTIMEOUT: bfin_wdt_start();
return put_user(timeout, p); ret = 0;
case WDIOC_SETOPTIONS: {
unsigned long flags;
int options, ret = -EINVAL;
if (get_user(options, p))
return -EFAULT;
spin_lock_irqsave(&bfin_wdt_spinlock, flags);
if (options & WDIOS_DISABLECARD) {
bfin_wdt_stop();
ret = 0;
}
if (options & WDIOS_ENABLECARD) {
bfin_wdt_start();
ret = 0;
}
spin_unlock_irqrestore(&bfin_wdt_spinlock, flags);
return ret;
} }
spin_unlock_irqrestore(&bfin_wdt_spinlock, flags);
return ret;
}
case WDIOC_KEEPALIVE:
bfin_wdt_keepalive();
return 0;
case WDIOC_SETTIMEOUT: {
int new_timeout;
if (get_user(new_timeout, p))
return -EFAULT;
if (bfin_wdt_set_timeout(new_timeout))
return -EINVAL;
}
/* Fall */
case WDIOC_GETTIMEOUT:
return put_user(timeout, p);
default:
return -ENOTTY;
} }
} }
...@@ -323,8 +312,8 @@ static int bfin_wdt_ioctl(struct inode *inode, struct file *file, ...@@ -323,8 +312,8 @@ static int bfin_wdt_ioctl(struct inode *inode, struct file *file,
* Handles specific events, such as turning off the watchdog during a * Handles specific events, such as turning off the watchdog during a
* shutdown event. * shutdown event.
*/ */
static int bfin_wdt_notify_sys(struct notifier_block *this, unsigned long code, static int bfin_wdt_notify_sys(struct notifier_block *this,
void *unused) unsigned long code, void *unused)
{ {
stampit(); stampit();
...@@ -379,12 +368,12 @@ static int bfin_wdt_resume(struct platform_device *pdev) ...@@ -379,12 +368,12 @@ static int bfin_wdt_resume(struct platform_device *pdev)
#endif #endif
static const struct file_operations bfin_wdt_fops = { static const struct file_operations bfin_wdt_fops = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.llseek = no_llseek, .llseek = no_llseek,
.write = bfin_wdt_write, .write = bfin_wdt_write,
.ioctl = bfin_wdt_ioctl, .unlocked_ioctl = bfin_wdt_ioctl,
.open = bfin_wdt_open, .open = bfin_wdt_open,
.release = bfin_wdt_release, .release = bfin_wdt_release,
}; };
static struct miscdevice bfin_wdt_miscdev = { static struct miscdevice bfin_wdt_miscdev = {
...@@ -396,8 +385,8 @@ static struct miscdevice bfin_wdt_miscdev = { ...@@ -396,8 +385,8 @@ static struct miscdevice bfin_wdt_miscdev = {
static struct watchdog_info bfin_wdt_info = { static struct watchdog_info bfin_wdt_info = {
.identity = "Blackfin Watchdog", .identity = "Blackfin Watchdog",
.options = WDIOF_SETTIMEOUT | .options = WDIOF_SETTIMEOUT |
WDIOF_KEEPALIVEPING | WDIOF_KEEPALIVEPING |
WDIOF_MAGICCLOSE, WDIOF_MAGICCLOSE,
}; };
static struct notifier_block bfin_wdt_notifier = { static struct notifier_block bfin_wdt_notifier = {
...@@ -416,14 +405,16 @@ static int __devinit bfin_wdt_probe(struct platform_device *pdev) ...@@ -416,14 +405,16 @@ static int __devinit bfin_wdt_probe(struct platform_device *pdev)
ret = register_reboot_notifier(&bfin_wdt_notifier); ret = register_reboot_notifier(&bfin_wdt_notifier);
if (ret) { if (ret) {
pr_devinit(KERN_ERR PFX "cannot register reboot notifier (err=%d)\n", ret); pr_devinit(KERN_ERR PFX
"cannot register reboot notifier (err=%d)\n", ret);
return ret; return ret;
} }
ret = misc_register(&bfin_wdt_miscdev); ret = misc_register(&bfin_wdt_miscdev);
if (ret) { if (ret) {
pr_devinit(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n", pr_devinit(KERN_ERR PFX
WATCHDOG_MINOR, ret); "cannot register miscdev on minor=%d (err=%d)\n",
WATCHDOG_MINOR, ret);
unregister_reboot_notifier(&bfin_wdt_notifier); unregister_reboot_notifier(&bfin_wdt_notifier);
return ret; return ret;
} }
...@@ -516,7 +507,11 @@ MODULE_LICENSE("GPL"); ...@@ -516,7 +507,11 @@ MODULE_LICENSE("GPL");
MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
module_param(timeout, uint, 0); module_param(timeout, uint, 0);
MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds. (1<=timeout<=((2^32)/SCLK), default=" __MODULE_STRING(WATCHDOG_TIMEOUT) ")"); MODULE_PARM_DESC(timeout,
"Watchdog timeout in seconds. (1<=timeout<=((2^32)/SCLK), default="
__MODULE_STRING(WATCHDOG_TIMEOUT) ")");
module_param(nowayout, int, 0); module_param(nowayout, int, 0);
MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); MODULE_PARM_DESC(nowayout,
"Watchdog cannot be stopped once started (default="
__MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
...@@ -18,9 +18,9 @@ ...@@ -18,9 +18,9 @@
#include <linux/miscdevice.h> #include <linux/miscdevice.h>
#include <linux/notifier.h> #include <linux/notifier.h>
#include <linux/watchdog.h> #include <linux/watchdog.h>
#include <linux/uaccess.h>
#include <asm/reg_booke.h> #include <asm/reg_booke.h>
#include <asm/uaccess.h>
#include <asm/system.h> #include <asm/system.h>
/* If the kernel parameter wdt=1, the watchdog will be enabled at boot. /* If the kernel parameter wdt=1, the watchdog will be enabled at boot.
...@@ -32,7 +32,7 @@ ...@@ -32,7 +32,7 @@
*/ */
#ifdef CONFIG_FSL_BOOKE #ifdef CONFIG_FSL_BOOKE
#define WDT_PERIOD_DEFAULT 63 /* Ex. wdt_period=28 bus=333Mhz , reset=~40sec */ #define WDT_PERIOD_DEFAULT 63 /* Ex. wdt_period=28 bus=333Mhz,reset=~40sec */
#else #else
#define WDT_PERIOD_DEFAULT 3 /* Refer to the PPC40x and PPC4xx manuals */ #define WDT_PERIOD_DEFAULT 3 /* Refer to the PPC40x and PPC4xx manuals */
#endif /* for timing information */ #endif /* for timing information */
...@@ -82,16 +82,15 @@ static struct watchdog_info ident = { ...@@ -82,16 +82,15 @@ static struct watchdog_info ident = {
.identity = "PowerPC Book-E Watchdog", .identity = "PowerPC Book-E Watchdog",
}; };
static int booke_wdt_ioctl(struct inode *inode, struct file *file, static long booke_wdt_ioctl(struct file *file,
unsigned int cmd, unsigned long arg) unsigned int cmd, unsigned long arg)
{ {
u32 tmp = 0; u32 tmp = 0;
u32 __user *p = (u32 __user *)arg; u32 __user *p = (u32 __user *)arg;
switch (cmd) { switch (cmd) {
case WDIOC_GETSUPPORT: case WDIOC_GETSUPPORT:
if (copy_to_user((struct watchdog_info __user *)arg, &ident, if (copy_to_user(arg, &ident, sizeof(struct watchdog_info)))
sizeof(struct watchdog_info)))
return -EFAULT; return -EFAULT;
case WDIOC_GETSTATUS: case WDIOC_GETSTATUS:
return put_user(ident.options, p); return put_user(ident.options, p);
...@@ -100,16 +99,6 @@ static int booke_wdt_ioctl(struct inode *inode, struct file *file, ...@@ -100,16 +99,6 @@ static int booke_wdt_ioctl(struct inode *inode, struct file *file,
tmp = mfspr(SPRN_TSR) & TSR_WRS(3); tmp = mfspr(SPRN_TSR) & TSR_WRS(3);
/* returns 1 if last reset was caused by the WDT */ /* returns 1 if last reset was caused by the WDT */
return (tmp ? 1 : 0); return (tmp ? 1 : 0);
case WDIOC_KEEPALIVE:
booke_wdt_ping();
return 0;
case WDIOC_SETTIMEOUT:
if (get_user(booke_wdt_period, p))
return -EFAULT;
mtspr(SPRN_TCR, (mfspr(SPRN_TCR)&~WDTP(0))|WDTP(booke_wdt_period));
return 0;
case WDIOC_GETTIMEOUT:
return put_user(booke_wdt_period, p);
case WDIOC_SETOPTIONS: case WDIOC_SETOPTIONS:
if (get_user(tmp, p)) if (get_user(tmp, p))
return -EINVAL; return -EINVAL;
...@@ -119,6 +108,17 @@ static int booke_wdt_ioctl(struct inode *inode, struct file *file, ...@@ -119,6 +108,17 @@ static int booke_wdt_ioctl(struct inode *inode, struct file *file,
} else } else
return -EINVAL; return -EINVAL;
return 0; return 0;
case WDIOC_KEEPALIVE:
booke_wdt_ping();
return 0;
case WDIOC_SETTIMEOUT:
if (get_user(booke_wdt_period, p))
return -EFAULT;
mtspr(SPRN_TCR, (mfspr(SPRN_TCR) & ~WDTP(0)) |
WDTP(booke_wdt_period));
return 0;
case WDIOC_GETTIMEOUT:
return put_user(booke_wdt_period, p);
default: default:
return -ENOTTY; return -ENOTTY;
} }
...@@ -132,8 +132,9 @@ static int booke_wdt_open(struct inode *inode, struct file *file) ...@@ -132,8 +132,9 @@ static int booke_wdt_open(struct inode *inode, struct file *file)
if (booke_wdt_enabled == 0) { if (booke_wdt_enabled == 0) {
booke_wdt_enabled = 1; booke_wdt_enabled = 1;
on_each_cpu(__booke_wdt_enable, NULL, 0); on_each_cpu(__booke_wdt_enable, NULL, 0);
printk(KERN_INFO "PowerPC Book-E Watchdog Timer Enabled " printk(KERN_INFO
"(wdt_period=%d)\n", booke_wdt_period); "PowerPC Book-E Watchdog Timer Enabled (wdt_period=%d)\n",
booke_wdt_period);
} }
spin_unlock(&booke_wdt_lock); spin_unlock(&booke_wdt_lock);
...@@ -144,7 +145,7 @@ static const struct file_operations booke_wdt_fops = { ...@@ -144,7 +145,7 @@ static const struct file_operations booke_wdt_fops = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.llseek = no_llseek, .llseek = no_llseek,
.write = booke_wdt_write, .write = booke_wdt_write,
.ioctl = booke_wdt_ioctl, .unlocked_ioctl = booke_wdt_ioctl,
.open = booke_wdt_open, .open = booke_wdt_open,
}; };
...@@ -175,8 +176,9 @@ static int __init booke_wdt_init(void) ...@@ -175,8 +176,9 @@ static int __init booke_wdt_init(void)
spin_lock(&booke_wdt_lock); spin_lock(&booke_wdt_lock);
if (booke_wdt_enabled == 1) { if (booke_wdt_enabled == 1) {
printk(KERN_INFO "PowerPC Book-E Watchdog Timer Enabled " printk(KERN_INFO
"(wdt_period=%d)\n", booke_wdt_period); "PowerPC Book-E Watchdog Timer Enabled (wdt_period=%d)\n",
booke_wdt_period);
on_each_cpu(__booke_wdt_enable, NULL, 0); on_each_cpu(__booke_wdt_enable, NULL, 0);
} }
spin_unlock(&booke_wdt_lock); spin_unlock(&booke_wdt_lock);
......
...@@ -30,16 +30,16 @@ ...@@ -30,16 +30,16 @@
#include <linux/timer.h> #include <linux/timer.h>
#include <linux/completion.h> #include <linux/completion.h>
#include <linux/jiffies.h> #include <linux/jiffies.h>
#include <asm/io.h> #include <linux/io.h>
#include <asm/uaccess.h> #include <linux/uaccess.h>
#include <linux/watchdog.h> #include <linux/watchdog.h>
/* adjustable parameters */ /* adjustable parameters */
static int verbose = 0; static int verbose;
static int port = 0x91; static int port = 0x91;
static int ticks = 10000; static int ticks = 10000;
static spinlock_t cpu5wdt_lock;
#define PFX "cpu5wdt: " #define PFX "cpu5wdt: "
...@@ -70,12 +70,13 @@ static struct { ...@@ -70,12 +70,13 @@ static struct {
static void cpu5wdt_trigger(unsigned long unused) static void cpu5wdt_trigger(unsigned long unused)
{ {
if ( verbose > 2 ) if (verbose > 2)
printk(KERN_DEBUG PFX "trigger at %i ticks\n", ticks); printk(KERN_DEBUG PFX "trigger at %i ticks\n", ticks);
if( cpu5wdt_device.running ) if (cpu5wdt_device.running)
ticks--; ticks--;
spin_lock(&cpu5wdt_lock);
/* keep watchdog alive */ /* keep watchdog alive */
outb(1, port + CPU5WDT_TRIGGER_REG); outb(1, port + CPU5WDT_TRIGGER_REG);
...@@ -86,6 +87,7 @@ static void cpu5wdt_trigger(unsigned long unused) ...@@ -86,6 +87,7 @@ static void cpu5wdt_trigger(unsigned long unused)
/* ticks doesn't matter anyway */ /* ticks doesn't matter anyway */
complete(&cpu5wdt_device.stop); complete(&cpu5wdt_device.stop);
} }
spin_unlock(&cpu5wdt_lock);
} }
...@@ -93,14 +95,17 @@ static void cpu5wdt_reset(void) ...@@ -93,14 +95,17 @@ static void cpu5wdt_reset(void)
{ {
ticks = cpu5wdt_device.default_ticks; ticks = cpu5wdt_device.default_ticks;
if ( verbose ) if (verbose)
printk(KERN_DEBUG PFX "reset (%i ticks)\n", (int) ticks); printk(KERN_DEBUG PFX "reset (%i ticks)\n", (int) ticks);
} }
static void cpu5wdt_start(void) static void cpu5wdt_start(void)
{ {
if ( !cpu5wdt_device.queue ) { unsigned long flags;
spin_lock_irqsave(&cpu5wdt_lock, flags);
if (!cpu5wdt_device.queue) {
cpu5wdt_device.queue = 1; cpu5wdt_device.queue = 1;
outb(0, port + CPU5WDT_TIME_A_REG); outb(0, port + CPU5WDT_TIME_A_REG);
outb(0, port + CPU5WDT_TIME_B_REG); outb(0, port + CPU5WDT_TIME_B_REG);
...@@ -111,18 +116,20 @@ static void cpu5wdt_start(void) ...@@ -111,18 +116,20 @@ static void cpu5wdt_start(void)
} }
/* if process dies, counter is not decremented */ /* if process dies, counter is not decremented */
cpu5wdt_device.running++; cpu5wdt_device.running++;
spin_unlock_irqrestore(&cpu5wdt_lock, flags);
} }
static int cpu5wdt_stop(void) static int cpu5wdt_stop(void)
{ {
if ( cpu5wdt_device.running ) unsigned long flags;
cpu5wdt_device.running = 0;
spin_lock_irqsave(&cpu5wdt_lock, flags);
if (cpu5wdt_device.running)
cpu5wdt_device.running = 0;
ticks = cpu5wdt_device.default_ticks; ticks = cpu5wdt_device.default_ticks;
spin_unlock_irqrestore(&cpu5wdt_lock, flags);
if ( verbose ) if (verbose)
printk(KERN_CRIT PFX "stop not possible\n"); printk(KERN_CRIT PFX "stop not possible\n");
return -EIO; return -EIO;
} }
...@@ -130,9 +137,8 @@ static int cpu5wdt_stop(void) ...@@ -130,9 +137,8 @@ static int cpu5wdt_stop(void)
static int cpu5wdt_open(struct inode *inode, struct file *file) static int cpu5wdt_open(struct inode *inode, struct file *file)
{ {
if ( test_and_set_bit(0, &cpu5wdt_device.inuse) ) if (test_and_set_bit(0, &cpu5wdt_device.inuse))
return -EBUSY; return -EBUSY;
return nonseekable_open(inode, file); return nonseekable_open(inode, file);
} }
...@@ -142,67 +148,58 @@ static int cpu5wdt_release(struct inode *inode, struct file *file) ...@@ -142,67 +148,58 @@ static int cpu5wdt_release(struct inode *inode, struct file *file)
return 0; return 0;
} }
static int cpu5wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) static long cpu5wdt_ioctl(struct file *file, unsigned int cmd,
unsigned long arg)
{ {
void __user *argp = (void __user *)arg; void __user *argp = (void __user *)arg;
int __user *p = argp;
unsigned int value; unsigned int value;
static struct watchdog_info ident = static struct watchdog_info ident = {
{
.options = WDIOF_CARDRESET, .options = WDIOF_CARDRESET,
.identity = "CPU5 WDT", .identity = "CPU5 WDT",
}; };
switch(cmd) { switch (cmd) {
case WDIOC_KEEPALIVE: case WDIOC_GETSUPPORT:
cpu5wdt_reset(); if (copy_to_user(argp, &ident, sizeof(ident)))
break; return -EFAULT;
case WDIOC_GETSTATUS: break;
value = inb(port + CPU5WDT_STATUS_REG); case WDIOC_GETSTATUS:
value = (value >> 2) & 1; value = inb(port + CPU5WDT_STATUS_REG);
if ( copy_to_user(argp, &value, sizeof(int)) ) value = (value >> 2) & 1;
return -EFAULT; return put_user(value, p);
break; case WDIOC_GETBOOTSTATUS:
case WDIOC_GETBOOTSTATUS: return put_user(0, p);
if ( copy_to_user(argp, &value, sizeof(int)) ) case WDIOC_SETOPTIONS:
return -EFAULT; if (get_user(value, p))
break; return -EFAULT;
case WDIOC_GETSUPPORT: if (value & WDIOS_ENABLECARD)
if ( copy_to_user(argp, &ident, sizeof(ident)) ) cpu5wdt_start();
return -EFAULT; if (value & WDIOS_DISABLECARD)
break; cpu5wdt_stop();
case WDIOC_SETOPTIONS: break;
if ( copy_from_user(&value, argp, sizeof(int)) ) case WDIOC_KEEPALIVE:
return -EFAULT; cpu5wdt_reset();
switch(value) { break;
case WDIOS_ENABLECARD: default:
cpu5wdt_start(); return -ENOTTY;
break;
case WDIOS_DISABLECARD:
return cpu5wdt_stop();
default:
return -EINVAL;
}
break;
default:
return -ENOTTY;
} }
return 0; return 0;
} }
static ssize_t cpu5wdt_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) static ssize_t cpu5wdt_write(struct file *file, const char __user *buf,
size_t count, loff_t *ppos)
{ {
if ( !count ) if (!count)
return -EIO; return -EIO;
cpu5wdt_reset(); cpu5wdt_reset();
return count; return count;
} }
static const struct file_operations cpu5wdt_fops = { static const struct file_operations cpu5wdt_fops = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.llseek = no_llseek, .llseek = no_llseek,
.ioctl = cpu5wdt_ioctl, .unlocked_ioctl = cpu5wdt_ioctl,
.open = cpu5wdt_open, .open = cpu5wdt_open,
.write = cpu5wdt_write, .write = cpu5wdt_write,
.release = cpu5wdt_release, .release = cpu5wdt_release,
...@@ -221,37 +218,36 @@ static int __devinit cpu5wdt_init(void) ...@@ -221,37 +218,36 @@ static int __devinit cpu5wdt_init(void)
unsigned int val; unsigned int val;
int err; int err;
if ( verbose ) if (verbose)
printk(KERN_DEBUG PFX "port=0x%x, verbose=%i\n", port, verbose); printk(KERN_DEBUG PFX
"port=0x%x, verbose=%i\n", port, verbose);
if ( !request_region(port, CPU5WDT_EXTENT, PFX) ) { init_completion(&cpu5wdt_device.stop);
spin_lock_init(&cpu5wdt_lock);
cpu5wdt_device.queue = 0;
setup_timer(&cpu5wdt_device.timer, cpu5wdt_trigger, 0);
cpu5wdt_device.default_ticks = ticks;
if (!request_region(port, CPU5WDT_EXTENT, PFX)) {
printk(KERN_ERR PFX "request_region failed\n"); printk(KERN_ERR PFX "request_region failed\n");
err = -EBUSY; err = -EBUSY;
goto no_port; goto no_port;
} }
if ( (err = misc_register(&cpu5wdt_misc)) < 0 ) {
printk(KERN_ERR PFX "misc_register failed\n");
goto no_misc;
}
/* watchdog reboot? */ /* watchdog reboot? */
val = inb(port + CPU5WDT_STATUS_REG); val = inb(port + CPU5WDT_STATUS_REG);
val = (val >> 2) & 1; val = (val >> 2) & 1;
if ( !val ) if (!val)
printk(KERN_INFO PFX "sorry, was my fault\n"); printk(KERN_INFO PFX "sorry, was my fault\n");
init_completion(&cpu5wdt_device.stop); err = misc_register(&cpu5wdt_misc);
cpu5wdt_device.queue = 0; if (err < 0) {
printk(KERN_ERR PFX "misc_register failed\n");
clear_bit(0, &cpu5wdt_device.inuse); goto no_misc;
}
setup_timer(&cpu5wdt_device.timer, cpu5wdt_trigger, 0);
cpu5wdt_device.default_ticks = ticks;
printk(KERN_INFO PFX "init success\n"); printk(KERN_INFO PFX "init success\n");
return 0; return 0;
no_misc: no_misc:
...@@ -267,7 +263,7 @@ static int __devinit cpu5wdt_init_module(void) ...@@ -267,7 +263,7 @@ static int __devinit cpu5wdt_init_module(void)
static void __devexit cpu5wdt_exit(void) static void __devexit cpu5wdt_exit(void)
{ {
if ( cpu5wdt_device.queue ) { if (cpu5wdt_device.queue) {
cpu5wdt_device.queue = 0; cpu5wdt_device.queue = 0;
wait_for_completion(&cpu5wdt_device.stop); wait_for_completion(&cpu5wdt_device.stop);
} }
......
...@@ -22,10 +22,10 @@ ...@@ -22,10 +22,10 @@
#include <linux/bitops.h> #include <linux/bitops.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/uaccess.h>
#include <linux/io.h>
#include <asm/hardware.h> #include <asm/hardware.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#define MODULE_NAME "DAVINCI-WDT: " #define MODULE_NAME "DAVINCI-WDT: "
...@@ -143,9 +143,8 @@ static struct watchdog_info ident = { ...@@ -143,9 +143,8 @@ static struct watchdog_info ident = {
.identity = "DaVinci Watchdog", .identity = "DaVinci Watchdog",
}; };
static int static long davinci_wdt_ioctl(struct file *file,
davinci_wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned int cmd, unsigned long arg)
unsigned long arg)
{ {
int ret = -ENOTTY; int ret = -ENOTTY;
...@@ -160,14 +159,14 @@ davinci_wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, ...@@ -160,14 +159,14 @@ davinci_wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
ret = put_user(0, (int *)arg); ret = put_user(0, (int *)arg);
break; break;
case WDIOC_GETTIMEOUT:
ret = put_user(heartbeat, (int *)arg);
break;
case WDIOC_KEEPALIVE: case WDIOC_KEEPALIVE:
wdt_service(); wdt_service();
ret = 0; ret = 0;
break; break;
case WDIOC_GETTIMEOUT:
ret = put_user(heartbeat, (int *)arg);
break;
} }
return ret; return ret;
} }
...@@ -184,7 +183,7 @@ static const struct file_operations davinci_wdt_fops = { ...@@ -184,7 +183,7 @@ static const struct file_operations davinci_wdt_fops = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.llseek = no_llseek, .llseek = no_llseek,
.write = davinci_wdt_write, .write = davinci_wdt_write,
.ioctl = davinci_wdt_ioctl, .unlocked_ioctl = davinci_wdt_ioctl,
.open = davinci_wdt_open, .open = davinci_wdt_open,
.release = davinci_wdt_release, .release = davinci_wdt_release,
}; };
......
...@@ -28,9 +28,9 @@ ...@@ -28,9 +28,9 @@
#include <linux/miscdevice.h> #include <linux/miscdevice.h>
#include <linux/watchdog.h> #include <linux/watchdog.h>
#include <linux/timer.h> #include <linux/timer.h>
#include <linux/uaccess.h>
#include <asm/hardware.h> #include <asm/hardware.h>
#include <asm/uaccess.h>
#define WDT_VERSION "0.3" #define WDT_VERSION "0.3"
#define PFX "ep93xx_wdt: " #define PFX "ep93xx_wdt: "
...@@ -136,9 +136,8 @@ static struct watchdog_info ident = { ...@@ -136,9 +136,8 @@ static struct watchdog_info ident = {
.identity = "EP93xx Watchdog", .identity = "EP93xx Watchdog",
}; };
static int static long ep93xx_wdt_ioctl(struct file *file,
ep93xx_wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned int cmd, unsigned long arg)
unsigned long arg)
{ {
int ret = -ENOTTY; int ret = -ENOTTY;
...@@ -156,15 +155,15 @@ ep93xx_wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, ...@@ -156,15 +155,15 @@ ep93xx_wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
ret = put_user(boot_status, (int __user *)arg); ret = put_user(boot_status, (int __user *)arg);
break; break;
case WDIOC_GETTIMEOUT:
/* actually, it is 0.250 seconds.... */
ret = put_user(1, (int __user *)arg);
break;
case WDIOC_KEEPALIVE: case WDIOC_KEEPALIVE:
wdt_keepalive(); wdt_keepalive();
ret = 0; ret = 0;
break; break;
case WDIOC_GETTIMEOUT:
/* actually, it is 0.250 seconds.... */
ret = put_user(1, (int __user *)arg);
break;
} }
return ret; return ret;
} }
...@@ -174,8 +173,8 @@ static int ep93xx_wdt_release(struct inode *inode, struct file *file) ...@@ -174,8 +173,8 @@ static int ep93xx_wdt_release(struct inode *inode, struct file *file)
if (test_bit(WDT_OK_TO_CLOSE, &wdt_status)) if (test_bit(WDT_OK_TO_CLOSE, &wdt_status))
wdt_shutdown(); wdt_shutdown();
else else
printk(KERN_CRIT PFX "Device closed unexpectedly - " printk(KERN_CRIT PFX
"timer will not stop\n"); "Device closed unexpectedly - timer will not stop\n");
clear_bit(WDT_IN_USE, &wdt_status); clear_bit(WDT_IN_USE, &wdt_status);
clear_bit(WDT_OK_TO_CLOSE, &wdt_status); clear_bit(WDT_OK_TO_CLOSE, &wdt_status);
...@@ -186,7 +185,7 @@ static int ep93xx_wdt_release(struct inode *inode, struct file *file) ...@@ -186,7 +185,7 @@ static int ep93xx_wdt_release(struct inode *inode, struct file *file)
static const struct file_operations ep93xx_wdt_fops = { static const struct file_operations ep93xx_wdt_fops = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.write = ep93xx_wdt_write, .write = ep93xx_wdt_write,
.ioctl = ep93xx_wdt_ioctl, .unlocked_ioctl = ep93xx_wdt_ioctl,
.open = ep93xx_wdt_open, .open = ep93xx_wdt_open,
.release = ep93xx_wdt_release, .release = ep93xx_wdt_release,
}; };
...@@ -243,7 +242,9 @@ module_param(nowayout, int, 0); ...@@ -243,7 +242,9 @@ module_param(nowayout, int, 0);
MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started"); MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started");
module_param(timeout, int, 0); module_param(timeout, int, 0);
MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds. (1<=timeout<=3600, default=" __MODULE_STRING(WATCHDOG_TIMEOUT) ")"); MODULE_PARM_DESC(timeout,
"Watchdog timeout in seconds. (1<=timeout<=3600, default="
__MODULE_STRING(WATCHDOG_TIMEOUT) ")");
MODULE_AUTHOR("Ray Lehtiniemi <rayl@mail.com>," MODULE_AUTHOR("Ray Lehtiniemi <rayl@mail.com>,"
"Alessandro Zummo <a.zummo@towertech.it>"); "Alessandro Zummo <a.zummo@towertech.it>");
......
...@@ -56,14 +56,15 @@ ...@@ -56,14 +56,15 @@
#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/io.h>
#include <linux/uaccess.h>
#include <asm/io.h>
#include <asm/uaccess.h>
#include <asm/system.h> #include <asm/system.h>
static unsigned long eurwdt_is_open; static unsigned long eurwdt_is_open;
static int eurwdt_timeout; static int eurwdt_timeout;
static char eur_expect_close; static char eur_expect_close;
static spinlock_t eurwdt_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.
...@@ -78,7 +79,9 @@ static char *ev = "int"; ...@@ -78,7 +79,9 @@ static char *ev = "int";
static int nowayout = WATCHDOG_NOWAYOUT; static int nowayout = WATCHDOG_NOWAYOUT;
module_param(nowayout, int, 0); module_param(nowayout, int, 0);
MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); MODULE_PARM_DESC(nowayout,
"Watchdog cannot be stopped once started (default="
__MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
/* /*
* Some symbolic names * Some symbolic names
...@@ -137,7 +140,8 @@ static void eurwdt_activate_timer(void) ...@@ -137,7 +140,8 @@ static void eurwdt_activate_timer(void)
{ {
eurwdt_disable_timer(); eurwdt_disable_timer();
eurwdt_write_reg(WDT_CTRL_REG, 0x01); /* activate the WDT */ eurwdt_write_reg(WDT_CTRL_REG, 0x01); /* activate the WDT */
eurwdt_write_reg(WDT_OUTPIN_CFG, !strcmp("int", ev) ? WDT_EVENT_INT : WDT_EVENT_REBOOT); eurwdt_write_reg(WDT_OUTPIN_CFG,
!strcmp("int", ev) ? WDT_EVENT_INT : WDT_EVENT_REBOOT);
/* Setting interrupt line */ /* Setting interrupt line */
if (irq == 2 || irq > 15 || irq < 0) { if (irq == 2 || irq > 15 || irq < 0) {
...@@ -206,21 +210,21 @@ size_t count, loff_t *ppos) ...@@ -206,21 +210,21 @@ 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')
eur_expect_close = 42; eur_expect_close = 42;
} }
} }
spin_lock(&eurwdt_lock);
eurwdt_ping(); /* the default timeout */ eurwdt_ping(); /* the default timeout */
spin_unlock(&eurwdt_lock);
} }
return count; return count;
} }
/** /**
* eurwdt_ioctl: * eurwdt_ioctl:
* @inode: inode of the device
* @file: file handle to the device * @file: file handle to the device
* @cmd: watchdog command * @cmd: watchdog command
* @arg: argument pointer * @arg: argument pointer
...@@ -229,13 +233,14 @@ size_t count, loff_t *ppos) ...@@ -229,13 +233,14 @@ size_t count, loff_t *ppos)
* according to their available features. * according to their available features.
*/ */
static int eurwdt_ioctl(struct inode *inode, struct file *file, static long eurwdt_ioctl(struct file *file,
unsigned int cmd, unsigned long arg) unsigned int cmd, unsigned long arg)
{ {
void __user *argp = (void __user *)arg; void __user *argp = (void __user *)arg;
int __user *p = argp; int __user *p = argp;
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,
.identity = "WDT Eurotech CPU-1220/1410", .identity = "WDT Eurotech CPU-1220/1410",
}; };
...@@ -243,10 +248,7 @@ static int eurwdt_ioctl(struct inode *inode, struct file *file, ...@@ -243,10 +248,7 @@ static int eurwdt_ioctl(struct inode *inode, struct file *file,
int time; int time;
int options, retval = -EINVAL; int options, retval = -EINVAL;
switch(cmd) { switch (cmd) {
default:
return -ENOTTY;
case WDIOC_GETSUPPORT: case WDIOC_GETSUPPORT:
return copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0; return copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0;
...@@ -254,8 +256,26 @@ static int eurwdt_ioctl(struct inode *inode, struct file *file, ...@@ -254,8 +256,26 @@ static int eurwdt_ioctl(struct inode *inode, struct file *file,
case WDIOC_GETBOOTSTATUS: case WDIOC_GETBOOTSTATUS:
return put_user(0, p); return put_user(0, p);
case WDIOC_SETOPTIONS:
if (get_user(options, p))
return -EFAULT;
spin_lock(&eurwdt_lock);
if (options & WDIOS_DISABLECARD) {
eurwdt_disable_timer();
retval = 0;
}
if (options & WDIOS_ENABLECARD) {
eurwdt_activate_timer();
eurwdt_ping();
retval = 0;
}
spin_unlock(&eurwdt_lock);
return retval;
case WDIOC_KEEPALIVE: case WDIOC_KEEPALIVE:
spin_lock(&eurwdt_lock);
eurwdt_ping(); eurwdt_ping();
spin_unlock(&eurwdt_lock);
return 0; return 0;
case WDIOC_SETTIMEOUT: case WDIOC_SETTIMEOUT:
...@@ -266,26 +286,17 @@ static int eurwdt_ioctl(struct inode *inode, struct file *file, ...@@ -266,26 +286,17 @@ static int eurwdt_ioctl(struct inode *inode, struct file *file,
if (time < 0 || time > 255) if (time < 0 || time > 255)
return -EINVAL; return -EINVAL;
spin_lock(&eurwdt_lock);
eurwdt_timeout = time; eurwdt_timeout = time;
eurwdt_set_timeout(time); eurwdt_set_timeout(time);
spin_unlock(&eurwdt_lock);
/* Fall */ /* Fall */
case WDIOC_GETTIMEOUT: case WDIOC_GETTIMEOUT:
return put_user(eurwdt_timeout, p); return put_user(eurwdt_timeout, p);
case WDIOC_SETOPTIONS: default:
if (get_user(options, p)) return -ENOTTY;
return -EFAULT;
if (options & WDIOS_DISABLECARD) {
eurwdt_disable_timer();
retval = 0;
}
if (options & WDIOS_ENABLECARD) {
eurwdt_activate_timer();
eurwdt_ping();
retval = 0;
}
return retval;
} }
} }
...@@ -322,10 +333,11 @@ static int eurwdt_open(struct inode *inode, struct file *file) ...@@ -322,10 +333,11 @@ 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 (eur_expect_close == 42) { if (eur_expect_close == 42)
eurwdt_disable_timer(); eurwdt_disable_timer();
} else { else {
printk(KERN_CRIT "eurwdt: Unexpected close, not stopping watchdog!\n"); printk(KERN_CRIT
"eurwdt: Unexpected close, not stopping watchdog!\n");
eurwdt_ping(); eurwdt_ping();
} }
clear_bit(0, &eurwdt_is_open); clear_bit(0, &eurwdt_is_open);
...@@ -348,10 +360,8 @@ static int eurwdt_release(struct inode *inode, struct file *file) ...@@ -348,10 +360,8 @@ static int eurwdt_release(struct inode *inode, struct file *file)
static int eurwdt_notify_sys(struct notifier_block *this, unsigned long code, static int eurwdt_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 card off */ eurwdt_disable_timer(); /* Turn the card off */
eurwdt_disable_timer();
}
return NOTIFY_DONE; return NOTIFY_DONE;
} }
...@@ -362,11 +372,11 @@ static int eurwdt_notify_sys(struct notifier_block *this, unsigned long code, ...@@ -362,11 +372,11 @@ static int eurwdt_notify_sys(struct notifier_block *this, unsigned long code,
static const struct file_operations eurwdt_fops = { static const struct file_operations eurwdt_fops = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.llseek = no_llseek, .llseek = no_llseek,
.write = eurwdt_write, .write = eurwdt_write,
.ioctl = eurwdt_ioctl, .unlocked_ioctl = eurwdt_ioctl,
.open = eurwdt_open, .open = eurwdt_open,
.release = eurwdt_release, .release = eurwdt_release,
}; };
...@@ -419,7 +429,7 @@ static int __init eurwdt_init(void) ...@@ -419,7 +429,7 @@ static int __init eurwdt_init(void)
int ret; int ret;
ret = request_irq(irq, eurwdt_interrupt, IRQF_DISABLED, "eurwdt", NULL); ret = request_irq(irq, eurwdt_interrupt, IRQF_DISABLED, "eurwdt", NULL);
if(ret) { if (ret) {
printk(KERN_ERR "eurwdt: IRQ %d is not free.\n", irq); printk(KERN_ERR "eurwdt: IRQ %d is not free.\n", irq);
goto out; goto out;
} }
...@@ -432,10 +442,13 @@ static int __init eurwdt_init(void) ...@@ -432,10 +442,13 @@ static int __init eurwdt_init(void)
ret = register_reboot_notifier(&eurwdt_notifier); ret = register_reboot_notifier(&eurwdt_notifier);
if (ret) { if (ret) {
printk(KERN_ERR "eurwdt: can't register reboot notifier (err=%d)\n", ret); printk(KERN_ERR
"eurwdt: can't register reboot notifier (err=%d)\n", ret);
goto outreg; goto outreg;
} }
spin_lock_init(&eurwdt_lock);
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",
......
...@@ -17,8 +17,8 @@ ...@@ -17,8 +17,8 @@
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/reboot.h> #include <linux/reboot.h>
#include <linux/uaccess.h>
#include <asm/uaccess.h>
#include <asm/geode.h> #include <asm/geode.h>
#define GEODEWDT_HZ 500 #define GEODEWDT_HZ 500
...@@ -77,27 +77,24 @@ static int geodewdt_set_heartbeat(int val) ...@@ -77,27 +77,24 @@ static int geodewdt_set_heartbeat(int val)
return 0; return 0;
} }
static int static int geodewdt_open(struct inode *inode, struct file *file)
geodewdt_open(struct inode *inode, struct file *file)
{ {
if (test_and_set_bit(WDT_FLAGS_OPEN, &wdt_flags)) if (test_and_set_bit(WDT_FLAGS_OPEN, &wdt_flags))
return -EBUSY; return -EBUSY;
if (!test_and_clear_bit(WDT_FLAGS_ORPHAN, &wdt_flags)) if (!test_and_clear_bit(WDT_FLAGS_ORPHAN, &wdt_flags))
__module_get(THIS_MODULE); __module_get(THIS_MODULE);
geodewdt_ping(); geodewdt_ping();
return nonseekable_open(inode, file); return nonseekable_open(inode, file);
} }
static int static int geodewdt_release(struct inode *inode, struct file *file)
geodewdt_release(struct inode *inode, struct file *file)
{ {
if (safe_close) { if (safe_close) {
geodewdt_disable(); geodewdt_disable();
module_put(THIS_MODULE); module_put(THIS_MODULE);
} } else {
else {
printk(KERN_CRIT "Unexpected close - watchdog is not stopping.\n"); printk(KERN_CRIT "Unexpected close - watchdog is not stopping.\n");
geodewdt_ping(); geodewdt_ping();
...@@ -109,11 +106,10 @@ geodewdt_release(struct inode *inode, struct file *file) ...@@ -109,11 +106,10 @@ geodewdt_release(struct inode *inode, struct file *file)
return 0; return 0;
} }
static ssize_t static ssize_t geodewdt_write(struct file *file, const char __user *data,
geodewdt_write(struct file *file, const char __user *data, size_t len, size_t len, loff_t *ppos)
loff_t *ppos)
{ {
if(len) { if (len) {
if (!nowayout) { if (!nowayout) {
size_t i; size_t i;
safe_close = 0; safe_close = 0;
...@@ -134,9 +130,8 @@ geodewdt_write(struct file *file, const char __user *data, size_t len, ...@@ -134,9 +130,8 @@ geodewdt_write(struct file *file, const char __user *data, size_t len,
return len; return len;
} }
static int static int geodewdt_ioctl(struct inode *inode, struct file *file,
geodewdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned int cmd, unsigned long arg)
unsigned long arg)
{ {
void __user *argp = (void __user *)arg; void __user *argp = (void __user *)arg;
int __user *p = argp; int __user *p = argp;
...@@ -147,9 +142,9 @@ geodewdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, ...@@ -147,9 +142,9 @@ geodewdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
| WDIOF_MAGICCLOSE, | WDIOF_MAGICCLOSE,
.firmware_version = 1, .firmware_version = 1,
.identity = WATCHDOG_NAME, .identity = WATCHDOG_NAME,
}; };
switch(cmd) { switch (cmd) {
case WDIOC_GETSUPPORT: case WDIOC_GETSUPPORT:
return copy_to_user(argp, &ident, return copy_to_user(argp, &ident,
sizeof(ident)) ? -EFAULT : 0; sizeof(ident)) ? -EFAULT : 0;
...@@ -159,22 +154,6 @@ geodewdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, ...@@ -159,22 +154,6 @@ geodewdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
case WDIOC_GETBOOTSTATUS: case WDIOC_GETBOOTSTATUS:
return put_user(0, p); return put_user(0, p);
case WDIOC_KEEPALIVE:
geodewdt_ping();
return 0;
case WDIOC_SETTIMEOUT:
if (get_user(interval, p))
return -EFAULT;
if (geodewdt_set_heartbeat(interval))
return -EINVAL;
/* Fall through */
case WDIOC_GETTIMEOUT:
return put_user(timeout, p);
case WDIOC_SETOPTIONS: case WDIOC_SETOPTIONS:
{ {
int options, ret = -EINVAL; int options, ret = -EINVAL;
...@@ -194,6 +173,20 @@ geodewdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, ...@@ -194,6 +173,20 @@ geodewdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
return ret; return ret;
} }
case WDIOC_KEEPALIVE:
geodewdt_ping();
return 0;
case WDIOC_SETTIMEOUT:
if (get_user(interval, p))
return -EFAULT;
if (geodewdt_set_heartbeat(interval))
return -EINVAL;
/* Fall through */
case WDIOC_GETTIMEOUT:
return put_user(timeout, p);
default: default:
return -ENOTTY; return -ENOTTY;
} }
...@@ -202,22 +195,21 @@ geodewdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, ...@@ -202,22 +195,21 @@ geodewdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
} }
static const struct file_operations geodewdt_fops = { static const struct file_operations geodewdt_fops = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.llseek = no_llseek, .llseek = no_llseek,
.write = geodewdt_write, .write = geodewdt_write,
.ioctl = geodewdt_ioctl, .ioctl = geodewdt_ioctl,
.open = geodewdt_open, .open = geodewdt_open,
.release = geodewdt_release, .release = geodewdt_release,
}; };
static struct miscdevice geodewdt_miscdev = { static struct miscdevice geodewdt_miscdev = {
.minor = WATCHDOG_MINOR, .minor = WATCHDOG_MINOR,
.name = "watchdog", .name = "watchdog",
.fops = &geodewdt_fops .fops = &geodewdt_fops,
}; };
static int __devinit static int __devinit geodewdt_probe(struct platform_device *dev)
geodewdt_probe(struct platform_device *dev)
{ {
int ret, timer; int ret, timer;
...@@ -248,15 +240,13 @@ geodewdt_probe(struct platform_device *dev) ...@@ -248,15 +240,13 @@ geodewdt_probe(struct platform_device *dev)
return ret; return ret;
} }
static int __devexit static int __devexit geodewdt_remove(struct platform_device *dev)
geodewdt_remove(struct platform_device *dev)
{ {
misc_deregister(&geodewdt_miscdev); misc_deregister(&geodewdt_miscdev);
return 0; return 0;
} }
static void static void geodewdt_shutdown(struct platform_device *dev)
geodewdt_shutdown(struct platform_device *dev)
{ {
geodewdt_disable(); geodewdt_disable();
} }
...@@ -271,8 +261,7 @@ static struct platform_driver geodewdt_driver = { ...@@ -271,8 +261,7 @@ static struct platform_driver geodewdt_driver = {
}, },
}; };
static int __init static int __init geodewdt_init(void)
geodewdt_init(void)
{ {
int ret; int ret;
...@@ -292,8 +281,7 @@ geodewdt_init(void) ...@@ -292,8 +281,7 @@ geodewdt_init(void)
return ret; return ret;
} }
static void __exit static void __exit geodewdt_exit(void)
geodewdt_exit(void)
{ {
platform_device_unregister(geodewdt_platform_device); platform_device_unregister(geodewdt_platform_device);
platform_driver_unregister(&geodewdt_driver); platform_driver_unregister(&geodewdt_driver);
......
...@@ -39,9 +39,7 @@ ...@@ -39,9 +39,7 @@
#include <linux/string.h> #include <linux/string.h>
#include <linux/bootmem.h> #include <linux/bootmem.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <asm/dmi.h>
#include <asm/desc.h> #include <asm/desc.h>
#include <asm/kdebug.h>
#define PCI_BIOS32_SD_VALUE 0x5F32335F /* "_32_" */ #define PCI_BIOS32_SD_VALUE 0x5F32335F /* "_32_" */
#define CRU_BIOS_SIGNATURE_VALUE 0x55524324 #define CRU_BIOS_SIGNATURE_VALUE 0x55524324
...@@ -407,7 +405,7 @@ static int __devinit detect_cru_service(void) ...@@ -407,7 +405,7 @@ static int __devinit detect_cru_service(void)
dmi_walk(dmi_find_cru); dmi_walk(dmi_find_cru);
/* if cru_rom_addr has been set then we found a CRU service */ /* if cru_rom_addr has been set then we found a CRU service */
return ((cru_rom_addr != NULL)? 0: -ENODEV); return ((cru_rom_addr != NULL) ? 0: -ENODEV);
} }
/* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */
...@@ -535,7 +533,7 @@ static ssize_t hpwdt_write(struct file *file, const char __user *data, ...@@ -535,7 +533,7 @@ static ssize_t hpwdt_write(struct file *file, const char __user *data,
/* scan to see whether or not we got the magic char. */ /* scan to see whether or not we got the magic char. */
for (i = 0; i != len; i++) { for (i = 0; i != len; i++) {
char c; char c;
if (get_user(c, data+i)) if (get_user(c, data + i))
return -EFAULT; return -EFAULT;
if (c == 'V') if (c == 'V')
expect_release = 42; expect_release = 42;
......
This diff is collapsed.
/* iTCO Vendor Specific Support hooks */
#ifdef CONFIG_ITCO_VENDOR_SUPPORT
extern void iTCO_vendor_pre_start(unsigned long, unsigned int);
extern void iTCO_vendor_pre_stop(unsigned long);
extern void iTCO_vendor_pre_keepalive(unsigned long, unsigned int);
extern void iTCO_vendor_pre_set_heartbeat(unsigned int);
extern int iTCO_vendor_check_noreboot_on(void);
#else
#define iTCO_vendor_pre_start(acpibase, heartbeat) {}
#define iTCO_vendor_pre_stop(acpibase) {}
#define iTCO_vendor_pre_keepalive(acpibase, heartbeat) {}
#define iTCO_vendor_pre_set_heartbeat(heartbeat) {}
#define iTCO_vendor_check_noreboot_on() 1
/* 1=check noreboot; 0=don't check */
#endif
...@@ -18,9 +18,9 @@ ...@@ -18,9 +18,9 @@
*/ */
/* Module and version information */ /* Module and version information */
#define DRV_NAME "iTCO_vendor_support" #define DRV_NAME "iTCO_vendor_support"
#define DRV_VERSION "1.01" #define DRV_VERSION "1.01"
#define DRV_RELDATE "11-Nov-2006" #define DRV_RELDATE "11-Nov-2006"
#define PFX DRV_NAME ": " #define PFX DRV_NAME ": "
/* Includes */ /* Includes */
...@@ -31,19 +31,22 @@ ...@@ -31,19 +31,22 @@
#include <linux/kernel.h> /* For printk/panic/... */ #include <linux/kernel.h> /* For printk/panic/... */
#include <linux/init.h> /* For __init/__exit/... */ #include <linux/init.h> /* For __init/__exit/... */
#include <linux/ioport.h> /* For io-port access */ #include <linux/ioport.h> /* For io-port access */
#include <linux/io.h> /* For inb/outb/... */
#include <asm/io.h> /* For inb/outb/... */ #include "iTCO_vendor.h"
/* iTCO defines */ /* iTCO defines */
#define SMI_EN acpibase + 0x30 /* SMI Control and Enable Register */ #define SMI_EN acpibase + 0x30 /* SMI Control and Enable Register */
#define TCOBASE acpibase + 0x60 /* TCO base address */ #define TCOBASE acpibase + 0x60 /* TCO base address */
#define TCO1_STS TCOBASE + 0x04 /* TCO1 Status Register */ #define TCO1_STS TCOBASE + 0x04 /* TCO1 Status Register */
/* List of vendor support modes */ /* List of vendor support modes */
#define SUPERMICRO_OLD_BOARD 1 /* SuperMicro Pentium 3 Era 370SSE+-OEM1/P3TSSE */ /* SuperMicro Pentium 3 Era 370SSE+-OEM1/P3TSSE */
#define SUPERMICRO_NEW_BOARD 2 /* SuperMicro Pentium 4 / Xeon 4 / EMT64T Era Systems */ #define SUPERMICRO_OLD_BOARD 1
/* SuperMicro Pentium 4 / Xeon 4 / EMT64T Era Systems */
#define SUPERMICRO_NEW_BOARD 2
static int vendorsupport = 0; static int vendorsupport;
module_param(vendorsupport, int, 0); module_param(vendorsupport, int, 0);
MODULE_PARM_DESC(vendorsupport, "iTCO vendor specific support mode, default=0 (none), 1=SuperMicro Pent3, 2=SuperMicro Pent4+"); MODULE_PARM_DESC(vendorsupport, "iTCO vendor specific support mode, default=0 (none), 1=SuperMicro Pent3, 2=SuperMicro Pent4+");
...@@ -143,34 +146,35 @@ static void supermicro_old_pre_keepalive(unsigned long acpibase) ...@@ -143,34 +146,35 @@ static void supermicro_old_pre_keepalive(unsigned long acpibase)
*/ */
/* I/O Port's */ /* I/O Port's */
#define SM_REGINDEX 0x2e /* SuperMicro ICH4+ Register Index */ #define SM_REGINDEX 0x2e /* SuperMicro ICH4+ Register Index */
#define SM_DATAIO 0x2f /* SuperMicro ICH4+ Register Data I/O */ #define SM_DATAIO 0x2f /* SuperMicro ICH4+ Register Data I/O */
/* Control Register's */ /* Control Register's */
#define SM_CTLPAGESW 0x07 /* SuperMicro ICH4+ Control Page Switch */ #define SM_CTLPAGESW 0x07 /* SuperMicro ICH4+ Control Page Switch */
#define SM_CTLPAGE 0x08 /* SuperMicro ICH4+ Control Page Num */ #define SM_CTLPAGE 0x08 /* SuperMicro ICH4+ Control Page Num */
#define SM_WATCHENABLE 0x30 /* Watchdog enable: Bit 0: 0=off, 1=on */ #define SM_WATCHENABLE 0x30 /* Watchdog enable: Bit 0: 0=off, 1=on */
#define SM_WATCHPAGE 0x87 /* Watchdog unlock control page */ #define SM_WATCHPAGE 0x87 /* Watchdog unlock control page */
#define SM_ENDWATCH 0xAA /* Watchdog lock control page */ #define SM_ENDWATCH 0xAA /* Watchdog lock control page */
#define SM_COUNTMODE 0xf5 /* Watchdog count mode select */ #define SM_COUNTMODE 0xf5 /* Watchdog count mode select */
/* (Bit 3: 0 = seconds, 1 = minutes */ /* (Bit 3: 0 = seconds, 1 = minutes */
#define SM_WATCHTIMER 0xf6 /* 8-bits, Watchdog timer counter (RW) */ #define SM_WATCHTIMER 0xf6 /* 8-bits, Watchdog timer counter (RW) */
#define SM_RESETCONTROL 0xf7 /* Watchdog reset control */ #define SM_RESETCONTROL 0xf7 /* Watchdog reset control */
/* Bit 6: timer is reset by kbd interrupt */ /* Bit 6: timer is reset by kbd interrupt */
/* Bit 7: timer is reset by mouse interrupt */ /* Bit 7: timer is reset by mouse interrupt */
static void supermicro_new_unlock_watchdog(void) static void supermicro_new_unlock_watchdog(void)
{ {
outb(SM_WATCHPAGE, SM_REGINDEX); /* Write 0x87 to port 0x2e twice */ /* Write 0x87 to port 0x2e twice */
outb(SM_WATCHPAGE, SM_REGINDEX); outb(SM_WATCHPAGE, SM_REGINDEX);
outb(SM_WATCHPAGE, SM_REGINDEX);
outb(SM_CTLPAGESW, SM_REGINDEX); /* Switch to watchdog control page */ /* Switch to watchdog control page */
outb(SM_CTLPAGESW, SM_REGINDEX);
outb(SM_CTLPAGE, SM_DATAIO); outb(SM_CTLPAGE, SM_DATAIO);
} }
...@@ -192,7 +196,7 @@ static void supermicro_new_pre_start(unsigned int heartbeat) ...@@ -192,7 +196,7 @@ static void supermicro_new_pre_start(unsigned int heartbeat)
outb(val, SM_DATAIO); outb(val, SM_DATAIO);
/* Write heartbeat interval to WDOG */ /* Write heartbeat interval to WDOG */
outb (SM_WATCHTIMER, SM_REGINDEX); outb(SM_WATCHTIMER, SM_REGINDEX);
outb((heartbeat & 255), SM_DATAIO); outb((heartbeat & 255), SM_DATAIO);
/* Make sure keyboard/mouse interrupts don't interfere */ /* Make sure keyboard/mouse interrupts don't interfere */
...@@ -277,7 +281,7 @@ EXPORT_SYMBOL(iTCO_vendor_pre_set_heartbeat); ...@@ -277,7 +281,7 @@ EXPORT_SYMBOL(iTCO_vendor_pre_set_heartbeat);
int iTCO_vendor_check_noreboot_on(void) int iTCO_vendor_check_noreboot_on(void)
{ {
switch(vendorsupport) { switch (vendorsupport) {
case SUPERMICRO_OLD_BOARD: case SUPERMICRO_OLD_BOARD:
return 0; return 0;
default: default:
...@@ -288,13 +292,13 @@ EXPORT_SYMBOL(iTCO_vendor_check_noreboot_on); ...@@ -288,13 +292,13 @@ EXPORT_SYMBOL(iTCO_vendor_check_noreboot_on);
static int __init iTCO_vendor_init_module(void) static int __init iTCO_vendor_init_module(void)
{ {
printk (KERN_INFO PFX "vendor-support=%d\n", vendorsupport); printk(KERN_INFO PFX "vendor-support=%d\n", vendorsupport);
return 0; return 0;
} }
static void __exit iTCO_vendor_exit_module(void) static void __exit iTCO_vendor_exit_module(void)
{ {
printk (KERN_INFO PFX "Module Unloaded\n"); printk(KERN_INFO PFX "Module Unloaded\n");
} }
module_init(iTCO_vendor_init_module); module_init(iTCO_vendor_init_module);
......
This diff is collapsed.
...@@ -41,9 +41,9 @@ ...@@ -41,9 +41,9 @@
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/moduleparam.h> #include <linux/moduleparam.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/io.h>
#include <linux/uaccess.h>
#include <asm/io.h>
#include <asm/uaccess.h>
#include <asm/system.h> #include <asm/system.h>
static struct platform_device *ibwdt_platform_device; static struct platform_device *ibwdt_platform_device;
...@@ -120,15 +120,16 @@ static int wd_margin = WD_TIMO; ...@@ -120,15 +120,16 @@ static int wd_margin = WD_TIMO;
static int nowayout = WATCHDOG_NOWAYOUT; static int nowayout = WATCHDOG_NOWAYOUT;
module_param(nowayout, int, 0); module_param(nowayout, int, 0);
MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); MODULE_PARM_DESC(nowayout,
"Watchdog cannot be stopped once started (default="
__MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
/* /*
* Watchdog Operations * Watchdog Operations
*/ */
static void static void ibwdt_ping(void)
ibwdt_ping(void)
{ {
spin_lock(&ibwdt_lock); spin_lock(&ibwdt_lock);
...@@ -138,16 +139,14 @@ ibwdt_ping(void) ...@@ -138,16 +139,14 @@ ibwdt_ping(void)
spin_unlock(&ibwdt_lock); spin_unlock(&ibwdt_lock);
} }
static void static void ibwdt_disable(void)
ibwdt_disable(void)
{ {
spin_lock(&ibwdt_lock); spin_lock(&ibwdt_lock);
outb_p(0, WDT_STOP); outb_p(0, WDT_STOP);
spin_unlock(&ibwdt_lock); spin_unlock(&ibwdt_lock);
} }
static int static int ibwdt_set_heartbeat(int t)
ibwdt_set_heartbeat(int t)
{ {
int i; int i;
...@@ -165,8 +164,8 @@ ibwdt_set_heartbeat(int t) ...@@ -165,8 +164,8 @@ ibwdt_set_heartbeat(int t)
* /dev/watchdog handling * /dev/watchdog handling
*/ */
static ssize_t static ssize_t ibwdt_write(struct file *file, const char __user *buf,
ibwdt_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) size_t count, loff_t *ppos)
{ {
if (count) { if (count) {
if (!nowayout) { if (!nowayout) {
...@@ -188,77 +187,71 @@ ibwdt_write(struct file *file, const char __user *buf, size_t count, loff_t *ppo ...@@ -188,77 +187,71 @@ ibwdt_write(struct file *file, const char __user *buf, size_t count, loff_t *ppo
return count; return count;
} }
static int static long ibwdt_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
ibwdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
unsigned long arg)
{ {
int new_margin; int new_margin;
void __user *argp = (void __user *)arg; void __user *argp = (void __user *)arg;
int __user *p = argp; int __user *p = argp;
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,
.identity = "IB700 WDT", .identity = "IB700 WDT",
}; };
switch (cmd) { switch (cmd) {
case WDIOC_GETSUPPORT: case WDIOC_GETSUPPORT:
if (copy_to_user(argp, &ident, sizeof(ident))) if (copy_to_user(argp, &ident, sizeof(ident)))
return -EFAULT; return -EFAULT;
break; break;
case WDIOC_GETSTATUS: case WDIOC_GETSTATUS:
case WDIOC_GETBOOTSTATUS: case WDIOC_GETBOOTSTATUS:
return put_user(0, p); return put_user(0, p);
case WDIOC_KEEPALIVE:
ibwdt_ping();
break;
case WDIOC_SETTIMEOUT:
if (get_user(new_margin, p))
return -EFAULT;
if (ibwdt_set_heartbeat(new_margin))
return -EINVAL;
ibwdt_ping();
/* Fall */
case WDIOC_GETTIMEOUT:
return put_user(wd_times[wd_margin], p);
case WDIOC_SETOPTIONS: case WDIOC_SETOPTIONS:
{ {
int options, retval = -EINVAL; int options, retval = -EINVAL;
if (get_user(options, p)) if (get_user(options, p))
return -EFAULT; return -EFAULT;
if (options & WDIOS_DISABLECARD) { if (options & WDIOS_DISABLECARD) {
ibwdt_disable(); ibwdt_disable();
retval = 0; retval = 0;
} }
if (options & WDIOS_ENABLECARD) {
ibwdt_ping();
retval = 0;
}
return retval;
}
case WDIOC_KEEPALIVE:
ibwdt_ping();
break;
if (options & WDIOS_ENABLECARD) { case WDIOC_SETTIMEOUT:
ibwdt_ping(); if (get_user(new_margin, p))
retval = 0; return -EFAULT;
} if (ibwdt_set_heartbeat(new_margin))
return -EINVAL;
ibwdt_ping();
/* Fall */
return retval; case WDIOC_GETTIMEOUT:
} return put_user(wd_times[wd_margin], p);
default: default:
return -ENOTTY; return -ENOTTY;
} }
return 0; return 0;
} }
static int static int ibwdt_open(struct inode *inode, struct file *file)
ibwdt_open(struct inode *inode, struct file *file)
{ {
if (test_and_set_bit(0, &ibwdt_is_open)) { if (test_and_set_bit(0, &ibwdt_is_open))
return -EBUSY; return -EBUSY;
}
if (nowayout) if (nowayout)
__module_get(THIS_MODULE); __module_get(THIS_MODULE);
...@@ -267,13 +260,13 @@ ibwdt_open(struct inode *inode, struct file *file) ...@@ -267,13 +260,13 @@ ibwdt_open(struct inode *inode, struct file *file)
return nonseekable_open(inode, file); return nonseekable_open(inode, file);
} }
static int static int ibwdt_close(struct inode *inode, struct file *file)
ibwdt_close(struct inode *inode, struct file *file)
{ {
if (expect_close == 42) { if (expect_close == 42) {
ibwdt_disable(); ibwdt_disable();
} else { } else {
printk(KERN_CRIT PFX "WDT device closed unexpectedly. WDT will not stop!\n"); printk(KERN_CRIT PFX
"WDT device closed unexpectedly. WDT will not stop!\n");
ibwdt_ping(); ibwdt_ping();
} }
clear_bit(0, &ibwdt_is_open); clear_bit(0, &ibwdt_is_open);
...@@ -289,7 +282,7 @@ static const struct file_operations ibwdt_fops = { ...@@ -289,7 +282,7 @@ static const struct file_operations ibwdt_fops = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.llseek = no_llseek, .llseek = no_llseek,
.write = ibwdt_write, .write = ibwdt_write,
.ioctl = ibwdt_ioctl, .unlocked_ioctl = ibwdt_ioctl,
.open = ibwdt_open, .open = ibwdt_open,
.release = ibwdt_close, .release = ibwdt_close,
}; };
...@@ -310,21 +303,23 @@ static int __devinit ibwdt_probe(struct platform_device *dev) ...@@ -310,21 +303,23 @@ static int __devinit ibwdt_probe(struct platform_device *dev)
#if WDT_START != WDT_STOP #if WDT_START != WDT_STOP
if (!request_region(WDT_STOP, 1, "IB700 WDT")) { if (!request_region(WDT_STOP, 1, "IB700 WDT")) {
printk (KERN_ERR PFX "STOP method I/O %X is not available.\n", WDT_STOP); printk(KERN_ERR PFX "STOP method I/O %X is not available.\n",
WDT_STOP);
res = -EIO; res = -EIO;
goto out_nostopreg; goto out_nostopreg;
} }
#endif #endif
if (!request_region(WDT_START, 1, "IB700 WDT")) { if (!request_region(WDT_START, 1, "IB700 WDT")) {
printk (KERN_ERR PFX "START method I/O %X is not available.\n", WDT_START); printk(KERN_ERR PFX "START method I/O %X is not available.\n",
WDT_START);
res = -EIO; res = -EIO;
goto out_nostartreg; goto out_nostartreg;
} }
res = misc_register(&ibwdt_miscdev); res = misc_register(&ibwdt_miscdev);
if (res) { if (res) {
printk (KERN_ERR PFX "failed to register misc device\n"); printk(KERN_ERR PFX "failed to register misc device\n");
goto out_nomisc; goto out_nomisc;
} }
return 0; return 0;
...@@ -342,9 +337,9 @@ static int __devinit ibwdt_probe(struct platform_device *dev) ...@@ -342,9 +337,9 @@ static int __devinit ibwdt_probe(struct platform_device *dev)
static int __devexit ibwdt_remove(struct platform_device *dev) static int __devexit ibwdt_remove(struct platform_device *dev)
{ {
misc_deregister(&ibwdt_miscdev); misc_deregister(&ibwdt_miscdev);
release_region(WDT_START,1); release_region(WDT_START, 1);
#if WDT_START != WDT_STOP #if WDT_START != WDT_STOP
release_region(WDT_STOP,1); release_region(WDT_STOP, 1);
#endif #endif
return 0; return 0;
} }
...@@ -369,13 +364,15 @@ static int __init ibwdt_init(void) ...@@ -369,13 +364,15 @@ static int __init ibwdt_init(void)
{ {
int err; int err;
printk(KERN_INFO PFX "WDT driver for IB700 single board computer initialising.\n"); printk(KERN_INFO PFX
"WDT driver for IB700 single board computer initialising.\n");
err = platform_driver_register(&ibwdt_driver); err = platform_driver_register(&ibwdt_driver);
if (err) if (err)
return err; return err;
ibwdt_platform_device = platform_device_register_simple(DRV_NAME, -1, NULL, 0); ibwdt_platform_device = platform_device_register_simple(DRV_NAME,
-1, NULL, 0);
if (IS_ERR(ibwdt_platform_device)) { if (IS_ERR(ibwdt_platform_device)) {
err = PTR_ERR(ibwdt_platform_device); err = PTR_ERR(ibwdt_platform_device);
goto unreg_platform_driver; goto unreg_platform_driver;
......
...@@ -19,9 +19,8 @@ ...@@ -19,9 +19,8 @@
#include <linux/miscdevice.h> #include <linux/miscdevice.h>
#include <linux/watchdog.h> #include <linux/watchdog.h>
#include <linux/dmi.h> #include <linux/dmi.h>
#include <linux/io.h>
#include <asm/io.h> #include <linux/uaccess.h>
#include <asm/uaccess.h>
enum { enum {
...@@ -70,10 +69,13 @@ static char asr_expect_close; ...@@ -70,10 +69,13 @@ static char asr_expect_close;
static unsigned int asr_type, asr_base, asr_length; static unsigned int asr_type, asr_base, asr_length;
static unsigned int asr_read_addr, asr_write_addr; static unsigned int asr_read_addr, asr_write_addr;
static unsigned char asr_toggle_mask, asr_disable_mask; static unsigned char asr_toggle_mask, asr_disable_mask;
static spinlock_t asr_lock;
static void asr_toggle(void) static void __asr_toggle(void)
{ {
unsigned char reg = inb(asr_read_addr); unsigned char reg;
reg = inb(asr_read_addr);
outb(reg & ~asr_toggle_mask, asr_write_addr); outb(reg & ~asr_toggle_mask, asr_write_addr);
reg = inb(asr_read_addr); reg = inb(asr_read_addr);
...@@ -83,12 +85,21 @@ static void asr_toggle(void) ...@@ -83,12 +85,21 @@ static void asr_toggle(void)
outb(reg & ~asr_toggle_mask, asr_write_addr); outb(reg & ~asr_toggle_mask, asr_write_addr);
reg = inb(asr_read_addr); reg = inb(asr_read_addr);
spin_unlock(&asr_lock);
}
static void asr_toggle(void)
{
spin_lock(&asr_lock);
__asr_toggle();
spin_unlock(&asr_lock);
} }
static void asr_enable(void) static void asr_enable(void)
{ {
unsigned char reg; unsigned char reg;
spin_lock(&asr_lock);
if (asr_type == ASMTYPE_TOPAZ) { if (asr_type == ASMTYPE_TOPAZ) {
/* asr_write_addr == asr_read_addr */ /* asr_write_addr == asr_read_addr */
reg = inb(asr_read_addr); reg = inb(asr_read_addr);
...@@ -99,17 +110,21 @@ static void asr_enable(void) ...@@ -99,17 +110,21 @@ static void asr_enable(void)
* First make sure the hardware timer is reset by toggling * First make sure the hardware timer is reset by toggling
* ASR hardware timer line. * ASR hardware timer line.
*/ */
asr_toggle(); __asr_toggle();
reg = inb(asr_read_addr); reg = inb(asr_read_addr);
outb(reg & ~asr_disable_mask, asr_write_addr); outb(reg & ~asr_disable_mask, asr_write_addr);
} }
reg = inb(asr_read_addr); reg = inb(asr_read_addr);
spin_unlock(&asr_lock);
} }
static void asr_disable(void) static void asr_disable(void)
{ {
unsigned char reg = inb(asr_read_addr); unsigned char reg;
spin_lock(&asr_lock);
reg = inb(asr_read_addr);
if (asr_type == ASMTYPE_TOPAZ) if (asr_type == ASMTYPE_TOPAZ)
/* asr_write_addr == asr_read_addr */ /* asr_write_addr == asr_read_addr */
...@@ -122,6 +137,7 @@ static void asr_disable(void) ...@@ -122,6 +137,7 @@ static void asr_disable(void)
outb(reg | asr_disable_mask, asr_write_addr); outb(reg | asr_disable_mask, asr_write_addr);
} }
reg = inb(asr_read_addr); reg = inb(asr_read_addr);
spin_unlock(&asr_lock);
} }
static int __init asr_get_base_address(void) static int __init asr_get_base_address(void)
...@@ -133,7 +149,8 @@ static int __init asr_get_base_address(void) ...@@ -133,7 +149,8 @@ static int __init asr_get_base_address(void)
switch (asr_type) { switch (asr_type) {
case ASMTYPE_TOPAZ: case ASMTYPE_TOPAZ:
/* SELECT SuperIO CHIP FOR QUERYING (WRITE 0x07 TO BOTH 0x2E and 0x2F) */ /* SELECT SuperIO CHIP FOR QUERYING
(WRITE 0x07 TO BOTH 0x2E and 0x2F) */
outb(0x07, 0x2e); outb(0x07, 0x2e);
outb(0x07, 0x2f); outb(0x07, 0x2f);
...@@ -154,14 +171,26 @@ static int __init asr_get_base_address(void) ...@@ -154,14 +171,26 @@ static int __init asr_get_base_address(void)
case ASMTYPE_JASPER: case ASMTYPE_JASPER:
type = "Jaspers "; type = "Jaspers ";
#if 0
/* FIXME: need to use pci_config_lock here, but it's not exported */ u32 r;
/* Suggested fix */
pdev = pci_get_bus_and_slot(0, DEVFN(0x1f, 0));
if (pdev == NULL)
return -ENODEV;
pci_read_config_dword(pdev, 0x58, &r);
asr_base = r & 0xFFFE;
pci_dev_put(pdev);
#else
/* FIXME: need to use pci_config_lock here,
but it's not exported */
/* spin_lock_irqsave(&pci_config_lock, flags);*/ /* spin_lock_irqsave(&pci_config_lock, flags);*/
/* Select the SuperIO chip in the PCI I/O port register */ /* Select the SuperIO chip in the PCI I/O port register */
outl(0x8000f858, 0xcf8); outl(0x8000f858, 0xcf8);
/* BUS 0, Slot 1F, fnc 0, offset 58 */
/* /*
* Read the base address for the SuperIO chip. * Read the base address for the SuperIO chip.
* Only the lower 16 bits are valid, but the address is word * Only the lower 16 bits are valid, but the address is word
...@@ -170,7 +199,7 @@ static int __init asr_get_base_address(void) ...@@ -170,7 +199,7 @@ static int __init asr_get_base_address(void)
asr_base = inl(0xcfc) & 0xfffe; asr_base = inl(0xcfc) & 0xfffe;
/* spin_unlock_irqrestore(&pci_config_lock, flags);*/ /* spin_unlock_irqrestore(&pci_config_lock, flags);*/
#endif
asr_read_addr = asr_write_addr = asr_read_addr = asr_write_addr =
asr_base + JASPER_ASR_REG_OFFSET; asr_base + JASPER_ASR_REG_OFFSET;
asr_toggle_mask = JASPER_ASR_TOGGLE_MASK; asr_toggle_mask = JASPER_ASR_TOGGLE_MASK;
...@@ -241,66 +270,57 @@ static ssize_t asr_write(struct file *file, const char __user *buf, ...@@ -241,66 +270,57 @@ static ssize_t asr_write(struct file *file, const char __user *buf,
return count; return count;
} }
static int asr_ioctl(struct inode *inode, struct file *file, static long asr_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
unsigned int cmd, unsigned long arg)
{ {
static const struct watchdog_info ident = { static const struct watchdog_info ident = {
.options = WDIOF_KEEPALIVEPING | .options = WDIOF_KEEPALIVEPING |
WDIOF_MAGICCLOSE, WDIOF_MAGICCLOSE,
.identity = "IBM ASR" .identity = "IBM ASR",
}; };
void __user *argp = (void __user *)arg; void __user *argp = (void __user *)arg;
int __user *p = argp; int __user *p = argp;
int heartbeat; int heartbeat;
switch (cmd) { switch (cmd) {
case WDIOC_GETSUPPORT: case WDIOC_GETSUPPORT:
return copy_to_user(argp, &ident, sizeof(ident)) ? return copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0;
-EFAULT : 0; case WDIOC_GETSTATUS:
case WDIOC_GETBOOTSTATUS:
case WDIOC_GETSTATUS: return put_user(0, p);
case WDIOC_GETBOOTSTATUS: case WDIOC_SETOPTIONS:
return put_user(0, p); {
int new_options, retval = -EINVAL;
case WDIOC_KEEPALIVE: if (get_user(new_options, p))
return -EFAULT;
if (new_options & WDIOS_DISABLECARD) {
asr_disable();
retval = 0;
}
if (new_options & WDIOS_ENABLECARD) {
asr_enable();
asr_toggle(); asr_toggle();
return 0; retval = 0;
/*
* The hardware has a fixed timeout value, so no WDIOC_SETTIMEOUT
* and WDIOC_GETTIMEOUT always returns 256.
*/
case WDIOC_GETTIMEOUT:
heartbeat = 256;
return put_user(heartbeat, p);
case WDIOC_SETOPTIONS: {
int new_options, retval = -EINVAL;
if (get_user(new_options, p))
return -EFAULT;
if (new_options & WDIOS_DISABLECARD) {
asr_disable();
retval = 0;
}
if (new_options & WDIOS_ENABLECARD) {
asr_enable();
asr_toggle();
retval = 0;
}
return retval;
} }
return retval;
}
case WDIOC_KEEPALIVE:
asr_toggle();
return 0;
/*
* The hardware has a fixed timeout value, so no WDIOC_SETTIMEOUT
* and WDIOC_GETTIMEOUT always returns 256.
*/
case WDIOC_GETTIMEOUT:
heartbeat = 256;
return put_user(heartbeat, p);
default:
return -ENOTTY;
} }
return -ENOTTY;
} }
static int asr_open(struct inode *inode, struct file *file) static int asr_open(struct inode *inode, struct file *file)
{ {
if(test_and_set_bit(0, &asr_is_open)) if (test_and_set_bit(0, &asr_is_open))
return -EBUSY; return -EBUSY;
asr_toggle(); asr_toggle();
...@@ -314,7 +334,8 @@ static int asr_release(struct inode *inode, struct file *file) ...@@ -314,7 +334,8 @@ static int asr_release(struct inode *inode, struct file *file)
if (asr_expect_close == 42) if (asr_expect_close == 42)
asr_disable(); asr_disable();
else { else {
printk(KERN_CRIT PFX "unexpected close, not stopping watchdog!\n"); printk(KERN_CRIT PFX
"unexpected close, not stopping watchdog!\n");
asr_toggle(); asr_toggle();
} }
clear_bit(0, &asr_is_open); clear_bit(0, &asr_is_open);
...@@ -323,12 +344,12 @@ static int asr_release(struct inode *inode, struct file *file) ...@@ -323,12 +344,12 @@ static int asr_release(struct inode *inode, struct file *file)
} }
static const struct file_operations asr_fops = { static const struct file_operations asr_fops = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.llseek = no_llseek, .llseek = no_llseek,
.write = asr_write, .write = asr_write,
.ioctl = asr_ioctl, .unlocked_ioctl = asr_ioctl,
.open = asr_open, .open = asr_open,
.release = asr_release, .release = asr_release,
}; };
static struct miscdevice asr_miscdev = { static struct miscdevice asr_miscdev = {
...@@ -367,6 +388,8 @@ static int __init ibmasr_init(void) ...@@ -367,6 +388,8 @@ static int __init ibmasr_init(void)
if (!asr_type) if (!asr_type)
return -ENODEV; return -ENODEV;
spin_lock_init(&asr_lock);
rc = asr_get_base_address(); rc = asr_get_base_address();
if (rc) if (rc)
return rc; return rc;
...@@ -395,7 +418,9 @@ module_init(ibmasr_init); ...@@ -395,7 +418,9 @@ module_init(ibmasr_init);
module_exit(ibmasr_exit); module_exit(ibmasr_exit);
module_param(nowayout, int, 0); module_param(nowayout, int, 0);
MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); MODULE_PARM_DESC(nowayout,
"Watchdog cannot be stopped once started (default="
__MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
MODULE_DESCRIPTION("IBM Automatic Server Restart driver"); MODULE_DESCRIPTION("IBM Automatic Server Restart driver");
MODULE_AUTHOR("Andrey Panin"); MODULE_AUTHOR("Andrey Panin");
......
/* /*
* IndyDog 0.3 A Hardware Watchdog Device for SGI IP22 * IndyDog 0.3 A Hardware Watchdog Device for SGI IP22
* *
* (c) Copyright 2002 Guido Guenther <agx@sigxcpu.org>, All Rights Reserved. * (c) Copyright 2002 Guido Guenther <agx@sigxcpu.org>,
* All Rights Reserved.
* *
* 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
...@@ -22,32 +23,42 @@ ...@@ -22,32 +23,42 @@
#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/uaccess.h> #include <linux/uaccess.h>
#include <asm/sgi/mc.h> #include <asm/sgi/mc.h>
#define PFX "indydog: " #define PFX "indydog: "
static int indydog_alive; static unsigned long indydog_alive;
static spinlock_t indydog_lock;
#define WATCHDOG_TIMEOUT 30 /* 30 sec default timeout */ #define WATCHDOG_TIMEOUT 30 /* 30 sec default timeout */
static int nowayout = WATCHDOG_NOWAYOUT; static int nowayout = WATCHDOG_NOWAYOUT;
module_param(nowayout, int, 0); module_param(nowayout, int, 0);
MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); MODULE_PARM_DESC(nowayout,
"Watchdog cannot be stopped once started (default="
__MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
static void indydog_start(void) static void indydog_start(void)
{ {
u32 mc_ctrl0 = sgimc->cpuctrl0; u32 mc_ctrl0;
spin_lock(&indydog_lock);
mc_ctrl0 = sgimc->cpuctrl0;
mc_ctrl0 = sgimc->cpuctrl0 | SGIMC_CCTRL0_WDOG; mc_ctrl0 = sgimc->cpuctrl0 | SGIMC_CCTRL0_WDOG;
sgimc->cpuctrl0 = mc_ctrl0; sgimc->cpuctrl0 = mc_ctrl0;
spin_unlock(&indydog_lock);
} }
static void indydog_stop(void) static void indydog_stop(void)
{ {
u32 mc_ctrl0 = sgimc->cpuctrl0; u32 mc_ctrl0;
spin_lock(&indydog_lock);
mc_ctrl0 = sgimc->cpuctrl0;
mc_ctrl0 &= ~SGIMC_CCTRL0_WDOG; mc_ctrl0 &= ~SGIMC_CCTRL0_WDOG;
sgimc->cpuctrl0 = mc_ctrl0; sgimc->cpuctrl0 = mc_ctrl0;
spin_unlock(&indydog_lock);
printk(KERN_INFO PFX "Stopped watchdog timer.\n"); printk(KERN_INFO PFX "Stopped watchdog timer.\n");
} }
...@@ -62,7 +73,7 @@ static void indydog_ping(void) ...@@ -62,7 +73,7 @@ static void indydog_ping(void)
*/ */
static int indydog_open(struct inode *inode, struct file *file) static int indydog_open(struct inode *inode, struct file *file)
{ {
if (indydog_alive) if (test_and_set_bit(0, &indydog_alive))
return -EBUSY; return -EBUSY;
if (nowayout) if (nowayout)
...@@ -84,23 +95,21 @@ static int indydog_release(struct inode *inode, struct file *file) ...@@ -84,23 +95,21 @@ static int indydog_release(struct inode *inode, struct file *file)
* Lock it in if it's a module and we defined ...NOWAYOUT */ * Lock it in if it's a module and we defined ...NOWAYOUT */
if (!nowayout) if (!nowayout)
indydog_stop(); /* Turn the WDT off */ indydog_stop(); /* Turn the WDT off */
clear_bit(0, &indydog_alive);
indydog_alive = 0;
return 0; return 0;
} }
static ssize_t indydog_write(struct file *file, const char *data, size_t len, loff_t *ppos) static ssize_t indydog_write(struct file *file, const char *data,
size_t len, loff_t *ppos)
{ {
/* Refresh the timer. */ /* Refresh the timer. */
if (len) { if (len)
indydog_ping(); indydog_ping();
}
return len; return len;
} }
static int indydog_ioctl(struct inode *inode, struct file *file, static long indydog_ioctl(struct file *file, unsigned int cmd,
unsigned int cmd, unsigned long arg) unsigned long arg)
{ {
int options, retval = -EINVAL; int options, retval = -EINVAL;
static struct watchdog_info ident = { static struct watchdog_info ident = {
...@@ -111,42 +120,40 @@ static int indydog_ioctl(struct inode *inode, struct file *file, ...@@ -111,42 +120,40 @@ static int indydog_ioctl(struct inode *inode, struct file *file,
}; };
switch (cmd) { switch (cmd) {
default: case WDIOC_GETSUPPORT:
return -ENOTTY; if (copy_to_user((struct watchdog_info *)arg,
case WDIOC_GETSUPPORT: &ident, sizeof(ident)))
if (copy_to_user((struct watchdog_info *)arg, return -EFAULT;
&ident, sizeof(ident))) return 0;
return -EFAULT; case WDIOC_GETSTATUS:
return 0; case WDIOC_GETBOOTSTATUS:
case WDIOC_GETSTATUS: return put_user(0, (int *)arg);
case WDIOC_GETBOOTSTATUS: case WDIOC_SETOPTIONS:
return put_user(0,(int *)arg); {
case WDIOC_KEEPALIVE: if (get_user(options, (int *)arg))
indydog_ping(); return -EFAULT;
return 0; if (options & WDIOS_DISABLECARD) {
case WDIOC_GETTIMEOUT: indydog_stop();
return put_user(WATCHDOG_TIMEOUT,(int *)arg); retval = 0;
case WDIOC_SETOPTIONS:
{
if (get_user(options, (int *)arg))
return -EFAULT;
if (options & WDIOS_DISABLECARD) {
indydog_stop();
retval = 0;
}
if (options & WDIOS_ENABLECARD) {
indydog_start();
retval = 0;
}
return retval;
} }
if (options & WDIOS_ENABLECARD) {
indydog_start();
retval = 0;
}
return retval;
}
case WDIOC_KEEPALIVE:
indydog_ping();
return 0;
case WDIOC_GETTIMEOUT:
return put_user(WATCHDOG_TIMEOUT, (int *)arg);
default:
return -ENOTTY;
} }
} }
static int indydog_notify_sys(struct notifier_block *this, unsigned long code, void *unused) static int indydog_notify_sys(struct notifier_block *this,
unsigned long code, void *unused)
{ {
if (code == SYS_DOWN || code == SYS_HALT) if (code == SYS_DOWN || code == SYS_HALT)
indydog_stop(); /* Turn the WDT off */ indydog_stop(); /* Turn the WDT off */
...@@ -158,7 +165,7 @@ static const struct file_operations indydog_fops = { ...@@ -158,7 +165,7 @@ static const struct file_operations indydog_fops = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.llseek = no_llseek, .llseek = no_llseek,
.write = indydog_write, .write = indydog_write,
.ioctl = indydog_ioctl, .unlocked_ioctl = indydog_ioctl,
.open = indydog_open, .open = indydog_open,
.release = indydog_release, .release = indydog_release,
}; };
...@@ -180,17 +187,20 @@ static int __init watchdog_init(void) ...@@ -180,17 +187,20 @@ static int __init watchdog_init(void)
{ {
int ret; int ret;
spin_lock_init(&indydog_lock);
ret = register_reboot_notifier(&indydog_notifier); ret = register_reboot_notifier(&indydog_notifier);
if (ret) { if (ret) {
printk(KERN_ERR PFX "cannot register reboot notifier (err=%d)\n", printk(KERN_ERR PFX
ret); "cannot register reboot notifier (err=%d)\n", ret);
return ret; return ret;
} }
ret = misc_register(&indydog_miscdev); ret = misc_register(&indydog_miscdev);
if (ret) { if (ret) {
printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n", printk(KERN_ERR PFX
WATCHDOG_MINOR, ret); "cannot register miscdev on minor=%d (err=%d)\n",
WATCHDOG_MINOR, ret);
unregister_reboot_notifier(&indydog_notifier); unregister_reboot_notifier(&indydog_notifier);
return ret; return ret;
} }
......
...@@ -37,6 +37,7 @@ ...@@ -37,6 +37,7 @@
static int nowayout = WATCHDOG_NOWAYOUT; static int nowayout = WATCHDOG_NOWAYOUT;
static unsigned long wdt_status; static unsigned long wdt_status;
static unsigned long boot_status; static unsigned long boot_status;
static spinlock_t wdt_lock;
#define WDT_IN_USE 0 #define WDT_IN_USE 0
#define WDT_OK_TO_CLOSE 1 #define WDT_OK_TO_CLOSE 1
...@@ -68,8 +69,10 @@ static void wdt_enable(void) ...@@ -68,8 +69,10 @@ static void wdt_enable(void)
/* Arm and enable the Timer to starting counting down from 0xFFFF.FFFF /* Arm and enable the Timer to starting counting down from 0xFFFF.FFFF
* Takes approx. 10.7s to timeout * Takes approx. 10.7s to timeout
*/ */
spin_lock(&wdt_lock);
write_wdtcr(IOP_WDTCR_EN_ARM); write_wdtcr(IOP_WDTCR_EN_ARM);
write_wdtcr(IOP_WDTCR_EN); write_wdtcr(IOP_WDTCR_EN);
spin_unlock(&wdt_lock);
} }
/* returns 0 if the timer was successfully disabled */ /* returns 0 if the timer was successfully disabled */
...@@ -77,9 +80,11 @@ static int wdt_disable(void) ...@@ -77,9 +80,11 @@ static int wdt_disable(void)
{ {
/* Stop Counting */ /* Stop Counting */
if (wdt_supports_disable()) { if (wdt_supports_disable()) {
spin_lock(&wdt_lock);
write_wdtcr(IOP_WDTCR_DIS_ARM); write_wdtcr(IOP_WDTCR_DIS_ARM);
write_wdtcr(IOP_WDTCR_DIS); write_wdtcr(IOP_WDTCR_DIS);
clear_bit(WDT_ENABLED, &wdt_status); clear_bit(WDT_ENABLED, &wdt_status);
spin_unlock(&wdt_lock);
printk(KERN_INFO "WATCHDOG: Disabled\n"); printk(KERN_INFO "WATCHDOG: Disabled\n");
return 0; return 0;
} else } else
...@@ -92,16 +97,12 @@ static int iop_wdt_open(struct inode *inode, struct file *file) ...@@ -92,16 +97,12 @@ static int iop_wdt_open(struct inode *inode, struct file *file)
return -EBUSY; return -EBUSY;
clear_bit(WDT_OK_TO_CLOSE, &wdt_status); clear_bit(WDT_OK_TO_CLOSE, &wdt_status);
wdt_enable(); wdt_enable();
set_bit(WDT_ENABLED, &wdt_status); set_bit(WDT_ENABLED, &wdt_status);
return nonseekable_open(inode, file); return nonseekable_open(inode, file);
} }
static ssize_t static ssize_t iop_wdt_write(struct file *file, const char *data, size_t len,
iop_wdt_write(struct file *file, const char *data, size_t len,
loff_t *ppos) loff_t *ppos)
{ {
if (len) { if (len) {
...@@ -121,46 +122,35 @@ iop_wdt_write(struct file *file, const char *data, size_t len, ...@@ -121,46 +122,35 @@ iop_wdt_write(struct file *file, const char *data, size_t len,
} }
wdt_enable(); wdt_enable();
} }
return len; return len;
} }
static struct watchdog_info ident = { static const struct watchdog_info ident = {
.options = WDIOF_CARDRESET | WDIOF_MAGICCLOSE | WDIOF_KEEPALIVEPING, .options = WDIOF_CARDRESET | WDIOF_MAGICCLOSE | WDIOF_KEEPALIVEPING,
.identity = "iop watchdog", .identity = "iop watchdog",
}; };
static int static long iop_wdt_ioctl(struct file *file,
iop_wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned int cmd, unsigned long arg)
unsigned long arg)
{ {
int options; int options;
int ret = -ENOTTY; int ret = -ENOTTY;
int __user *argp = (int __user *)arg;
switch (cmd) { switch (cmd) {
case WDIOC_GETSUPPORT: case WDIOC_GETSUPPORT:
if (copy_to_user if (copy_to_user(argp, &ident, sizeof ident))
((struct watchdog_info *)arg, &ident, sizeof ident))
ret = -EFAULT; ret = -EFAULT;
else else
ret = 0; ret = 0;
break; break;
case WDIOC_GETSTATUS: case WDIOC_GETSTATUS:
ret = put_user(0, (int *)arg); ret = put_user(0, argp);
break; break;
case WDIOC_GETBOOTSTATUS: case WDIOC_GETBOOTSTATUS:
ret = put_user(boot_status, (int *)arg); ret = put_user(boot_status, argp);
break;
case WDIOC_GETTIMEOUT:
ret = put_user(iop_watchdog_timeout(), (int *)arg);
break;
case WDIOC_KEEPALIVE:
wdt_enable();
ret = 0;
break; break;
case WDIOC_SETOPTIONS: case WDIOC_SETOPTIONS:
...@@ -177,14 +167,21 @@ iop_wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, ...@@ -177,14 +167,21 @@ iop_wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
} else } else
ret = 0; ret = 0;
} }
if (options & WDIOS_ENABLECARD) { if (options & WDIOS_ENABLECARD) {
wdt_enable(); wdt_enable();
ret = 0; ret = 0;
} }
break; break;
}
case WDIOC_KEEPALIVE:
wdt_enable();
ret = 0;
break;
case WDIOC_GETTIMEOUT:
ret = put_user(iop_watchdog_timeout(), argp);
break;
}
return ret; return ret;
} }
...@@ -214,7 +211,7 @@ static const struct file_operations iop_wdt_fops = { ...@@ -214,7 +211,7 @@ static const struct file_operations iop_wdt_fops = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.llseek = no_llseek, .llseek = no_llseek,
.write = iop_wdt_write, .write = iop_wdt_write,
.ioctl = iop_wdt_ioctl, .unlocked_ioctl = iop_wdt_ioctl,
.open = iop_wdt_open, .open = iop_wdt_open,
.release = iop_wdt_release, .release = iop_wdt_release,
}; };
...@@ -229,10 +226,8 @@ static int __init iop_wdt_init(void) ...@@ -229,10 +226,8 @@ static int __init iop_wdt_init(void)
{ {
int ret; int ret;
ret = misc_register(&iop_wdt_miscdev); spin_lock_init(&wdt_lock);
if (ret == 0)
printk("iop watchdog timer: timeout %lu sec\n",
iop_watchdog_timeout());
/* check if the reset was caused by the watchdog timer */ /* check if the reset was caused by the watchdog timer */
boot_status = (read_rcsr() & IOP_RCSR_WDT) ? WDIOF_CARDRESET : 0; boot_status = (read_rcsr() & IOP_RCSR_WDT) ? WDIOF_CARDRESET : 0;
...@@ -242,6 +237,13 @@ static int __init iop_wdt_init(void) ...@@ -242,6 +237,13 @@ static int __init iop_wdt_init(void)
*/ */
write_wdtsr(IOP13XX_WDTCR_IB_RESET); write_wdtsr(IOP13XX_WDTCR_IB_RESET);
/* Register after we have the device set up so we cannot race
with an open */
ret = misc_register(&iop_wdt_miscdev);
if (ret == 0)
printk(KERN_INFO "iop watchdog timer: timeout %lu sec\n",
iop_watchdog_timeout());
return ret; return ret;
} }
......
...@@ -221,7 +221,7 @@ static ssize_t it8712f_wdt_write(struct file *file, const char __user *data, ...@@ -221,7 +221,7 @@ static ssize_t it8712f_wdt_write(struct file *file, const char __user *data,
expect_close = 0; expect_close = 0;
for (i = 0; i < len; ++i) { for (i = 0; i < len; ++i) {
char c; char c;
if (get_user(c, data+i)) if (get_user(c, data + i))
return -EFAULT; return -EFAULT;
if (c == 'V') if (c == 'V')
expect_close = 42; expect_close = 42;
...@@ -244,8 +244,6 @@ static long it8712f_wdt_ioctl(struct file *file, unsigned int cmd, ...@@ -244,8 +244,6 @@ static long it8712f_wdt_ioctl(struct file *file, unsigned int cmd,
int value; int value;
switch (cmd) { switch (cmd) {
default:
return -ENOTTY;
case WDIOC_GETSUPPORT: case WDIOC_GETSUPPORT:
if (copy_to_user(argp, &ident, sizeof(ident))) if (copy_to_user(argp, &ident, sizeof(ident)))
return -EFAULT; return -EFAULT;
...@@ -284,6 +282,8 @@ static long it8712f_wdt_ioctl(struct file *file, unsigned int cmd, ...@@ -284,6 +282,8 @@ static long it8712f_wdt_ioctl(struct file *file, unsigned int cmd,
if (put_user(margin, p)) if (put_user(margin, p))
return -EFAULT; return -EFAULT;
return 0; return 0;
default:
return -ENOTTY;
} }
} }
......
...@@ -25,42 +25,45 @@ ...@@ -25,42 +25,45 @@
#include <linux/watchdog.h> #include <linux/watchdog.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/bitops.h> #include <linux/bitops.h>
#include <linux/uaccess.h>
#include <asm/hardware.h> #include <asm/hardware.h>
#include <asm/uaccess.h>
static int nowayout = WATCHDOG_NOWAYOUT; static int nowayout = WATCHDOG_NOWAYOUT;
static unsigned int heartbeat = 60; /* (secs) Default is 1 minute */ static unsigned int heartbeat = 60; /* (secs) Default is 1 minute */
static unsigned long wdt_status; static unsigned long wdt_status;
static spinlock_t wdt_lock;
#define WDT_IN_USE 0 #define WDT_IN_USE 0
#define WDT_OK_TO_CLOSE 1 #define WDT_OK_TO_CLOSE 1
static unsigned long wdt_tick_rate; static unsigned long wdt_tick_rate;
static void static void wdt_enable(void)
wdt_enable(void)
{ {
spin_lock(&wdt_lock);
ixp2000_reg_write(IXP2000_RESET0, *(IXP2000_RESET0) | WDT_RESET_ENABLE); ixp2000_reg_write(IXP2000_RESET0, *(IXP2000_RESET0) | WDT_RESET_ENABLE);
ixp2000_reg_write(IXP2000_TWDE, WDT_ENABLE); ixp2000_reg_write(IXP2000_TWDE, WDT_ENABLE);
ixp2000_reg_write(IXP2000_T4_CLD, heartbeat * wdt_tick_rate); ixp2000_reg_write(IXP2000_T4_CLD, heartbeat * wdt_tick_rate);
ixp2000_reg_write(IXP2000_T4_CTL, TIMER_DIVIDER_256 | TIMER_ENABLE); ixp2000_reg_write(IXP2000_T4_CTL, TIMER_DIVIDER_256 | TIMER_ENABLE);
spin_unlock(&wdt_lock);
} }
static void static void wdt_disable(void)
wdt_disable(void)
{ {
spin_lock(&wdt_lock);
ixp2000_reg_write(IXP2000_T4_CTL, 0); ixp2000_reg_write(IXP2000_T4_CTL, 0);
spin_unlock(&wdt_lock);
} }
static void static void wdt_keepalive(void)
wdt_keepalive(void)
{ {
spin_lock(&wdt_lock);
ixp2000_reg_write(IXP2000_T4_CLD, heartbeat * wdt_tick_rate); ixp2000_reg_write(IXP2000_T4_CLD, heartbeat * wdt_tick_rate);
spin_unlock(&wdt_lock);
} }
static int static int ixp2000_wdt_open(struct inode *inode, struct file *file)
ixp2000_wdt_open(struct inode *inode, struct file *file)
{ {
if (test_and_set_bit(WDT_IN_USE, &wdt_status)) if (test_and_set_bit(WDT_IN_USE, &wdt_status))
return -EBUSY; return -EBUSY;
...@@ -72,8 +75,8 @@ ixp2000_wdt_open(struct inode *inode, struct file *file) ...@@ -72,8 +75,8 @@ ixp2000_wdt_open(struct inode *inode, struct file *file)
return nonseekable_open(inode, file); return nonseekable_open(inode, file);
} }
static ssize_t static ssize_t ixp2000_wdt_write(struct file *file, const char *data,
ixp2000_wdt_write(struct file *file, const char *data, size_t len, loff_t *ppos) size_t len, loff_t *ppos)
{ {
if (len) { if (len) {
if (!nowayout) { if (!nowayout) {
...@@ -103,9 +106,8 @@ static struct watchdog_info ident = { ...@@ -103,9 +106,8 @@ static struct watchdog_info ident = {
.identity = "IXP2000 Watchdog", .identity = "IXP2000 Watchdog",
}; };
static int static long ixp2000_wdt_ioctl(struct file *file, unsigned int cmd,
ixp2000_wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
unsigned long arg)
{ {
int ret = -ENOTTY; int ret = -ENOTTY;
int time; int time;
...@@ -124,6 +126,11 @@ ixp2000_wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, ...@@ -124,6 +126,11 @@ ixp2000_wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
ret = put_user(0, (int *)arg); ret = put_user(0, (int *)arg);
break; break;
case WDIOC_KEEPALIVE:
wdt_enable();
ret = 0;
break;
case WDIOC_SETTIMEOUT: case WDIOC_SETTIMEOUT:
ret = get_user(time, (int *)arg); ret = get_user(time, (int *)arg);
if (ret) if (ret)
...@@ -141,26 +148,18 @@ ixp2000_wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, ...@@ -141,26 +148,18 @@ ixp2000_wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
case WDIOC_GETTIMEOUT: case WDIOC_GETTIMEOUT:
ret = put_user(heartbeat, (int *)arg); ret = put_user(heartbeat, (int *)arg);
break; break;
case WDIOC_KEEPALIVE:
wdt_enable();
ret = 0;
break;
} }
return ret; return ret;
} }
static int static int ixp2000_wdt_release(struct inode *inode, struct file *file)
ixp2000_wdt_release(struct inode *inode, struct file *file)
{ {
if (test_bit(WDT_OK_TO_CLOSE, &wdt_status)) { if (test_bit(WDT_OK_TO_CLOSE, &wdt_status))
wdt_disable(); wdt_disable();
} else { else
printk(KERN_CRIT "WATCHDOG: Device closed unexpectedly - " printk(KERN_CRIT "WATCHDOG: Device closed unexpectedly - "
"timer will not stop\n"); "timer will not stop\n");
}
clear_bit(WDT_IN_USE, &wdt_status); clear_bit(WDT_IN_USE, &wdt_status);
clear_bit(WDT_OK_TO_CLOSE, &wdt_status); clear_bit(WDT_OK_TO_CLOSE, &wdt_status);
...@@ -168,18 +167,16 @@ ixp2000_wdt_release(struct inode *inode, struct file *file) ...@@ -168,18 +167,16 @@ ixp2000_wdt_release(struct inode *inode, struct file *file)
} }
static const struct file_operations ixp2000_wdt_fops = static const struct file_operations ixp2000_wdt_fops = {
{
.owner = THIS_MODULE, .owner = THIS_MODULE,
.llseek = no_llseek, .llseek = no_llseek,
.write = ixp2000_wdt_write, .write = ixp2000_wdt_write,
.ioctl = ixp2000_wdt_ioctl, .unlocked_ioctl = ixp2000_wdt_ioctl,
.open = ixp2000_wdt_open, .open = ixp2000_wdt_open,
.release = ixp2000_wdt_release, .release = ixp2000_wdt_release,
}; };
static struct miscdevice ixp2000_wdt_miscdev = static struct miscdevice ixp2000_wdt_miscdev = {
{
.minor = WATCHDOG_MINOR, .minor = WATCHDOG_MINOR,
.name = "watchdog", .name = "watchdog",
.fops = &ixp2000_wdt_fops, .fops = &ixp2000_wdt_fops,
...@@ -191,9 +188,8 @@ static int __init ixp2000_wdt_init(void) ...@@ -191,9 +188,8 @@ static int __init ixp2000_wdt_init(void)
printk(KERN_INFO "Unable to use IXP2000 watchdog due to IXP2800 erratum #25.\n"); printk(KERN_INFO "Unable to use IXP2000 watchdog due to IXP2800 erratum #25.\n");
return -EIO; return -EIO;
} }
wdt_tick_rate = (*IXP2000_T1_CLD * HZ) / 256; wdt_tick_rate = (*IXP2000_T1_CLD * HZ) / 256;
spin_lock_init(&wdt_lock);
return misc_register(&ixp2000_wdt_miscdev); return misc_register(&ixp2000_wdt_miscdev);
} }
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -305,8 +305,6 @@ static long s3c2410wdt_ioctl(struct file *file, unsigned int cmd, ...@@ -305,8 +305,6 @@ static long s3c2410wdt_ioctl(struct file *file, unsigned int cmd,
int new_margin; int new_margin;
switch (cmd) { switch (cmd) {
default:
return -ENOTTY;
case WDIOC_GETSUPPORT: case WDIOC_GETSUPPORT:
return copy_to_user(argp, &s3c2410_wdt_ident, return copy_to_user(argp, &s3c2410_wdt_ident,
sizeof(s3c2410_wdt_ident)) ? -EFAULT : 0; sizeof(s3c2410_wdt_ident)) ? -EFAULT : 0;
...@@ -325,6 +323,8 @@ static long s3c2410wdt_ioctl(struct file *file, unsigned int cmd, ...@@ -325,6 +323,8 @@ static long s3c2410wdt_ioctl(struct file *file, unsigned int cmd,
return put_user(tmr_margin, p); return put_user(tmr_margin, p);
case WDIOC_GETTIMEOUT: case WDIOC_GETTIMEOUT:
return put_user(tmr_margin, p); return put_user(tmr_margin, p);
default:
return -ENOTTY;
} }
} }
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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