summaryrefslogtreecommitdiffstats
path: root/drivers/watchdog/ar7_wdt.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/watchdog/ar7_wdt.c')
-rw-r--r--drivers/watchdog/ar7_wdt.c37
1 files changed, 21 insertions, 16 deletions
diff --git a/drivers/watchdog/ar7_wdt.c b/drivers/watchdog/ar7_wdt.c
index 2eb48c0df32c..55dcbfe2bb72 100644
--- a/drivers/watchdog/ar7_wdt.c
+++ b/drivers/watchdog/ar7_wdt.c
@@ -69,7 +69,8 @@ struct ar7_wdt {
u32 prescale;
};
-static struct semaphore open_semaphore;
+static unsigned long wdt_is_open;
+static spinlock_t wdt_lock;
static unsigned expect_close;
/* XXX currently fixed, allows max margin ~68.72 secs */
@@ -154,8 +155,10 @@ static void ar7_wdt_update_margin(int new_margin)
u32 change;
change = new_margin * (ar7_vbus_freq() / prescale_value);
- if (change < 1) change = 1;
- if (change > 0xffff) change = 0xffff;
+ if (change < 1)
+ change = 1;
+ if (change > 0xffff)
+ change = 0xffff;
ar7_wdt_change(change);
margin = change * prescale_value / ar7_vbus_freq();
printk(KERN_INFO DRVNAME
@@ -179,7 +182,7 @@ static void ar7_wdt_disable_wdt(void)
static int ar7_wdt_open(struct inode *inode, struct file *file)
{
/* only allow one at a time */
- if (down_trylock(&open_semaphore))
+ if (test_and_set_bit(0, &wdt_is_open))
return -EBUSY;
ar7_wdt_enable_wdt();
expect_close = 0;
@@ -195,9 +198,7 @@ static int ar7_wdt_release(struct inode *inode, struct file *file)
"will not disable the watchdog timer\n");
else if (!nowayout)
ar7_wdt_disable_wdt();
-
- up(&open_semaphore);
-
+ clear_bit(0, &wdt_is_open);
return 0;
}
@@ -212,7 +213,7 @@ static int ar7_wdt_notify_sys(struct notifier_block *this,
}
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,
@@ -222,12 +223,14 @@ static ssize_t ar7_wdt_write(struct file *file, const char *data,
if (len) {
size_t i;
+ spin_lock(&wdt_lock);
ar7_wdt_kick(1);
+ spin_unlock(&wdt_lock);
expect_close = 0;
for (i = 0; i < len; ++i) {
char c;
- if (get_user(c, data+i))
+ if (get_user(c, data + i))
return -EFAULT;
if (c == 'V')
expect_close = 1;
@@ -237,8 +240,8 @@ static ssize_t ar7_wdt_write(struct file *file, const char *data,
return len;
}
-static int ar7_wdt_ioctl(struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg)
+static long ar7_wdt_ioctl(struct file *file,
+ unsigned int cmd, unsigned long arg)
{
static struct watchdog_info ident = {
.identity = LONGNAME,
@@ -248,8 +251,6 @@ static int ar7_wdt_ioctl(struct inode *inode, struct file *file,
int new_margin;
switch (cmd) {
- default:
- return -ENOTTY;
case WDIOC_GETSUPPORT:
if (copy_to_user((struct watchdog_info *)arg, &ident,
sizeof(ident)))
@@ -269,20 +270,24 @@ static int ar7_wdt_ioctl(struct inode *inode, struct file *file,
if (new_margin < 1)
return -EINVAL;
+ spin_lock(&wdt_lock);
ar7_wdt_update_margin(new_margin);
ar7_wdt_kick(1);
+ spin_unlock(&wdt_lock);
case WDIOC_GETTIMEOUT:
if (put_user(margin, (int *)arg))
return -EFAULT;
return 0;
+ default:
+ return -ENOTTY;
}
}
static const struct file_operations ar7_wdt_fops = {
.owner = THIS_MODULE,
.write = ar7_wdt_write,
- .ioctl = ar7_wdt_ioctl,
+ .unlocked_ioctl = ar7_wdt_ioctl,
.open = ar7_wdt_open,
.release = ar7_wdt_release,
};
@@ -297,6 +302,8 @@ static int __init ar7_wdt_init(void)
{
int rc;
+ spin_lock_init(&wdt_lock);
+
ar7_wdt_get_regs();
if (!request_mem_region(ar7_regs_wdt, sizeof(struct ar7_wdt),
@@ -312,8 +319,6 @@ static int __init ar7_wdt_init(void)
ar7_wdt_prescale(prescale_value);
ar7_wdt_update_margin(margin);
- sema_init(&open_semaphore, 1);
-
rc = register_reboot_notifier(&ar7_wdt_notifier);
if (rc) {
printk(KERN_ERR DRVNAME