Patch for SLES9 SP2 and higher. Please review.
diff -urNp --exclude-from=/home/mdomsch/excludes --minimal
linux-2.6.5-SLES9_SP3_BRANCH_20050907143416.openipmi/drivers/char/ipmi/ipmi_msghandler.c
linux-2.6.5-SLES9_SP3_BRANCH_20050907143416.openipmi.startup/drivers/char/ipmi/ipmi_msghandler.c
---
linux-2.6.5-SLES9_SP3_BRANCH_20050907143416.openipmi/drivers/char/ipmi/ipmi_msghandler.c
Wed Mar 29 10:32:57 2006
+++
linux-2.6.5-SLES9_SP3_BRANCH_20050907143416.openipmi.startup/drivers/char/ipmi/ipmi_msghandler.c
Wed Mar 29 10:35:47 2006
@@ -1725,8 +1725,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 *intf)
+ unsigned char slave_addr)
{
int i, j;
int rv;
@@ -1797,15 +1796,17 @@ int ipmi_register_smi(struct ipmi_smi_ha
spin_unlock_irqrestore(&interfaces_lock, flags);
rv = 0;
- *intf = new_intf;
break;
}
}
downgrade_write(&interfaces_sem);
+ if (rv)
+ goto out;
- if (rv == 0)
- rv = add_proc_entries(*intf, i);
+ rv = handlers->start_processing(send_info, new_intf);
+ if (rv)
+ goto out;
if (rv == 0) {
if ((version_major > 1)
@@ -1813,16 +1814,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)
@@ -1830,8 +1831,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;
}
@@ -1839,6 +1840,9 @@ int ipmi_register_smi(struct ipmi_smi_ha
them that a new interface is available. */
call_smi_watchers(i);
}
+
+ if (rv == 0)
+ rv = add_proc_entries(new_intf, i);
out:
up_read(&interfaces_sem);
diff -urNp --exclude-from=/home/mdomsch/excludes --minimal
linux-2.6.5-SLES9_SP3_BRANCH_20050907143416.openipmi/drivers/char/ipmi/ipmi_si_intf.c
linux-2.6.5-SLES9_SP3_BRANCH_20050907143416.openipmi.startup/drivers/char/ipmi/ipmi_si_intf.c
---
linux-2.6.5-SLES9_SP3_BRANCH_20050907143416.openipmi/drivers/char/ipmi/ipmi_si_intf.c
Wed Mar 29 10:32:57 2006
+++
linux-2.6.5-SLES9_SP3_BRANCH_20050907143416.openipmi.startup/drivers/char/ipmi/ipmi_si_intf.c
Wed Mar 29 10:36:45 2006
@@ -959,10 +959,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,
@@ -2279,9 +2309,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. */
@@ -2401,27 +2435,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",
diff -urNp --exclude-from=/home/mdomsch/excludes --minimal
linux-2.6.5-SLES9_SP3_BRANCH_20050907143416.openipmi/include/linux/ipmi_smi.h
linux-2.6.5-SLES9_SP3_BRANCH_20050907143416.openipmi.startup/include/linux/ipmi_smi.h
---
linux-2.6.5-SLES9_SP3_BRANCH_20050907143416.openipmi/include/linux/ipmi_smi.h
Wed Mar 29 10:32:57 2006
+++
linux-2.6.5-SLES9_SP3_BRANCH_20050907143416.openipmi.startup/include/linux/ipmi_smi.h
Wed Mar 29 10:35:47 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,17 @@ 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
--
Matt Domsch
Software Architect
Dell Linux Solutions linux.dell.com & www.dell.com/linux
Linux on Dell mailing lists @ http://lists.us.dell.com
-------------------------------------------------------
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