aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char/ipmi/ipmi_watchdog.c
diff options
context:
space:
mode:
authorCorey Minyard <minyard@acm.org>2005-11-07 04:00:05 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2005-11-07 10:53:45 -0500
commitb385676b355549afc9a7507ce09c7df47f166521 (patch)
treef24226209eca4f67e2bacead4767be919a8557bf /drivers/char/ipmi/ipmi_watchdog.c
parente61fb5b65150ace7192d1f0ce840fe4cd6285e73 (diff)
[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>
Diffstat (limited to 'drivers/char/ipmi/ipmi_watchdog.c')
-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 @@
49#include <linux/poll.h> 49#include <linux/poll.h>
50#include <linux/string.h> 50#include <linux/string.h>
51#include <linux/ctype.h> 51#include <linux/ctype.h>
52#include <asm/atomic.h>
52#ifdef CONFIG_X86_LOCAL_APIC 53#ifdef CONFIG_X86_LOCAL_APIC
53#include <asm/apic.h> 54#include <asm/apic.h>
54#endif 55#endif
@@ -295,6 +296,8 @@ static int ipmi_start_timer_on_heartbeat = 0;
295static unsigned char ipmi_version_major; 296static unsigned char ipmi_version_major;
296static unsigned char ipmi_version_minor; 297static unsigned char ipmi_version_minor;
297 298
299/* If a pretimeout occurs, this is used to allow only one panic to happen. */
300static atomic_t preop_panic_excl = ATOMIC_INIT(-1);
298 301
299static int ipmi_heartbeat(void); 302static int ipmi_heartbeat(void);
300static void panic_halt_ipmi_heartbeat(void); 303static void panic_halt_ipmi_heartbeat(void);
@@ -837,9 +840,10 @@ static void ipmi_wdog_msg_handler(struct ipmi_recv_msg *msg,
837static void ipmi_wdog_pretimeout_handler(void *handler_data) 840static void ipmi_wdog_pretimeout_handler(void *handler_data)
838{ 841{
839 if (preaction_val != WDOG_PRETIMEOUT_NONE) { 842 if (preaction_val != WDOG_PRETIMEOUT_NONE) {
840 if (preop_val == WDOG_PREOP_PANIC) 843 if (preop_val == WDOG_PREOP_PANIC) {
841 panic("Watchdog pre-timeout"); 844 if (atomic_inc_and_test(&preop_panic_excl))
842 else if (preop_val == WDOG_PREOP_GIVE_DATA) { 845 panic("Watchdog pre-timeout");
846 } else if (preop_val == WDOG_PREOP_GIVE_DATA) {
843 spin_lock(&ipmi_read_lock); 847 spin_lock(&ipmi_read_lock);
844 data_to_read = 1; 848 data_to_read = 1;
845 wake_up_interruptible(&read_q); 849 wake_up_interruptible(&read_q);
@@ -913,7 +917,8 @@ ipmi_nmi(void *dev_id, struct pt_regs *regs, int cpu, int handled)
913 an error and not work unless we re-enable 917 an error and not work unless we re-enable
914 the timer. So do so. */ 918 the timer. So do so. */
915 pretimeout_since_last_heartbeat = 1; 919 pretimeout_since_last_heartbeat = 1;
916 panic(PFX "pre-timeout"); 920 if (atomic_inc_and_test(&preop_panic_excl))
921 panic(PFX "pre-timeout");
917 } 922 }
918 923
919 return NOTIFY_DONE; 924 return NOTIFY_DONE;