From: Andrew Morton commit 4dec302ff71ebf48f5784a2d2fc5e3745e6d4d52 Author: dann frazier Date: Tue Apr 21 12:24:05 2009 -0700 ipmi: add oem message handling Enable userspace to receive messages that a BMC transmits using an OEM medium. This is used by the HP iLO2. Based on code originally written by Patrick Schoeller. Signed-off-by: dann frazier Signed-off-by: Corey Minyard Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Andrew Morton --- drivers/char/ipmi/ipmi_msghandler.c | 138 -------------------------- include/linux/ipmi.h | 2 include/linux/ipmi_msgdefs.h | 2 3 files changed, 5 insertions(+), 137 deletions(-) diff -puN drivers/char/ipmi/ipmi_msghandler.c~revert-1 drivers/char/ipmi/ipmi_msghandler.c --- a/drivers/char/ipmi/ipmi_msghandler.c~revert-1 +++ a/drivers/char/ipmi/ipmi_msghandler.c @@ -3284,114 +3284,6 @@ static int handle_lan_get_msg_cmd(ipmi_s return rv; } -/* - * This routine will handle "Get Message" command responses with - * channels that use an OEM Medium. The message format belongs to - * the OEM. See IPMI 2.0 specification, Chapter 6 and - * Chapter 22, sections 22.6 and 22.24 for more details. - */ -static int handle_oem_get_msg_cmd(ipmi_smi_t intf, - struct ipmi_smi_msg *msg) -{ - struct cmd_rcvr *rcvr; - int rv = 0; - unsigned char netfn; - unsigned char cmd; - unsigned char chan; - ipmi_user_t user = NULL; - struct ipmi_system_interface_addr *smi_addr; - struct ipmi_recv_msg *recv_msg; - - /* - * We expect the OEM SW to perform error checking - * so we just do some basic sanity checks - */ - if (msg->rsp_size < 4) { - /* Message not big enough, just ignore it. */ - ipmi_inc_stat(intf, invalid_commands); - return 0; - } - - if (msg->rsp[2] != 0) { - /* An error getting the response, just ignore it. */ - return 0; - } - - /* - * This is an OEM Message so the OEM needs to know how - * handle the message. We do no interpretation. - */ - netfn = msg->rsp[0] >> 2; - cmd = msg->rsp[1]; - chan = msg->rsp[3] & 0xf; - - rcu_read_lock(); - rcvr = find_cmd_rcvr(intf, netfn, cmd, chan); - if (rcvr) { - user = rcvr->user; - kref_get(&user->refcount); - } else - user = NULL; - rcu_read_unlock(); - - if (user == NULL) { - /* We didn't find a user, just give up. */ - ipmi_inc_stat(intf, unhandled_commands); - - /* - * Don't do anything with these messages, just allow - * them to be freed. - */ - - rv = 0; - } else { - /* Deliver the message to the user. */ - ipmi_inc_stat(intf, handled_commands); - - recv_msg = ipmi_alloc_recv_msg(); - if (!recv_msg) { - /* - * We couldn't allocate memory for the - * message, so requeue it for handling - * later. - */ - rv = 1; - kref_put(&user->refcount, free_user); - } else { - /* - * OEM Messages are expected to be delivered via - * the system interface to SMS software. We might - * need to visit this again depending on OEM - * requirements - */ - smi_addr = ((struct ipmi_system_interface_addr *) - &(recv_msg->addr)); - smi_addr->addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE; - smi_addr->channel = IPMI_BMC_CHANNEL; - smi_addr->lun = msg->rsp[0] & 3; - - recv_msg->user = user; - recv_msg->user_msg_data = NULL; - recv_msg->recv_type = IPMI_OEM_RECV_TYPE; - recv_msg->msg.netfn = msg->rsp[0] >> 2; - recv_msg->msg.cmd = msg->rsp[1]; - recv_msg->msg.data = recv_msg->msg_data; - - /* - * The message starts at byte 4 which follows the - * the Channel Byte in the "GET MESSAGE" command - */ - recv_msg->msg.data_len = msg->rsp_size - 4; - memcpy(recv_msg->msg_data, - &(msg->rsp[4]), - msg->rsp_size - 4); - deliver_response(recv_msg); - } - } - - return rv; -} - static void copy_event_into_recv_msg(struct ipmi_recv_msg *recv_msg, struct ipmi_smi_msg *msg) { @@ -3647,17 +3539,6 @@ static int handle_new_recv_msg(ipmi_smi_ goto out; } - /* - ** We need to make sure the channels have been initialized. - ** The channel_handler routine will set the "curr_channel" - ** equal to or greater than IPMI_MAX_CHANNELS when all the - ** channels for this interface have been initialized. - */ - if (intf->curr_channel < IPMI_MAX_CHANNELS) { - requeue = 1; /* Just put the message back for now */ - goto out; - } - switch (intf->channels[chan].medium) { case IPMI_CHANNEL_MEDIUM_IPMB: if (msg->rsp[4] & 0x04) { @@ -3693,20 +3574,11 @@ static int handle_new_recv_msg(ipmi_smi_ break; default: - /* Check for OEM Channels. Clients had better - register for these commands. */ - if ((intf->channels[chan].medium - >= IPMI_CHANNEL_MEDIUM_OEM_MIN) - && (intf->channels[chan].medium - <= IPMI_CHANNEL_MEDIUM_OEM_MAX)) { - requeue = handle_oem_get_msg_cmd(intf, msg); - } else { - /* - * We don't handle the channel type, so just - * free the message. - */ - requeue = 0; - } + /* + * We don't handle the channel type, so just + * free the message. + */ + requeue = 0; } } else if ((msg->rsp[0] == ((IPMI_NETFN_APP_REQUEST|1) << 2)) diff -puN include/linux/ipmi.h~revert-1 include/linux/ipmi.h --- a/include/linux/ipmi.h~revert-1 +++ a/include/linux/ipmi.h @@ -198,8 +198,6 @@ struct kernel_ipmi_msg { response. When you send a response message, this will be returned. */ -#define IPMI_OEM_RECV_TYPE 5 /* The response for OEM Channels */ - /* Note that async events and received commands do not have a completion code as the first byte of the incoming data, unlike a response. */ diff -puN include/linux/ipmi_msgdefs.h~revert-1 include/linux/ipmi_msgdefs.h --- a/include/linux/ipmi_msgdefs.h~revert-1 +++ a/include/linux/ipmi_msgdefs.h @@ -115,7 +115,5 @@ #define IPMI_CHANNEL_MEDIUM_USB1 10 #define IPMI_CHANNEL_MEDIUM_USB2 11 #define IPMI_CHANNEL_MEDIUM_SYSINTF 12 -#define IPMI_CHANNEL_MEDIUM_OEM_MIN 0x60 -#define IPMI_CHANNEL_MEDIUM_OEM_MAX 0x7f #endif /* __LINUX_IPMI_MSGDEFS_H */ _