summaryrefslogtreecommitdiff
path: root/drivers/watchdog/iop_wdt.c
diff options
context:
space:
mode:
authorRussell King <rmk@dyn-67.arm.linux.org.uk>2008-08-08 20:33:47 +0400
committerRussell King <rmk+kernel@arm.linux.org.uk>2008-08-08 22:18:18 +0400
commit097d9eb537ff4d88b74c3fe67392e27c478ca3c5 (patch)
tree9034d676d9096857a380aab9d99e3e88fccb6bfe /drivers/watchdog/iop_wdt.c
parentc41107c2d4fd31924533f4dbc4c3428acc2b5894 (diff)
parentaeee90dfa01844168cd7f8051d0a0f969c573067 (diff)
downloadlinux-097d9eb537ff4d88b74c3fe67392e27c478ca3c5.tar.xz
Merge Linus' latest into master
Conflicts: drivers/watchdog/at91rm9200_wdt.c drivers/watchdog/davinci_wdt.c drivers/watchdog/ep93xx_wdt.c drivers/watchdog/ixp2000_wdt.c drivers/watchdog/ixp4xx_wdt.c drivers/watchdog/ks8695_wdt.c drivers/watchdog/omap_wdt.c drivers/watchdog/pnx4008_wdt.c drivers/watchdog/sa1100_wdt.c drivers/watchdog/wdt285.c
Diffstat (limited to 'drivers/watchdog/iop_wdt.c')
-rw-r--r--drivers/watchdog/iop_wdt.c62
1 files changed, 32 insertions, 30 deletions
diff --git a/drivers/watchdog/iop_wdt.c b/drivers/watchdog/iop_wdt.c
index 1946dd06d815..96eb2cbe5874 100644
--- a/drivers/watchdog/iop_wdt.c
+++ b/drivers/watchdog/iop_wdt.c
@@ -37,6 +37,7 @@
static int nowayout = WATCHDOG_NOWAYOUT;
static unsigned long wdt_status;
static unsigned long boot_status;
+static spinlock_t wdt_lock;
#define WDT_IN_USE 0
#define WDT_OK_TO_CLOSE 1
@@ -68,8 +69,10 @@ static void wdt_enable(void)
/* Arm and enable the Timer to starting counting down from 0xFFFF.FFFF
* Takes approx. 10.7s to timeout
*/
+ spin_lock(&wdt_lock);
write_wdtcr(IOP_WDTCR_EN_ARM);
write_wdtcr(IOP_WDTCR_EN);
+ spin_unlock(&wdt_lock);
}
/* returns 0 if the timer was successfully disabled */
@@ -77,9 +80,11 @@ static int wdt_disable(void)
{
/* Stop Counting */
if (wdt_supports_disable()) {
+ spin_lock(&wdt_lock);
write_wdtcr(IOP_WDTCR_DIS_ARM);
write_wdtcr(IOP_WDTCR_DIS);
clear_bit(WDT_ENABLED, &wdt_status);
+ spin_unlock(&wdt_lock);
printk(KERN_INFO "WATCHDOG: Disabled\n");
return 0;
} else
@@ -92,16 +97,12 @@ static int iop_wdt_open(struct inode *inode, struct file *file)
return -EBUSY;
clear_bit(WDT_OK_TO_CLOSE, &wdt_status);
-
wdt_enable();
-
set_bit(WDT_ENABLED, &wdt_status);
-
return nonseekable_open(inode, file);
}
-static ssize_t
-iop_wdt_write(struct file *file, const char *data, size_t len,
+static ssize_t iop_wdt_write(struct file *file, const char *data, size_t len,
loff_t *ppos)
{
if (len) {
@@ -121,46 +122,35 @@ iop_wdt_write(struct file *file, const char *data, size_t len,
}
wdt_enable();
}
-
return len;
}
-static struct watchdog_info ident = {
+static const struct watchdog_info ident = {
.options = WDIOF_CARDRESET | WDIOF_MAGICCLOSE | WDIOF_KEEPALIVEPING,
.identity = "iop watchdog",
};
-static int
-iop_wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
- unsigned long arg)
+static long iop_wdt_ioctl(struct file *file,
+ unsigned int cmd, unsigned long arg)
{
int options;
int ret = -ENOTTY;
+ int __user *argp = (int __user *)arg;
switch (cmd) {
case WDIOC_GETSUPPORT:
- if (copy_to_user
- ((struct watchdog_info *)arg, &ident, sizeof ident))
+ if (copy_to_user(argp, &ident, sizeof ident))
ret = -EFAULT;
else
ret = 0;
break;
case WDIOC_GETSTATUS:
- ret = put_user(0, (int *)arg);
+ ret = put_user(0, argp);
break;
case WDIOC_GETBOOTSTATUS:
- ret = put_user(boot_status, (int *)arg);
- break;
-
- case WDIOC_GETTIMEOUT:
- ret = put_user(iop_watchdog_timeout(), (int *)arg);
- break;
-
- case WDIOC_KEEPALIVE:
- wdt_enable();
- ret = 0;
+ ret = put_user(boot_status, argp);
break;
case WDIOC_SETOPTIONS:
@@ -177,14 +167,21 @@ iop_wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
} else
ret = 0;
}
-
if (options & WDIOS_ENABLECARD) {
wdt_enable();
ret = 0;
}
break;
- }
+ case WDIOC_KEEPALIVE:
+ wdt_enable();
+ ret = 0;
+ break;
+
+ case WDIOC_GETTIMEOUT:
+ ret = put_user(iop_watchdog_timeout(), argp);
+ break;
+ }
return ret;
}
@@ -214,7 +211,7 @@ static const struct file_operations iop_wdt_fops = {
.owner = THIS_MODULE,
.llseek = no_llseek,
.write = iop_wdt_write,
- .ioctl = iop_wdt_ioctl,
+ .unlocked_ioctl = iop_wdt_ioctl,
.open = iop_wdt_open,
.release = iop_wdt_release,
};
@@ -229,10 +226,8 @@ static int __init iop_wdt_init(void)
{
int ret;
- ret = misc_register(&iop_wdt_miscdev);
- if (ret == 0)
- printk("iop watchdog timer: timeout %lu sec\n",
- iop_watchdog_timeout());
+ spin_lock_init(&wdt_lock);
+
/* check if the reset was caused by the watchdog timer */
boot_status = (read_rcsr() & IOP_RCSR_WDT) ? WDIOF_CARDRESET : 0;
@@ -242,6 +237,13 @@ static int __init iop_wdt_init(void)
*/
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;
}