Startup race condition fix for SLES10 kernel-of-the-day from ftp.suse.com.  
Please review.

-- 
Matt Domsch
Software Architect
Dell Linux Solutions linux.dell.com & www.dell.com/linux
Linux on Dell mailing lists @ http://lists.us.dell.com

diff -urNp --exclude-from=/home/mdomsch/excludes --minimal 
linux-2.6.16-20060411175326/drivers/char/ipmi/ipmi_msghandler.c 
linux-2.6.16-20060411175326.openipmi/drivers/char/ipmi/ipmi_msghandler.c
--- linux-2.6.16-20060411175326/drivers/char/ipmi/ipmi_msghandler.c     Sun Mar 
19 23:53:29 2006
+++ linux-2.6.16-20060411175326.openipmi/drivers/char/ipmi/ipmi_msghandler.c    
Wed Apr 12 16:56:03 2006
@@ -48,7 +48,7 @@
 
 #define PFX "IPMI message handler: "
 
-#define IPMI_DRIVER_VERSION "38.0"
+#define IPMI_DRIVER_VERSION "38.1"
 
 static struct ipmi_recv_msg *ipmi_alloc_recv_msg(void);
 static int ipmi_init_msghandler(void);
@@ -1804,8 +1804,7 @@ int ipmi_register_smi(struct ipmi_smi_ha
                      void                     *send_info,
                      unsigned char            version_major,
                      unsigned char            version_minor,
-                     unsigned char            slave_addr,
-                     ipmi_smi_t               *new_intf)
+                     unsigned char            slave_addr)
 {
        int              i, j;
        int              rv;
@@ -1878,9 +1877,9 @@ int ipmi_register_smi(struct ipmi_smi_ha
        if (rv)
                goto out;
 
-       /* FIXME - this is an ugly kludge, this sets the intf for the
-          caller before sending any messages with it. */
-       *new_intf = intf;
+       rv = handlers->start_processing(send_info, intf);
+       if (rv)
+               goto out;
 
        if ((version_major > 1)
            || ((version_major == 1) && (version_minor >= 5)))
diff -urNp --exclude-from=/home/mdomsch/excludes --minimal 
linux-2.6.16-20060411175326/drivers/char/ipmi/ipmi_si_intf.c 
linux-2.6.16-20060411175326.openipmi/drivers/char/ipmi/ipmi_si_intf.c
--- linux-2.6.16-20060411175326/drivers/char/ipmi/ipmi_si_intf.c        Sun Mar 
19 23:53:29 2006
+++ linux-2.6.16-20060411175326.openipmi/drivers/char/ipmi/ipmi_si_intf.c       
Wed Apr 12 16:55:48 2006
@@ -960,10 +960,40 @@ static irqreturn_t si_bt_irq_handler(int
        return si_irq_handler(irq, data, regs);
 }
 
+static int smi_start_processing(void       *send_info,
+                               ipmi_smi_t intf)
+{
+       struct smi_info *new_smi = send_info;
+
+       new_smi->intf = intf;
+
+       /* Set up the timer that drives the interface. */
+       init_timer(&new_smi->si_timer);
+       new_smi->si_timer.data = (long) new_smi;
+       new_smi->si_timer.function = smi_timeout;
+       new_smi->last_timeout_jiffies = jiffies;
+       new_smi->si_timer.expires = jiffies + SI_TIMEOUT_JIFFIES;
+       add_timer(&new_smi->si_timer);
+
+       if (new_smi->si_type != SI_BT) {
+               new_smi->thread = kthread_run(ipmi_thread, new_smi,
+                                             "kipmi%d", new_smi->intf_num);
+               if (IS_ERR(new_smi->thread)) {
+                       printk(KERN_NOTICE "ipmi_si_intf: Could not start"
+                              " kernel thread due to error %ld, only using"
+                              " timers to drive the interface\n",
+                              PTR_ERR(new_smi->thread));
+                       new_smi->thread = NULL;
+               }
+       }
+
+       return 0;
+}
 
 static struct ipmi_smi_handlers handlers =
 {
        .owner                  = THIS_MODULE,
+       .start_processing       = smi_start_processing,
        .sender                 = sender,
        .request_events         = request_events,
        .set_run_to_completion  = set_run_to_completion,
@@ -2195,9 +2225,13 @@ static void setup_xaction_handlers(struc
 
 static inline void wait_for_timer_and_thread(struct smi_info *smi_info)
 {
-       if (smi_info->thread != NULL && smi_info->thread != ERR_PTR(-ENOMEM))
-               kthread_stop(smi_info->thread);
-       del_timer_sync(&smi_info->si_timer);
+       if (smi_info->intf) {
+               /* The timer and thread are only running if the
+                  interface has been started up and registered. */
+               if (smi_info->thread != NULL)
+                       kthread_stop(smi_info->thread);
+               del_timer_sync(&smi_info->si_timer);
+       }
 }
 
 /* Returns 0 if initialized, or negative on an error. */
@@ -2317,27 +2351,11 @@ static int init_one_smi(int intf_num, st
        if (new_smi->irq)
                new_smi->si_state = SI_CLEARING_FLAGS_THEN_SET_IRQ;
 
-       /* The ipmi_register_smi() code does some operations to
-          determine the channel information, so we must be ready to
-          handle operations before it is called.  This means we have
-          to stop the timer if we get an error after this point. */
-       init_timer(&(new_smi->si_timer));
-       new_smi->si_timer.data = (long) new_smi;
-       new_smi->si_timer.function = smi_timeout;
-       new_smi->last_timeout_jiffies = jiffies;
-       new_smi->si_timer.expires = jiffies + SI_TIMEOUT_JIFFIES;
-
-       add_timer(&(new_smi->si_timer));
-       if (new_smi->si_type != SI_BT)
-               new_smi->thread = kthread_run(ipmi_thread, new_smi,
-                                             "kipmi%d", new_smi->intf_num);
-
        rv = ipmi_register_smi(&handlers,
                               new_smi,
                               ipmi_version_major(&new_smi->device_id),
                               ipmi_version_minor(&new_smi->device_id),
-                              new_smi->slave_addr,
-                              &(new_smi->intf));
+                              new_smi->slave_addr);
        if (rv) {
                printk(KERN_ERR
                       "ipmi_si: Unable to register device: error %d\n",
@@ -2362,7 +2380,7 @@ static int init_one_smi(int intf_num, st
                printk(KERN_ERR
                       "ipmi_si: Unable to create proc entry: %d\n",
                       rv);
-               goto out_err_stop_timer;
+                       goto out_err_stop_timer;
        }
 
        *smi = new_smi;
diff -urNp --exclude-from=/home/mdomsch/excludes --minimal 
linux-2.6.16-20060411175326/include/linux/ipmi_smi.h 
linux-2.6.16-20060411175326.openipmi/include/linux/ipmi_smi.h
--- linux-2.6.16-20060411175326/include/linux/ipmi_smi.h        Sun Mar 19 
23:53:29 2006
+++ linux-2.6.16-20060411175326.openipmi/include/linux/ipmi_smi.h       Wed Apr 
12 16:55:48 2006
@@ -79,6 +79,13 @@ struct ipmi_smi_handlers
 {
        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
@@ -114,13 +121,16 @@ struct ipmi_smi_handlers
 };
 
 /* 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,
                      unsigned char            version_major,
                      unsigned char            version_minor,
-                     unsigned char            slave_addr,
-                     ipmi_smi_t               *intf);
+                     unsigned char            slave_addr);
 
 /*
  * Remove a low-level interface from the IPMI driver.  This will


-------------------------------------------------------
This SF.Net email is sponsored by xPML, a groundbreaking scripting language
that extends applications into web and mobile media. Attend the live webcast
and join the prime developer group breaking into this new coding territory!
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=110944&bid=241720&dat=121642
_______________________________________________
Openipmi-developer mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/openipmi-developer

Reply via email to