Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ieee1394...
[pandora-kernel.git] / drivers / char / ipmi / ipmi_watchdog.c
index 8f45ca9..235fab0 100644 (file)
@@ -35,6 +35,7 @@
 #include <linux/moduleparam.h>
 #include <linux/ipmi.h>
 #include <linux/ipmi_smi.h>
+#include <linux/smp_lock.h>
 #include <linux/watchdog.h>
 #include <linux/miscdevice.h>
 #include <linux/init.h>
 #include <asm/atomic.h>
 
 #ifdef CONFIG_X86
-/* This is ugly, but I've determined that x86 is the only architecture
-   that can reasonably support the IPMI NMI watchdog timeout at this
-   time.  If another architecture adds this capability somehow, it
-   will have to be a somewhat different mechanism and I have no idea
-   how it will work.  So in the unlikely event that another
-   architecture supports this, we can figure out a good generic
-   mechanism for it at that time. */
+/*
+ * This is ugly, but I've determined that x86 is the only architecture
+ * that can reasonably support the IPMI NMI watchdog timeout at this
+ * time.  If another architecture adds this capability somehow, it
+ * will have to be a somewhat different mechanism and I have no idea
+ * how it will work.  So in the unlikely event that another
+ * architecture supports this, we can figure out a good generic
+ * mechanism for it at that time.
+ */
 #include <asm/kdebug.h>
 #define HAVE_DIE_NMI
 #endif
@@ -95,9 +98,8 @@
 /* Operations that can be performed on a pretimout. */
 #define WDOG_PREOP_NONE                0
 #define WDOG_PREOP_PANIC       1
-#define WDOG_PREOP_GIVE_DATA   2 /* Cause data to be available to
-                                     read.  Doesn't work in NMI
-                                     mode. */
+/* Cause data to be available to read.  Doesn't work in NMI mode. */
+#define WDOG_PREOP_GIVE_DATA   2
 
 /* Actions to perform on a full timeout. */
 #define WDOG_SET_TIMEOUT_ACT(byte, use) \
 #define WDOG_TIMEOUT_POWER_DOWN                2
 #define WDOG_TIMEOUT_POWER_CYCLE       3
 
-/* Byte 3 of the get command, byte 4 of the get response is the
-   pre-timeout in seconds. */
+/*
+ * Byte 3 of the get command, byte 4 of the get response is the
+ * pre-timeout in seconds.
+ */
 
 /* Bits for setting byte 4 of the set command, byte 5 of the get response. */
 #define WDOG_EXPIRE_CLEAR_BIOS_FRB2    (1 << 1)
 #define WDOG_EXPIRE_CLEAR_SMS_OS       (1 << 4)
 #define WDOG_EXPIRE_CLEAR_OEM          (1 << 5)
 
-/* Setting/getting the watchdog timer value.  This is for bytes 5 and
-   6 (the timeout time) of the set command, and bytes 6 and 7 (the
-   timeout time) and 8 and 9 (the current countdown value) of the
-   response.  The timeout value is given in seconds (in the command it
-   is 100ms intervals). */
+/*
+ * Setting/getting the watchdog timer value.  This is for bytes 5 and
+ * 6 (the timeout time) of the set command, and bytes 6 and 7 (the
+ * timeout time) and 8 and 9 (the current countdown value) of the
+ * response.  The timeout value is given in seconds (in the command it
+ * is 100ms intervals).
+ */
 #define WDOG_SET_TIMEOUT(byte1, byte2, val) \
        (byte1) = (((val) * 10) & 0xff), (byte2) = (((val) * 10) >> 8)
 #define WDOG_GET_TIMEOUT(byte1, byte2) \
@@ -184,8 +190,10 @@ static int ipmi_set_timeout(int do_heartbeat);
 static void ipmi_register_watchdog(int ipmi_intf);
 static void ipmi_unregister_watchdog(int ipmi_intf);
 
-/* If true, the driver will start running as soon as it is configured
-   and ready. */
+/*
+ * If true, the driver will start running as soon as it is configured
+ * and ready.
+ */
 static int start_now;
 
 static int set_param_int(const char *val, struct kernel_param *kp)
@@ -309,10 +317,12 @@ static int ipmi_ignore_heartbeat;
 /* Is someone using the watchdog?  Only one user is allowed. */
 static unsigned long ipmi_wdog_open;
 
-/* If set to 1, the heartbeat command will set the state to reset and
-   start the timer.  The timer doesn't normally run when the driver is
-   first opened until the heartbeat is set the first time, this
-   variable is used to accomplish this. */
+/*
+ * If set to 1, the heartbeat command will set the state to reset and
+ * start the timer.  The timer doesn't normally run when the driver is
+ * first opened until the heartbeat is set the first time, this
+ * variable is used to accomplish this.
+ */
 static int ipmi_start_timer_on_heartbeat;
 
 /* IPMI version of the BMC. */
@@ -329,10 +339,12 @@ static int nmi_handler_registered;
 
 static int ipmi_heartbeat(void);
 
-/* 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 mutex is claimed when the set_timeout is sent and freed
-   when both messages are free. */
+/*
+ * 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 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 DEFINE_MUTEX(set_timeout_lock);
 static DECLARE_COMPLETION(set_timeout_wait);
@@ -346,15 +358,13 @@ static void set_timeout_free_recv(struct ipmi_recv_msg *msg)
     if (atomic_dec_and_test(&set_timeout_tofree))
            complete(&set_timeout_wait);
 }
-static struct ipmi_smi_msg set_timeout_smi_msg =
-{
+static struct ipmi_smi_msg set_timeout_smi_msg = {
        .done = set_timeout_free_smi
 };
-static struct ipmi_recv_msg set_timeout_recv_msg =
-{
+static struct ipmi_recv_msg set_timeout_recv_msg = {
        .done = set_timeout_free_recv
 };
+
 static int i_ipmi_set_timeout(struct ipmi_smi_msg  *smi_msg,
                              struct ipmi_recv_msg *recv_msg,
                              int                  *send_heartbeat_now)
@@ -373,13 +383,14 @@ static int i_ipmi_set_timeout(struct ipmi_smi_msg  *smi_msg,
        WDOG_SET_TIMER_USE(data[0], WDOG_TIMER_USE_SMS_OS);
 
        if ((ipmi_version_major > 1)
-           || ((ipmi_version_major == 1) && (ipmi_version_minor >= 5)))
-       {
+           || ((ipmi_version_major == 1) && (ipmi_version_minor >= 5))) {
                /* This is an IPMI 1.5-only feature. */
                data[0] |= WDOG_DONT_STOP_ON_SET;
        } else if (ipmi_watchdog_state != WDOG_TIMEOUT_NONE) {
-               /* In ipmi 1.0, setting the timer stops the watchdog, we
-                  need to start it back up again. */
+               /*
+                * In ipmi 1.0, setting the timer stops the watchdog, we
+                * need to start it back up again.
+                */
                hbnow = 1;
        }
 
@@ -465,12 +476,10 @@ static void panic_recv_free(struct ipmi_recv_msg *msg)
        atomic_dec(&panic_done_count);
 }
 
-static struct ipmi_smi_msg panic_halt_heartbeat_smi_msg =
-{
+static struct ipmi_smi_msg panic_halt_heartbeat_smi_msg = {
        .done = panic_smi_free
 };
-static struct ipmi_recv_msg panic_halt_heartbeat_recv_msg =
-{
+static struct ipmi_recv_msg panic_halt_heartbeat_recv_msg = {
        .done = panic_recv_free
 };
 
@@ -480,8 +489,10 @@ static void panic_halt_ipmi_heartbeat(void)
        struct ipmi_system_interface_addr addr;
        int rv;
 
-       /* Don't reset the timer if we have the timer turned off, that
-           re-enables the watchdog. */
+       /*
+        * Don't reset the timer if we have the timer turned off, that
+        * re-enables the watchdog.
+        */
        if (ipmi_watchdog_state == WDOG_TIMEOUT_NONE)
                return;
 
@@ -505,19 +516,19 @@ static void panic_halt_ipmi_heartbeat(void)
                atomic_add(2, &panic_done_count);
 }
 
-static struct ipmi_smi_msg panic_halt_smi_msg =
-{
+static struct ipmi_smi_msg panic_halt_smi_msg = {
        .done = panic_smi_free
 };
-static struct ipmi_recv_msg panic_halt_recv_msg =
-{
+static struct ipmi_recv_msg panic_halt_recv_msg = {
        .done = panic_recv_free
 };
 
-/* Special call, doesn't claim any locks.  This is only to be called
-   at panic or halt time, in run-to-completion mode, when the caller
-   is the only CPU and the only thing that will be going is these IPMI
-   calls. */
+/*
+ * Special call, doesn't claim any locks.  This is only to be called
+ * at panic or halt time, in run-to-completion mode, when the caller
+ * is the only CPU and the only thing that will be going is these IPMI
+ * calls.
+ */
 static void panic_halt_ipmi_set_timeout(void)
 {
        int send_heartbeat_now;
@@ -540,10 +551,12 @@ static void panic_halt_ipmi_set_timeout(void)
                ipmi_poll_interface(watchdog_user);
 }
 
-/* We use a semaphore to make sure that only one thing can send a
-   heartbeat at one time, because we only have one copy of the data.
-   The semaphore is claimed when the set_timeout is sent and freed
-   when both messages are free. */
+/*
+ * We use a mutex to make sure that only one thing can send a
+ * heartbeat at one time, because we only have one copy of the data.
+ * 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);
@@ -557,15 +570,13 @@ static void heartbeat_free_recv(struct ipmi_recv_msg *msg)
     if (atomic_dec_and_test(&heartbeat_tofree))
            complete(&heartbeat_wait);
 }
-static struct ipmi_smi_msg heartbeat_smi_msg =
-{
+static struct ipmi_smi_msg heartbeat_smi_msg = {
        .done = heartbeat_free_smi
 };
-static struct ipmi_recv_msg heartbeat_recv_msg =
-{
+static struct ipmi_recv_msg heartbeat_recv_msg = {
        .done = heartbeat_free_recv
 };
+
 static int ipmi_heartbeat(void)
 {
        struct kernel_ipmi_msg            msg;
@@ -580,10 +591,12 @@ static int ipmi_heartbeat(void)
                ipmi_watchdog_state = action_val;
                return ipmi_set_timeout(IPMI_SET_TIMEOUT_FORCE_HB);
        } else if (pretimeout_since_last_heartbeat) {
-               /* A pretimeout occurred, make sure we set the timeout.
-                  We don't want to set the action, though, we want to
-                  leave that alone (thus it can't be combined with the
-                  above operation. */
+               /*
+                * A pretimeout occurred, make sure we set the timeout.
+                * We don't want to set the action, though, we want to
+                * leave that alone (thus it can't be combined with the
+                * above operation.
+                */
                return ipmi_set_timeout(IPMI_SET_TIMEOUT_HB_IF_NECESSARY);
        }
 
@@ -591,8 +604,10 @@ static int ipmi_heartbeat(void)
 
        atomic_set(&heartbeat_tofree, 2);
 
-       /* Don't reset the timer if we have the timer turned off, that
-           re-enables the watchdog. */
+       /*
+        * 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);
                return 0;
@@ -625,10 +640,12 @@ static int ipmi_heartbeat(void)
        wait_for_completion(&heartbeat_wait);
 
        if (heartbeat_recv_msg.msg.data[0] != 0) {
-           /* Got an error in the heartbeat response.  It was already
-              reported in ipmi_wdog_msg_handler, but we should return
-              an error here. */
-           rv = -EINVAL;
+               /*
+                * Got an error in the heartbeat response.  It was already
+                * reported in ipmi_wdog_msg_handler, but we should return
+                * an error here.
+                */
+               rv = -EINVAL;
        }
 
        mutex_unlock(&heartbeat_lock);
@@ -636,8 +653,7 @@ static int ipmi_heartbeat(void)
        return rv;
 }
 
-static struct watchdog_info ident =
-{
+static struct watchdog_info ident = {
        .options        = 0,    /* WDIOF_SETTIMEOUT, */
        .firmware_version = 1,
        .identity       = "IPMI"
@@ -650,7 +666,7 @@ static int ipmi_ioctl(struct inode *inode, struct file *file,
        int i;
        int val;
 
-       switch(cmd) {
+       switch (cmd) {
        case WDIOC_GETSUPPORT:
                i = copy_to_user(argp, &ident, sizeof(ident));
                return i ? -EFAULT : 0;
@@ -690,15 +706,13 @@ static int ipmi_ioctl(struct inode *inode, struct file *file,
                i = copy_from_user(&val, argp, sizeof(int));
                if (i)
                        return -EFAULT;
-               if (val & WDIOS_DISABLECARD)
-               {
+               if (val & WDIOS_DISABLECARD) {
                        ipmi_watchdog_state = WDOG_TIMEOUT_NONE;
                        ipmi_set_timeout(IPMI_SET_TIMEOUT_NO_HB);
                        ipmi_start_timer_on_heartbeat = 0;
                }
 
-               if (val & WDIOS_ENABLECARD)
-               {
+               if (val & WDIOS_ENABLECARD) {
                        ipmi_watchdog_state = action_val;
                        ipmi_set_timeout(IPMI_SET_TIMEOUT_FORCE_HB);
                }
@@ -724,13 +738,13 @@ static ssize_t ipmi_write(struct file *file,
        int rv;
 
        if (len) {
-               if (!nowayout) {
-                       size_t i;
+               if (!nowayout) {
+                       size_t i;
 
                        /* In case it was set long ago */
                        expect_close = 0;
 
-                       for (i = 0; i != len; i++) {
+                       for (i = 0; i != len; i++) {
                                char c;
 
                                if (get_user(c, buf + i))
@@ -742,9 +756,8 @@ static ssize_t ipmi_write(struct file *file,
                rv = ipmi_heartbeat();
                if (rv)
                        return rv;
-               return 1;
        }
-       return 0;
+       return len;
 }
 
 static ssize_t ipmi_read(struct file *file,
@@ -758,15 +771,17 @@ static ssize_t ipmi_read(struct file *file,
        if (count <= 0)
                return 0;
 
-       /* Reading returns if the pretimeout has gone off, and it only does
-          it once per pretimeout. */
+       /*
+        * Reading returns if the pretimeout has gone off, and it only does
+        * it once per pretimeout.
+        */
        spin_lock(&ipmi_read_lock);
        if (!data_to_read) {
                if (file->f_flags & O_NONBLOCK) {
                        rv = -EAGAIN;
                        goto out;
                }
-               
+
                init_waitqueue_entry(&wait, current);
                add_wait_queue(&read_q, &wait);
                while (!data_to_read) {
@@ -776,7 +791,7 @@ static ssize_t ipmi_read(struct file *file,
                        spin_lock(&ipmi_read_lock);
                }
                remove_wait_queue(&read_q, &wait);
-           
+
                if (signal_pending(current)) {
                        rv = -ERESTARTSYS;
                        goto out;
@@ -799,25 +814,29 @@ static ssize_t ipmi_read(struct file *file,
 
 static int ipmi_open(struct inode *ino, struct file *filep)
 {
-        switch (iminor(ino)) {
-        case WATCHDOG_MINOR:
+       switch (iminor(ino)) {
+       case WATCHDOG_MINOR:
                if (test_and_set_bit(0, &ipmi_wdog_open))
-                        return -EBUSY;
+                       return -EBUSY;
+
+               cycle_kernel_lock();
 
-               /* Don't start the timer now, let it start on the
-                  first heartbeat. */
+               /*
+                * Don't start the timer now, let it start on the
+                * first heartbeat.
+                */
                ipmi_start_timer_on_heartbeat = 1;
                return nonseekable_open(ino, filep);
 
        default:
                return (-ENODEV);
-        }
+       }
 }
 
 static unsigned int ipmi_poll(struct file *file, poll_table *wait)
 {
        unsigned int mask = 0;
-       
+
        poll_wait(file, &read_q, wait);
 
        spin_lock(&ipmi_read_lock);
@@ -851,7 +870,7 @@ static int ipmi_close(struct inode *ino, struct file *filep)
                clear_bit(0, &ipmi_wdog_open);
        }
 
-       ipmi_fasync (-1, filep, 0);
+       ipmi_fasync(-1, filep, 0);
        expect_close = 0;
 
        return 0;
@@ -882,7 +901,7 @@ static void ipmi_wdog_msg_handler(struct ipmi_recv_msg *msg,
                       msg->msg.data[0],
                       msg->msg.cmd);
        }
-       
+
        ipmi_free_recv_msg(msg);
 }
 
@@ -902,14 +921,14 @@ static void ipmi_wdog_pretimeout_handler(void *handler_data)
                }
        }
 
-       /* On some machines, the heartbeat will give
-          an error and not work unless we re-enable
-          the timer.   So do so. */
+       /*
+        * On some machines, the heartbeat will give an error and not
+        * work unless we re-enable the timer.  So do so.
+        */
        pretimeout_since_last_heartbeat = 1;
 }
 
-static struct ipmi_user_hndl ipmi_hndlrs =
-{
+static struct ipmi_user_hndl ipmi_hndlrs = {
        .ipmi_recv_hndl           = ipmi_wdog_msg_handler,
        .ipmi_watchdog_pretimeout = ipmi_wdog_pretimeout_handler
 };
@@ -949,8 +968,10 @@ static void ipmi_register_watchdog(int ipmi_intf)
                int old_timeout = timeout;
                int old_preop_val = preop_val;
 
-               /* Set the pretimeout to go off in a second and give
-                  ourselves plenty of time to stop the timer. */
+               /*
+                * Set the pretimeout to go off in a second and give
+                * ourselves plenty of time to stop the timer.
+                */
                ipmi_watchdog_state = WDOG_TIMEOUT_RESET;
                preop_val = WDOG_PREOP_NONE; /* Make sure nothing happens */
                pretimeout = 99;
@@ -974,7 +995,7 @@ static void ipmi_register_watchdog(int ipmi_intf)
                               " occur.  The NMI pretimeout will"
                               " likely not work\n");
                }
      out_restore:
+ out_restore:
                testing_nmi = 0;
                preop_val = old_preop_val;
                pretimeout = old_pretimeout;
@@ -1009,9 +1030,11 @@ static void ipmi_unregister_watchdog(int ipmi_intf)
        /* Make sure no one can call us any more. */
        misc_deregister(&ipmi_wdog_miscdev);
 
-       /* Wait to make sure the message makes it out.  The lower layer has
-          pointers to our buffers, we want to make sure they are done before
-          we release our memory. */
+       /*
+        * Wait to make sure the message makes it out.  The lower layer has
+        * pointers to our buffers, we want to make sure they are done before
+        * we release our memory.
+        */
        while (atomic_read(&set_timeout_tofree))
                schedule_timeout_uninterruptible(1);
 
@@ -1052,15 +1075,17 @@ ipmi_nmi(struct notifier_block *self, unsigned long val, void *data)
                return NOTIFY_STOP;
        }
 
-        /* If we are not expecting a timeout, ignore it. */
+       /* If we are not expecting a timeout, ignore it. */
        if (ipmi_watchdog_state == WDOG_TIMEOUT_NONE)
                return NOTIFY_OK;
 
        if (preaction_val != WDOG_PRETIMEOUT_NMI)
                return NOTIFY_OK;
 
-       /* If no one else handled the NMI, we assume it was the IPMI
-           watchdog. */
+       /*
+        * If no one else handled the NMI, we assume it was the IPMI
+        * watchdog.
+        */
        if (preop_val == WDOG_PREOP_PANIC) {
                /* On some machines, the heartbeat will give
                   an error and not work unless we re-enable
@@ -1082,7 +1107,7 @@ static int wdog_reboot_handler(struct notifier_block *this,
                               unsigned long         code,
                               void                  *unused)
 {
-       static int reboot_event_handled = 0;
+       static int reboot_event_handled;
 
        if ((watchdog_user) && (!reboot_event_handled)) {
                /* Make sure we only do this once. */
@@ -1115,7 +1140,7 @@ static int wdog_panic_handler(struct notifier_block *this,
                              unsigned long         event,
                              void                  *unused)
 {
-       static int panic_event_handled = 0;
+       static int panic_event_handled;
 
        /* On a panic, if we have a panic timeout, make sure to extend
           the watchdog timer to a reasonable value to complete the
@@ -1125,7 +1150,7 @@ static int wdog_panic_handler(struct notifier_block *this,
            ipmi_watchdog_state != WDOG_TIMEOUT_NONE) {
                /* Make sure we do this only once. */
                panic_event_handled = 1;
-           
+
                timeout = 255;
                pretimeout = 0;
                panic_halt_ipmi_set_timeout();
@@ -1151,8 +1176,7 @@ static void ipmi_smi_gone(int if_num)
        ipmi_unregister_watchdog(if_num);
 }
 
-static struct ipmi_smi_watcher smi_watcher =
-{
+static struct ipmi_smi_watcher smi_watcher = {
        .owner    = THIS_MODULE,
        .new_smi  = ipmi_new_smi,
        .smi_gone = ipmi_smi_gone