summaryrefslogtreecommitdiff
path: root/drivers/watchdog/it8712f_wdt.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/watchdog/it8712f_wdt.c')
-rw-r--r--drivers/watchdog/it8712f_wdt.c63
1 files changed, 45 insertions, 18 deletions
diff --git a/drivers/watchdog/it8712f_wdt.c b/drivers/watchdog/it8712f_wdt.c
index 6143f52ba6b8..8d2d8502d3e8 100644
--- a/drivers/watchdog/it8712f_wdt.c
+++ b/drivers/watchdog/it8712f_wdt.c
@@ -28,10 +28,10 @@
#include <linux/notifier.h>
#include <linux/reboot.h>
#include <linux/fs.h>
-#include <linux/pci.h>
#include <linux/spinlock.h>
#include <linux/uaccess.h>
#include <linux/io.h>
+#include <linux/ioport.h>
#define NAME "it8712f_wdt"
@@ -51,7 +51,6 @@ MODULE_PARM_DESC(nowayout, "Disable watchdog shutdown on close");
static unsigned long wdt_open;
static unsigned expect_close;
-static spinlock_t io_lock;
static unsigned char revision;
/* Dog Food address - We use the game port address */
@@ -121,20 +120,26 @@ static inline void superio_select(int ldn)
outb(ldn, VAL);
}
-static inline void superio_enter(void)
+static inline int superio_enter(void)
{
- spin_lock(&io_lock);
+ /*
+ * Try to reserve REG and REG + 1 for exclusive access.
+ */
+ if (!request_muxed_region(REG, 2, NAME))
+ return -EBUSY;
+
outb(0x87, REG);
outb(0x01, REG);
outb(0x55, REG);
outb(0x55, REG);
+ return 0;
}
static inline void superio_exit(void)
{
outb(0x02, REG);
outb(0x02, VAL);
- spin_unlock(&io_lock);
+ release_region(REG, 2);
}
static inline void it8712f_wdt_ping(void)
@@ -173,10 +178,13 @@ static int it8712f_wdt_get_status(void)
return 0;
}
-static void it8712f_wdt_enable(void)
+static int it8712f_wdt_enable(void)
{
+ int ret = superio_enter();
+ if (ret)
+ return ret;
+
printk(KERN_DEBUG NAME ": enabling watchdog timer\n");
- superio_enter();
superio_select(LDN_GPIO);
superio_outb(wdt_control_reg, WDT_CONTROL);
@@ -186,13 +194,17 @@ static void it8712f_wdt_enable(void)
superio_exit();
it8712f_wdt_ping();
+
+ return 0;
}
-static void it8712f_wdt_disable(void)
+static int it8712f_wdt_disable(void)
{
- printk(KERN_DEBUG NAME ": disabling watchdog timer\n");
+ int ret = superio_enter();
+ if (ret)
+ return ret;
- superio_enter();
+ printk(KERN_DEBUG NAME ": disabling watchdog timer\n");
superio_select(LDN_GPIO);
superio_outb(0, WDT_CONFIG);
@@ -202,6 +214,7 @@ static void it8712f_wdt_disable(void)
superio_outb(0, WDT_TIMEOUT);
superio_exit();
+ return 0;
}
static int it8712f_wdt_notify(struct notifier_block *this,
@@ -252,6 +265,7 @@ static long it8712f_wdt_ioctl(struct file *file, unsigned int cmd,
WDIOF_MAGICCLOSE,
};
int value;
+ int ret;
switch (cmd) {
case WDIOC_GETSUPPORT:
@@ -259,7 +273,9 @@ static long it8712f_wdt_ioctl(struct file *file, unsigned int cmd,
return -EFAULT;
return 0;
case WDIOC_GETSTATUS:
- superio_enter();
+ ret = superio_enter();
+ if (ret)
+ return ret;
superio_select(LDN_GPIO);
value = it8712f_wdt_get_status();
@@ -280,7 +296,9 @@ static long it8712f_wdt_ioctl(struct file *file, unsigned int cmd,
if (value > (max_units * 60))
return -EINVAL;
margin = value;
- superio_enter();
+ ret = superio_enter();
+ if (ret)
+ return ret;
superio_select(LDN_GPIO);
it8712f_wdt_update_margin();
@@ -299,10 +317,14 @@ static long it8712f_wdt_ioctl(struct file *file, unsigned int cmd,
static int it8712f_wdt_open(struct inode *inode, struct file *file)
{
+ int ret;
/* only allow one at a time */
if (test_and_set_bit(0, &wdt_open))
return -EBUSY;
- it8712f_wdt_enable();
+
+ ret = it8712f_wdt_enable();
+ if (ret)
+ return ret;
return nonseekable_open(inode, file);
}
@@ -313,7 +335,8 @@ static int it8712f_wdt_release(struct inode *inode, struct file *file)
": watchdog device closed unexpectedly, will not"
" disable the watchdog timer\n");
} else if (!nowayout) {
- it8712f_wdt_disable();
+ if (it8712f_wdt_disable())
+ printk(KERN_WARNING NAME "Watchdog disable failed\n");
}
expect_close = 0;
clear_bit(0, &wdt_open);
@@ -340,8 +363,10 @@ static int __init it8712f_wdt_find(unsigned short *address)
{
int err = -ENODEV;
int chip_type;
+ int ret = superio_enter();
+ if (ret)
+ return ret;
- superio_enter();
chip_type = superio_inw(DEVID);
if (chip_type != IT8712F_DEVID)
goto exit;
@@ -382,8 +407,6 @@ static int __init it8712f_wdt_init(void)
{
int err = 0;
- spin_lock_init(&io_lock);
-
if (it8712f_wdt_find(&address))
return -ENODEV;
@@ -392,7 +415,11 @@ static int __init it8712f_wdt_init(void)
return -EBUSY;
}
- it8712f_wdt_disable();
+ err = it8712f_wdt_disable();
+ if (err) {
+ printk(KERN_ERR NAME ": unable to disable watchdog timer.\n");
+ goto out;
+ }
err = register_reboot_notifier(&it8712f_wdt_notifier);
if (err) {