diff options
Diffstat (limited to 'drivers/watchdog/it8712f_wdt.c')
-rw-r--r-- | drivers/watchdog/it8712f_wdt.c | 61 |
1 files changed, 44 insertions, 17 deletions
diff --git a/drivers/watchdog/it8712f_wdt.c b/drivers/watchdog/it8712f_wdt.c index 6143f52ba6b..690144917a4 100644 --- a/drivers/watchdog/it8712f_wdt.c +++ b/drivers/watchdog/it8712f_wdt.c @@ -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) { |