Commit e948c126 authored by Dave Jones's avatar Dave Jones Committed by Linus Torvalds

[PATCH] add spinlocking to w83877f_wdt driver

parent 928098c9
...@@ -13,9 +13,10 @@ ...@@ -13,9 +13,10 @@
* any of this software. This material is provided "AS-IS" in * any of this software. This material is provided "AS-IS" in
* the hope that it may be useful for others. * the hope that it may be useful for others.
* *
* (c) Copyright 2001 Scott Jennings <management@oro.net> * (c) Copyright 2001 Scott Jennings <linuxdrivers@oro.net>
* *
* 4/19 - 2001 [Initial revision] * 4/19 - 2001 [Initial revision]
* 9/27 - 2001 Added spinlocking
* *
* *
* Theory of operation: * Theory of operation:
...@@ -88,8 +89,9 @@ ...@@ -88,8 +89,9 @@
static void wdt_timer_ping(unsigned long); static void wdt_timer_ping(unsigned long);
static struct timer_list timer; static struct timer_list timer;
static unsigned long next_heartbeat; static unsigned long next_heartbeat;
static int wdt_is_open; static unsigned long wdt_is_open;
static int wdt_expect_close; static int wdt_expect_close;
static spinlock_t wdt_spinlock;
/* /*
* Whack the dog * Whack the dog
...@@ -102,11 +104,18 @@ static void wdt_timer_ping(unsigned long data) ...@@ -102,11 +104,18 @@ static void wdt_timer_ping(unsigned long data)
*/ */
if(time_before(jiffies, next_heartbeat)) if(time_before(jiffies, next_heartbeat))
{ {
/* Ping the WDT */
spin_lock(&wdt_spinlock);
/* Ping the WDT by reading from WDT_PING */ /* Ping the WDT by reading from WDT_PING */
inb_p(WDT_PING); inb_p(WDT_PING);
/* Re-set the timer interval */ /* Re-set the timer interval */
timer.expires = jiffies + WDT_INTERVAL; timer.expires = jiffies + WDT_INTERVAL;
add_timer(&timer); add_timer(&timer);
spin_unlock(&wdt_spinlock);
} else { } else {
printk(OUR_NAME ": Heartbeat lost! Will not ping the watchdog\n"); printk(OUR_NAME ": Heartbeat lost! Will not ping the watchdog\n");
} }
...@@ -118,19 +127,24 @@ static void wdt_timer_ping(unsigned long data) ...@@ -118,19 +127,24 @@ static void wdt_timer_ping(unsigned long data)
static void wdt_change(int writeval) static void wdt_change(int writeval)
{ {
unsigned long flags;
spin_lock_irqsave(&wdt_spinlock, flags);
/* buy some time */ /* buy some time */
inb_p(WDT_PING); inb_p(WDT_PING);
/* make W83877F available */ /* make W83877F available */
outb_p(ENABLE_W83877F,ENABLE_W83877F_PORT); outb_p(ENABLE_W83877F, ENABLE_W83877F_PORT);
outb_p(ENABLE_W83877F,ENABLE_W83877F_PORT); outb_p(ENABLE_W83877F, ENABLE_W83877F_PORT);
/* enable watchdog */ /* enable watchdog */
outb_p(WDT_REGISTER,ENABLE_W83877F_PORT); outb_p(WDT_REGISTER, ENABLE_W83877F_PORT);
outb_p(writeval,ENABLE_W83877F_PORT+1); outb_p(writeval, ENABLE_W83877F_PORT+1);
/* lock the W8387FF away */ /* lock the W8387FF away */
outb_p(DISABLE_W83877F,ENABLE_W83877F_PORT); outb_p(DISABLE_W83877F, ENABLE_W83877F_PORT);
spin_unlock_irqrestore(&wdt_spinlock, flags);
} }
static void wdt_startup(void) static void wdt_startup(void)
...@@ -178,7 +192,7 @@ static ssize_t fop_write(struct file * file, const char * buf, size_t count, lof ...@@ -178,7 +192,7 @@ static ssize_t fop_write(struct file * file, const char * buf, size_t count, lof
/* now scan */ /* now scan */
for(ofs = 0; ofs != count; ofs++) for(ofs = 0; ofs != count; ofs++)
if(buf[ofs] == 'V') if(buf[ofs] == 'V')
wdt_expect_close = 1; wdt_expect_close = 1;
/* someone wrote to us, we should restart timer */ /* someone wrote to us, we should restart timer */
...@@ -200,10 +214,10 @@ static int fop_open(struct inode * inode, struct file * file) ...@@ -200,10 +214,10 @@ static int fop_open(struct inode * inode, struct file * file)
{ {
case WATCHDOG_MINOR: case WATCHDOG_MINOR:
/* Just in case we're already talking to someone... */ /* Just in case we're already talking to someone... */
if(wdt_is_open) if(test_and_set_bit(0, &wdt_is_open)) {
return -EBUSY; return -EBUSY;
}
/* Good, fire up the show */ /* Good, fire up the show */
wdt_is_open = 1;
wdt_startup(); wdt_startup();
return 0; return 0;
...@@ -305,6 +319,8 @@ static int __init w83877f_wdt_init(void) ...@@ -305,6 +319,8 @@ static int __init w83877f_wdt_init(void)
{ {
int rc = -EBUSY; int rc = -EBUSY;
spin_lock_init(&wdt_spinlock);
if (!request_region(ENABLE_W83877F_PORT, 2, "W83877F WDT")) if (!request_region(ENABLE_W83877F_PORT, 2, "W83877F WDT"))
goto err_out; goto err_out;
if (!request_region(WDT_PING, 1, "W8387FF WDT")) if (!request_region(WDT_PING, 1, "W8387FF WDT"))
...@@ -339,4 +355,7 @@ static int __init w83877f_wdt_init(void) ...@@ -339,4 +355,7 @@ static int __init w83877f_wdt_init(void)
module_init(w83877f_wdt_init); module_init(w83877f_wdt_init);
module_exit(w83877f_wdt_unload); module_exit(w83877f_wdt_unload);
MODULE_AUTHOR("Scott and Bill Jennings");
MODULE_DESCRIPTION("Driver for watchdog timer in w83877f chip");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
EXPORT_NO_SYMBOLS;
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment