blob: 9e9c5de2e549b9dc9053270608b3150430bf5d8c [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * ipmi_watchdog.c
3 *
4 * A watchdog timer based upon the IPMI interface.
5 *
6 * Author: MontaVista Software, Inc.
7 * Corey Minyard <minyard@mvista.com>
8 * source@mvista.com
9 *
10 * Copyright 2002 MontaVista Software Inc.
11 *
12 * This program is free software; you can redistribute it and/or modify it
13 * under the terms of the GNU General Public License as published by the
14 * Free Software Foundation; either version 2 of the License, or (at your
15 * option) any later version.
16 *
17 *
18 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
19 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
20 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
23 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
24 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
26 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
27 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 *
29 * You should have received a copy of the GNU General Public License along
30 * with this program; if not, write to the Free Software Foundation, Inc.,
31 * 675 Mass Ave, Cambridge, MA 02139, USA.
32 */
33
Linus Torvalds1da177e2005-04-16 15:20:36 -070034#include <linux/module.h>
35#include <linux/moduleparam.h>
36#include <linux/ipmi.h>
37#include <linux/ipmi_smi.h>
38#include <linux/watchdog.h>
39#include <linux/miscdevice.h>
40#include <linux/init.h>
Corey Minyardd6dfd132006-03-31 02:30:41 -080041#include <linux/completion.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070042#include <linux/rwsem.h>
43#include <linux/errno.h>
44#include <asm/uaccess.h>
45#include <linux/notifier.h>
46#include <linux/nmi.h>
47#include <linux/reboot.h>
48#include <linux/wait.h>
49#include <linux/poll.h>
Corey Minyardcc4673e2005-11-07 00:59:57 -080050#include <linux/string.h>
51#include <linux/ctype.h>
Corey Minyardf64da952007-05-08 00:23:58 -070052#include <linux/delay.h>
Corey Minyardb3856762005-11-07 01:00:05 -080053#include <asm/atomic.h>
Corey Minyardf64da952007-05-08 00:23:58 -070054
55#ifdef CONFIG_X86
56/* This is ugly, but I've determined that x86 is the only architecture
57 that can reasonably support the IPMI NMI watchdog timeout at this
58 time. If another architecture adds this capability somehow, it
59 will have to be a somewhat different mechanism and I have no idea
60 how it will work. So in the unlikely event that another
61 architecture supports this, we can figure out a good generic
62 mechanism for it at that time. */
63#include <asm/kdebug.h>
64#define HAVE_DIE_NMI_POST
Linus Torvalds1da177e2005-04-16 15:20:36 -070065#endif
66
67#define PFX "IPMI Watchdog: "
68
Linus Torvalds1da177e2005-04-16 15:20:36 -070069/*
70 * The IPMI command/response information for the watchdog timer.
71 */
72
73/* values for byte 1 of the set command, byte 2 of the get response. */
74#define WDOG_DONT_LOG (1 << 7)
75#define WDOG_DONT_STOP_ON_SET (1 << 6)
76#define WDOG_SET_TIMER_USE(byte, use) \
77 byte = ((byte) & 0xf8) | ((use) & 0x7)
78#define WDOG_GET_TIMER_USE(byte) ((byte) & 0x7)
79#define WDOG_TIMER_USE_BIOS_FRB2 1
80#define WDOG_TIMER_USE_BIOS_POST 2
81#define WDOG_TIMER_USE_OS_LOAD 3
82#define WDOG_TIMER_USE_SMS_OS 4
83#define WDOG_TIMER_USE_OEM 5
84
85/* values for byte 2 of the set command, byte 3 of the get response. */
86#define WDOG_SET_PRETIMEOUT_ACT(byte, use) \
87 byte = ((byte) & 0x8f) | (((use) & 0x7) << 4)
88#define WDOG_GET_PRETIMEOUT_ACT(byte) (((byte) >> 4) & 0x7)
89#define WDOG_PRETIMEOUT_NONE 0
90#define WDOG_PRETIMEOUT_SMI 1
91#define WDOG_PRETIMEOUT_NMI 2
92#define WDOG_PRETIMEOUT_MSG_INT 3
93
94/* Operations that can be performed on a pretimout. */
95#define WDOG_PREOP_NONE 0
96#define WDOG_PREOP_PANIC 1
97#define WDOG_PREOP_GIVE_DATA 2 /* Cause data to be available to
98 read. Doesn't work in NMI
99 mode. */
100
101/* Actions to perform on a full timeout. */
102#define WDOG_SET_TIMEOUT_ACT(byte, use) \
103 byte = ((byte) & 0xf8) | ((use) & 0x7)
104#define WDOG_GET_TIMEOUT_ACT(byte) ((byte) & 0x7)
105#define WDOG_TIMEOUT_NONE 0
106#define WDOG_TIMEOUT_RESET 1
107#define WDOG_TIMEOUT_POWER_DOWN 2
108#define WDOG_TIMEOUT_POWER_CYCLE 3
109
110/* Byte 3 of the get command, byte 4 of the get response is the
111 pre-timeout in seconds. */
112
113/* Bits for setting byte 4 of the set command, byte 5 of the get response. */
114#define WDOG_EXPIRE_CLEAR_BIOS_FRB2 (1 << 1)
115#define WDOG_EXPIRE_CLEAR_BIOS_POST (1 << 2)
116#define WDOG_EXPIRE_CLEAR_OS_LOAD (1 << 3)
117#define WDOG_EXPIRE_CLEAR_SMS_OS (1 << 4)
118#define WDOG_EXPIRE_CLEAR_OEM (1 << 5)
119
120/* Setting/getting the watchdog timer value. This is for bytes 5 and
121 6 (the timeout time) of the set command, and bytes 6 and 7 (the
122 timeout time) and 8 and 9 (the current countdown value) of the
123 response. The timeout value is given in seconds (in the command it
124 is 100ms intervals). */
125#define WDOG_SET_TIMEOUT(byte1, byte2, val) \
126 (byte1) = (((val) * 10) & 0xff), (byte2) = (((val) * 10) >> 8)
127#define WDOG_GET_TIMEOUT(byte1, byte2) \
128 (((byte1) | ((byte2) << 8)) / 10)
129
130#define IPMI_WDOG_RESET_TIMER 0x22
131#define IPMI_WDOG_SET_TIMER 0x24
132#define IPMI_WDOG_GET_TIMER 0x25
133
134/* These are here until the real ones get into the watchdog.h interface. */
135#ifndef WDIOC_GETTIMEOUT
136#define WDIOC_GETTIMEOUT _IOW(WATCHDOG_IOCTL_BASE, 20, int)
137#endif
138#ifndef WDIOC_SET_PRETIMEOUT
139#define WDIOC_SET_PRETIMEOUT _IOW(WATCHDOG_IOCTL_BASE, 21, int)
140#endif
141#ifndef WDIOC_GET_PRETIMEOUT
142#define WDIOC_GET_PRETIMEOUT _IOW(WATCHDOG_IOCTL_BASE, 22, int)
143#endif
144
Andrey Panin4bfdf372005-07-27 11:43:58 -0700145static int nowayout = WATCHDOG_NOWAYOUT;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700146
Randy Dunlap0c8204b2006-12-10 02:19:06 -0800147static ipmi_user_t watchdog_user;
Corey Minyardb2c03942006-12-06 20:41:00 -0800148static int watchdog_ifnum;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700149
150/* Default the timeout to 10 seconds. */
151static int timeout = 10;
152
153/* The pre-timeout is disabled by default. */
Randy Dunlap0c8204b2006-12-10 02:19:06 -0800154static int pretimeout;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700155
156/* Default action is to reset the board on a timeout. */
157static unsigned char action_val = WDOG_TIMEOUT_RESET;
158
159static char action[16] = "reset";
160
161static unsigned char preaction_val = WDOG_PRETIMEOUT_NONE;
162
163static char preaction[16] = "pre_none";
164
165static unsigned char preop_val = WDOG_PREOP_NONE;
166
167static char preop[16] = "preop_none";
168static DEFINE_SPINLOCK(ipmi_read_lock);
Randy Dunlap0c8204b2006-12-10 02:19:06 -0800169static char data_to_read;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700170static DECLARE_WAIT_QUEUE_HEAD(read_q);
Randy Dunlap0c8204b2006-12-10 02:19:06 -0800171static struct fasync_struct *fasync_q;
172static char pretimeout_since_last_heartbeat;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700173static char expect_close;
174
Corey Minyardb2c03942006-12-06 20:41:00 -0800175static int ifnum_to_use = -1;
176
Corey Minyardcc4673e2005-11-07 00:59:57 -0800177static DECLARE_RWSEM(register_sem);
178
179/* Parameters to ipmi_set_timeout */
180#define IPMI_SET_TIMEOUT_NO_HB 0
181#define IPMI_SET_TIMEOUT_HB_IF_NECESSARY 1
182#define IPMI_SET_TIMEOUT_FORCE_HB 2
183
184static int ipmi_set_timeout(int do_heartbeat);
Corey Minyardb2c03942006-12-06 20:41:00 -0800185static void ipmi_register_watchdog(int ipmi_intf);
186static void ipmi_unregister_watchdog(int ipmi_intf);
Corey Minyardcc4673e2005-11-07 00:59:57 -0800187
Linus Torvalds1da177e2005-04-16 15:20:36 -0700188/* If true, the driver will start running as soon as it is configured
189 and ready. */
Randy Dunlap0c8204b2006-12-10 02:19:06 -0800190static int start_now;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700191
Corey Minyardcc4673e2005-11-07 00:59:57 -0800192static int set_param_int(const char *val, struct kernel_param *kp)
193{
194 char *endp;
195 int l;
196 int rv = 0;
197
198 if (!val)
199 return -EINVAL;
200 l = simple_strtoul(val, &endp, 0);
201 if (endp == val)
202 return -EINVAL;
203
204 down_read(&register_sem);
205 *((int *)kp->arg) = l;
206 if (watchdog_user)
207 rv = ipmi_set_timeout(IPMI_SET_TIMEOUT_HB_IF_NECESSARY);
208 up_read(&register_sem);
209
210 return rv;
211}
212
213static int get_param_int(char *buffer, struct kernel_param *kp)
214{
215 return sprintf(buffer, "%i", *((int *)kp->arg));
216}
217
218typedef int (*action_fn)(const char *intval, char *outval);
219
220static int action_op(const char *inval, char *outval);
221static int preaction_op(const char *inval, char *outval);
222static int preop_op(const char *inval, char *outval);
223static void check_parms(void);
224
225static int set_param_str(const char *val, struct kernel_param *kp)
226{
227 action_fn fn = (action_fn) kp->arg;
228 int rv = 0;
Sebastien Dugué43cdff92006-12-29 16:46:53 -0800229 char valcp[16];
230 char *s;
Corey Minyardcc4673e2005-11-07 00:59:57 -0800231
Sebastien Dugué43cdff92006-12-29 16:46:53 -0800232 strncpy(valcp, val, 16);
233 valcp[15] = '\0';
Pekka Enberg66f969d2006-06-23 02:05:45 -0700234
Sebastien Dugué43cdff92006-12-29 16:46:53 -0800235 s = strstrip(valcp);
Corey Minyardcc4673e2005-11-07 00:59:57 -0800236
237 down_read(&register_sem);
Pekka Enberg66f969d2006-06-23 02:05:45 -0700238 rv = fn(s, NULL);
Corey Minyardcc4673e2005-11-07 00:59:57 -0800239 if (rv)
240 goto out_unlock;
241
242 check_parms();
243 if (watchdog_user)
244 rv = ipmi_set_timeout(IPMI_SET_TIMEOUT_HB_IF_NECESSARY);
245
246 out_unlock:
247 up_read(&register_sem);
248 return rv;
249}
250
251static int get_param_str(char *buffer, struct kernel_param *kp)
252{
253 action_fn fn = (action_fn) kp->arg;
254 int rv;
255
256 rv = fn(NULL, buffer);
257 if (rv)
258 return rv;
259 return strlen(buffer);
260}
261
Corey Minyardb2c03942006-12-06 20:41:00 -0800262
263static int set_param_wdog_ifnum(const char *val, struct kernel_param *kp)
264{
265 int rv = param_set_int(val, kp);
266 if (rv)
267 return rv;
268 if ((ifnum_to_use < 0) || (ifnum_to_use == watchdog_ifnum))
269 return 0;
270
271 ipmi_unregister_watchdog(watchdog_ifnum);
272 ipmi_register_watchdog(ifnum_to_use);
273 return 0;
274}
275
276module_param_call(ifnum_to_use, set_param_wdog_ifnum, get_param_int,
277 &ifnum_to_use, 0644);
278MODULE_PARM_DESC(ifnum_to_use, "The interface number to use for the watchdog "
279 "timer. Setting to -1 defaults to the first registered "
280 "interface");
281
Corey Minyardcc4673e2005-11-07 00:59:57 -0800282module_param_call(timeout, set_param_int, get_param_int, &timeout, 0644);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700283MODULE_PARM_DESC(timeout, "Timeout value in seconds.");
Corey Minyardcc4673e2005-11-07 00:59:57 -0800284
285module_param_call(pretimeout, set_param_int, get_param_int, &pretimeout, 0644);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700286MODULE_PARM_DESC(pretimeout, "Pretimeout value in seconds.");
Corey Minyardcc4673e2005-11-07 00:59:57 -0800287
288module_param_call(action, set_param_str, get_param_str, action_op, 0644);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700289MODULE_PARM_DESC(action, "Timeout action. One of: "
290 "reset, none, power_cycle, power_off.");
Corey Minyardcc4673e2005-11-07 00:59:57 -0800291
292module_param_call(preaction, set_param_str, get_param_str, preaction_op, 0644);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700293MODULE_PARM_DESC(preaction, "Pretimeout action. One of: "
294 "pre_none, pre_smi, pre_nmi, pre_int.");
Corey Minyardcc4673e2005-11-07 00:59:57 -0800295
296module_param_call(preop, set_param_str, get_param_str, preop_op, 0644);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700297MODULE_PARM_DESC(preop, "Pretimeout driver operation. One of: "
298 "preop_none, preop_panic, preop_give_data.");
Corey Minyardcc4673e2005-11-07 00:59:57 -0800299
Corey Minyardb2c03942006-12-06 20:41:00 -0800300module_param(start_now, int, 0444);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700301MODULE_PARM_DESC(start_now, "Set to 1 to start the watchdog as"
302 "soon as the driver is loaded.");
Corey Minyardcc4673e2005-11-07 00:59:57 -0800303
304module_param(nowayout, int, 0644);
Corey Minyardb2c03942006-12-06 20:41:00 -0800305MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started "
306 "(default=CONFIG_WATCHDOG_NOWAYOUT)");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700307
308/* Default state of the timer. */
309static unsigned char ipmi_watchdog_state = WDOG_TIMEOUT_NONE;
310
311/* If shutting down via IPMI, we ignore the heartbeat. */
Randy Dunlap0c8204b2006-12-10 02:19:06 -0800312static int ipmi_ignore_heartbeat;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700313
314/* Is someone using the watchdog? Only one user is allowed. */
Randy Dunlap0c8204b2006-12-10 02:19:06 -0800315static unsigned long ipmi_wdog_open;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700316
317/* If set to 1, the heartbeat command will set the state to reset and
318 start the timer. The timer doesn't normally run when the driver is
319 first opened until the heartbeat is set the first time, this
320 variable is used to accomplish this. */
Randy Dunlap0c8204b2006-12-10 02:19:06 -0800321static int ipmi_start_timer_on_heartbeat;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700322
323/* IPMI version of the BMC. */
324static unsigned char ipmi_version_major;
325static unsigned char ipmi_version_minor;
326
Corey Minyardb3856762005-11-07 01:00:05 -0800327/* If a pretimeout occurs, this is used to allow only one panic to happen. */
328static atomic_t preop_panic_excl = ATOMIC_INIT(-1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700329
Corey Minyardf64da952007-05-08 00:23:58 -0700330#ifdef HAVE_DIE_NMI_POST
331static int testing_nmi;
332static int nmi_handler_registered;
333#endif
334
Linus Torvalds1da177e2005-04-16 15:20:36 -0700335static int ipmi_heartbeat(void);
336static void panic_halt_ipmi_heartbeat(void);
337
338
Corey Minyardd6dfd132006-03-31 02:30:41 -0800339/* We use a mutex to make sure that only one thing can send a set
Linus Torvalds1da177e2005-04-16 15:20:36 -0700340 timeout at one time, because we only have one copy of the data.
Corey Minyardd6dfd132006-03-31 02:30:41 -0800341 The mutex is claimed when the set_timeout is sent and freed
Linus Torvalds1da177e2005-04-16 15:20:36 -0700342 when both messages are free. */
343static atomic_t set_timeout_tofree = ATOMIC_INIT(0);
Corey Minyardd6dfd132006-03-31 02:30:41 -0800344static DEFINE_MUTEX(set_timeout_lock);
345static DECLARE_COMPLETION(set_timeout_wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700346static void set_timeout_free_smi(struct ipmi_smi_msg *msg)
347{
348 if (atomic_dec_and_test(&set_timeout_tofree))
Corey Minyardd6dfd132006-03-31 02:30:41 -0800349 complete(&set_timeout_wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700350}
351static void set_timeout_free_recv(struct ipmi_recv_msg *msg)
352{
353 if (atomic_dec_and_test(&set_timeout_tofree))
Corey Minyardd6dfd132006-03-31 02:30:41 -0800354 complete(&set_timeout_wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700355}
356static struct ipmi_smi_msg set_timeout_smi_msg =
357{
358 .done = set_timeout_free_smi
359};
360static struct ipmi_recv_msg set_timeout_recv_msg =
361{
362 .done = set_timeout_free_recv
363};
364
365static int i_ipmi_set_timeout(struct ipmi_smi_msg *smi_msg,
366 struct ipmi_recv_msg *recv_msg,
367 int *send_heartbeat_now)
368{
369 struct kernel_ipmi_msg msg;
370 unsigned char data[6];
371 int rv;
372 struct ipmi_system_interface_addr addr;
373 int hbnow = 0;
374
375
Corey Minyardf64da952007-05-08 00:23:58 -0700376 /* These can be cleared as we are setting the timeout. */
377 ipmi_start_timer_on_heartbeat = 0;
378 pretimeout_since_last_heartbeat = 0;
379
Linus Torvalds1da177e2005-04-16 15:20:36 -0700380 data[0] = 0;
381 WDOG_SET_TIMER_USE(data[0], WDOG_TIMER_USE_SMS_OS);
382
383 if ((ipmi_version_major > 1)
384 || ((ipmi_version_major == 1) && (ipmi_version_minor >= 5)))
385 {
386 /* This is an IPMI 1.5-only feature. */
387 data[0] |= WDOG_DONT_STOP_ON_SET;
388 } else if (ipmi_watchdog_state != WDOG_TIMEOUT_NONE) {
389 /* In ipmi 1.0, setting the timer stops the watchdog, we
390 need to start it back up again. */
391 hbnow = 1;
392 }
393
394 data[1] = 0;
395 WDOG_SET_TIMEOUT_ACT(data[1], ipmi_watchdog_state);
Corey Minyard8f05ee92005-09-06 15:18:39 -0700396 if ((pretimeout > 0) && (ipmi_watchdog_state != WDOG_TIMEOUT_NONE)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700397 WDOG_SET_PRETIMEOUT_ACT(data[1], preaction_val);
398 data[2] = pretimeout;
399 } else {
400 WDOG_SET_PRETIMEOUT_ACT(data[1], WDOG_PRETIMEOUT_NONE);
401 data[2] = 0; /* No pretimeout. */
402 }
403 data[3] = 0;
404 WDOG_SET_TIMEOUT(data[4], data[5], timeout);
405
406 addr.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE;
407 addr.channel = IPMI_BMC_CHANNEL;
408 addr.lun = 0;
409
410 msg.netfn = 0x06;
411 msg.cmd = IPMI_WDOG_SET_TIMER;
412 msg.data = data;
413 msg.data_len = sizeof(data);
414 rv = ipmi_request_supply_msgs(watchdog_user,
415 (struct ipmi_addr *) &addr,
416 0,
417 &msg,
418 NULL,
419 smi_msg,
420 recv_msg,
421 1);
422 if (rv) {
423 printk(KERN_WARNING PFX "set timeout error: %d\n",
424 rv);
425 }
426
427 if (send_heartbeat_now)
428 *send_heartbeat_now = hbnow;
429
430 return rv;
431}
432
Linus Torvalds1da177e2005-04-16 15:20:36 -0700433static int ipmi_set_timeout(int do_heartbeat)
434{
435 int send_heartbeat_now;
436 int rv;
437
438
439 /* We can only send one of these at a time. */
Corey Minyardd6dfd132006-03-31 02:30:41 -0800440 mutex_lock(&set_timeout_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700441
442 atomic_set(&set_timeout_tofree, 2);
443
444 rv = i_ipmi_set_timeout(&set_timeout_smi_msg,
445 &set_timeout_recv_msg,
446 &send_heartbeat_now);
447 if (rv) {
Corey Minyardd6dfd132006-03-31 02:30:41 -0800448 mutex_unlock(&set_timeout_lock);
449 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700450 }
451
Corey Minyardd6dfd132006-03-31 02:30:41 -0800452 wait_for_completion(&set_timeout_wait);
453
Corey Minyardf64da952007-05-08 00:23:58 -0700454 mutex_unlock(&set_timeout_lock);
455
Corey Minyardd6dfd132006-03-31 02:30:41 -0800456 if ((do_heartbeat == IPMI_SET_TIMEOUT_FORCE_HB)
457 || ((send_heartbeat_now)
458 && (do_heartbeat == IPMI_SET_TIMEOUT_HB_IF_NECESSARY)))
Corey Minyardd6dfd132006-03-31 02:30:41 -0800459 rv = ipmi_heartbeat();
Corey Minyardd6dfd132006-03-31 02:30:41 -0800460
461out:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700462 return rv;
463}
464
465static void dummy_smi_free(struct ipmi_smi_msg *msg)
466{
467}
468static void dummy_recv_free(struct ipmi_recv_msg *msg)
469{
470}
471static struct ipmi_smi_msg panic_halt_smi_msg =
472{
473 .done = dummy_smi_free
474};
475static struct ipmi_recv_msg panic_halt_recv_msg =
476{
477 .done = dummy_recv_free
478};
479
480/* Special call, doesn't claim any locks. This is only to be called
481 at panic or halt time, in run-to-completion mode, when the caller
482 is the only CPU and the only thing that will be going is these IPMI
483 calls. */
484static void panic_halt_ipmi_set_timeout(void)
485{
486 int send_heartbeat_now;
487 int rv;
488
489 rv = i_ipmi_set_timeout(&panic_halt_smi_msg,
490 &panic_halt_recv_msg,
491 &send_heartbeat_now);
492 if (!rv) {
493 if (send_heartbeat_now)
494 panic_halt_ipmi_heartbeat();
495 }
496}
497
498/* We use a semaphore to make sure that only one thing can send a
499 heartbeat at one time, because we only have one copy of the data.
500 The semaphore is claimed when the set_timeout is sent and freed
501 when both messages are free. */
502static atomic_t heartbeat_tofree = ATOMIC_INIT(0);
Corey Minyardd6dfd132006-03-31 02:30:41 -0800503static DEFINE_MUTEX(heartbeat_lock);
504static DECLARE_COMPLETION(heartbeat_wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700505static void heartbeat_free_smi(struct ipmi_smi_msg *msg)
506{
507 if (atomic_dec_and_test(&heartbeat_tofree))
Corey Minyardd6dfd132006-03-31 02:30:41 -0800508 complete(&heartbeat_wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700509}
510static void heartbeat_free_recv(struct ipmi_recv_msg *msg)
511{
512 if (atomic_dec_and_test(&heartbeat_tofree))
Corey Minyardd6dfd132006-03-31 02:30:41 -0800513 complete(&heartbeat_wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700514}
515static struct ipmi_smi_msg heartbeat_smi_msg =
516{
517 .done = heartbeat_free_smi
518};
519static struct ipmi_recv_msg heartbeat_recv_msg =
520{
521 .done = heartbeat_free_recv
522};
523
524static struct ipmi_smi_msg panic_halt_heartbeat_smi_msg =
525{
526 .done = dummy_smi_free
527};
528static struct ipmi_recv_msg panic_halt_heartbeat_recv_msg =
529{
530 .done = dummy_recv_free
531};
532
533static int ipmi_heartbeat(void)
534{
535 struct kernel_ipmi_msg msg;
536 int rv;
537 struct ipmi_system_interface_addr addr;
538
Corey Minyardf64da952007-05-08 00:23:58 -0700539 if (ipmi_ignore_heartbeat)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700540 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700541
542 if (ipmi_start_timer_on_heartbeat) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700543 ipmi_watchdog_state = action_val;
544 return ipmi_set_timeout(IPMI_SET_TIMEOUT_FORCE_HB);
545 } else if (pretimeout_since_last_heartbeat) {
546 /* A pretimeout occurred, make sure we set the timeout.
547 We don't want to set the action, though, we want to
548 leave that alone (thus it can't be combined with the
549 above operation. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700550 return ipmi_set_timeout(IPMI_SET_TIMEOUT_HB_IF_NECESSARY);
551 }
552
Corey Minyardd6dfd132006-03-31 02:30:41 -0800553 mutex_lock(&heartbeat_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700554
555 atomic_set(&heartbeat_tofree, 2);
556
557 /* Don't reset the timer if we have the timer turned off, that
558 re-enables the watchdog. */
559 if (ipmi_watchdog_state == WDOG_TIMEOUT_NONE) {
Corey Minyardd6dfd132006-03-31 02:30:41 -0800560 mutex_unlock(&heartbeat_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700561 return 0;
562 }
563
564 addr.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE;
565 addr.channel = IPMI_BMC_CHANNEL;
566 addr.lun = 0;
567
568 msg.netfn = 0x06;
569 msg.cmd = IPMI_WDOG_RESET_TIMER;
570 msg.data = NULL;
571 msg.data_len = 0;
572 rv = ipmi_request_supply_msgs(watchdog_user,
573 (struct ipmi_addr *) &addr,
574 0,
575 &msg,
576 NULL,
577 &heartbeat_smi_msg,
578 &heartbeat_recv_msg,
579 1);
580 if (rv) {
Corey Minyardd6dfd132006-03-31 02:30:41 -0800581 mutex_unlock(&heartbeat_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700582 printk(KERN_WARNING PFX "heartbeat failure: %d\n",
583 rv);
584 return rv;
585 }
586
587 /* Wait for the heartbeat to be sent. */
Corey Minyardd6dfd132006-03-31 02:30:41 -0800588 wait_for_completion(&heartbeat_wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700589
590 if (heartbeat_recv_msg.msg.data[0] != 0) {
591 /* Got an error in the heartbeat response. It was already
592 reported in ipmi_wdog_msg_handler, but we should return
593 an error here. */
594 rv = -EINVAL;
595 }
596
Corey Minyardd6dfd132006-03-31 02:30:41 -0800597 mutex_unlock(&heartbeat_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700598
599 return rv;
600}
601
602static void panic_halt_ipmi_heartbeat(void)
603{
604 struct kernel_ipmi_msg msg;
605 struct ipmi_system_interface_addr addr;
606
607
608 /* Don't reset the timer if we have the timer turned off, that
609 re-enables the watchdog. */
610 if (ipmi_watchdog_state == WDOG_TIMEOUT_NONE)
611 return;
612
613 addr.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE;
614 addr.channel = IPMI_BMC_CHANNEL;
615 addr.lun = 0;
616
617 msg.netfn = 0x06;
618 msg.cmd = IPMI_WDOG_RESET_TIMER;
619 msg.data = NULL;
620 msg.data_len = 0;
621 ipmi_request_supply_msgs(watchdog_user,
622 (struct ipmi_addr *) &addr,
623 0,
624 &msg,
625 NULL,
626 &panic_halt_heartbeat_smi_msg,
627 &panic_halt_heartbeat_recv_msg,
628 1);
629}
630
Corey Minyard8a3628d2006-03-31 02:30:40 -0800631static struct watchdog_info ident =
Linus Torvalds1da177e2005-04-16 15:20:36 -0700632{
633 .options = 0, /* WDIOF_SETTIMEOUT, */
634 .firmware_version = 1,
635 .identity = "IPMI"
636};
637
638static int ipmi_ioctl(struct inode *inode, struct file *file,
639 unsigned int cmd, unsigned long arg)
640{
641 void __user *argp = (void __user *)arg;
642 int i;
643 int val;
644
645 switch(cmd) {
646 case WDIOC_GETSUPPORT:
647 i = copy_to_user(argp, &ident, sizeof(ident));
648 return i ? -EFAULT : 0;
649
650 case WDIOC_SETTIMEOUT:
651 i = copy_from_user(&val, argp, sizeof(int));
652 if (i)
653 return -EFAULT;
654 timeout = val;
655 return ipmi_set_timeout(IPMI_SET_TIMEOUT_HB_IF_NECESSARY);
656
657 case WDIOC_GETTIMEOUT:
658 i = copy_to_user(argp, &timeout, sizeof(timeout));
659 if (i)
660 return -EFAULT;
661 return 0;
662
663 case WDIOC_SET_PRETIMEOUT:
664 i = copy_from_user(&val, argp, sizeof(int));
665 if (i)
666 return -EFAULT;
667 pretimeout = val;
668 return ipmi_set_timeout(IPMI_SET_TIMEOUT_HB_IF_NECESSARY);
669
670 case WDIOC_GET_PRETIMEOUT:
671 i = copy_to_user(argp, &pretimeout, sizeof(pretimeout));
672 if (i)
673 return -EFAULT;
674 return 0;
675
676 case WDIOC_KEEPALIVE:
677 return ipmi_heartbeat();
678
679 case WDIOC_SETOPTIONS:
680 i = copy_from_user(&val, argp, sizeof(int));
681 if (i)
682 return -EFAULT;
683 if (val & WDIOS_DISABLECARD)
684 {
685 ipmi_watchdog_state = WDOG_TIMEOUT_NONE;
686 ipmi_set_timeout(IPMI_SET_TIMEOUT_NO_HB);
687 ipmi_start_timer_on_heartbeat = 0;
688 }
689
690 if (val & WDIOS_ENABLECARD)
691 {
692 ipmi_watchdog_state = action_val;
693 ipmi_set_timeout(IPMI_SET_TIMEOUT_FORCE_HB);
694 }
695 return 0;
696
697 case WDIOC_GETSTATUS:
698 val = 0;
699 i = copy_to_user(argp, &val, sizeof(val));
700 if (i)
701 return -EFAULT;
702 return 0;
703
704 default:
705 return -ENOIOCTLCMD;
706 }
707}
708
709static ssize_t ipmi_write(struct file *file,
710 const char __user *buf,
711 size_t len,
712 loff_t *ppos)
713{
714 int rv;
715
716 if (len) {
717 if (!nowayout) {
718 size_t i;
719
720 /* In case it was set long ago */
721 expect_close = 0;
722
723 for (i = 0; i != len; i++) {
724 char c;
725
726 if (get_user(c, buf + i))
727 return -EFAULT;
728 if (c == 'V')
729 expect_close = 42;
730 }
731 }
732 rv = ipmi_heartbeat();
733 if (rv)
734 return rv;
735 return 1;
736 }
737 return 0;
738}
739
740static ssize_t ipmi_read(struct file *file,
741 char __user *buf,
742 size_t count,
743 loff_t *ppos)
744{
745 int rv = 0;
746 wait_queue_t wait;
747
748 if (count <= 0)
749 return 0;
750
751 /* Reading returns if the pretimeout has gone off, and it only does
752 it once per pretimeout. */
753 spin_lock(&ipmi_read_lock);
754 if (!data_to_read) {
755 if (file->f_flags & O_NONBLOCK) {
756 rv = -EAGAIN;
757 goto out;
758 }
759
760 init_waitqueue_entry(&wait, current);
761 add_wait_queue(&read_q, &wait);
762 while (!data_to_read) {
763 set_current_state(TASK_INTERRUPTIBLE);
764 spin_unlock(&ipmi_read_lock);
765 schedule();
766 spin_lock(&ipmi_read_lock);
767 }
768 remove_wait_queue(&read_q, &wait);
769
770 if (signal_pending(current)) {
771 rv = -ERESTARTSYS;
772 goto out;
773 }
774 }
775 data_to_read = 0;
776
777 out:
778 spin_unlock(&ipmi_read_lock);
779
780 if (rv == 0) {
781 if (copy_to_user(buf, &data_to_read, 1))
782 rv = -EFAULT;
783 else
784 rv = 1;
785 }
786
787 return rv;
788}
789
790static int ipmi_open(struct inode *ino, struct file *filep)
791{
Corey Minyarde8b33612005-09-06 15:18:45 -0700792 switch (iminor(ino)) {
793 case WATCHDOG_MINOR:
794 if (test_and_set_bit(0, &ipmi_wdog_open))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700795 return -EBUSY;
796
Corey Minyarde8b33612005-09-06 15:18:45 -0700797 /* Don't start the timer now, let it start on the
798 first heartbeat. */
799 ipmi_start_timer_on_heartbeat = 1;
800 return nonseekable_open(ino, filep);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700801
Corey Minyarde8b33612005-09-06 15:18:45 -0700802 default:
803 return (-ENODEV);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700804 }
805}
806
807static unsigned int ipmi_poll(struct file *file, poll_table *wait)
808{
809 unsigned int mask = 0;
810
811 poll_wait(file, &read_q, wait);
812
813 spin_lock(&ipmi_read_lock);
814 if (data_to_read)
815 mask |= (POLLIN | POLLRDNORM);
816 spin_unlock(&ipmi_read_lock);
817
818 return mask;
819}
820
821static int ipmi_fasync(int fd, struct file *file, int on)
822{
823 int result;
824
825 result = fasync_helper(fd, file, on, &fasync_q);
826
827 return (result);
828}
829
830static int ipmi_close(struct inode *ino, struct file *filep)
831{
Corey Minyard8a3628d2006-03-31 02:30:40 -0800832 if (iminor(ino) == WATCHDOG_MINOR) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700833 if (expect_close == 42) {
834 ipmi_watchdog_state = WDOG_TIMEOUT_NONE;
835 ipmi_set_timeout(IPMI_SET_TIMEOUT_NO_HB);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700836 } else {
Corey Minyard8a3628d2006-03-31 02:30:40 -0800837 printk(KERN_CRIT PFX
838 "Unexpected close, not stopping watchdog!\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700839 ipmi_heartbeat();
840 }
Corey Minyardec26d792005-05-01 08:59:11 -0700841 clear_bit(0, &ipmi_wdog_open);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700842 }
843
844 ipmi_fasync (-1, filep, 0);
845 expect_close = 0;
846
847 return 0;
848}
849
Arjan van de Ven62322d22006-07-03 00:24:21 -0700850static const struct file_operations ipmi_wdog_fops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700851 .owner = THIS_MODULE,
852 .read = ipmi_read,
853 .poll = ipmi_poll,
854 .write = ipmi_write,
855 .ioctl = ipmi_ioctl,
856 .open = ipmi_open,
857 .release = ipmi_close,
858 .fasync = ipmi_fasync,
859};
860
861static struct miscdevice ipmi_wdog_miscdev = {
862 .minor = WATCHDOG_MINOR,
863 .name = "watchdog",
864 .fops = &ipmi_wdog_fops
865};
866
Linus Torvalds1da177e2005-04-16 15:20:36 -0700867static void ipmi_wdog_msg_handler(struct ipmi_recv_msg *msg,
868 void *handler_data)
869{
870 if (msg->msg.data[0] != 0) {
871 printk(KERN_ERR PFX "response: Error %x on cmd %x\n",
872 msg->msg.data[0],
873 msg->msg.cmd);
874 }
875
876 ipmi_free_recv_msg(msg);
877}
878
879static void ipmi_wdog_pretimeout_handler(void *handler_data)
880{
881 if (preaction_val != WDOG_PRETIMEOUT_NONE) {
Corey Minyardb3856762005-11-07 01:00:05 -0800882 if (preop_val == WDOG_PREOP_PANIC) {
883 if (atomic_inc_and_test(&preop_panic_excl))
884 panic("Watchdog pre-timeout");
885 } else if (preop_val == WDOG_PREOP_GIVE_DATA) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700886 spin_lock(&ipmi_read_lock);
887 data_to_read = 1;
888 wake_up_interruptible(&read_q);
889 kill_fasync(&fasync_q, SIGIO, POLL_IN);
890
891 spin_unlock(&ipmi_read_lock);
892 }
893 }
894
895 /* On some machines, the heartbeat will give
896 an error and not work unless we re-enable
897 the timer. So do so. */
898 pretimeout_since_last_heartbeat = 1;
899}
900
901static struct ipmi_user_hndl ipmi_hndlrs =
902{
903 .ipmi_recv_hndl = ipmi_wdog_msg_handler,
904 .ipmi_watchdog_pretimeout = ipmi_wdog_pretimeout_handler
905};
906
907static void ipmi_register_watchdog(int ipmi_intf)
908{
909 int rv = -EBUSY;
910
911 down_write(&register_sem);
912 if (watchdog_user)
913 goto out;
914
Corey Minyardb2c03942006-12-06 20:41:00 -0800915 if ((ifnum_to_use >= 0) && (ifnum_to_use != ipmi_intf))
916 goto out;
917
918 watchdog_ifnum = ipmi_intf;
919
Linus Torvalds1da177e2005-04-16 15:20:36 -0700920 rv = ipmi_create_user(ipmi_intf, &ipmi_hndlrs, NULL, &watchdog_user);
921 if (rv < 0) {
922 printk(KERN_CRIT PFX "Unable to register with ipmi\n");
923 goto out;
924 }
925
926 ipmi_get_version(watchdog_user,
927 &ipmi_version_major,
928 &ipmi_version_minor);
929
930 rv = misc_register(&ipmi_wdog_miscdev);
931 if (rv < 0) {
932 ipmi_destroy_user(watchdog_user);
933 watchdog_user = NULL;
934 printk(KERN_CRIT PFX "Unable to register misc device\n");
935 }
936
Corey Minyardf64da952007-05-08 00:23:58 -0700937#ifdef HAVE_DIE_NMI_POST
938 if (nmi_handler_registered) {
939 int old_pretimeout = pretimeout;
940 int old_timeout = timeout;
941 int old_preop_val = preop_val;
942
943 /* Set the pretimeout to go off in a second and give
944 ourselves plenty of time to stop the timer. */
945 ipmi_watchdog_state = WDOG_TIMEOUT_RESET;
946 preop_val = WDOG_PREOP_NONE; /* Make sure nothing happens */
947 pretimeout = 99;
948 timeout = 100;
949
950 testing_nmi = 1;
951
952 rv = ipmi_set_timeout(IPMI_SET_TIMEOUT_FORCE_HB);
953 if (rv) {
954 printk(KERN_WARNING PFX "Error starting timer to"
955 " test NMI: 0x%x. The NMI pretimeout will"
956 " likely not work\n", rv);
957 rv = 0;
958 goto out_restore;
959 }
960
961 msleep(1500);
962
963 if (testing_nmi != 2) {
964 printk(KERN_WARNING PFX "IPMI NMI didn't seem to"
965 " occur. The NMI pretimeout will"
966 " likely not work\n");
967 }
968 out_restore:
969 testing_nmi = 0;
970 preop_val = old_preop_val;
971 pretimeout = old_pretimeout;
972 timeout = old_timeout;
973 }
974#endif
975
Linus Torvalds1da177e2005-04-16 15:20:36 -0700976 out:
977 up_write(&register_sem);
978
979 if ((start_now) && (rv == 0)) {
980 /* Run from startup, so start the timer now. */
981 start_now = 0; /* Disable this function after first startup. */
982 ipmi_watchdog_state = action_val;
983 ipmi_set_timeout(IPMI_SET_TIMEOUT_FORCE_HB);
984 printk(KERN_INFO PFX "Starting now!\n");
Corey Minyardf64da952007-05-08 00:23:58 -0700985 } else {
986 /* Stop the timer now. */
987 ipmi_watchdog_state = WDOG_TIMEOUT_NONE;
988 ipmi_set_timeout(IPMI_SET_TIMEOUT_NO_HB);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700989 }
990}
991
Corey Minyardb2c03942006-12-06 20:41:00 -0800992static void ipmi_unregister_watchdog(int ipmi_intf)
993{
994 int rv;
995
996 down_write(&register_sem);
997
998 if (!watchdog_user)
999 goto out;
1000
1001 if (watchdog_ifnum != ipmi_intf)
1002 goto out;
1003
1004 /* Make sure no one can call us any more. */
1005 misc_deregister(&ipmi_wdog_miscdev);
1006
1007 /* Wait to make sure the message makes it out. The lower layer has
1008 pointers to our buffers, we want to make sure they are done before
1009 we release our memory. */
1010 while (atomic_read(&set_timeout_tofree))
1011 schedule_timeout_uninterruptible(1);
1012
1013 /* Disconnect from IPMI. */
1014 rv = ipmi_destroy_user(watchdog_user);
1015 if (rv) {
1016 printk(KERN_WARNING PFX "error unlinking from IPMI: %d\n",
1017 rv);
1018 }
1019 watchdog_user = NULL;
1020
1021 out:
1022 up_write(&register_sem);
1023}
1024
Corey Minyardf64da952007-05-08 00:23:58 -07001025#ifdef HAVE_DIE_NMI_POST
Linus Torvalds1da177e2005-04-16 15:20:36 -07001026static int
Corey Minyardf64da952007-05-08 00:23:58 -07001027ipmi_nmi(struct notifier_block *self, unsigned long val, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001028{
Corey Minyardf64da952007-05-08 00:23:58 -07001029 if (val != DIE_NMI_POST)
1030 return NOTIFY_OK;
1031
1032 if (testing_nmi) {
1033 testing_nmi = 2;
1034 return NOTIFY_STOP;
1035 }
1036
Corey Minyard8f05ee92005-09-06 15:18:39 -07001037 /* If we are not expecting a timeout, ignore it. */
1038 if (ipmi_watchdog_state == WDOG_TIMEOUT_NONE)
Corey Minyardf64da952007-05-08 00:23:58 -07001039 return NOTIFY_OK;
1040
1041 if (preaction_val != WDOG_PRETIMEOUT_NMI)
1042 return NOTIFY_OK;
Corey Minyard8f05ee92005-09-06 15:18:39 -07001043
Linus Torvalds1da177e2005-04-16 15:20:36 -07001044 /* If no one else handled the NMI, we assume it was the IPMI
1045 watchdog. */
Corey Minyardf64da952007-05-08 00:23:58 -07001046 if (preop_val == WDOG_PREOP_PANIC) {
Corey Minyard8f05ee92005-09-06 15:18:39 -07001047 /* On some machines, the heartbeat will give
1048 an error and not work unless we re-enable
1049 the timer. So do so. */
1050 pretimeout_since_last_heartbeat = 1;
Corey Minyardb3856762005-11-07 01:00:05 -08001051 if (atomic_inc_and_test(&preop_panic_excl))
1052 panic(PFX "pre-timeout");
Corey Minyard8f05ee92005-09-06 15:18:39 -07001053 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001054
Corey Minyardf64da952007-05-08 00:23:58 -07001055 return NOTIFY_STOP;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001056}
1057
Corey Minyardf64da952007-05-08 00:23:58 -07001058static struct notifier_block ipmi_nmi_handler = {
1059 .notifier_call = ipmi_nmi
Linus Torvalds1da177e2005-04-16 15:20:36 -07001060};
1061#endif
1062
1063static int wdog_reboot_handler(struct notifier_block *this,
1064 unsigned long code,
1065 void *unused)
1066{
1067 static int reboot_event_handled = 0;
1068
1069 if ((watchdog_user) && (!reboot_event_handled)) {
1070 /* Make sure we only do this once. */
1071 reboot_event_handled = 1;
1072
1073 if (code == SYS_DOWN || code == SYS_HALT) {
1074 /* Disable the WDT if we are shutting down. */
1075 ipmi_watchdog_state = WDOG_TIMEOUT_NONE;
1076 panic_halt_ipmi_set_timeout();
Corey Minyard96febe92006-06-28 04:26:55 -07001077 } else if (ipmi_watchdog_state != WDOG_TIMEOUT_NONE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001078 /* Set a long timer to let the reboot happens, but
Corey Minyard96febe92006-06-28 04:26:55 -07001079 reboot if it hangs, but only if the watchdog
1080 timer was already running. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001081 timeout = 120;
1082 pretimeout = 0;
1083 ipmi_watchdog_state = WDOG_TIMEOUT_RESET;
1084 panic_halt_ipmi_set_timeout();
1085 }
1086 }
1087 return NOTIFY_OK;
1088}
1089
1090static struct notifier_block wdog_reboot_notifier = {
1091 .notifier_call = wdog_reboot_handler,
1092 .next = NULL,
1093 .priority = 0
1094};
1095
1096static int wdog_panic_handler(struct notifier_block *this,
1097 unsigned long event,
1098 void *unused)
1099{
1100 static int panic_event_handled = 0;
1101
Corey Minyard96febe92006-06-28 04:26:55 -07001102 /* On a panic, if we have a panic timeout, make sure to extend
1103 the watchdog timer to a reasonable value to complete the
1104 panic, if the watchdog timer is running. Plus the
1105 pretimeout is meaningless at panic time. */
1106 if (watchdog_user && !panic_event_handled &&
1107 ipmi_watchdog_state != WDOG_TIMEOUT_NONE) {
1108 /* Make sure we do this only once. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001109 panic_event_handled = 1;
1110
1111 timeout = 255;
1112 pretimeout = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001113 panic_halt_ipmi_set_timeout();
1114 }
1115
1116 return NOTIFY_OK;
1117}
1118
1119static struct notifier_block wdog_panic_notifier = {
1120 .notifier_call = wdog_panic_handler,
1121 .next = NULL,
1122 .priority = 150 /* priority: INT_MAX >= x >= 0 */
1123};
1124
1125
Corey Minyard50c812b2006-03-26 01:37:21 -08001126static void ipmi_new_smi(int if_num, struct device *device)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001127{
1128 ipmi_register_watchdog(if_num);
1129}
1130
1131static void ipmi_smi_gone(int if_num)
1132{
Corey Minyardb2c03942006-12-06 20:41:00 -08001133 ipmi_unregister_watchdog(if_num);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001134}
1135
1136static struct ipmi_smi_watcher smi_watcher =
1137{
1138 .owner = THIS_MODULE,
1139 .new_smi = ipmi_new_smi,
1140 .smi_gone = ipmi_smi_gone
1141};
1142
Corey Minyardcc4673e2005-11-07 00:59:57 -08001143static int action_op(const char *inval, char *outval)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001144{
Corey Minyardcc4673e2005-11-07 00:59:57 -08001145 if (outval)
1146 strcpy(outval, action);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001147
Corey Minyardcc4673e2005-11-07 00:59:57 -08001148 if (!inval)
1149 return 0;
1150
1151 if (strcmp(inval, "reset") == 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001152 action_val = WDOG_TIMEOUT_RESET;
Corey Minyardcc4673e2005-11-07 00:59:57 -08001153 else if (strcmp(inval, "none") == 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001154 action_val = WDOG_TIMEOUT_NONE;
Corey Minyardcc4673e2005-11-07 00:59:57 -08001155 else if (strcmp(inval, "power_cycle") == 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001156 action_val = WDOG_TIMEOUT_POWER_CYCLE;
Corey Minyardcc4673e2005-11-07 00:59:57 -08001157 else if (strcmp(inval, "power_off") == 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001158 action_val = WDOG_TIMEOUT_POWER_DOWN;
Corey Minyardcc4673e2005-11-07 00:59:57 -08001159 else
1160 return -EINVAL;
1161 strcpy(action, inval);
1162 return 0;
1163}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001164
Corey Minyardcc4673e2005-11-07 00:59:57 -08001165static int preaction_op(const char *inval, char *outval)
1166{
1167 if (outval)
1168 strcpy(outval, preaction);
1169
1170 if (!inval)
1171 return 0;
1172
1173 if (strcmp(inval, "pre_none") == 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001174 preaction_val = WDOG_PRETIMEOUT_NONE;
Corey Minyardcc4673e2005-11-07 00:59:57 -08001175 else if (strcmp(inval, "pre_smi") == 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001176 preaction_val = WDOG_PRETIMEOUT_SMI;
Corey Minyardf64da952007-05-08 00:23:58 -07001177#ifdef HAVE_DIE_NMI_POST
Corey Minyardcc4673e2005-11-07 00:59:57 -08001178 else if (strcmp(inval, "pre_nmi") == 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001179 preaction_val = WDOG_PRETIMEOUT_NMI;
1180#endif
Corey Minyardcc4673e2005-11-07 00:59:57 -08001181 else if (strcmp(inval, "pre_int") == 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001182 preaction_val = WDOG_PRETIMEOUT_MSG_INT;
Corey Minyardcc4673e2005-11-07 00:59:57 -08001183 else
1184 return -EINVAL;
1185 strcpy(preaction, inval);
1186 return 0;
1187}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001188
Corey Minyardcc4673e2005-11-07 00:59:57 -08001189static int preop_op(const char *inval, char *outval)
1190{
1191 if (outval)
1192 strcpy(outval, preop);
1193
1194 if (!inval)
1195 return 0;
1196
1197 if (strcmp(inval, "preop_none") == 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001198 preop_val = WDOG_PREOP_NONE;
Corey Minyardcc4673e2005-11-07 00:59:57 -08001199 else if (strcmp(inval, "preop_panic") == 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001200 preop_val = WDOG_PREOP_PANIC;
Corey Minyardcc4673e2005-11-07 00:59:57 -08001201 else if (strcmp(inval, "preop_give_data") == 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001202 preop_val = WDOG_PREOP_GIVE_DATA;
Corey Minyardcc4673e2005-11-07 00:59:57 -08001203 else
1204 return -EINVAL;
1205 strcpy(preop, inval);
1206 return 0;
1207}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001208
Corey Minyardcc4673e2005-11-07 00:59:57 -08001209static void check_parms(void)
1210{
Corey Minyardf64da952007-05-08 00:23:58 -07001211#ifdef HAVE_DIE_NMI_POST
Corey Minyardcc4673e2005-11-07 00:59:57 -08001212 int do_nmi = 0;
1213 int rv;
1214
Linus Torvalds1da177e2005-04-16 15:20:36 -07001215 if (preaction_val == WDOG_PRETIMEOUT_NMI) {
Corey Minyardcc4673e2005-11-07 00:59:57 -08001216 do_nmi = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001217 if (preop_val == WDOG_PREOP_GIVE_DATA) {
1218 printk(KERN_WARNING PFX "Pretimeout op is to give data"
1219 " but NMI pretimeout is enabled, setting"
1220 " pretimeout op to none\n");
Corey Minyardcc4673e2005-11-07 00:59:57 -08001221 preop_op("preop_none", NULL);
1222 do_nmi = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001223 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001224 }
Corey Minyardcc4673e2005-11-07 00:59:57 -08001225 if (do_nmi && !nmi_handler_registered) {
Corey Minyardf64da952007-05-08 00:23:58 -07001226 rv = register_die_notifier(&ipmi_nmi_handler);
Corey Minyardcc4673e2005-11-07 00:59:57 -08001227 if (rv) {
1228 printk(KERN_WARNING PFX
1229 "Can't register nmi handler\n");
1230 return;
1231 } else
1232 nmi_handler_registered = 1;
1233 } else if (!do_nmi && nmi_handler_registered) {
Corey Minyardf64da952007-05-08 00:23:58 -07001234 unregister_die_notifier(&ipmi_nmi_handler);
Corey Minyardcc4673e2005-11-07 00:59:57 -08001235 nmi_handler_registered = 0;
1236 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001237#endif
Corey Minyardcc4673e2005-11-07 00:59:57 -08001238}
1239
1240static int __init ipmi_wdog_init(void)
1241{
1242 int rv;
1243
1244 if (action_op(action, NULL)) {
1245 action_op("reset", NULL);
1246 printk(KERN_INFO PFX "Unknown action '%s', defaulting to"
1247 " reset\n", action);
1248 }
1249
1250 if (preaction_op(preaction, NULL)) {
1251 preaction_op("pre_none", NULL);
1252 printk(KERN_INFO PFX "Unknown preaction '%s', defaulting to"
1253 " none\n", preaction);
1254 }
1255
1256 if (preop_op(preop, NULL)) {
1257 preop_op("preop_none", NULL);
1258 printk(KERN_INFO PFX "Unknown preop '%s', defaulting to"
1259 " none\n", preop);
1260 }
1261
1262 check_parms();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001263
Corey Minyardb2c03942006-12-06 20:41:00 -08001264 register_reboot_notifier(&wdog_reboot_notifier);
1265 atomic_notifier_chain_register(&panic_notifier_list,
1266 &wdog_panic_notifier);
1267
Linus Torvalds1da177e2005-04-16 15:20:36 -07001268 rv = ipmi_smi_watcher_register(&smi_watcher);
1269 if (rv) {
Corey Minyardf64da952007-05-08 00:23:58 -07001270#ifdef HAVE_DIE_NMI_POST
1271 if (nmi_handler_registered)
1272 unregister_die_notifier(&ipmi_nmi_handler);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001273#endif
Corey Minyardb2c03942006-12-06 20:41:00 -08001274 atomic_notifier_chain_unregister(&panic_notifier_list,
1275 &wdog_panic_notifier);
1276 unregister_reboot_notifier(&wdog_reboot_notifier);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001277 printk(KERN_WARNING PFX "can't register smi watcher\n");
1278 return rv;
1279 }
1280
Corey Minyard1fdd75b2005-09-06 15:18:42 -07001281 printk(KERN_INFO PFX "driver initialized\n");
1282
Linus Torvalds1da177e2005-04-16 15:20:36 -07001283 return 0;
1284}
1285
Corey Minyardb2c03942006-12-06 20:41:00 -08001286static void __exit ipmi_wdog_exit(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001287{
Corey Minyardb2c03942006-12-06 20:41:00 -08001288 ipmi_smi_watcher_unregister(&smi_watcher);
1289 ipmi_unregister_watchdog(watchdog_ifnum);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001290
Corey Minyardf64da952007-05-08 00:23:58 -07001291#ifdef HAVE_DIE_NMI_POST
Corey Minyardcc4673e2005-11-07 00:59:57 -08001292 if (nmi_handler_registered)
Corey Minyardf64da952007-05-08 00:23:58 -07001293 unregister_die_notifier(&ipmi_nmi_handler);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001294#endif
1295
Alan Sterne041c682006-03-27 01:16:30 -08001296 atomic_notifier_chain_unregister(&panic_notifier_list,
Corey Minyardb2c03942006-12-06 20:41:00 -08001297 &wdog_panic_notifier);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001298 unregister_reboot_notifier(&wdog_reboot_notifier);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001299}
1300module_exit(ipmi_wdog_exit);
1301module_init(ipmi_wdog_init);
1302MODULE_LICENSE("GPL");
Corey Minyard1fdd75b2005-09-06 15:18:42 -07001303MODULE_AUTHOR("Corey Minyard <minyard@mvista.com>");
1304MODULE_DESCRIPTION("watchdog timer based upon the IPMI interface.");