Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

watchdog: dw_wdt: No need for a spinlock

Right now the dw_wdt uses a spinlock to protect dw_wdt_open(). The
problem is that while holding the spinlock we call:
-> dw_wdt_set_top()
-> dw_wdt_top_in_seconds()
-> clk_get_rate()
-> clk_prepare_lock()
-> mutex_lock()

Locking a mutex while holding a spinlock is not allowed and leads to
warnings like "BUG: spinlock wrong CPU on CPU#1", among other
problems.

There's no reason to use a spinlock. Only dw_wdt_open() was protected
and the test_and_set_bit() at the start of that function protects us
anyway.

Signed-off-by: Doug Anderson <dianders@chromium.org>
Tested-by: Jisheng Zhang <jszhang@marvell.com>
Reviewed-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Reviewed-by: Guenter Roeck <linux@roeck-us.net>
Signed-off-by: Wim Van Sebroeck <wim@iguana.be>

authored by

Doug Anderson and committed by
Wim Van Sebroeck
7fb466a7 30dd4a8f

-7
-7
drivers/watchdog/dw_wdt.c
··· 35 35 #include <linux/pm.h> 36 36 #include <linux/platform_device.h> 37 37 #include <linux/reboot.h> 38 - #include <linux/spinlock.h> 39 38 #include <linux/timer.h> 40 39 #include <linux/uaccess.h> 41 40 #include <linux/watchdog.h> ··· 60 61 #define WDT_TIMEOUT (HZ / 2) 61 62 62 63 static struct { 63 - spinlock_t lock; 64 64 void __iomem *regs; 65 65 struct clk *clk; 66 66 unsigned long in_use; ··· 175 177 /* Make sure we don't get unloaded. */ 176 178 __module_get(THIS_MODULE); 177 179 178 - spin_lock(&dw_wdt.lock); 179 180 if (!dw_wdt_is_enabled()) { 180 181 /* 181 182 * The watchdog is not currently enabled. Set the timeout to ··· 186 189 } 187 190 188 191 dw_wdt_set_next_heartbeat(); 189 - 190 - spin_unlock(&dw_wdt.lock); 191 192 192 193 return nonseekable_open(inode, filp); 193 194 } ··· 342 347 ret = clk_prepare_enable(dw_wdt.clk); 343 348 if (ret) 344 349 return ret; 345 - 346 - spin_lock_init(&dw_wdt.lock); 347 350 348 351 ret = misc_register(&dw_wdt_miscdev); 349 352 if (ret)