aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/watchdog/softdog.c
diff options
context:
space:
mode:
authorLi RongQing <roy.qing.li@gmail.com>2015-12-17 08:30:02 -0500
committerWim Van Sebroeck <wim@iguana.be>2015-12-27 15:02:21 -0500
commit5889f06bd31d542766046faa6b17d957c08e1484 (patch)
tree37e0bec23c48aa457d3ea7d23dceb0effb626c13 /drivers/watchdog/softdog.c
parent8d2fa17151ea33a98b5f70839fd2ffa3bce51de5 (diff)
watchdog: refuse to unload softdog module when its timer is running
the softdog has static variables which are accessed if its timer is still running after the driver is unloaded. and lead to crash: $modprobe softdog $echo 1 >/dev/watchdog $modprobe -r softdog CPU 20 Unable to handle kernel paging request at virtual address Oops[#1]: CPU: 20 PID: 0 Comm: swapper/20 Not tainted 4.1.13-WR8.0.0.0_standard ... Modules linked in: [last unloaded: softdog] .... Call Trace: [<ffffffff801e142c>] cascade+0x34/0xb0 [<ffffffff801e1964>] run_timer_softirq+0x30c/0x368 [<ffffffff80181044>] __do_softirq+0x1ec/0x418 [<ffffffff801815d0>] irq_exit+0x90/0x98 [<ffffffff8010749c>] plat_irq_dispatch+0xa4/0x140 [<ffffffff80152740>] ret_from_irq+0x0/0x4 [<ffffffff801529e0>] __r4k_wait+0x20/0x40 [<ffffffff801c2278>] cpu_startup_entry+0x2a0/0x368 [<ffffffff8015fa64>] start_secondary+0x444/0x4d8 add the module ref when timer is running to avoid to unload the softdog module Signed-off-by: Li RongQing <roy.qing.li@gmail.com> Signed-off-by: Guenter Roeck <linux@roeck-us.net> Signed-off-by: Wim Van Sebroeck <wim@iguana.be>
Diffstat (limited to 'drivers/watchdog/softdog.c')
-rw-r--r--drivers/watchdog/softdog.c8
1 files changed, 6 insertions, 2 deletions
diff --git a/drivers/watchdog/softdog.c b/drivers/watchdog/softdog.c
index fe1e15137bf6..99a06f9e3930 100644
--- a/drivers/watchdog/softdog.c
+++ b/drivers/watchdog/softdog.c
@@ -86,6 +86,7 @@ static struct timer_list watchdog_ticktock =
86 86
87static void watchdog_fire(unsigned long data) 87static void watchdog_fire(unsigned long data)
88{ 88{
89 module_put(THIS_MODULE);
89 if (soft_noboot) 90 if (soft_noboot)
90 pr_crit("Triggered - Reboot ignored\n"); 91 pr_crit("Triggered - Reboot ignored\n");
91 else if (soft_panic) { 92 else if (soft_panic) {
@@ -104,13 +105,16 @@ static void watchdog_fire(unsigned long data)
104 105
105static int softdog_ping(struct watchdog_device *w) 106static int softdog_ping(struct watchdog_device *w)
106{ 107{
107 mod_timer(&watchdog_ticktock, jiffies+(w->timeout*HZ)); 108 if (!mod_timer(&watchdog_ticktock, jiffies+(w->timeout*HZ)))
109 __module_get(THIS_MODULE);
108 return 0; 110 return 0;
109} 111}
110 112
111static int softdog_stop(struct watchdog_device *w) 113static int softdog_stop(struct watchdog_device *w)
112{ 114{
113 del_timer(&watchdog_ticktock); 115 if (del_timer(&watchdog_ticktock))
116 module_put(THIS_MODULE);
117
114 return 0; 118 return 0;
115} 119}
116 120