IPMI: add polled interface
[pandora-kernel.git] / drivers / char / ipmi / ipmi_watchdog.c
index 806106b..19a8683 100644 (file)
@@ -314,8 +314,6 @@ static unsigned char ipmi_version_minor;
 static atomic_t preop_panic_excl = ATOMIC_INIT(-1);
 
 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
    timeout at one time, because we only have one copy of the data.
@@ -440,19 +438,64 @@ out:
        return rv;
 }
 
-static void dummy_smi_free(struct ipmi_smi_msg *msg)
+static atomic_t panic_done_count = ATOMIC_INIT(0);
+
+static void panic_smi_free(struct ipmi_smi_msg *msg)
 {
+       atomic_dec(&panic_done_count);
 }
-static void dummy_recv_free(struct ipmi_recv_msg *msg)
+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 =
+{
+       .done = panic_smi_free
+};
+static struct ipmi_recv_msg panic_halt_heartbeat_recv_msg =
 {
+       .done = panic_recv_free
+};
+
+static void panic_halt_ipmi_heartbeat(void)
+{
+       struct kernel_ipmi_msg             msg;
+       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. */
+       if (ipmi_watchdog_state == WDOG_TIMEOUT_NONE)
+               return;
+
+       addr.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE;
+       addr.channel = IPMI_BMC_CHANNEL;
+       addr.lun = 0;
+
+       msg.netfn = 0x06;
+       msg.cmd = IPMI_WDOG_RESET_TIMER;
+       msg.data = NULL;
+       msg.data_len = 0;
+       rv = ipmi_request_supply_msgs(watchdog_user,
+                                     (struct ipmi_addr *) &addr,
+                                     0,
+                                     &msg,
+                                     NULL,
+                                     &panic_halt_heartbeat_smi_msg,
+                                     &panic_halt_heartbeat_recv_msg,
+                                     1);
+       if (!rv)
+               atomic_add(2, &panic_done_count);
 }
+
 static struct ipmi_smi_msg panic_halt_smi_msg =
 {
-       .done = dummy_smi_free
+       .done = panic_smi_free
 };
 static struct ipmi_recv_msg panic_halt_recv_msg =
 {
-       .done = dummy_recv_free
+       .done = panic_recv_free
 };
 
 /* Special call, doesn't claim any locks.  This is only to be called
@@ -464,13 +507,21 @@ static void panic_halt_ipmi_set_timeout(void)
        int send_heartbeat_now;
        int rv;
 
+       /* Wait for the messages to be free. */
+       while (atomic_read(&panic_done_count) != 0)
+               ipmi_poll_interface(watchdog_user);
        rv = i_ipmi_set_timeout(&panic_halt_smi_msg,
                                &panic_halt_recv_msg,
                                &send_heartbeat_now);
        if (!rv) {
+               atomic_add(2, &panic_done_count);
                if (send_heartbeat_now)
                        panic_halt_ipmi_heartbeat();
-       }
+       } else
+               printk(KERN_WARNING PFX
+                      "Unable to extend the watchdog timeout.");
+       while (atomic_read(&panic_done_count) != 0)
+               ipmi_poll_interface(watchdog_user);
 }
 
 /* We use a semaphore to make sure that only one thing can send a
@@ -499,15 +550,6 @@ static struct ipmi_recv_msg heartbeat_recv_msg =
        .done = heartbeat_free_recv
 };
  
-static struct ipmi_smi_msg panic_halt_heartbeat_smi_msg =
-{
-       .done = dummy_smi_free
-};
-static struct ipmi_recv_msg panic_halt_heartbeat_recv_msg =
-{
-       .done = dummy_recv_free
-};
 static int ipmi_heartbeat(void)
 {
        struct kernel_ipmi_msg            msg;
@@ -580,35 +622,6 @@ static int ipmi_heartbeat(void)
        return rv;
 }
 
-static void panic_halt_ipmi_heartbeat(void)
-{
-       struct kernel_ipmi_msg             msg;
-       struct ipmi_system_interface_addr addr;
-
-
-       /* 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;
-
-       addr.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE;
-       addr.channel = IPMI_BMC_CHANNEL;
-       addr.lun = 0;
-
-       msg.netfn = 0x06;
-       msg.cmd = IPMI_WDOG_RESET_TIMER;
-       msg.data = NULL;
-       msg.data_len = 0;
-       ipmi_request_supply_msgs(watchdog_user,
-                                (struct ipmi_addr *) &addr,
-                                0,
-                                &msg,
-                                NULL,
-                                &panic_halt_heartbeat_smi_msg,
-                                &panic_halt_heartbeat_recv_msg,
-                                1);
-}
-
 static struct watchdog_info ident =
 {
        .options        = 0,    /* WDIOF_SETTIMEOUT, */
@@ -998,7 +1011,7 @@ static int wdog_reboot_handler(struct notifier_block *this,
                /* Make sure we only do this once. */
                reboot_event_handled = 1;
 
-               if (code == SYS_DOWN || code == SYS_HALT) {
+               if (code == SYS_POWER_OFF || code == SYS_HALT) {
                        /* Disable the WDT if we are shutting down. */
                        ipmi_watchdog_state = WDOG_TIMEOUT_NONE;
                        panic_halt_ipmi_set_timeout();