linux 2.6.16.38 w/ vs2.0.3-rc1
[linux-2.6.git] / drivers / char / ipmi / ipmi_watchdog.c
index accaaf1..1f3159e 100644 (file)
@@ -31,6 +31,7 @@
  *  675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/ipmi.h>
@@ -38,7 +39,6 @@
 #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,16 +211,24 @@ static int set_param_str(const char *val, struct kernel_param *kp)
 {
        action_fn  fn = (action_fn) kp->arg;
        int        rv = 0;
-       char       *dup, *s;
-
-       dup = kstrdup(val, GFP_KERNEL);
-       if (!dup)
-               return -ENOMEM;
-
-       s = strstrip(dup);
+       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';
 
        down_read(&register_sem);
-       rv = fn(s, NULL);
+       rv = fn(valcp, NULL);
        if (rv)
                goto out_unlock;
 
@@ -230,7 +238,6 @@ static int set_param_str(const char *val, struct kernel_param *kp)
 
  out_unlock:
        up_read(&register_sem);
-       kfree(dup);
        return rv;
 }
 
@@ -296,22 +303,21 @@ static int ipmi_heartbeat(void);
 static void panic_halt_ipmi_heartbeat(void);
 
 
-/* We use a mutex to make sure that only one thing can send a set
+/* We use a semaphore 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 mutex is claimed when the set_timeout is sent and freed
+   The semaphore 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 DEFINE_MUTEX(set_timeout_lock);
-static DECLARE_COMPLETION(set_timeout_wait);
+static DECLARE_MUTEX(set_timeout_lock);
 static void set_timeout_free_smi(struct ipmi_smi_msg *msg)
 {
     if (atomic_dec_and_test(&set_timeout_tofree))
-           complete(&set_timeout_wait);
+           up(&set_timeout_lock);
 }
 static void set_timeout_free_recv(struct ipmi_recv_msg *msg)
 {
     if (atomic_dec_and_test(&set_timeout_tofree))
-           complete(&set_timeout_wait);
+           up(&set_timeout_lock);
 }
 static struct ipmi_smi_msg set_timeout_smi_msg =
 {
@@ -393,7 +399,7 @@ static int ipmi_set_timeout(int do_heartbeat)
 
 
        /* We can only send one of these at a time. */
-       mutex_lock(&set_timeout_lock);
+       down(&set_timeout_lock);
 
        atomic_set(&set_timeout_tofree, 2);
 
@@ -401,21 +407,16 @@ static int ipmi_set_timeout(int do_heartbeat)
                                &set_timeout_recv_msg,
                                &send_heartbeat_now);
        if (rv) {
-               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();
+               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);
 
-out:
        return rv;
 }
 
@@ -457,17 +458,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 DEFINE_MUTEX(heartbeat_lock);
-static DECLARE_COMPLETION(heartbeat_wait);
+static DECLARE_MUTEX(heartbeat_lock);
+static DECLARE_MUTEX_LOCKED(heartbeat_wait_lock);
 static void heartbeat_free_smi(struct ipmi_smi_msg *msg)
 {
     if (atomic_dec_and_test(&heartbeat_tofree))
-           complete(&heartbeat_wait);
+           up(&heartbeat_wait_lock);
 }
 static void heartbeat_free_recv(struct ipmi_recv_msg *msg)
 {
     if (atomic_dec_and_test(&heartbeat_tofree))
-           complete(&heartbeat_wait);
+           up(&heartbeat_wait_lock);
 }
 static struct ipmi_smi_msg heartbeat_smi_msg =
 {
@@ -510,14 +511,14 @@ static int ipmi_heartbeat(void)
                return ipmi_set_timeout(IPMI_SET_TIMEOUT_HB_IF_NECESSARY);
        }
 
-       mutex_lock(&heartbeat_lock);
+       down(&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) {
-               mutex_unlock(&heartbeat_lock);
+               up(&heartbeat_lock);
                return 0;
        }
 
@@ -538,14 +539,14 @@ static int ipmi_heartbeat(void)
                                      &heartbeat_recv_msg,
                                      1);
        if (rv) {
-               mutex_unlock(&heartbeat_lock);
+               up(&heartbeat_lock);
                printk(KERN_WARNING PFX "heartbeat failure: %d\n",
                       rv);
                return rv;
        }
 
        /* Wait for the heartbeat to be sent. */
-       wait_for_completion(&heartbeat_wait);
+       down(&heartbeat_wait_lock);
 
        if (heartbeat_recv_msg.msg.data[0] != 0) {
            /* Got an error in the heartbeat response.  It was already
@@ -554,7 +555,7 @@ static int ipmi_heartbeat(void)
            rv = -EINVAL;
        }
 
-       mutex_unlock(&heartbeat_lock);
+       up(&heartbeat_lock);
 
        return rv;
 }
@@ -588,7 +589,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,
@@ -789,13 +790,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);
@@ -807,7 +808,7 @@ static int ipmi_close(struct inode *ino, struct file *filep)
        return 0;
 }
 
-static const struct file_operations ipmi_wdog_fops = {
+static struct file_operations ipmi_wdog_fops = {
        .owner   = THIS_MODULE,
        .read    = ipmi_read,
        .poll    = ipmi_poll,
@@ -948,10 +949,9 @@ 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 if (ipmi_watchdog_state != WDOG_TIMEOUT_NONE) {
+               } else {
                        /* Set a long timer to let the reboot happens, but
-                          reboot if it hangs, but only if the watchdog
-                          timer was already running. */
+                          reboot if it hangs. */
                        timeout = 120;
                        pretimeout = 0;
                        ipmi_watchdog_state = WDOG_TIMEOUT_RESET;
@@ -973,17 +973,16 @@ 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 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. */
+       /* 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. */
                panic_event_handled = 1;
            
                timeout = 255;
                pretimeout = 0;
+               ipmi_watchdog_state = WDOG_TIMEOUT_RESET;
                panic_halt_ipmi_set_timeout();
        }
 
@@ -997,7 +996,7 @@ static struct notifier_block wdog_panic_notifier = {
 };
 
 
-static void ipmi_new_smi(int if_num, struct device *device)
+static void ipmi_new_smi(int if_num)
 {
        ipmi_register_watchdog(if_num);
 }
@@ -1159,8 +1158,7 @@ static int __init ipmi_wdog_init(void)
        }
 
        register_reboot_notifier(&wdog_reboot_notifier);
-       atomic_notifier_chain_register(&panic_notifier_list,
-                       &wdog_panic_notifier);
+       notifier_chain_register(&panic_notifier_list, &wdog_panic_notifier);
 
        printk(KERN_INFO PFX "driver initialized\n");
 
@@ -1178,8 +1176,7 @@ static __exit void ipmi_unregister_watchdog(void)
                release_nmi(&ipmi_nmi_handler);
 #endif
 
-       atomic_notifier_chain_unregister(&panic_notifier_list,
-                       &wdog_panic_notifier);
+       notifier_chain_unregister(&panic_notifier_list, &wdog_panic_notifier);
        unregister_reboot_notifier(&wdog_reboot_notifier);
 
        if (! watchdog_user)