This is broken hardware/firmware, and this general workaround is not a
good idea. The trouble is that some systems don't have any IPMB bus,
and you need to correctly identify these systems.
My first recommendation is to try to get the hardware vendor to fix the
problem, since it is their bug. You seem to have the BMC code, so the
fix should be there and a firmware upgrade should be able to fix the
problem. Barring that, this would need some type of blacklist type
thing based upon the manufacturer and product id.
But you should really fix the firmware, because other higher-level code
sends this command to know what channels are available. So it will
break other things besides the driver.
A few comments on the patch:
* I don't like the change to send_channel_info_cmd(). That makes
the function useless for other purposes, and doesn't really save
anything.
* Skipping channels 8-14 (or 8-15, really) is probably a good idea,
but scanning them is somewhat harmless. I'll think about that one.
-Corey
Philip Pokorny wrote:
> 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)
>
>------------------------------------------------------------------------
>
>--- 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
>
>
_______________________________________________
Openipmi-developer mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/openipmi-developer