I'm having a problem with the latest kernels not allowing me to
communicate over the IPMB bus.
I've been testing the latest Fedora, Red Hat 4 and SLES 10 (Beta/Release
candidates) kernels and they have all started failing with the most
recent versions.
The symptom is that when I attempt to send a message over the IPMB I get
the following error:
linux-0w10:~ # ipmitool -m 142 -t 32 bmc info
Unable to send command: Invalid argument
Get Device ID command failed
I have drilled down through the code and found that the reason is that
the code that identifies the channels is receiving something it doesn't
expect from my BMC and marking channel 0 as unavailable and therefore
messages addressed to the IPMB are denied as "invalid argument".
The hardware I am testing is somewhat like an ATCA in that I have on
chassis with 12 server blades and two management/networking blades. The
BMC on the server blades and the management blade communicate over a
IPMB to effect management of the chassis. The chassis is a Penguin
Computing BladeRunner.
In my reading of the spec, channel 0 is always and only an IPMB bus.
Therefore, I have written a patch that forces this assumption, while
keeping the rest of the channel scanning logic. I have tried to
simplify the scanning logic. Also, I have modified the code to *not*
scan channels 8-14 which are reserved or special.
The attached patch is against the SLES 10 Release Candidate 2
(2.6.16-xxx) kernel. I'll happily rebase it against some other kernel
tree if you can tell me what tree you would prefer the patch against.
With it applied, I get the following output when loading the ipmi
drivers. I've enabled DEBUG_MSGING so that the actual messages
sent/received are printed out.
ipmi message handler version 38.1
IPMI System Interface driver.
ipmi_si: Found SMBIOS-specified state machine at I/O address 0xca2,
slave address 0x20
Send: 18 42 01
Recv: 1c 42 ff
Send: 18 42 02
Recv: 1c 42 d3
Send: 18 42 03
Recv: 1c 42 ff
Send: 18 42 04
Recv: 1c 42 00 04 0c 05 00 f2 1b 00 00 00
Send: 18 42 05
Recv: 1c 42 d3
Send: 18 42 06
Recv: 1c 42 ff
Send: 18 42 07
Recv: 1c 42 d3
Send: 18 42 0f
Recv: 1c 42 ff
IPMI kcs interface initialized
ipmi device interface
You can see that the BMC is replying with 'ff' as the status. It does
this when queried about channel 0 as well, but not all the time. (but
probably 95% of the time) I am working with the BMC code to try and
figure out why it's responding with 'ff', but the attached patch
resolves the primary pain I have now where I can't manage the chassis
because I can't send messages over the IPMB.
Thanks,
:v)
--
Philip Pokorny, Director of Engineering
Tel: 415-370-0835 Fax: 415-954-2899 Toll Free: 888-PENGUIN
PENGUIN COMPUTING, INC.
www.penguincomputing.com
--- linux-2.6.16.11-7/drivers/char/ipmi/ipmi_msghandler.c 2006-04-26 03:21:58.000000000 -0700
+++ linux-2.6.16.11-7.ipmi/drivers/char/ipmi/ipmi_msghandler.c 2006-05-31 19:54:31.000000000 -0700
@@ -1439,6 +1439,7 @@
#ifdef DEBUG_MSGING
{
int m;
+ printk("Send:");
for (m = 0; m < smi_msg->data_size; m++)
printk(" %2.2x", smi_msg->data[m]);
printk("\n");
@@ -1711,7 +1712,7 @@
}
static int
-send_channel_info_cmd(ipmi_smi_t intf, int chan)
+send_channel_info_cmd(ipmi_smi_t intf)
{
struct kernel_ipmi_msg msg;
unsigned char data[1];
@@ -1725,7 +1726,7 @@
msg.cmd = IPMI_GET_CHANNEL_INFO_CMD;
msg.data = data;
msg.data_len = 1;
- data[0] = chan;
+ data[0] = intf->curr_channel ;
return i_ipmi_request(NULL,
intf,
(struct ipmi_addr *) &si,
@@ -1751,52 +1752,49 @@
&& (msg->msg.cmd == IPMI_GET_CHANNEL_INFO_CMD))
{
/* It's the one we want */
- if (msg->msg.data[0] != 0) {
- /* Got an error from the channel, just go on. */
-
- if (msg->msg.data[0] == IPMI_INVALID_COMMAND_ERR) {
- /* If the MC does not support this
- command, that is legal. We just
- assume it has one IPMB at channel
- zero. */
- intf->channels[0].medium
- = IPMI_CHANNEL_MEDIUM_IPMB;
- intf->channels[0].protocol
- = IPMI_CHANNEL_PROTOCOL_IPMB;
- rv = -ENOSYS;
-
- intf->curr_channel = IPMI_MAX_CHANNELS;
- wake_up(&intf->waitq);
- goto out;
- }
- goto next_channel;
+ if (msg->msg.data[0] == IPMI_INVALID_COMMAND_ERR) {
+ /* If the MC does not support this
+ command, that is legal. Just
+ stop scanning. We previously marked
+ channel 0 as IPMB. */
+ rv = -ENOSYS;
+ intf->curr_channel = IPMI_MAX_CHANNELS;
+ goto out ;
}
- if (msg->msg.data_len < 4) {
- /* Message not big enough, just go on. */
- goto next_channel;
+
+ if (msg->msg.data[0] == 0 && msg->msg.data_len == 4) {
+ /* Got what we wanted, save it */
+ chan = intf->curr_channel;
+ intf->channels[chan].medium = msg->msg.data[2] & 0x7f;
+ intf->channels[chan].protocol = msg->msg.data[3] & 0x1f;
}
- chan = intf->curr_channel;
- intf->channels[chan].medium = msg->msg.data[2] & 0x7f;
- intf->channels[chan].protocol = msg->msg.data[3] & 0x1f;
- next_channel:
+ /* Next channel */
intf->curr_channel++;
- if (intf->curr_channel >= IPMI_MAX_CHANNELS)
- wake_up(&intf->waitq);
- else
- rv = send_channel_info_cmd(intf, intf->curr_channel);
+ if( intf->curr_channel == 8 ) {
+ /* Channels 8-13 are reserved.
+ * Channel 14 has special meaning
+ * So skip to 15 (System Interface Channel)
+ */
+ intf->curr_channel = 15 ;
+ }
- if (rv) {
- /* Got an error somehow, just give up. */
- intf->curr_channel = IPMI_MAX_CHANNELS;
- wake_up(&intf->waitq);
+ if (intf->curr_channel < IPMI_MAX_CHANNELS) {
+ rv = send_channel_info_cmd(intf);
- printk(KERN_WARNING PFX
- "Error sending channel information: %d\n",
- rv);
+ if (rv) {
+ /* Got an error somehow, just give up. */
+ intf->curr_channel = IPMI_MAX_CHANNELS;
+ printk(KERN_WARNING PFX
+ "Error sending channel information request: %d\n",
+ rv);
+ }
}
}
out:
+ if (intf->curr_channel >= IPMI_MAX_CHANNELS)
+ wake_up(&intf->waitq);
+
return;
}
@@ -1884,11 +1882,14 @@
if ((version_major > 1)
|| ((version_major == 1) && (version_minor >= 5)))
{
+ /* IPMI spec says channel 0 is alwasy IPMB */
+ intf->channels[0].medium = IPMI_CHANNEL_MEDIUM_IPMB;
+ intf->channels[0].protocol = IPMI_CHANNEL_PROTOCOL_IPMB;
/* 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);
+ intf->curr_channel = 1;
+ rv = send_channel_info_cmd(intf);
if (rv)
goto out;
_______________________________________________
Openipmi-developer mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/openipmi-developer