Loading drivers/char/ipmi/ipmi_msghandler.c +111 −58 Original line number Diff line number Diff line Loading @@ -242,11 +242,16 @@ struct seq_table { #define NEXT_SEQID(seqid) (((seqid) + 1) & 0x3ffffff) #define IPMI_MAX_CHANNELS 16 struct ipmi_channel { unsigned char medium; unsigned char protocol; }; struct ipmi_channel_set { struct ipmi_channel c[IPMI_MAX_CHANNELS]; }; struct ipmi_my_addrinfo { /* * My slave address. This is initialized to IPMI_BMC_SLAVE_ADDR, Loading Loading @@ -398,7 +403,6 @@ enum ipmi_stat_indexes { #define IPMI_IPMB_NUM_SEQ 64 #define IPMI_MAX_CHANNELS 16 struct ipmi_smi { /* What interface number are we? */ int intf_num; Loading Loading @@ -531,8 +535,11 @@ struct ipmi_smi { int curr_channel; /* Channel information */ struct ipmi_channel channels[IPMI_MAX_CHANNELS]; struct ipmi_channel_set *channel_list; unsigned int curr_working_cset; /* First index into the following. */ struct ipmi_channel_set wchannels[2]; struct ipmi_my_addrinfo addrinfo[IPMI_MAX_CHANNELS]; bool channels_ready; /* Proc FS stuff. */ struct proc_dir_entry *proc_dir; Loading @@ -554,6 +561,7 @@ static void __ipmi_bmc_unregister(ipmi_smi_t intf); static int __ipmi_bmc_register(ipmi_smi_t intf, struct ipmi_device_id *id, bool guid_set, u8 *guid, int intf_num); static int __scan_channels(ipmi_smi_t intf, struct ipmi_device_id *id); /** Loading Loading @@ -1775,6 +1783,7 @@ static int i_ipmi_request(ipmi_user_t user, unsigned char ipmb_seq; long seqid; int broadcast = 0; struct ipmi_channel *chans; if (addr->channel >= IPMI_MAX_CHANNELS) { ipmi_inc_stat(intf, sent_invalid_commands); Loading @@ -1782,8 +1791,9 @@ static int i_ipmi_request(ipmi_user_t user, goto out_err; } if (intf->channels[addr->channel].medium != IPMI_CHANNEL_MEDIUM_IPMB) { chans = READ_ONCE(intf->channel_list)->c; if (chans[addr->channel].medium != IPMI_CHANNEL_MEDIUM_IPMB) { ipmi_inc_stat(intf, sent_invalid_commands); rv = -EINVAL; goto out_err; Loading Loading @@ -1905,6 +1915,7 @@ static int i_ipmi_request(ipmi_user_t user, struct ipmi_lan_addr *lan_addr; unsigned char ipmb_seq; long seqid; struct ipmi_channel *chans; if (addr->channel >= IPMI_MAX_CHANNELS) { ipmi_inc_stat(intf, sent_invalid_commands); Loading @@ -1912,9 +1923,11 @@ static int i_ipmi_request(ipmi_user_t user, goto out_err; } if ((intf->channels[addr->channel].medium chans = READ_ONCE(intf->channel_list)->c; if ((chans[addr->channel].medium != IPMI_CHANNEL_MEDIUM_8023LAN) && (intf->channels[addr->channel].medium && (chans[addr->channel].medium != IPMI_CHANNEL_MEDIUM_ASYNC)) { ipmi_inc_stat(intf, sent_invalid_commands); rv = -EINVAL; Loading Loading @@ -2282,6 +2295,9 @@ static int __bmc_get_device_id(ipmi_smi_t intf, struct bmc_device *bmc, memcpy(intf->bmc->guid, guid, 16); if (__ipmi_bmc_register(intf, &id, guid_set, guid, intf_num)) need_waiter(intf); /* Retry later on an error. */ else __scan_channels(intf, &id); if (!intf_set) { /* Loading @@ -2298,7 +2314,9 @@ static int __bmc_get_device_id(ipmi_smi_t intf, struct bmc_device *bmc, bmc = intf->bmc; mutex_lock(&bmc->dyn_mutex); goto out_noprocessing; } } else if (memcmp(&bmc->fetch_id, &bmc->id, sizeof(bmc->id))) /* Version info changes, scan the channels again. */ __scan_channels(intf, &bmc->fetch_id); bmc->dyn_id_expiry = jiffies + IPMI_DYN_DEV_ID_EXPIRY; Loading Loading @@ -3212,7 +3230,9 @@ static void channel_handler(ipmi_smi_t intf, struct ipmi_recv_msg *msg) { int rv = 0; int chan; int ch; unsigned int set = intf->curr_working_cset; struct ipmi_channel *chans; if ((msg->addr.addr_type == IPMI_SYSTEM_INTERFACE_ADDR_TYPE) && (msg->msg.netfn == IPMI_NETFN_APP_RESPONSE) Loading @@ -3228,12 +3248,13 @@ channel_handler(ipmi_smi_t intf, struct ipmi_recv_msg *msg) * assume it has one IPMB at channel * zero. */ intf->channels[0].medium intf->wchannels[set].c[0].medium = IPMI_CHANNEL_MEDIUM_IPMB; intf->channels[0].protocol intf->wchannels[set].c[0].protocol = IPMI_CHANNEL_PROTOCOL_IPMB; intf->curr_channel = IPMI_MAX_CHANNELS; intf->channel_list = intf->wchannels + set; intf->channels_ready = true; wake_up(&intf->waitq); goto out; } Loading @@ -3243,16 +3264,22 @@ channel_handler(ipmi_smi_t intf, struct ipmi_recv_msg *msg) /* Message not big enough, just go on. */ goto next_channel; } chan = intf->curr_channel; intf->channels[chan].medium = msg->msg.data[2] & 0x7f; intf->channels[chan].protocol = msg->msg.data[3] & 0x1f; ch = intf->curr_channel; chans = intf->wchannels[set].c; chans[ch].medium = msg->msg.data[2] & 0x7f; chans[ch].protocol = msg->msg.data[3] & 0x1f; next_channel: intf->curr_channel++; if (intf->curr_channel >= IPMI_MAX_CHANNELS) if (intf->curr_channel >= IPMI_MAX_CHANNELS) { intf->channel_list = intf->wchannels + set; intf->channels_ready = true; wake_up(&intf->waitq); else } else { intf->channel_list = intf->wchannels + set; intf->channels_ready = true; rv = send_channel_info_cmd(intf, intf->curr_channel); } if (rv) { /* Got an error somehow, just give up. */ Loading @@ -3260,7 +3287,8 @@ channel_handler(ipmi_smi_t intf, struct ipmi_recv_msg *msg) "Error sending channel information for channel" " %d: %d\n", intf->curr_channel, rv); intf->curr_channel = IPMI_MAX_CHANNELS; intf->channel_list = intf->wchannels + set; intf->channels_ready = true; wake_up(&intf->waitq); } } Loading @@ -3268,6 +3296,53 @@ channel_handler(ipmi_smi_t intf, struct ipmi_recv_msg *msg) return; } /* * Must be holding intf->bmc_reg_mutex to call this. */ static int __scan_channels(ipmi_smi_t intf, struct ipmi_device_id *id) { int rv; if (ipmi_version_major(id) > 1 || (ipmi_version_major(id) == 1 && ipmi_version_minor(id) >= 5)) { unsigned int set; /* * Start scanning the channels to see what is * available. */ set = !intf->curr_working_cset; intf->curr_working_cset = set; memset(&intf->wchannels[set], 0, sizeof(struct ipmi_channel_set)); intf->null_user_handler = channel_handler; intf->curr_channel = 0; rv = send_channel_info_cmd(intf, 0); if (rv) { dev_warn(intf->si_dev, "Error sending channel information for channel 0, %d\n", rv); return -EIO; } /* Wait for the channel info to be read. */ wait_event(intf->waitq, intf->channels_ready); intf->null_user_handler = NULL; } else { unsigned int set = intf->curr_working_cset; /* Assume a single IPMB channel at zero. */ intf->wchannels[set].c[0].medium = IPMI_CHANNEL_MEDIUM_IPMB; intf->wchannels[set].c[0].protocol = IPMI_CHANNEL_PROTOCOL_IPMB; intf->channel_list = intf->wchannels + set; intf->channels_ready = true; } return 0; } static void ipmi_poll(ipmi_smi_t intf) { if (intf->handlers->poll) Loading Loading @@ -3402,35 +3477,11 @@ int ipmi_register_smi(const struct ipmi_smi_handlers *handlers, goto out; } if (ipmi_version_major(&id) > 1 || (ipmi_version_major(&id) == 1 && ipmi_version_minor(&id) >= 5)) { /* * Start scanning the channels to see what is * available. */ mutex_lock(&intf->bmc_reg_mutex); intf->null_user_handler = channel_handler; intf->curr_channel = 0; rv = send_channel_info_cmd(intf, 0); if (rv) { printk(KERN_WARNING PFX "Error sending channel information for channel" " 0, %d\n", rv); goto out; } /* Wait for the channel info to be read. */ wait_event(intf->waitq, intf->curr_channel >= IPMI_MAX_CHANNELS); intf->null_user_handler = NULL; rv = __scan_channels(intf, &id); mutex_unlock(&intf->bmc_reg_mutex); } else { /* Assume a single IPMB channel at zero. */ intf->channels[0].medium = IPMI_CHANNEL_MEDIUM_IPMB; intf->channels[0].protocol = IPMI_CHANNEL_PROTOCOL_IPMB; intf->curr_channel = IPMI_MAX_CHANNELS; } if (rv) goto out; rv = add_proc_entries(intf, i); Loading Loading @@ -4259,6 +4310,8 @@ static int handle_one_recv_msg(ipmi_smi_t intf, deliver_response(recv_msg); } else if ((msg->rsp[0] == ((IPMI_NETFN_APP_REQUEST|1) << 2)) && (msg->rsp[1] == IPMI_GET_MSG_CMD)) { struct ipmi_channel *chans; /* It's from the receive queue. */ chan = msg->rsp[3] & 0xf; if (chan >= IPMI_MAX_CHANNELS) { Loading @@ -4273,12 +4326,14 @@ static int handle_one_recv_msg(ipmi_smi_t intf, * 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) { if (!intf->channels_ready) { requeue = 0; /* Throw the message away */ goto out; } switch (intf->channels[chan].medium) { chans = READ_ONCE(intf->channel_list)->c; switch (chans[chan].medium) { case IPMI_CHANNEL_MEDIUM_IPMB: if (msg->rsp[4] & 0x04) { /* Loading Loading @@ -4315,9 +4370,8 @@ static int handle_one_recv_msg(ipmi_smi_t intf, 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 if ((chans[chan].medium >= IPMI_CHANNEL_MEDIUM_OEM_MIN) && (chans[chan].medium <= IPMI_CHANNEL_MEDIUM_OEM_MAX)) { requeue = handle_oem_get_msg_cmd(intf, msg); } else { Loading Loading @@ -4479,15 +4533,14 @@ void ipmi_smi_msg_received(ipmi_smi_t intf, && (msg->rsp[2] != IPMI_LOST_ARBITRATION_ERR) && (msg->rsp[2] != IPMI_BUS_ERR) && (msg->rsp[2] != IPMI_NAK_ON_WRITE_ERR)) { int chan = msg->rsp[3] & 0xf; int ch = msg->rsp[3] & 0xf; struct ipmi_channel *chans; /* Got an error sending the message, handle it. */ if (chan >= IPMI_MAX_CHANNELS) ; /* This shouldn't happen */ else if ((intf->channels[chan].medium == IPMI_CHANNEL_MEDIUM_8023LAN) || (intf->channels[chan].medium == IPMI_CHANNEL_MEDIUM_ASYNC)) chans = READ_ONCE(intf->channel_list)->c; if ((chans[ch].medium == IPMI_CHANNEL_MEDIUM_8023LAN) || (chans[ch].medium == IPMI_CHANNEL_MEDIUM_ASYNC)) ipmi_inc_stat(intf, sent_lan_command_errs); else ipmi_inc_stat(intf, sent_ipmb_command_errs); Loading Loading
drivers/char/ipmi/ipmi_msghandler.c +111 −58 Original line number Diff line number Diff line Loading @@ -242,11 +242,16 @@ struct seq_table { #define NEXT_SEQID(seqid) (((seqid) + 1) & 0x3ffffff) #define IPMI_MAX_CHANNELS 16 struct ipmi_channel { unsigned char medium; unsigned char protocol; }; struct ipmi_channel_set { struct ipmi_channel c[IPMI_MAX_CHANNELS]; }; struct ipmi_my_addrinfo { /* * My slave address. This is initialized to IPMI_BMC_SLAVE_ADDR, Loading Loading @@ -398,7 +403,6 @@ enum ipmi_stat_indexes { #define IPMI_IPMB_NUM_SEQ 64 #define IPMI_MAX_CHANNELS 16 struct ipmi_smi { /* What interface number are we? */ int intf_num; Loading Loading @@ -531,8 +535,11 @@ struct ipmi_smi { int curr_channel; /* Channel information */ struct ipmi_channel channels[IPMI_MAX_CHANNELS]; struct ipmi_channel_set *channel_list; unsigned int curr_working_cset; /* First index into the following. */ struct ipmi_channel_set wchannels[2]; struct ipmi_my_addrinfo addrinfo[IPMI_MAX_CHANNELS]; bool channels_ready; /* Proc FS stuff. */ struct proc_dir_entry *proc_dir; Loading @@ -554,6 +561,7 @@ static void __ipmi_bmc_unregister(ipmi_smi_t intf); static int __ipmi_bmc_register(ipmi_smi_t intf, struct ipmi_device_id *id, bool guid_set, u8 *guid, int intf_num); static int __scan_channels(ipmi_smi_t intf, struct ipmi_device_id *id); /** Loading Loading @@ -1775,6 +1783,7 @@ static int i_ipmi_request(ipmi_user_t user, unsigned char ipmb_seq; long seqid; int broadcast = 0; struct ipmi_channel *chans; if (addr->channel >= IPMI_MAX_CHANNELS) { ipmi_inc_stat(intf, sent_invalid_commands); Loading @@ -1782,8 +1791,9 @@ static int i_ipmi_request(ipmi_user_t user, goto out_err; } if (intf->channels[addr->channel].medium != IPMI_CHANNEL_MEDIUM_IPMB) { chans = READ_ONCE(intf->channel_list)->c; if (chans[addr->channel].medium != IPMI_CHANNEL_MEDIUM_IPMB) { ipmi_inc_stat(intf, sent_invalid_commands); rv = -EINVAL; goto out_err; Loading Loading @@ -1905,6 +1915,7 @@ static int i_ipmi_request(ipmi_user_t user, struct ipmi_lan_addr *lan_addr; unsigned char ipmb_seq; long seqid; struct ipmi_channel *chans; if (addr->channel >= IPMI_MAX_CHANNELS) { ipmi_inc_stat(intf, sent_invalid_commands); Loading @@ -1912,9 +1923,11 @@ static int i_ipmi_request(ipmi_user_t user, goto out_err; } if ((intf->channels[addr->channel].medium chans = READ_ONCE(intf->channel_list)->c; if ((chans[addr->channel].medium != IPMI_CHANNEL_MEDIUM_8023LAN) && (intf->channels[addr->channel].medium && (chans[addr->channel].medium != IPMI_CHANNEL_MEDIUM_ASYNC)) { ipmi_inc_stat(intf, sent_invalid_commands); rv = -EINVAL; Loading Loading @@ -2282,6 +2295,9 @@ static int __bmc_get_device_id(ipmi_smi_t intf, struct bmc_device *bmc, memcpy(intf->bmc->guid, guid, 16); if (__ipmi_bmc_register(intf, &id, guid_set, guid, intf_num)) need_waiter(intf); /* Retry later on an error. */ else __scan_channels(intf, &id); if (!intf_set) { /* Loading @@ -2298,7 +2314,9 @@ static int __bmc_get_device_id(ipmi_smi_t intf, struct bmc_device *bmc, bmc = intf->bmc; mutex_lock(&bmc->dyn_mutex); goto out_noprocessing; } } else if (memcmp(&bmc->fetch_id, &bmc->id, sizeof(bmc->id))) /* Version info changes, scan the channels again. */ __scan_channels(intf, &bmc->fetch_id); bmc->dyn_id_expiry = jiffies + IPMI_DYN_DEV_ID_EXPIRY; Loading Loading @@ -3212,7 +3230,9 @@ static void channel_handler(ipmi_smi_t intf, struct ipmi_recv_msg *msg) { int rv = 0; int chan; int ch; unsigned int set = intf->curr_working_cset; struct ipmi_channel *chans; if ((msg->addr.addr_type == IPMI_SYSTEM_INTERFACE_ADDR_TYPE) && (msg->msg.netfn == IPMI_NETFN_APP_RESPONSE) Loading @@ -3228,12 +3248,13 @@ channel_handler(ipmi_smi_t intf, struct ipmi_recv_msg *msg) * assume it has one IPMB at channel * zero. */ intf->channels[0].medium intf->wchannels[set].c[0].medium = IPMI_CHANNEL_MEDIUM_IPMB; intf->channels[0].protocol intf->wchannels[set].c[0].protocol = IPMI_CHANNEL_PROTOCOL_IPMB; intf->curr_channel = IPMI_MAX_CHANNELS; intf->channel_list = intf->wchannels + set; intf->channels_ready = true; wake_up(&intf->waitq); goto out; } Loading @@ -3243,16 +3264,22 @@ channel_handler(ipmi_smi_t intf, struct ipmi_recv_msg *msg) /* Message not big enough, just go on. */ goto next_channel; } chan = intf->curr_channel; intf->channels[chan].medium = msg->msg.data[2] & 0x7f; intf->channels[chan].protocol = msg->msg.data[3] & 0x1f; ch = intf->curr_channel; chans = intf->wchannels[set].c; chans[ch].medium = msg->msg.data[2] & 0x7f; chans[ch].protocol = msg->msg.data[3] & 0x1f; next_channel: intf->curr_channel++; if (intf->curr_channel >= IPMI_MAX_CHANNELS) if (intf->curr_channel >= IPMI_MAX_CHANNELS) { intf->channel_list = intf->wchannels + set; intf->channels_ready = true; wake_up(&intf->waitq); else } else { intf->channel_list = intf->wchannels + set; intf->channels_ready = true; rv = send_channel_info_cmd(intf, intf->curr_channel); } if (rv) { /* Got an error somehow, just give up. */ Loading @@ -3260,7 +3287,8 @@ channel_handler(ipmi_smi_t intf, struct ipmi_recv_msg *msg) "Error sending channel information for channel" " %d: %d\n", intf->curr_channel, rv); intf->curr_channel = IPMI_MAX_CHANNELS; intf->channel_list = intf->wchannels + set; intf->channels_ready = true; wake_up(&intf->waitq); } } Loading @@ -3268,6 +3296,53 @@ channel_handler(ipmi_smi_t intf, struct ipmi_recv_msg *msg) return; } /* * Must be holding intf->bmc_reg_mutex to call this. */ static int __scan_channels(ipmi_smi_t intf, struct ipmi_device_id *id) { int rv; if (ipmi_version_major(id) > 1 || (ipmi_version_major(id) == 1 && ipmi_version_minor(id) >= 5)) { unsigned int set; /* * Start scanning the channels to see what is * available. */ set = !intf->curr_working_cset; intf->curr_working_cset = set; memset(&intf->wchannels[set], 0, sizeof(struct ipmi_channel_set)); intf->null_user_handler = channel_handler; intf->curr_channel = 0; rv = send_channel_info_cmd(intf, 0); if (rv) { dev_warn(intf->si_dev, "Error sending channel information for channel 0, %d\n", rv); return -EIO; } /* Wait for the channel info to be read. */ wait_event(intf->waitq, intf->channels_ready); intf->null_user_handler = NULL; } else { unsigned int set = intf->curr_working_cset; /* Assume a single IPMB channel at zero. */ intf->wchannels[set].c[0].medium = IPMI_CHANNEL_MEDIUM_IPMB; intf->wchannels[set].c[0].protocol = IPMI_CHANNEL_PROTOCOL_IPMB; intf->channel_list = intf->wchannels + set; intf->channels_ready = true; } return 0; } static void ipmi_poll(ipmi_smi_t intf) { if (intf->handlers->poll) Loading Loading @@ -3402,35 +3477,11 @@ int ipmi_register_smi(const struct ipmi_smi_handlers *handlers, goto out; } if (ipmi_version_major(&id) > 1 || (ipmi_version_major(&id) == 1 && ipmi_version_minor(&id) >= 5)) { /* * Start scanning the channels to see what is * available. */ mutex_lock(&intf->bmc_reg_mutex); intf->null_user_handler = channel_handler; intf->curr_channel = 0; rv = send_channel_info_cmd(intf, 0); if (rv) { printk(KERN_WARNING PFX "Error sending channel information for channel" " 0, %d\n", rv); goto out; } /* Wait for the channel info to be read. */ wait_event(intf->waitq, intf->curr_channel >= IPMI_MAX_CHANNELS); intf->null_user_handler = NULL; rv = __scan_channels(intf, &id); mutex_unlock(&intf->bmc_reg_mutex); } else { /* Assume a single IPMB channel at zero. */ intf->channels[0].medium = IPMI_CHANNEL_MEDIUM_IPMB; intf->channels[0].protocol = IPMI_CHANNEL_PROTOCOL_IPMB; intf->curr_channel = IPMI_MAX_CHANNELS; } if (rv) goto out; rv = add_proc_entries(intf, i); Loading Loading @@ -4259,6 +4310,8 @@ static int handle_one_recv_msg(ipmi_smi_t intf, deliver_response(recv_msg); } else if ((msg->rsp[0] == ((IPMI_NETFN_APP_REQUEST|1) << 2)) && (msg->rsp[1] == IPMI_GET_MSG_CMD)) { struct ipmi_channel *chans; /* It's from the receive queue. */ chan = msg->rsp[3] & 0xf; if (chan >= IPMI_MAX_CHANNELS) { Loading @@ -4273,12 +4326,14 @@ static int handle_one_recv_msg(ipmi_smi_t intf, * 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) { if (!intf->channels_ready) { requeue = 0; /* Throw the message away */ goto out; } switch (intf->channels[chan].medium) { chans = READ_ONCE(intf->channel_list)->c; switch (chans[chan].medium) { case IPMI_CHANNEL_MEDIUM_IPMB: if (msg->rsp[4] & 0x04) { /* Loading Loading @@ -4315,9 +4370,8 @@ static int handle_one_recv_msg(ipmi_smi_t intf, 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 if ((chans[chan].medium >= IPMI_CHANNEL_MEDIUM_OEM_MIN) && (chans[chan].medium <= IPMI_CHANNEL_MEDIUM_OEM_MAX)) { requeue = handle_oem_get_msg_cmd(intf, msg); } else { Loading Loading @@ -4479,15 +4533,14 @@ void ipmi_smi_msg_received(ipmi_smi_t intf, && (msg->rsp[2] != IPMI_LOST_ARBITRATION_ERR) && (msg->rsp[2] != IPMI_BUS_ERR) && (msg->rsp[2] != IPMI_NAK_ON_WRITE_ERR)) { int chan = msg->rsp[3] & 0xf; int ch = msg->rsp[3] & 0xf; struct ipmi_channel *chans; /* Got an error sending the message, handle it. */ if (chan >= IPMI_MAX_CHANNELS) ; /* This shouldn't happen */ else if ((intf->channels[chan].medium == IPMI_CHANNEL_MEDIUM_8023LAN) || (intf->channels[chan].medium == IPMI_CHANNEL_MEDIUM_ASYNC)) chans = READ_ONCE(intf->channel_list)->c; if ((chans[ch].medium == IPMI_CHANNEL_MEDIUM_8023LAN) || (chans[ch].medium == IPMI_CHANNEL_MEDIUM_ASYNC)) ipmi_inc_stat(intf, sent_lan_command_errs); else ipmi_inc_stat(intf, sent_ipmb_command_errs); Loading