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
