[PATCH] IPMI: fix startup race condition

Matt Domsch noticed a startup race with the IPMI kernel thread, it was
possible (though extraordinarly unlikely) that a message could come in
before the upper layer was ready to handle it.  This patch splits the
startup processing of an IPMI interface into two parts, one to get ready
and one to actually start the processes to receive messages from the
interface.

[akpm@osdl.org: cleanups]
Signed-off-by: Corey Minyard <minyard@acm.org>
Cc: Matt Domsch <Matt_Domsch@dell.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
diff --git a/include/linux/ipmi_smi.h b/include/linux/ipmi_smi.h
index 5357128..6d9c7e4 100644
--- a/include/linux/ipmi_smi.h
+++ b/include/linux/ipmi_smi.h
@@ -82,6 +82,13 @@
 {
 	struct module *owner;
 
+	/* The low-level interface cannot start sending messages to
+	   the upper layer until this function is called.  This may
+	   not be NULL, the lower layer must take the interface from
+	   this call. */
+	int (*start_processing)(void       *send_info,
+				ipmi_smi_t new_intf);
+
 	/* Called to enqueue an SMI message to be sent.  This
 	   operation is not allowed to fail.  If an error occurs, it
 	   should report back the error in a received message.  It may
@@ -157,13 +164,16 @@
 }
 
 /* Add a low-level interface to the IPMI driver.  Note that if the
-   interface doesn't know its slave address, it should pass in zero. */
+   interface doesn't know its slave address, it should pass in zero.
+   The low-level interface should not deliver any messages to the
+   upper layer until the start_processing() function in the handlers
+   is called, and the lower layer must get the interface from that
+   call. */
 int ipmi_register_smi(struct ipmi_smi_handlers *handlers,
 		      void                     *send_info,
 		      struct ipmi_device_id    *device_id,
 		      struct device            *dev,
-		      unsigned char            slave_addr,
-		      ipmi_smi_t               *intf);
+		      unsigned char            slave_addr);
 
 /*
  * Remove a low-level interface from the IPMI driver.  This will