Patch for my RHEL3 driver set. Please review. Other distro patches to follow.
-- 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.4.21-32.EL.openipmi.startup/drivers/char/ipmi/ipmi_msghandler.c linux-2.4.21-32.EL.openipmi/drivers/char/ipmi/ipmi_msghandler.c --- linux-2.4.21-32.EL.openipmi.startup/drivers/char/ipmi/ipmi_msghandler.c Tue Mar 28 22:40:44 2006 +++ linux-2.4.21-32.EL.openipmi/drivers/char/ipmi/ipmi_msghandler.c Tue Mar 28 23:12:16 2006 @@ -1701,8 +1701,7 @@ void ipmi_poll_interface(ipmi_user_t use int ipmi_register_smi(struct ipmi_smi_handlers *handlers, void *send_info, unsigned char version_major, - unsigned char version_minor, - ipmi_smi_t *intf) + unsigned char version_minor) { int i, j; int rv; @@ -1766,7 +1765,6 @@ int ipmi_register_smi(struct ipmi_smi_ha spin_unlock_irqrestore(&interfaces_lock, flags); rv = 0; - *intf = new_intf; break; } } @@ -1781,8 +1779,14 @@ int ipmi_register_smi(struct ipmi_smi_ha /* Well, it went away. Just return. */ goto out; + if (rv == 0) { + rv = handlers->start_processing(send_info, new_intf); + if (rv) + goto out; + } + if (rv == 0) - rv = add_proc_entries(*intf, i); + rv = add_proc_entries(new_intf, i); if (rv == 0) { if ((version_major > 1) @@ -1790,16 +1794,16 @@ int ipmi_register_smi(struct ipmi_smi_ha { /* Start scanning the channels to see what is available. */ - (*intf)->null_user_handler = channel_handler; - (*intf)->curr_channel = 0; - rv = send_channel_info_cmd(*intf, 0); + new_intf->null_user_handler = channel_handler; + new_intf->curr_channel = 0; + rv = send_channel_info_cmd(new_intf, 0); if (rv) goto out; /* Wait for the channel info to be read. */ up_read(&interfaces_sem); - wait_event((*intf)->waitq, - ((*intf)->curr_channel>=IPMI_MAX_CHANNELS)); + wait_event(new_intf->waitq, + (new_intf->curr_channel>=IPMI_MAX_CHANNELS)); down_read(&interfaces_sem); if (ipmi_interfaces[i] != new_intf) @@ -1807,8 +1811,8 @@ int ipmi_register_smi(struct ipmi_smi_ha goto out; } else { /* Assume a single IPMB channel at zero. */ - (*intf)->channels[0].medium = IPMI_CHANNEL_MEDIUM_IPMB; - (*intf)->channels[0].protocol + new_intf->channels[0].medium = IPMI_CHANNEL_MEDIUM_IPMB; + new_intf->channels[0].protocol = IPMI_CHANNEL_PROTOCOL_IPMB; } diff -urNp --exclude-from=/home/mdomsch/excludes --minimal linux-2.4.21-32.EL.openipmi.startup/drivers/char/ipmi/ipmi_si.c linux-2.4.21-32.EL.openipmi/drivers/char/ipmi/ipmi_si.c --- linux-2.4.21-32.EL.openipmi.startup/drivers/char/ipmi/ipmi_si.c Tue Mar 28 22:40:44 2006 +++ linux-2.4.21-32.EL.openipmi/drivers/char/ipmi/ipmi_si.c Tue Mar 28 23:09:35 2006 @@ -956,9 +956,37 @@ static void si_irq_handler(int irq, void spin_unlock_irqrestore(&(smi_info->si_lock), flags); } +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) { + init_completion(&(new_smi->exiting)); + new_smi->thread_pid = kernel_thread(ipmi_thread, new_smi, + CLONE_FS|CLONE_FILES| + CLONE_SIGHAND); + if (new_smi->thread_pid <= 0) { + printk(KERN_NOTICE "ipmi_si: Could not start" + " kernel thread due to error, only using" + " timers to drive the interface\n"); + } + } + return 0; +} + static struct ipmi_smi_handlers handlers = { sender: sender, + start_processing: smi_start_processing, request_events: request_events, new_user: new_user, user_left: user_left, @@ -2174,12 +2202,16 @@ static void setup_xaction_handlers(struc static inline void wait_for_timer_and_thread(struct smi_info *smi_info) { - if (smi_info->thread_pid > 0) { - /* wake the potentially sleeping thread */ - kill_proc(smi_info->thread_pid, SIGKILL, 0); - wait_for_completion(&(smi_info->exiting)); + if (smi_info->intf) { + /* The timer and thread are only running if the + interface has been started up and registered. */ + if (smi_info->thread_pid > 0) { + /* wake the potentially sleeping thread */ + kill_proc(smi_info->thread_pid, SIGKILL, 0); + wait_for_completion(&(smi_info->exiting)); + } + del_timer_sync(&smi_info->si_timer); } - del_timer_sync(&smi_info->si_timer); } /* Returns 0 if initialized, or negative on an error. */ @@ -2303,29 +2335,10 @@ 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) { - init_completion(&(new_smi->exiting)); - new_smi->thread_pid = kernel_thread(ipmi_thread, new_smi, - CLONE_FS|CLONE_FILES| - CLONE_SIGHAND); - } - rv = ipmi_register_smi(&handlers, new_smi, ipmi_version_major(new_smi->device_id.ipmi_version), - ipmi_version_minor(new_smi->device_id.ipmi_version), - &(new_smi->intf)); + ipmi_version_minor(new_smi->device_id.ipmi_version)); if (rv) { printk(KERN_ERR "ipmi_si: Unable to register device: error %d\n", diff -urNp --exclude-from=/home/mdomsch/excludes --minimal linux-2.4.21-32.EL.openipmi.startup/include/linux/ipmi_smi.h linux-2.4.21-32.EL.openipmi/include/linux/ipmi_smi.h --- linux-2.4.21-32.EL.openipmi.startup/include/linux/ipmi_smi.h Tue Mar 28 22:40:44 2006 +++ linux-2.4.21-32.EL.openipmi/include/linux/ipmi_smi.h Tue Mar 28 23:06:35 2006 @@ -77,6 +77,13 @@ struct ipmi_smi_msg struct ipmi_smi_handlers { + /* 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 @@ -113,12 +120,15 @@ struct ipmi_smi_handlers void (*poll)(void *send_info); }; -/* Add a low-level interface to the IPMI driver. */ +/* Add a low-level interface to the IPMI driver. + 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, - ipmi_smi_t *intf); + unsigned char version_minor); /* * 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
