|
@@ -54,13 +54,15 @@
|
|
#include <asm/atomic.h>
|
|
#include <asm/atomic.h>
|
|
|
|
|
|
#ifdef CONFIG_X86
|
|
#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. */
|
|
|
|
|
|
+/*
|
|
|
|
+ * 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/kdebug.h>
|
|
#define HAVE_DIE_NMI
|
|
#define HAVE_DIE_NMI
|
|
#endif
|
|
#endif
|
|
@@ -95,9 +97,8 @@
|
|
/* Operations that can be performed on a pretimout. */
|
|
/* Operations that can be performed on a pretimout. */
|
|
#define WDOG_PREOP_NONE 0
|
|
#define WDOG_PREOP_NONE 0
|
|
#define WDOG_PREOP_PANIC 1
|
|
#define WDOG_PREOP_PANIC 1
|
|
-#define WDOG_PREOP_GIVE_DATA 2 /* Cause data to be available to
|
|
|
|
- read. Doesn't work in NMI
|
|
|
|
- mode. */
|
|
|
|
|
|
+/* 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. */
|
|
/* Actions to perform on a full timeout. */
|
|
#define WDOG_SET_TIMEOUT_ACT(byte, use) \
|
|
#define WDOG_SET_TIMEOUT_ACT(byte, use) \
|
|
@@ -108,8 +109,10 @@
|
|
#define WDOG_TIMEOUT_POWER_DOWN 2
|
|
#define WDOG_TIMEOUT_POWER_DOWN 2
|
|
#define WDOG_TIMEOUT_POWER_CYCLE 3
|
|
#define WDOG_TIMEOUT_POWER_CYCLE 3
|
|
|
|
|
|
-/* Byte 3 of the get command, byte 4 of the get response is the
|
|
|
|
- pre-timeout in seconds. */
|
|
|
|
|
|
+/*
|
|
|
|
+ * 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. */
|
|
/* 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_FRB2 (1 << 1)
|
|
@@ -118,11 +121,13 @@
|
|
#define WDOG_EXPIRE_CLEAR_SMS_OS (1 << 4)
|
|
#define WDOG_EXPIRE_CLEAR_SMS_OS (1 << 4)
|
|
#define WDOG_EXPIRE_CLEAR_OEM (1 << 5)
|
|
#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). */
|
|
|
|
|
|
+/*
|
|
|
|
+ * 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) \
|
|
#define WDOG_SET_TIMEOUT(byte1, byte2, val) \
|
|
(byte1) = (((val) * 10) & 0xff), (byte2) = (((val) * 10) >> 8)
|
|
(byte1) = (((val) * 10) & 0xff), (byte2) = (((val) * 10) >> 8)
|
|
#define WDOG_GET_TIMEOUT(byte1, byte2) \
|
|
#define WDOG_GET_TIMEOUT(byte1, byte2) \
|
|
@@ -184,8 +189,10 @@ static int ipmi_set_timeout(int do_heartbeat);
|
|
static void ipmi_register_watchdog(int ipmi_intf);
|
|
static void ipmi_register_watchdog(int ipmi_intf);
|
|
static void ipmi_unregister_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. */
|
|
|
|
|
|
+/*
|
|
|
|
+ * If true, the driver will start running as soon as it is configured
|
|
|
|
+ * and ready.
|
|
|
|
+ */
|
|
static int start_now;
|
|
static int start_now;
|
|
|
|
|
|
static int set_param_int(const char *val, struct kernel_param *kp)
|
|
static int set_param_int(const char *val, struct kernel_param *kp)
|
|
@@ -309,10 +316,12 @@ static int ipmi_ignore_heartbeat;
|
|
/* Is someone using the watchdog? Only one user is allowed. */
|
|
/* Is someone using the watchdog? Only one user is allowed. */
|
|
static unsigned long ipmi_wdog_open;
|
|
static unsigned long ipmi_wdog_open;
|
|
|
|
|
|
-/* If set to 1, the heartbeat command will set the state to reset and
|
|
|
|
- start the timer. The timer doesn't normally run when the driver is
|
|
|
|
- first opened until the heartbeat is set the first time, this
|
|
|
|
- variable is used to accomplish this. */
|
|
|
|
|
|
+/*
|
|
|
|
+ * If set to 1, the heartbeat command will set the state to reset and
|
|
|
|
+ * start the timer. The timer doesn't normally run when the driver is
|
|
|
|
+ * first opened until the heartbeat is set the first time, this
|
|
|
|
+ * variable is used to accomplish this.
|
|
|
|
+ */
|
|
static int ipmi_start_timer_on_heartbeat;
|
|
static int ipmi_start_timer_on_heartbeat;
|
|
|
|
|
|
/* IPMI version of the BMC. */
|
|
/* IPMI version of the BMC. */
|
|
@@ -329,10 +338,12 @@ static int nmi_handler_registered;
|
|
|
|
|
|
static int ipmi_heartbeat(void);
|
|
static int ipmi_heartbeat(void);
|
|
|
|
|
|
-/* We use a mutex to make sure that only one thing can send a set
|
|
|
|
- timeout at one time, because we only have one copy of the data.
|
|
|
|
- The mutex is claimed when the set_timeout is sent and freed
|
|
|
|
- when both messages are free. */
|
|
|
|
|
|
+/*
|
|
|
|
+ * We use a mutex to make sure that only one thing can send a set
|
|
|
|
+ * timeout at one time, because we only have one copy of the data.
|
|
|
|
+ * The mutex is claimed when the set_timeout is sent and freed
|
|
|
|
+ * when both messages are free.
|
|
|
|
+ */
|
|
static atomic_t set_timeout_tofree = ATOMIC_INIT(0);
|
|
static atomic_t set_timeout_tofree = ATOMIC_INIT(0);
|
|
static DEFINE_MUTEX(set_timeout_lock);
|
|
static DEFINE_MUTEX(set_timeout_lock);
|
|
static DECLARE_COMPLETION(set_timeout_wait);
|
|
static DECLARE_COMPLETION(set_timeout_wait);
|
|
@@ -346,15 +357,13 @@ static void set_timeout_free_recv(struct ipmi_recv_msg *msg)
|
|
if (atomic_dec_and_test(&set_timeout_tofree))
|
|
if (atomic_dec_and_test(&set_timeout_tofree))
|
|
complete(&set_timeout_wait);
|
|
complete(&set_timeout_wait);
|
|
}
|
|
}
|
|
-static struct ipmi_smi_msg set_timeout_smi_msg =
|
|
|
|
-{
|
|
|
|
|
|
+static struct ipmi_smi_msg set_timeout_smi_msg = {
|
|
.done = set_timeout_free_smi
|
|
.done = set_timeout_free_smi
|
|
};
|
|
};
|
|
-static struct ipmi_recv_msg set_timeout_recv_msg =
|
|
|
|
-{
|
|
|
|
|
|
+static struct ipmi_recv_msg set_timeout_recv_msg = {
|
|
.done = set_timeout_free_recv
|
|
.done = set_timeout_free_recv
|
|
};
|
|
};
|
|
-
|
|
|
|
|
|
+
|
|
static int i_ipmi_set_timeout(struct ipmi_smi_msg *smi_msg,
|
|
static int i_ipmi_set_timeout(struct ipmi_smi_msg *smi_msg,
|
|
struct ipmi_recv_msg *recv_msg,
|
|
struct ipmi_recv_msg *recv_msg,
|
|
int *send_heartbeat_now)
|
|
int *send_heartbeat_now)
|
|
@@ -373,13 +382,14 @@ static int i_ipmi_set_timeout(struct ipmi_smi_msg *smi_msg,
|
|
WDOG_SET_TIMER_USE(data[0], WDOG_TIMER_USE_SMS_OS);
|
|
WDOG_SET_TIMER_USE(data[0], WDOG_TIMER_USE_SMS_OS);
|
|
|
|
|
|
if ((ipmi_version_major > 1)
|
|
if ((ipmi_version_major > 1)
|
|
- || ((ipmi_version_major == 1) && (ipmi_version_minor >= 5)))
|
|
|
|
- {
|
|
|
|
|
|
+ || ((ipmi_version_major == 1) && (ipmi_version_minor >= 5))) {
|
|
/* This is an IPMI 1.5-only feature. */
|
|
/* This is an IPMI 1.5-only feature. */
|
|
data[0] |= WDOG_DONT_STOP_ON_SET;
|
|
data[0] |= WDOG_DONT_STOP_ON_SET;
|
|
} else if (ipmi_watchdog_state != WDOG_TIMEOUT_NONE) {
|
|
} else if (ipmi_watchdog_state != WDOG_TIMEOUT_NONE) {
|
|
- /* In ipmi 1.0, setting the timer stops the watchdog, we
|
|
|
|
- need to start it back up again. */
|
|
|
|
|
|
+ /*
|
|
|
|
+ * In ipmi 1.0, setting the timer stops the watchdog, we
|
|
|
|
+ * need to start it back up again.
|
|
|
|
+ */
|
|
hbnow = 1;
|
|
hbnow = 1;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -465,12 +475,10 @@ static void panic_recv_free(struct ipmi_recv_msg *msg)
|
|
atomic_dec(&panic_done_count);
|
|
atomic_dec(&panic_done_count);
|
|
}
|
|
}
|
|
|
|
|
|
-static struct ipmi_smi_msg panic_halt_heartbeat_smi_msg =
|
|
|
|
-{
|
|
|
|
|
|
+static struct ipmi_smi_msg panic_halt_heartbeat_smi_msg = {
|
|
.done = panic_smi_free
|
|
.done = panic_smi_free
|
|
};
|
|
};
|
|
-static struct ipmi_recv_msg panic_halt_heartbeat_recv_msg =
|
|
|
|
-{
|
|
|
|
|
|
+static struct ipmi_recv_msg panic_halt_heartbeat_recv_msg = {
|
|
.done = panic_recv_free
|
|
.done = panic_recv_free
|
|
};
|
|
};
|
|
|
|
|
|
@@ -480,8 +488,10 @@ static void panic_halt_ipmi_heartbeat(void)
|
|
struct ipmi_system_interface_addr addr;
|
|
struct ipmi_system_interface_addr addr;
|
|
int rv;
|
|
int rv;
|
|
|
|
|
|
- /* Don't reset the timer if we have the timer turned off, that
|
|
|
|
- re-enables the watchdog. */
|
|
|
|
|
|
+ /*
|
|
|
|
+ * Don't reset the timer if we have the timer turned off, that
|
|
|
|
+ * re-enables the watchdog.
|
|
|
|
+ */
|
|
if (ipmi_watchdog_state == WDOG_TIMEOUT_NONE)
|
|
if (ipmi_watchdog_state == WDOG_TIMEOUT_NONE)
|
|
return;
|
|
return;
|
|
|
|
|
|
@@ -505,19 +515,19 @@ static void panic_halt_ipmi_heartbeat(void)
|
|
atomic_add(2, &panic_done_count);
|
|
atomic_add(2, &panic_done_count);
|
|
}
|
|
}
|
|
|
|
|
|
-static struct ipmi_smi_msg panic_halt_smi_msg =
|
|
|
|
-{
|
|
|
|
|
|
+static struct ipmi_smi_msg panic_halt_smi_msg = {
|
|
.done = panic_smi_free
|
|
.done = panic_smi_free
|
|
};
|
|
};
|
|
-static struct ipmi_recv_msg panic_halt_recv_msg =
|
|
|
|
-{
|
|
|
|
|
|
+static struct ipmi_recv_msg panic_halt_recv_msg = {
|
|
.done = panic_recv_free
|
|
.done = panic_recv_free
|
|
};
|
|
};
|
|
|
|
|
|
-/* Special call, doesn't claim any locks. This is only to be called
|
|
|
|
- at panic or halt time, in run-to-completion mode, when the caller
|
|
|
|
- is the only CPU and the only thing that will be going is these IPMI
|
|
|
|
- calls. */
|
|
|
|
|
|
+/*
|
|
|
|
+ * Special call, doesn't claim any locks. This is only to be called
|
|
|
|
+ * at panic or halt time, in run-to-completion mode, when the caller
|
|
|
|
+ * is the only CPU and the only thing that will be going is these IPMI
|
|
|
|
+ * calls.
|
|
|
|
+ */
|
|
static void panic_halt_ipmi_set_timeout(void)
|
|
static void panic_halt_ipmi_set_timeout(void)
|
|
{
|
|
{
|
|
int send_heartbeat_now;
|
|
int send_heartbeat_now;
|
|
@@ -540,10 +550,12 @@ static void panic_halt_ipmi_set_timeout(void)
|
|
ipmi_poll_interface(watchdog_user);
|
|
ipmi_poll_interface(watchdog_user);
|
|
}
|
|
}
|
|
|
|
|
|
-/* We use a semaphore to make sure that only one thing can send a
|
|
|
|
- heartbeat at one time, because we only have one copy of the data.
|
|
|
|
- The semaphore is claimed when the set_timeout is sent and freed
|
|
|
|
- when both messages are free. */
|
|
|
|
|
|
+/*
|
|
|
|
+ * We use a mutex to make sure that only one thing can send a
|
|
|
|
+ * heartbeat at one time, because we only have one copy of the data.
|
|
|
|
+ * The semaphore is claimed when the set_timeout is sent and freed
|
|
|
|
+ * when both messages are free.
|
|
|
|
+ */
|
|
static atomic_t heartbeat_tofree = ATOMIC_INIT(0);
|
|
static atomic_t heartbeat_tofree = ATOMIC_INIT(0);
|
|
static DEFINE_MUTEX(heartbeat_lock);
|
|
static DEFINE_MUTEX(heartbeat_lock);
|
|
static DECLARE_COMPLETION(heartbeat_wait);
|
|
static DECLARE_COMPLETION(heartbeat_wait);
|
|
@@ -557,15 +569,13 @@ static void heartbeat_free_recv(struct ipmi_recv_msg *msg)
|
|
if (atomic_dec_and_test(&heartbeat_tofree))
|
|
if (atomic_dec_and_test(&heartbeat_tofree))
|
|
complete(&heartbeat_wait);
|
|
complete(&heartbeat_wait);
|
|
}
|
|
}
|
|
-static struct ipmi_smi_msg heartbeat_smi_msg =
|
|
|
|
-{
|
|
|
|
|
|
+static struct ipmi_smi_msg heartbeat_smi_msg = {
|
|
.done = heartbeat_free_smi
|
|
.done = heartbeat_free_smi
|
|
};
|
|
};
|
|
-static struct ipmi_recv_msg heartbeat_recv_msg =
|
|
|
|
-{
|
|
|
|
|
|
+static struct ipmi_recv_msg heartbeat_recv_msg = {
|
|
.done = heartbeat_free_recv
|
|
.done = heartbeat_free_recv
|
|
};
|
|
};
|
|
-
|
|
|
|
|
|
+
|
|
static int ipmi_heartbeat(void)
|
|
static int ipmi_heartbeat(void)
|
|
{
|
|
{
|
|
struct kernel_ipmi_msg msg;
|
|
struct kernel_ipmi_msg msg;
|
|
@@ -580,10 +590,12 @@ static int ipmi_heartbeat(void)
|
|
ipmi_watchdog_state = action_val;
|
|
ipmi_watchdog_state = action_val;
|
|
return ipmi_set_timeout(IPMI_SET_TIMEOUT_FORCE_HB);
|
|
return ipmi_set_timeout(IPMI_SET_TIMEOUT_FORCE_HB);
|
|
} else if (pretimeout_since_last_heartbeat) {
|
|
} else if (pretimeout_since_last_heartbeat) {
|
|
- /* A pretimeout occurred, make sure we set the timeout.
|
|
|
|
- We don't want to set the action, though, we want to
|
|
|
|
- leave that alone (thus it can't be combined with the
|
|
|
|
- above operation. */
|
|
|
|
|
|
+ /*
|
|
|
|
+ * A pretimeout occurred, make sure we set the timeout.
|
|
|
|
+ * We don't want to set the action, though, we want to
|
|
|
|
+ * leave that alone (thus it can't be combined with the
|
|
|
|
+ * above operation.
|
|
|
|
+ */
|
|
return ipmi_set_timeout(IPMI_SET_TIMEOUT_HB_IF_NECESSARY);
|
|
return ipmi_set_timeout(IPMI_SET_TIMEOUT_HB_IF_NECESSARY);
|
|
}
|
|
}
|
|
|
|
|
|
@@ -591,8 +603,10 @@ static int ipmi_heartbeat(void)
|
|
|
|
|
|
atomic_set(&heartbeat_tofree, 2);
|
|
atomic_set(&heartbeat_tofree, 2);
|
|
|
|
|
|
- /* Don't reset the timer if we have the timer turned off, that
|
|
|
|
- re-enables the watchdog. */
|
|
|
|
|
|
+ /*
|
|
|
|
+ * Don't reset the timer if we have the timer turned off, that
|
|
|
|
+ * re-enables the watchdog.
|
|
|
|
+ */
|
|
if (ipmi_watchdog_state == WDOG_TIMEOUT_NONE) {
|
|
if (ipmi_watchdog_state == WDOG_TIMEOUT_NONE) {
|
|
mutex_unlock(&heartbeat_lock);
|
|
mutex_unlock(&heartbeat_lock);
|
|
return 0;
|
|
return 0;
|
|
@@ -625,10 +639,12 @@ static int ipmi_heartbeat(void)
|
|
wait_for_completion(&heartbeat_wait);
|
|
wait_for_completion(&heartbeat_wait);
|
|
|
|
|
|
if (heartbeat_recv_msg.msg.data[0] != 0) {
|
|
if (heartbeat_recv_msg.msg.data[0] != 0) {
|
|
- /* Got an error in the heartbeat response. It was already
|
|
|
|
- reported in ipmi_wdog_msg_handler, but we should return
|
|
|
|
- an error here. */
|
|
|
|
- rv = -EINVAL;
|
|
|
|
|
|
+ /*
|
|
|
|
+ * Got an error in the heartbeat response. It was already
|
|
|
|
+ * reported in ipmi_wdog_msg_handler, but we should return
|
|
|
|
+ * an error here.
|
|
|
|
+ */
|
|
|
|
+ rv = -EINVAL;
|
|
}
|
|
}
|
|
|
|
|
|
mutex_unlock(&heartbeat_lock);
|
|
mutex_unlock(&heartbeat_lock);
|
|
@@ -636,8 +652,7 @@ static int ipmi_heartbeat(void)
|
|
return rv;
|
|
return rv;
|
|
}
|
|
}
|
|
|
|
|
|
-static struct watchdog_info ident =
|
|
|
|
-{
|
|
|
|
|
|
+static struct watchdog_info ident = {
|
|
.options = 0, /* WDIOF_SETTIMEOUT, */
|
|
.options = 0, /* WDIOF_SETTIMEOUT, */
|
|
.firmware_version = 1,
|
|
.firmware_version = 1,
|
|
.identity = "IPMI"
|
|
.identity = "IPMI"
|
|
@@ -650,7 +665,7 @@ static int ipmi_ioctl(struct inode *inode, struct file *file,
|
|
int i;
|
|
int i;
|
|
int val;
|
|
int val;
|
|
|
|
|
|
- switch(cmd) {
|
|
|
|
|
|
+ switch (cmd) {
|
|
case WDIOC_GETSUPPORT:
|
|
case WDIOC_GETSUPPORT:
|
|
i = copy_to_user(argp, &ident, sizeof(ident));
|
|
i = copy_to_user(argp, &ident, sizeof(ident));
|
|
return i ? -EFAULT : 0;
|
|
return i ? -EFAULT : 0;
|
|
@@ -690,15 +705,13 @@ static int ipmi_ioctl(struct inode *inode, struct file *file,
|
|
i = copy_from_user(&val, argp, sizeof(int));
|
|
i = copy_from_user(&val, argp, sizeof(int));
|
|
if (i)
|
|
if (i)
|
|
return -EFAULT;
|
|
return -EFAULT;
|
|
- if (val & WDIOS_DISABLECARD)
|
|
|
|
- {
|
|
|
|
|
|
+ if (val & WDIOS_DISABLECARD) {
|
|
ipmi_watchdog_state = WDOG_TIMEOUT_NONE;
|
|
ipmi_watchdog_state = WDOG_TIMEOUT_NONE;
|
|
ipmi_set_timeout(IPMI_SET_TIMEOUT_NO_HB);
|
|
ipmi_set_timeout(IPMI_SET_TIMEOUT_NO_HB);
|
|
ipmi_start_timer_on_heartbeat = 0;
|
|
ipmi_start_timer_on_heartbeat = 0;
|
|
}
|
|
}
|
|
|
|
|
|
- if (val & WDIOS_ENABLECARD)
|
|
|
|
- {
|
|
|
|
|
|
+ if (val & WDIOS_ENABLECARD) {
|
|
ipmi_watchdog_state = action_val;
|
|
ipmi_watchdog_state = action_val;
|
|
ipmi_set_timeout(IPMI_SET_TIMEOUT_FORCE_HB);
|
|
ipmi_set_timeout(IPMI_SET_TIMEOUT_FORCE_HB);
|
|
}
|
|
}
|
|
@@ -724,13 +737,13 @@ static ssize_t ipmi_write(struct file *file,
|
|
int rv;
|
|
int rv;
|
|
|
|
|
|
if (len) {
|
|
if (len) {
|
|
- if (!nowayout) {
|
|
|
|
- size_t i;
|
|
|
|
|
|
+ if (!nowayout) {
|
|
|
|
+ size_t i;
|
|
|
|
|
|
/* In case it was set long ago */
|
|
/* In case it was set long ago */
|
|
expect_close = 0;
|
|
expect_close = 0;
|
|
|
|
|
|
- for (i = 0; i != len; i++) {
|
|
|
|
|
|
+ for (i = 0; i != len; i++) {
|
|
char c;
|
|
char c;
|
|
|
|
|
|
if (get_user(c, buf + i))
|
|
if (get_user(c, buf + i))
|
|
@@ -758,15 +771,17 @@ static ssize_t ipmi_read(struct file *file,
|
|
if (count <= 0)
|
|
if (count <= 0)
|
|
return 0;
|
|
return 0;
|
|
|
|
|
|
- /* Reading returns if the pretimeout has gone off, and it only does
|
|
|
|
- it once per pretimeout. */
|
|
|
|
|
|
+ /*
|
|
|
|
+ * Reading returns if the pretimeout has gone off, and it only does
|
|
|
|
+ * it once per pretimeout.
|
|
|
|
+ */
|
|
spin_lock(&ipmi_read_lock);
|
|
spin_lock(&ipmi_read_lock);
|
|
if (!data_to_read) {
|
|
if (!data_to_read) {
|
|
if (file->f_flags & O_NONBLOCK) {
|
|
if (file->f_flags & O_NONBLOCK) {
|
|
rv = -EAGAIN;
|
|
rv = -EAGAIN;
|
|
goto out;
|
|
goto out;
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
init_waitqueue_entry(&wait, current);
|
|
init_waitqueue_entry(&wait, current);
|
|
add_wait_queue(&read_q, &wait);
|
|
add_wait_queue(&read_q, &wait);
|
|
while (!data_to_read) {
|
|
while (!data_to_read) {
|
|
@@ -776,7 +791,7 @@ static ssize_t ipmi_read(struct file *file,
|
|
spin_lock(&ipmi_read_lock);
|
|
spin_lock(&ipmi_read_lock);
|
|
}
|
|
}
|
|
remove_wait_queue(&read_q, &wait);
|
|
remove_wait_queue(&read_q, &wait);
|
|
-
|
|
|
|
|
|
+
|
|
if (signal_pending(current)) {
|
|
if (signal_pending(current)) {
|
|
rv = -ERESTARTSYS;
|
|
rv = -ERESTARTSYS;
|
|
goto out;
|
|
goto out;
|
|
@@ -799,25 +814,27 @@ static ssize_t ipmi_read(struct file *file,
|
|
|
|
|
|
static int ipmi_open(struct inode *ino, struct file *filep)
|
|
static int ipmi_open(struct inode *ino, struct file *filep)
|
|
{
|
|
{
|
|
- switch (iminor(ino)) {
|
|
|
|
- case WATCHDOG_MINOR:
|
|
|
|
|
|
+ switch (iminor(ino)) {
|
|
|
|
+ case WATCHDOG_MINOR:
|
|
if (test_and_set_bit(0, &ipmi_wdog_open))
|
|
if (test_and_set_bit(0, &ipmi_wdog_open))
|
|
- return -EBUSY;
|
|
|
|
|
|
+ return -EBUSY;
|
|
|
|
|
|
- /* Don't start the timer now, let it start on the
|
|
|
|
- first heartbeat. */
|
|
|
|
|
|
+ /*
|
|
|
|
+ * Don't start the timer now, let it start on the
|
|
|
|
+ * first heartbeat.
|
|
|
|
+ */
|
|
ipmi_start_timer_on_heartbeat = 1;
|
|
ipmi_start_timer_on_heartbeat = 1;
|
|
return nonseekable_open(ino, filep);
|
|
return nonseekable_open(ino, filep);
|
|
|
|
|
|
default:
|
|
default:
|
|
return (-ENODEV);
|
|
return (-ENODEV);
|
|
- }
|
|
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
static unsigned int ipmi_poll(struct file *file, poll_table *wait)
|
|
static unsigned int ipmi_poll(struct file *file, poll_table *wait)
|
|
{
|
|
{
|
|
unsigned int mask = 0;
|
|
unsigned int mask = 0;
|
|
-
|
|
|
|
|
|
+
|
|
poll_wait(file, &read_q, wait);
|
|
poll_wait(file, &read_q, wait);
|
|
|
|
|
|
spin_lock(&ipmi_read_lock);
|
|
spin_lock(&ipmi_read_lock);
|
|
@@ -851,7 +868,7 @@ static int ipmi_close(struct inode *ino, struct file *filep)
|
|
clear_bit(0, &ipmi_wdog_open);
|
|
clear_bit(0, &ipmi_wdog_open);
|
|
}
|
|
}
|
|
|
|
|
|
- ipmi_fasync (-1, filep, 0);
|
|
|
|
|
|
+ ipmi_fasync(-1, filep, 0);
|
|
expect_close = 0;
|
|
expect_close = 0;
|
|
|
|
|
|
return 0;
|
|
return 0;
|
|
@@ -882,7 +899,7 @@ static void ipmi_wdog_msg_handler(struct ipmi_recv_msg *msg,
|
|
msg->msg.data[0],
|
|
msg->msg.data[0],
|
|
msg->msg.cmd);
|
|
msg->msg.cmd);
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
ipmi_free_recv_msg(msg);
|
|
ipmi_free_recv_msg(msg);
|
|
}
|
|
}
|
|
|
|
|
|
@@ -902,14 +919,14 @@ static void ipmi_wdog_pretimeout_handler(void *handler_data)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- /* On some machines, the heartbeat will give
|
|
|
|
- an error and not work unless we re-enable
|
|
|
|
- the timer. So do so. */
|
|
|
|
|
|
+ /*
|
|
|
|
+ * On some machines, the heartbeat will give an error and not
|
|
|
|
+ * work unless we re-enable the timer. So do so.
|
|
|
|
+ */
|
|
pretimeout_since_last_heartbeat = 1;
|
|
pretimeout_since_last_heartbeat = 1;
|
|
}
|
|
}
|
|
|
|
|
|
-static struct ipmi_user_hndl ipmi_hndlrs =
|
|
|
|
-{
|
|
|
|
|
|
+static struct ipmi_user_hndl ipmi_hndlrs = {
|
|
.ipmi_recv_hndl = ipmi_wdog_msg_handler,
|
|
.ipmi_recv_hndl = ipmi_wdog_msg_handler,
|
|
.ipmi_watchdog_pretimeout = ipmi_wdog_pretimeout_handler
|
|
.ipmi_watchdog_pretimeout = ipmi_wdog_pretimeout_handler
|
|
};
|
|
};
|
|
@@ -949,8 +966,10 @@ static void ipmi_register_watchdog(int ipmi_intf)
|
|
int old_timeout = timeout;
|
|
int old_timeout = timeout;
|
|
int old_preop_val = preop_val;
|
|
int old_preop_val = preop_val;
|
|
|
|
|
|
- /* Set the pretimeout to go off in a second and give
|
|
|
|
- ourselves plenty of time to stop the timer. */
|
|
|
|
|
|
+ /*
|
|
|
|
+ * Set the pretimeout to go off in a second and give
|
|
|
|
+ * ourselves plenty of time to stop the timer.
|
|
|
|
+ */
|
|
ipmi_watchdog_state = WDOG_TIMEOUT_RESET;
|
|
ipmi_watchdog_state = WDOG_TIMEOUT_RESET;
|
|
preop_val = WDOG_PREOP_NONE; /* Make sure nothing happens */
|
|
preop_val = WDOG_PREOP_NONE; /* Make sure nothing happens */
|
|
pretimeout = 99;
|
|
pretimeout = 99;
|
|
@@ -974,7 +993,7 @@ static void ipmi_register_watchdog(int ipmi_intf)
|
|
" occur. The NMI pretimeout will"
|
|
" occur. The NMI pretimeout will"
|
|
" likely not work\n");
|
|
" likely not work\n");
|
|
}
|
|
}
|
|
- out_restore:
|
|
|
|
|
|
+ out_restore:
|
|
testing_nmi = 0;
|
|
testing_nmi = 0;
|
|
preop_val = old_preop_val;
|
|
preop_val = old_preop_val;
|
|
pretimeout = old_pretimeout;
|
|
pretimeout = old_pretimeout;
|
|
@@ -1009,9 +1028,11 @@ static void ipmi_unregister_watchdog(int ipmi_intf)
|
|
/* Make sure no one can call us any more. */
|
|
/* Make sure no one can call us any more. */
|
|
misc_deregister(&ipmi_wdog_miscdev);
|
|
misc_deregister(&ipmi_wdog_miscdev);
|
|
|
|
|
|
- /* Wait to make sure the message makes it out. The lower layer has
|
|
|
|
- pointers to our buffers, we want to make sure they are done before
|
|
|
|
- we release our memory. */
|
|
|
|
|
|
+ /*
|
|
|
|
+ * Wait to make sure the message makes it out. The lower layer has
|
|
|
|
+ * pointers to our buffers, we want to make sure they are done before
|
|
|
|
+ * we release our memory.
|
|
|
|
+ */
|
|
while (atomic_read(&set_timeout_tofree))
|
|
while (atomic_read(&set_timeout_tofree))
|
|
schedule_timeout_uninterruptible(1);
|
|
schedule_timeout_uninterruptible(1);
|
|
|
|
|
|
@@ -1052,15 +1073,17 @@ ipmi_nmi(struct notifier_block *self, unsigned long val, void *data)
|
|
return NOTIFY_STOP;
|
|
return NOTIFY_STOP;
|
|
}
|
|
}
|
|
|
|
|
|
- /* If we are not expecting a timeout, ignore it. */
|
|
|
|
|
|
+ /* If we are not expecting a timeout, ignore it. */
|
|
if (ipmi_watchdog_state == WDOG_TIMEOUT_NONE)
|
|
if (ipmi_watchdog_state == WDOG_TIMEOUT_NONE)
|
|
return NOTIFY_OK;
|
|
return NOTIFY_OK;
|
|
|
|
|
|
if (preaction_val != WDOG_PRETIMEOUT_NMI)
|
|
if (preaction_val != WDOG_PRETIMEOUT_NMI)
|
|
return NOTIFY_OK;
|
|
return NOTIFY_OK;
|
|
|
|
|
|
- /* If no one else handled the NMI, we assume it was the IPMI
|
|
|
|
- watchdog. */
|
|
|
|
|
|
+ /*
|
|
|
|
+ * If no one else handled the NMI, we assume it was the IPMI
|
|
|
|
+ * watchdog.
|
|
|
|
+ */
|
|
if (preop_val == WDOG_PREOP_PANIC) {
|
|
if (preop_val == WDOG_PREOP_PANIC) {
|
|
/* On some machines, the heartbeat will give
|
|
/* On some machines, the heartbeat will give
|
|
an error and not work unless we re-enable
|
|
an error and not work unless we re-enable
|
|
@@ -1082,7 +1105,7 @@ static int wdog_reboot_handler(struct notifier_block *this,
|
|
unsigned long code,
|
|
unsigned long code,
|
|
void *unused)
|
|
void *unused)
|
|
{
|
|
{
|
|
- static int reboot_event_handled = 0;
|
|
|
|
|
|
+ static int reboot_event_handled;
|
|
|
|
|
|
if ((watchdog_user) && (!reboot_event_handled)) {
|
|
if ((watchdog_user) && (!reboot_event_handled)) {
|
|
/* Make sure we only do this once. */
|
|
/* Make sure we only do this once. */
|
|
@@ -1115,7 +1138,7 @@ static int wdog_panic_handler(struct notifier_block *this,
|
|
unsigned long event,
|
|
unsigned long event,
|
|
void *unused)
|
|
void *unused)
|
|
{
|
|
{
|
|
- static int panic_event_handled = 0;
|
|
|
|
|
|
+ static int panic_event_handled;
|
|
|
|
|
|
/* On a panic, if we have a panic timeout, make sure to extend
|
|
/* On a panic, if we have a panic timeout, make sure to extend
|
|
the watchdog timer to a reasonable value to complete the
|
|
the watchdog timer to a reasonable value to complete the
|
|
@@ -1125,7 +1148,7 @@ static int wdog_panic_handler(struct notifier_block *this,
|
|
ipmi_watchdog_state != WDOG_TIMEOUT_NONE) {
|
|
ipmi_watchdog_state != WDOG_TIMEOUT_NONE) {
|
|
/* Make sure we do this only once. */
|
|
/* Make sure we do this only once. */
|
|
panic_event_handled = 1;
|
|
panic_event_handled = 1;
|
|
-
|
|
|
|
|
|
+
|
|
timeout = 255;
|
|
timeout = 255;
|
|
pretimeout = 0;
|
|
pretimeout = 0;
|
|
panic_halt_ipmi_set_timeout();
|
|
panic_halt_ipmi_set_timeout();
|
|
@@ -1151,8 +1174,7 @@ static void ipmi_smi_gone(int if_num)
|
|
ipmi_unregister_watchdog(if_num);
|
|
ipmi_unregister_watchdog(if_num);
|
|
}
|
|
}
|
|
|
|
|
|
-static struct ipmi_smi_watcher smi_watcher =
|
|
|
|
-{
|
|
|
|
|
|
+static struct ipmi_smi_watcher smi_watcher = {
|
|
.owner = THIS_MODULE,
|
|
.owner = THIS_MODULE,
|
|
.new_smi = ipmi_new_smi,
|
|
.new_smi = ipmi_new_smi,
|
|
.smi_gone = ipmi_smi_gone
|
|
.smi_gone = ipmi_smi_gone
|