summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCorey Minyard <minyard@acm.org>2005-11-07 01:00:05 -0800
committerLinus Torvalds <torvalds@g5.osdl.org>2005-11-07 07:53:45 -0800
commitb385676b355549afc9a7507ce09c7df47f166521 (patch)
treef24226209eca4f67e2bacead4767be919a8557bf
parente61fb5b65150ace7192d1f0ce840fe4cd6285e73 (diff)
downloadlwn-b385676b355549afc9a7507ce09c7df47f166521.tar.gz
lwn-b385676b355549afc9a7507ce09c7df47f166521.zip
[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: Corey Minyard <cminyard@mvista.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r--drivers/char/ipmi/ipmi_watchdog.c13
1 files changed, 9 insertions, 4 deletions
diff --git a/drivers/char/ipmi/ipmi_watchdog.c b/drivers/char/ipmi/ipmi_watchdog.c
index 405697a9f4d9..1f3159eb1ede 100644
--- a/drivers/char/ipmi/ipmi_watchdog.c
+++ b/drivers/char/ipmi/ipmi_watchdog.c
@@ -49,6 +49,7 @@
#include <linux/poll.h>
#include <linux/string.h>
#include <linux/ctype.h>
+#include <asm/atomic.h>
#ifdef CONFIG_X86_LOCAL_APIC
#include <asm/apic.h>
#endif
@@ -295,6 +296,8 @@ static int ipmi_start_timer_on_heartbeat = 0;
static unsigned char ipmi_version_major;
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 void panic_halt_ipmi_heartbeat(void);
@@ -837,9 +840,10 @@ static void ipmi_wdog_msg_handler(struct ipmi_recv_msg *msg,
static void ipmi_wdog_pretimeout_handler(void *handler_data)
{
if (preaction_val != WDOG_PRETIMEOUT_NONE) {
- if (preop_val == WDOG_PREOP_PANIC)
- panic("Watchdog pre-timeout");
- else if (preop_val == WDOG_PREOP_GIVE_DATA) {
+ if (preop_val == WDOG_PREOP_PANIC) {
+ if (atomic_inc_and_test(&preop_panic_excl))
+ panic("Watchdog pre-timeout");
+ } else if (preop_val == WDOG_PREOP_GIVE_DATA) {
spin_lock(&ipmi_read_lock);
data_to_read = 1;
wake_up_interruptible(&read_q);
@@ -913,7 +917,8 @@ ipmi_nmi(void *dev_id, struct pt_regs *regs, int cpu, int handled)
an error and not work unless we re-enable
the timer. So do so. */
pretimeout_since_last_heartbeat = 1;
- panic(PFX "pre-timeout");
+ if (atomic_inc_and_test(&preop_panic_excl))
+ panic(PFX "pre-timeout");
}
return NOTIFY_DONE;