diff options
Diffstat (limited to 'drivers/watchdog/it8712f_wdt.c')
| -rw-r--r-- | drivers/watchdog/it8712f_wdt.c | 63 | 
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) { | 
