Commit b385676b authored by Corey Minyard's avatar Corey Minyard Committed by Linus Torvalds

[PATCH] ipmi: fix watchdog timeout panic handling

If a panic came from the IPMI watchdog pretimeout and that was reported via
an NMI, it would also be reported via the standard IPMI flags, which would
get picked up when reporting panic events and cause another panic.  This
adds an atomic to avoid calling panic twice.
Signed-off-by: default avatarCorey Minyard <cminyard@mvista.com>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent e61fb5b6
...@@ -49,6 +49,7 @@ ...@@ -49,6 +49,7 @@
#include <linux/poll.h> #include <linux/poll.h>
#include <linux/string.h> #include <linux/string.h>
#include <linux/ctype.h> #include <linux/ctype.h>
#include <asm/atomic.h>
#ifdef CONFIG_X86_LOCAL_APIC #ifdef CONFIG_X86_LOCAL_APIC
#include <asm/apic.h> #include <asm/apic.h>
#endif #endif
...@@ -295,6 +296,8 @@ static int ipmi_start_timer_on_heartbeat = 0; ...@@ -295,6 +296,8 @@ static int ipmi_start_timer_on_heartbeat = 0;
static unsigned char ipmi_version_major; static unsigned char ipmi_version_major;
static unsigned char ipmi_version_minor; static unsigned char ipmi_version_minor;
/* If a pretimeout occurs, this is used to allow only one panic to happen. */
static atomic_t preop_panic_excl = ATOMIC_INIT(-1);
static int ipmi_heartbeat(void); static int ipmi_heartbeat(void);
static void panic_halt_ipmi_heartbeat(void); static void panic_halt_ipmi_heartbeat(void);
...@@ -837,9 +840,10 @@ static void ipmi_wdog_msg_handler(struct ipmi_recv_msg *msg, ...@@ -837,9 +840,10 @@ static void ipmi_wdog_msg_handler(struct ipmi_recv_msg *msg,
static void ipmi_wdog_pretimeout_handler(void *handler_data) static void ipmi_wdog_pretimeout_handler(void *handler_data)
{ {
if (preaction_val != WDOG_PRETIMEOUT_NONE) { if (preaction_val != WDOG_PRETIMEOUT_NONE) {
if (preop_val == WDOG_PREOP_PANIC) if (preop_val == WDOG_PREOP_PANIC) {
if (atomic_inc_and_test(&preop_panic_excl))
panic("Watchdog pre-timeout"); panic("Watchdog pre-timeout");
else if (preop_val == WDOG_PREOP_GIVE_DATA) { } else if (preop_val == WDOG_PREOP_GIVE_DATA) {
spin_lock(&ipmi_read_lock); spin_lock(&ipmi_read_lock);
data_to_read = 1; data_to_read = 1;
wake_up_interruptible(&read_q); wake_up_interruptible(&read_q);
...@@ -913,6 +917,7 @@ ipmi_nmi(void *dev_id, struct pt_regs *regs, int cpu, int handled) ...@@ -913,6 +917,7 @@ ipmi_nmi(void *dev_id, struct pt_regs *regs, int cpu, int handled)
an error and not work unless we re-enable an error and not work unless we re-enable
the timer. So do so. */ the timer. So do so. */
pretimeout_since_last_heartbeat = 1; pretimeout_since_last_heartbeat = 1;
if (atomic_inc_and_test(&preop_panic_excl))
panic(PFX "pre-timeout"); panic(PFX "pre-timeout");
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment