/*
* A watchdog timer based upon the IPMI interface.
*/
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/ipmi.h>
#include <linux/ipmi_smi.h>
#include <linux/mutex.h>
#include <linux/watchdog.h>
#include <linux/miscdevice.h>
#include <linux/init.h>
#include <linux/completion.h>
#include <linux/kdebug.h>
#include <linux/rwsem.h>
#include <linux/errno.h>
#include <asm/uaccess.h>
#include <linux/notifier.h>
#include <linux/nmi.h>
#include <linux/reboot.h>
#include <linux/wait.h>
#include <linux/poll.h>
#include <linux/string.h>
#include <linux/ctype.h>
#include <linux/delay.h>
#include <linux/atomic.h>
#ifdef CONFIG_X86
/*
* This is ugly, but I've determined that x86 is the only architecture
* that can reasonably support the IPMI NMI watchdog timeout at this
* time. If another architecture adds this capability somehow, it
* will have to be a somewhat different mechanism and I have no idea
* how it will work. So in the unlikely event that another
* architecture supports this, we can figure out a good generic
* mechanism for it at that time.
*/
#include <asm/kdebug.h>
#include <asm/nmi.h>
#define HAVE_DIE_NMI
#endif
#define PFX "IPMI Watchdog: "
/*
* The IPMI command/response information for the watchdog timer.
*/
/* values for byte 1 of the set command, byte 2 of the get response. */
#define WDOG_DONT_LOG (1 << 7)
#define WDOG_DONT_STOP_ON_SET (1 << 6)
#define WDOG_SET_TIMER_USE(byte, use) \
byte = ((byte) & 0xf8) | ((use) & 0x7)
#define WDOG_GET_TIMER_USE(byte) ((byte) & 0x7)
#define WDOG_TIMER_USE_BIOS_FRB2 1
#define WDOG_TIMER_USE_BIOS_POST 2
#define WDOG_TIMER_USE_OS_LOAD 3
#define WDOG_TIMER_USE_SMS_OS 4
#define WDOG_TIMER_USE_OEM 5
/* values for byte 2 of the set command, byte 3 of the get response. */
#define WDOG_SET_PRETIMEOUT_ACT(byte, use) \
byte = ((byte) & 0x8f) | (((use) & 0x7) << 4)
#define WDOG_GET_PRETIMEOUT_ACT(byte) (((byte) >> 4) & 0x7)
#define WDOG_PRETIMEOUT_NONE 0
#define WDOG_PRETIMEOUT_SMI 1
#define WDOG_PRETIMEOUT_NMI 2
#define WDOG_PRETIMEOUT_MSG_INT 3
/* Operations that can be performed on a pretimout. */
#define WDOG_PREOP_NONE 0
#define WDOG_PREOP_PANIC 1
/* Cause data to be available to read. Doesn't work in NMI mode. */
#define WDOG_PREOP_GIVE_DATA 2
/* Actions to perform on a full timeout. */
#define WDOG_SET_TIMEOUT_ACT(byte, use) \
byte = ((byte) & 0xf8) | ((use) & 0x7)
#define WDOG_GET_TIMEOUT_ACT(byte) ((byte) & 0x7)
#define WDOG_TIMEOUT_NONE 0
#define WDOG_TIMEOUT_RESET 1
#define WDOG_TIMEOUT_POWER_DOWN 2
#define WDOG_TIMEOUT_POWER_CYCLE 3
/*
* Byte 3 of the get command, byte 4 of the get response is the
* pre-timeout in seconds.
*/
/* Bits for setting byte 4 of the set command, byte 5 of the get response. */
#define WDOG_EXPIRE_CLEAR_BIOS_FRB2 (1 << 1)
#define WDOG_EXPIRE_CLEAR_BIOS_POST (1 << 2)
#define WDOG_EXPIRE_CLEAR_OS_LOAD (1 << 3)
#define WDOG_EXPIRE_CLEAR_SMS_OS (1 << 4)
#define WDOG_EXPIRE_CLEAR_OEM (1 << 5)
/*
* Setting/getting the watchdog timer value. This is for bytes 5 and
* 6 (the timeout time) of the set command, and bytes 6 and 7 (the
* timeout time) and 8 and 9 (the current countdown value) of the
* response. The timeout value is given in seconds (in the command it
* is 100ms intervals).
*/
#define WDOG_SET_TIMEOUT(byte1, byte2, val) \
(byte1) = (((val) * 10) & 0xff), (byte2) = (((val) * 10) >> 8)
#define WDOG_GET_TIMEOUT(byte1, byte2) \
(((byte1) | ((byte2) << 8)) / 10)
#define IPMI_WDOG_RESET_TIMER 0x22
#define IPMI_WDOG_SET_TIMER 0x24
#define IPMI_WDOG_GET_TIMER 0x25
#define IPMI_WDOG_TIMER_NOT_INIT_RESP 0x80
static DEFINE_MUTEX(ipmi_watchdog_mutex);
static bool nowayout = WATCHDOG_NOWAYOUT;
static ipmi_user_t watchdog_user;
static int watchdog_ifnum;
/* Default the timeout to 10 seconds. */
static int timeout = 10;
/* The pre-timeout is disabled by default. */
static int pretimeout;
/* Default action is to reset the board on a timeout. */
static unsigned char action_val = WDOG_TIMEOUT_RESET;
static char action[16] = "reset";
static unsigned char preaction_val = WDOG_PRETIMEOUT_NONE;
static char preaction[16] = "pre_none";
static unsigned char preop_val = WDOG_PREOP_NONE;
static char preop[16] = "preop_none";
static DEFINE_SPINLOCK(ipmi_read_lock);
static char data_to_read;
static DECLARE_WAIT_QUEUE_HEAD(read_q);
static struct fasync_struct *fasync_q;
static char pretimeout_since_last_heartbeat;
static char expect_close;
static int ifnum_to_use = -1;
/* Parameters to ipmi_set_timeout */
#define IPMI_SET_TIMEOUT_NO_HB 0
#define IPMI_SET_TIMEOUT_HB_IF_NECESSARY 1
#define IPMI_SET_TIMEOUT_FORCE_HB 2
static int ipmi_set_timeout(int do_heartbeat);
static void ipmi_register_watchdog(int ipmi_intf);
static void ipmi_unregister_watchdog(int ipmi_intf);
/*
* If true, the driver will start running as soon as it is configured
* and ready.
*/
static int start_now;
static int set_param_timeout(const char *val, const struct kernel_param *kp)
{
char *endp;
int l;
int rv = 0;
if (!val)
return -EINVAL;
l = simple_strtoul(val, &endp, 0);
if (endp == val)
return -EINVAL;
*((int *)kp->arg) = l;
if (watchdog_user)
rv = ipmi_set_timeout(IPMI_SET_TIMEOUT_HB_IF_NECESSARY);
return rv;
}
static struct kernel_param_ops param_ops_timeout = {
.set = set_param_timeout,
.get = param_get_int,
};
#define param_check_timeout param_check_int
typedef int (*action_fn)(const char *intval, char *outval);
static int action_op(const char *inval, char *outval);
static int preaction_op(const char *inval, char *outval);
static int preop_op(const char *inval, char *outval);
static void check_parms(void);
static int set_param_str(const char *val, const struct kernel_param *kp)
{
action_fn fn = (action_fn) kp->arg;
int rv = 0;
char valcp[16];
char *s;
strncpy(valcp, val, 16);
valcp[15] = '\0';
s = strstrip(valcp);
rv = fn(s, NULL);
if (rv)
goto out;
check_parms();
if (watchdog_user)
rv = ipmi_set_timeout(IPMI_SET_TIMEOUT_HB_IF_NECESSARY);
out:
return rv;
}
static int get_param_str(char *buffer, const struct kernel_param *kp)
{
action_fn fn = (action_fn) kp->arg;
int rv;
rv = fn(NULL, buffer);
if (rv)
return rv;
return strlen(buffer);
}
static int set_param_wdog_ifnum(const char *val, const struct kernel_param *kp)
{
int rv = param_set_int(val, kp);
if (rv)
return rv;
if ((ifnum_to_use < 0) || (ifnum_to_use == watchdog_ifnum))
return 0;
ipmi_unregister_watchdog(watchdog_ifnum);
ipmi_register_watchdog(ifnum_to_use);
return 0;
}
static struct kernel_param_ops param_ops_wdog_ifnum = {
.set = set_param_wdog_ifnum,
.get = param_get_int,
};
#define param_check_wdog_ifnum param_check_int
static struct kernel_param_ops param_ops_str = {
.set = set_param_str,
.get = get_param_str,
};
module_param(ifnum_to_use, wdog_ifnum, 0644);
MODULE_PARM_DESC(ifnum_to_use, "The interface number to use for the watchdog "
"timer. Setting to -1 defaults to the first registered "
"interface");
module_param(timeout, timeout, 0644);
MODULE_PARM_DESC(timeout, "Timeout value in seconds.");
module_param(pretimeout, timeout, 0644);
MODULE_PARM_DESC(pretimeout, "Pretimeout value in seconds.");
module_param_cb(action, ¶m_ops_str, action_op, 0644);
MODULE_PARM_DESC(action, "Timeout action. One of: "
"reset, none, power_cycle, power_off.");
module_param_cb(preaction, ¶m_ops_str, preaction_op, 0644);
MODULE_PARM_DESC(preaction, "Pretimeout action. One of: "
"pre_none, pre_smi, pre_nmi, pre_int.");
module_param_cb(preop, ¶m_ops_str, preop_op, 0644);
MODULE_PARM_DESC(preop, "Pretimeout driver operation. One of: "
"preop_none, preop_panic, preop_give_data.");
module_param(start_now, int, 0444);
MODULE_PARM_DESC(start_now, "Set to 1 to start the watchdog as"
"soon as the driver is loaded.");
module_param(nowayout, bool, 0644);
MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started "
"(default=CONFIG_WATCHDOG_NOWAYOUT)");