[PATCH] Notifier chain update: API changes
[deliverable/linux.git] / drivers / char / ipmi / ipmi_watchdog.c
index 405697a9f4d962c895d4b5b77b49eab78ef5604e..7ece9f3c8f7065b74406c3b78c62206566b7f516 100644 (file)
@@ -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;
@@ -991,7 +996,7 @@ static struct notifier_block wdog_panic_notifier = {
 };
 
 
-static void ipmi_new_smi(int if_num)
+static void ipmi_new_smi(int if_num, struct device *device)
 {
        ipmi_register_watchdog(if_num);
 }
@@ -1153,7 +1158,8 @@ static int __init ipmi_wdog_init(void)
        }
 
        register_reboot_notifier(&wdog_reboot_notifier);
-       notifier_chain_register(&panic_notifier_list, &wdog_panic_notifier);
+       atomic_notifier_chain_register(&panic_notifier_list,
+                       &wdog_panic_notifier);
 
        printk(KERN_INFO PFX "driver initialized\n");
 
@@ -1171,7 +1177,8 @@ static __exit void ipmi_unregister_watchdog(void)
                release_nmi(&ipmi_nmi_handler);
 #endif
 
-       notifier_chain_unregister(&panic_notifier_list, &wdog_panic_notifier);
+       atomic_notifier_chain_unregister(&panic_notifier_list,
+                       &wdog_panic_notifier);
        unregister_reboot_notifier(&wdog_reboot_notifier);
 
        if (! watchdog_user)
This page took 0.048643 seconds and 5 git commands to generate.