2 * SoftDog: A Software Watchdog Device
4 * (c) Copyright 1996 Alan Cox <alan@lxorguk.ukuu.org.uk>,
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version
10 * 2 of the License, or (at your option) any later version.
12 * Neither Alan Cox nor CymruNet Ltd. admit liability nor provide
13 * warranty for any of this software. This material is provided
14 * "AS-IS" and at no charge.
16 * (c) Copyright 1995 Alan Cox <alan@lxorguk.ukuu.org.uk>
18 * Software only watchdog driver. Unlike its big brother the WDT501P
19 * driver this won't always recover a failed machine.
22 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
24 #include <linux/hrtimer.h>
25 #include <linux/init.h>
26 #include <linux/kernel.h>
27 #include <linux/module.h>
28 #include <linux/moduleparam.h>
29 #include <linux/reboot.h>
30 #include <linux/types.h>
31 #include <linux/watchdog.h>
33 #define TIMER_MARGIN 60 /* Default is 60 seconds */
34 static unsigned int soft_margin
= TIMER_MARGIN
; /* in seconds */
35 module_param(soft_margin
, uint
, 0);
36 MODULE_PARM_DESC(soft_margin
,
37 "Watchdog soft_margin in seconds. (0 < soft_margin < 65536, default="
38 __MODULE_STRING(TIMER_MARGIN
) ")");
40 static bool nowayout
= WATCHDOG_NOWAYOUT
;
41 module_param(nowayout
, bool, 0);
42 MODULE_PARM_DESC(nowayout
,
43 "Watchdog cannot be stopped once started (default="
44 __MODULE_STRING(WATCHDOG_NOWAYOUT
) ")");
46 static int soft_noboot
;
47 module_param(soft_noboot
, int, 0);
48 MODULE_PARM_DESC(soft_noboot
,
49 "Softdog action, set to 1 to ignore reboots, 0 to reboot (default=0)");
51 static int soft_panic
;
52 module_param(soft_panic
, int, 0);
53 MODULE_PARM_DESC(soft_panic
,
54 "Softdog action, set to 1 to panic, 0 to reboot (default=0)");
56 static struct hrtimer softdog_ticktock
;
57 static struct hrtimer softdog_preticktock
;
59 static enum hrtimer_restart
softdog_fire(struct hrtimer
*timer
)
61 module_put(THIS_MODULE
);
63 pr_crit("Triggered - Reboot ignored\n");
64 } else if (soft_panic
) {
65 pr_crit("Initiating panic\n");
66 panic("Software Watchdog Timer expired");
68 pr_crit("Initiating system reboot\n");
70 pr_crit("Reboot didn't ?????\n");
73 return HRTIMER_NORESTART
;
76 static struct watchdog_device softdog_dev
;
78 static enum hrtimer_restart
softdog_pretimeout(struct hrtimer
*timer
)
80 watchdog_notify_pretimeout(&softdog_dev
);
82 return HRTIMER_NORESTART
;
85 static int softdog_ping(struct watchdog_device
*w
)
87 if (!hrtimer_active(&softdog_ticktock
))
88 __module_get(THIS_MODULE
);
89 hrtimer_start(&softdog_ticktock
, ktime_set(w
->timeout
, 0),
92 if (IS_ENABLED(CONFIG_SOFT_WATCHDOG_PRETIMEOUT
)) {
94 hrtimer_start(&softdog_preticktock
,
95 ktime_set(w
->timeout
- w
->pretimeout
, 0),
98 hrtimer_cancel(&softdog_preticktock
);
104 static int softdog_stop(struct watchdog_device
*w
)
106 if (hrtimer_cancel(&softdog_ticktock
))
107 module_put(THIS_MODULE
);
109 if (IS_ENABLED(CONFIG_SOFT_WATCHDOG_PRETIMEOUT
))
110 hrtimer_cancel(&softdog_preticktock
);
115 static struct watchdog_info softdog_info
= {
116 .identity
= "Software Watchdog",
117 .options
= WDIOF_SETTIMEOUT
| WDIOF_KEEPALIVEPING
| WDIOF_MAGICCLOSE
,
120 static const struct watchdog_ops softdog_ops
= {
121 .owner
= THIS_MODULE
,
122 .start
= softdog_ping
,
123 .stop
= softdog_stop
,
126 static struct watchdog_device softdog_dev
= {
127 .info
= &softdog_info
,
130 .max_timeout
= 65535,
131 .timeout
= TIMER_MARGIN
,
134 static int __init
softdog_init(void)
138 watchdog_init_timeout(&softdog_dev
, soft_margin
, NULL
);
139 watchdog_set_nowayout(&softdog_dev
, nowayout
);
140 watchdog_stop_on_reboot(&softdog_dev
);
142 hrtimer_init(&softdog_ticktock
, CLOCK_MONOTONIC
, HRTIMER_MODE_REL
);
143 softdog_ticktock
.function
= softdog_fire
;
145 if (IS_ENABLED(CONFIG_SOFT_WATCHDOG_PRETIMEOUT
)) {
146 softdog_info
.options
|= WDIOF_PRETIMEOUT
;
147 hrtimer_init(&softdog_preticktock
, CLOCK_MONOTONIC
,
149 softdog_preticktock
.function
= softdog_pretimeout
;
152 ret
= watchdog_register_device(&softdog_dev
);
156 pr_info("initialized. soft_noboot=%d soft_margin=%d sec soft_panic=%d (nowayout=%d)\n",
157 soft_noboot
, softdog_dev
.timeout
, soft_panic
, nowayout
);
161 module_init(softdog_init
);
163 static void __exit
softdog_exit(void)
165 watchdog_unregister_device(&softdog_dev
);
167 module_exit(softdog_exit
);
169 MODULE_AUTHOR("Alan Cox");
170 MODULE_DESCRIPTION("Software Watchdog Device Driver");
171 MODULE_LICENSE("GPL");