[WATCHDOG] pnx4008_wdt.c - spinlock fixes.
authorWim Van Sebroeck <wim@iguana.be>
Sun, 10 Sep 2006 10:48:15 +0000 (12:48 +0200)
committerWim Van Sebroeck <wim@iguana.be>
Mon, 2 Oct 2006 21:05:28 +0000 (23:05 +0200)
Add io spinlocks to prevent possible race
conditions between start and stop operations
that are issued from different child processes
where the master process opened /dev/watchdog.

Signed-off-by: Wim Van Sebroeck <wim@iguana.be>
drivers/char/watchdog/pnx4008_wdt.c

index 465dfd3ba61ac3fb6e90379da135a168d7516fa3..359168e63c1d654aa45ff5eee35ea41b2868cb7b 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/device.h>
 #include <linux/platform_device.h>
 #include <linux/clk.h>
+#include <linux/spinlock.h>
 
 #include <asm/hardware.h>
 #include <asm/uaccess.h>
@@ -80,6 +81,7 @@
 static int nowayout = WATCHDOG_NOWAYOUT;
 static int heartbeat = DEFAULT_HEARTBEAT;
 
+static spinlock_t io_lock;
 static unsigned long wdt_status;
 #define WDT_IN_USE        0
 #define WDT_OK_TO_CLOSE   1
@@ -94,6 +96,8 @@ struct clk            *wdt_clk;
 
 static void wdt_enable(void)
 {
+       spin_lock(&io_lock);
+
        if (wdt_clk)
                clk_set_rate(wdt_clk, 1);
 
@@ -113,13 +117,19 @@ static void wdt_enable(void)
        __raw_writel(heartbeat * WDOG_COUNTER_RATE, WDTIM_MATCH0(wdt_base));
        /*enable counter, stop when debugger active */
        __raw_writel(COUNT_ENAB | DEBUG_EN, WDTIM_CTRL(wdt_base));
+
+       spin_unlock(&io_lock);
 }
 
 static void wdt_disable(void)
 {
+       spin_lock(&io_lock);
+
        __raw_writel(0, WDTIM_CTRL(wdt_base));  /*stop counter */
        if (wdt_clk)
                clk_set_rate(wdt_clk, 0);
+
+       spin_unlock(&io_lock);
 }
 
 static int pnx4008_wdt_open(struct inode *inode, struct file *file)
@@ -248,6 +258,8 @@ static int pnx4008_wdt_probe(struct platform_device *pdev)
        int ret = 0, size;
        struct resource *res;
 
+       spin_lock_init(&io_lock);
+
        if (heartbeat < 1 || heartbeat > MAX_HEARTBEAT)
                heartbeat = DEFAULT_HEARTBEAT;