Remove obsolete #include <linux/config.h>
[cascardo/linux.git] / drivers / char / ipmi / ipmi_watchdog.c
index 1f3159e..74a889c 100644 (file)
@@ -31,7 +31,6 @@
  *  675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/ipmi.h>
@@ -39,6 +38,7 @@
 #include <linux/watchdog.h>
 #include <linux/miscdevice.h>
 #include <linux/init.h>
+#include <linux/completion.h>
 #include <linux/rwsem.h>
 #include <linux/errno.h>
 #include <asm/uaccess.h>
@@ -211,24 +211,16 @@ static int set_param_str(const char *val, struct kernel_param *kp)
 {
        action_fn  fn = (action_fn) kp->arg;
        int        rv = 0;
-       const char *end;
-       char       valcp[16];
-       int        len;
-
-       /* Truncate leading and trailing spaces. */
-       while (isspace(*val))
-               val++;
-       end = val + strlen(val) - 1;
-       while ((end >= val) && isspace(*end))
-               end--;
-       len = end - val + 1;
-       if (len > sizeof(valcp) - 1)
-               return -EINVAL;
-       memcpy(valcp, val, len);
-       valcp[len] = '\0';
+       char       *dup, *s;
+
+       dup = kstrdup(val, GFP_KERNEL);
+       if (!dup)
+               return -ENOMEM;
+
+       s = strstrip(dup);
 
        down_read(&register_sem);
-       rv = fn(valcp, NULL);
+       rv = fn(s, NULL);
        if (rv)
                goto out_unlock;
 
@@ -238,6 +230,7 @@ static int set_param_str(const char *val, struct kernel_param *kp)
 
  out_unlock:
        up_read(&register_sem);
+       kfree(dup);
        return rv;
 }
 
@@ -303,21 +296,22 @@ static int ipmi_heartbeat(void);
 static void panic_halt_ipmi_heartbeat(void);
 
 
-/* We use a semaphore to make sure that only one thing can send a set
+/* 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 semaphore is claimed when the set_timeout is sent and freed
+   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 DECLARE_MUTEX(set_timeout_lock);
+static DEFINE_MUTEX(set_timeout_lock);
+static DECLARE_COMPLETION(set_timeout_wait);
 static void set_timeout_free_smi(struct ipmi_smi_msg *msg)
 {
     if (atomic_dec_and_test(&set_timeout_tofree))
-           up(&set_timeout_lock);
+           complete(&set_timeout_wait);
 }
 static void set_timeout_free_recv(struct ipmi_recv_msg *msg)
 {
     if (atomic_dec_and_test(&set_timeout_tofree))
-           up(&set_timeout_lock);
+           complete(&set_timeout_wait);
 }
 static struct ipmi_smi_msg set_timeout_smi_msg =
 {
@@ -399,7 +393,7 @@ static int ipmi_set_timeout(int do_heartbeat)
 
 
        /* We can only send one of these at a time. */
-       down(&set_timeout_lock);
+       mutex_lock(&set_timeout_lock);
 
        atomic_set(&set_timeout_tofree, 2);
 
@@ -407,16 +401,21 @@ static int ipmi_set_timeout(int do_heartbeat)
                                &set_timeout_recv_msg,
                                &send_heartbeat_now);
        if (rv) {
-               up(&set_timeout_lock);
-       } else {
-               if ((do_heartbeat == IPMI_SET_TIMEOUT_FORCE_HB)
-                   || ((send_heartbeat_now)
-                       && (do_heartbeat == IPMI_SET_TIMEOUT_HB_IF_NECESSARY)))
-               {
-                       rv = ipmi_heartbeat();
-               }
+               mutex_unlock(&set_timeout_lock);
+               goto out;
        }
 
+       wait_for_completion(&set_timeout_wait);
+
+       if ((do_heartbeat == IPMI_SET_TIMEOUT_FORCE_HB)
+           || ((send_heartbeat_now)
+               && (do_heartbeat == IPMI_SET_TIMEOUT_HB_IF_NECESSARY)))
+       {
+               rv = ipmi_heartbeat();
+       }
+       mutex_unlock(&set_timeout_lock);
+
+out:
        return rv;
 }
 
@@ -458,17 +457,17 @@ static void panic_halt_ipmi_set_timeout(void)
    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 DECLARE_MUTEX(heartbeat_lock);
-static DECLARE_MUTEX_LOCKED(heartbeat_wait_lock);
+static DEFINE_MUTEX(heartbeat_lock);
+static DECLARE_COMPLETION(heartbeat_wait);
 static void heartbeat_free_smi(struct ipmi_smi_msg *msg)
 {
     if (atomic_dec_and_test(&heartbeat_tofree))
-           up(&heartbeat_wait_lock);
+           complete(&heartbeat_wait);
 }
 static void heartbeat_free_recv(struct ipmi_recv_msg *msg)
 {
     if (atomic_dec_and_test(&heartbeat_tofree))
-           up(&heartbeat_wait_lock);
+           complete(&heartbeat_wait);
 }
 static struct ipmi_smi_msg heartbeat_smi_msg =
 {
@@ -511,14 +510,14 @@ static int ipmi_heartbeat(void)
                return ipmi_set_timeout(IPMI_SET_TIMEOUT_HB_IF_NECESSARY);
        }
 
-       down(&heartbeat_lock);
+       mutex_lock(&heartbeat_lock);
 
        atomic_set(&heartbeat_tofree, 2);
 
        /* Don't reset the timer if we have the timer turned off, that
            re-enables the watchdog. */
        if (ipmi_watchdog_state == WDOG_TIMEOUT_NONE) {
-               up(&heartbeat_lock);
+               mutex_unlock(&heartbeat_lock);
                return 0;
        }
 
@@ -539,14 +538,14 @@ static int ipmi_heartbeat(void)
                                      &heartbeat_recv_msg,
                                      1);
        if (rv) {
-               up(&heartbeat_lock);
+               mutex_unlock(&heartbeat_lock);
                printk(KERN_WARNING PFX "heartbeat failure: %d\n",
                       rv);
                return rv;
        }
 
        /* Wait for the heartbeat to be sent. */
-       down(&heartbeat_wait_lock);
+       wait_for_completion(&heartbeat_wait);
 
        if (heartbeat_recv_msg.msg.data[0] != 0) {
            /* Got an error in the heartbeat response.  It was already
@@ -555,7 +554,7 @@ static int ipmi_heartbeat(void)
            rv = -EINVAL;
        }
 
-       up(&heartbeat_lock);
+       mutex_unlock(&heartbeat_lock);
 
        return rv;
 }
@@ -589,7 +588,7 @@ static void panic_halt_ipmi_heartbeat(void)
                                 1);
 }
 
-static struct watchdog_info ident=
+static struct watchdog_info ident =
 {
        .options        = 0,    /* WDIOF_SETTIMEOUT, */
        .firmware_version = 1,
@@ -790,13 +789,13 @@ static int ipmi_fasync(int fd, struct file *file, int on)
 
 static int ipmi_close(struct inode *ino, struct file *filep)
 {
-       if (iminor(ino)==WATCHDOG_MINOR)
-       {
+       if (iminor(ino) == WATCHDOG_MINOR) {
                if (expect_close == 42) {
                        ipmi_watchdog_state = WDOG_TIMEOUT_NONE;
                        ipmi_set_timeout(IPMI_SET_TIMEOUT_NO_HB);
                } else {
-                       printk(KERN_CRIT PFX "Unexpected close, not stopping watchdog!\n");
+                       printk(KERN_CRIT PFX
+                              "Unexpected close, not stopping watchdog!\n");
                        ipmi_heartbeat();
                }
                clear_bit(0, &ipmi_wdog_open);
@@ -949,9 +948,10 @@ static int wdog_reboot_handler(struct notifier_block *this,
                        /* Disable the WDT if we are shutting down. */
                        ipmi_watchdog_state = WDOG_TIMEOUT_NONE;
                        panic_halt_ipmi_set_timeout();
-               } else {
+               } else if (ipmi_watchdog_state != WDOG_TIMEOUT_NONE) {
                        /* Set a long timer to let the reboot happens, but
-                          reboot if it hangs. */
+                          reboot if it hangs, but only if the watchdog
+                          timer was already running. */
                        timeout = 120;
                        pretimeout = 0;
                        ipmi_watchdog_state = WDOG_TIMEOUT_RESET;
@@ -973,16 +973,17 @@ static int wdog_panic_handler(struct notifier_block *this,
 {
        static int panic_event_handled = 0;
 
-       /* On a panic, if we have a panic timeout, make sure that the thing
-          reboots, even if it hangs during that panic. */
-       if (watchdog_user && !panic_event_handled) {
-               /* Make sure the panic doesn't hang, and make sure we
-                  do this only once. */
+       /* On a panic, if we have a panic timeout, make sure to extend
+          the watchdog timer to a reasonable value to complete the
+          panic, if the watchdog timer is running.  Plus the
+          pretimeout is meaningless at panic time. */
+       if (watchdog_user && !panic_event_handled &&
+           ipmi_watchdog_state != WDOG_TIMEOUT_NONE) {
+               /* Make sure we do this only once. */
                panic_event_handled = 1;
            
                timeout = 255;
                pretimeout = 0;
-               ipmi_watchdog_state = WDOG_TIMEOUT_RESET;
                panic_halt_ipmi_set_timeout();
        }
 
@@ -996,7 +997,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);
 }
@@ -1158,7 +1159,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");
 
@@ -1176,7 +1178,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)