diff options
-rw-r--r-- | drivers/char/ipmi/ipmi_msghandler.c | 107 | ||||
-rw-r--r-- | include/linux/ipmi.h | 3 |
2 files changed, 69 insertions, 41 deletions
diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c index 05293d0e6692..d0ed25278cbb 100644 --- a/drivers/char/ipmi/ipmi_msghandler.c +++ b/drivers/char/ipmi/ipmi_msghandler.c | |||
@@ -219,7 +219,7 @@ struct ipmi_smi | |||
219 | interface comes in with a NULL user, call this routine with | 219 | interface comes in with a NULL user, call this routine with |
220 | it. Note that the message will still be freed by the | 220 | it. Note that the message will still be freed by the |
221 | caller. This only works on the system interface. */ | 221 | caller. This only works on the system interface. */ |
222 | void (*null_user_handler)(ipmi_smi_t intf, struct ipmi_smi_msg *msg); | 222 | void (*null_user_handler)(ipmi_smi_t intf, struct ipmi_recv_msg *msg); |
223 | 223 | ||
224 | /* When we are scanning the channels for an SMI, this will | 224 | /* When we are scanning the channels for an SMI, this will |
225 | tell which channel we are scanning. */ | 225 | tell which channel we are scanning. */ |
@@ -459,7 +459,27 @@ unsigned int ipmi_addr_length(int addr_type) | |||
459 | 459 | ||
460 | static void deliver_response(struct ipmi_recv_msg *msg) | 460 | static void deliver_response(struct ipmi_recv_msg *msg) |
461 | { | 461 | { |
462 | msg->user->handler->ipmi_recv_hndl(msg, msg->user->handler_data); | 462 | if (! msg->user) { |
463 | ipmi_smi_t intf = msg->user_msg_data; | ||
464 | unsigned long flags; | ||
465 | |||
466 | /* Special handling for NULL users. */ | ||
467 | if (intf->null_user_handler) { | ||
468 | intf->null_user_handler(intf, msg); | ||
469 | spin_lock_irqsave(&intf->counter_lock, flags); | ||
470 | intf->handled_local_responses++; | ||
471 | spin_unlock_irqrestore(&intf->counter_lock, flags); | ||
472 | } else { | ||
473 | /* No handler, so give up. */ | ||
474 | spin_lock_irqsave(&intf->counter_lock, flags); | ||
475 | intf->unhandled_local_responses++; | ||
476 | spin_unlock_irqrestore(&intf->counter_lock, flags); | ||
477 | } | ||
478 | ipmi_free_recv_msg(msg); | ||
479 | } else { | ||
480 | msg->user->handler->ipmi_recv_hndl(msg, | ||
481 | msg->user->handler_data); | ||
482 | } | ||
463 | } | 483 | } |
464 | 484 | ||
465 | /* Find the next sequence number not being used and add the given | 485 | /* Find the next sequence number not being used and add the given |
@@ -1389,6 +1409,8 @@ int ipmi_request_settime(ipmi_user_t user, | |||
1389 | unsigned char saddr, lun; | 1409 | unsigned char saddr, lun; |
1390 | int rv; | 1410 | int rv; |
1391 | 1411 | ||
1412 | if (! user) | ||
1413 | return -EINVAL; | ||
1392 | rv = check_addr(user->intf, addr, &saddr, &lun); | 1414 | rv = check_addr(user->intf, addr, &saddr, &lun); |
1393 | if (rv) | 1415 | if (rv) |
1394 | return rv; | 1416 | return rv; |
@@ -1418,6 +1440,8 @@ int ipmi_request_supply_msgs(ipmi_user_t user, | |||
1418 | unsigned char saddr, lun; | 1440 | unsigned char saddr, lun; |
1419 | int rv; | 1441 | int rv; |
1420 | 1442 | ||
1443 | if (! user) | ||
1444 | return -EINVAL; | ||
1421 | rv = check_addr(user->intf, addr, &saddr, &lun); | 1445 | rv = check_addr(user->intf, addr, &saddr, &lun); |
1422 | if (rv) | 1446 | if (rv) |
1423 | return rv; | 1447 | return rv; |
@@ -1638,7 +1662,7 @@ send_channel_info_cmd(ipmi_smi_t intf, int chan) | |||
1638 | (struct ipmi_addr *) &si, | 1662 | (struct ipmi_addr *) &si, |
1639 | 0, | 1663 | 0, |
1640 | &msg, | 1664 | &msg, |
1641 | NULL, | 1665 | intf, |
1642 | NULL, | 1666 | NULL, |
1643 | NULL, | 1667 | NULL, |
1644 | 0, | 1668 | 0, |
@@ -1648,19 +1672,20 @@ send_channel_info_cmd(ipmi_smi_t intf, int chan) | |||
1648 | } | 1672 | } |
1649 | 1673 | ||
1650 | static void | 1674 | static void |
1651 | channel_handler(ipmi_smi_t intf, struct ipmi_smi_msg *msg) | 1675 | channel_handler(ipmi_smi_t intf, struct ipmi_recv_msg *msg) |
1652 | { | 1676 | { |
1653 | int rv = 0; | 1677 | int rv = 0; |
1654 | int chan; | 1678 | int chan; |
1655 | 1679 | ||
1656 | if ((msg->rsp[0] == (IPMI_NETFN_APP_RESPONSE << 2)) | 1680 | if ((msg->addr.addr_type == IPMI_SYSTEM_INTERFACE_ADDR_TYPE) |
1657 | && (msg->rsp[1] == IPMI_GET_CHANNEL_INFO_CMD)) | 1681 | && (msg->msg.netfn == IPMI_NETFN_APP_RESPONSE) |
1682 | && (msg->msg.cmd == IPMI_GET_CHANNEL_INFO_CMD)) | ||
1658 | { | 1683 | { |
1659 | /* It's the one we want */ | 1684 | /* It's the one we want */ |
1660 | if (msg->rsp[2] != 0) { | 1685 | if (msg->msg.data[0] != 0) { |
1661 | /* Got an error from the channel, just go on. */ | 1686 | /* Got an error from the channel, just go on. */ |
1662 | 1687 | ||
1663 | if (msg->rsp[2] == IPMI_INVALID_COMMAND_ERR) { | 1688 | if (msg->msg.data[0] == IPMI_INVALID_COMMAND_ERR) { |
1664 | /* If the MC does not support this | 1689 | /* If the MC does not support this |
1665 | command, that is legal. We just | 1690 | command, that is legal. We just |
1666 | assume it has one IPMB at channel | 1691 | assume it has one IPMB at channel |
@@ -1677,13 +1702,13 @@ channel_handler(ipmi_smi_t intf, struct ipmi_smi_msg *msg) | |||
1677 | } | 1702 | } |
1678 | goto next_channel; | 1703 | goto next_channel; |
1679 | } | 1704 | } |
1680 | if (msg->rsp_size < 6) { | 1705 | if (msg->msg.data_len < 4) { |
1681 | /* Message not big enough, just go on. */ | 1706 | /* Message not big enough, just go on. */ |
1682 | goto next_channel; | 1707 | goto next_channel; |
1683 | } | 1708 | } |
1684 | chan = intf->curr_channel; | 1709 | chan = intf->curr_channel; |
1685 | intf->channels[chan].medium = msg->rsp[4] & 0x7f; | 1710 | intf->channels[chan].medium = msg->msg.data[2] & 0x7f; |
1686 | intf->channels[chan].protocol = msg->rsp[5] & 0x1f; | 1711 | intf->channels[chan].protocol = msg->msg.data[3] & 0x1f; |
1687 | 1712 | ||
1688 | next_channel: | 1713 | next_channel: |
1689 | intf->curr_channel++; | 1714 | intf->curr_channel++; |
@@ -2382,6 +2407,14 @@ static int handle_bmc_rsp(ipmi_smi_t intf, | |||
2382 | unsigned long flags; | 2407 | unsigned long flags; |
2383 | 2408 | ||
2384 | recv_msg = (struct ipmi_recv_msg *) msg->user_data; | 2409 | recv_msg = (struct ipmi_recv_msg *) msg->user_data; |
2410 | if (recv_msg == NULL) | ||
2411 | { | ||
2412 | printk(KERN_WARNING"IPMI message received with no owner. This\n" | ||
2413 | "could be because of a malformed message, or\n" | ||
2414 | "because of a hardware error. Contact your\n" | ||
2415 | "hardware vender for assistance\n"); | ||
2416 | return 0; | ||
2417 | } | ||
2385 | 2418 | ||
2386 | /* Make sure the user still exists. */ | 2419 | /* Make sure the user still exists. */ |
2387 | list_for_each_entry(user, &(intf->users), link) { | 2420 | list_for_each_entry(user, &(intf->users), link) { |
@@ -2392,19 +2425,11 @@ static int handle_bmc_rsp(ipmi_smi_t intf, | |||
2392 | } | 2425 | } |
2393 | } | 2426 | } |
2394 | 2427 | ||
2395 | if (!found) { | 2428 | if ((! found) && recv_msg->user) { |
2396 | /* Special handling for NULL users. */ | 2429 | /* The user for the message went away, so give up. */ |
2397 | if (!recv_msg->user && intf->null_user_handler){ | 2430 | spin_lock_irqsave(&intf->counter_lock, flags); |
2398 | intf->null_user_handler(intf, msg); | 2431 | intf->unhandled_local_responses++; |
2399 | spin_lock_irqsave(&intf->counter_lock, flags); | 2432 | spin_unlock_irqrestore(&intf->counter_lock, flags); |
2400 | intf->handled_local_responses++; | ||
2401 | spin_unlock_irqrestore(&intf->counter_lock, flags); | ||
2402 | }else{ | ||
2403 | /* The user for the message went away, so give up. */ | ||
2404 | spin_lock_irqsave(&intf->counter_lock, flags); | ||
2405 | intf->unhandled_local_responses++; | ||
2406 | spin_unlock_irqrestore(&intf->counter_lock, flags); | ||
2407 | } | ||
2408 | ipmi_free_recv_msg(recv_msg); | 2433 | ipmi_free_recv_msg(recv_msg); |
2409 | } else { | 2434 | } else { |
2410 | struct ipmi_system_interface_addr *smi_addr; | 2435 | struct ipmi_system_interface_addr *smi_addr; |
@@ -2890,28 +2915,30 @@ static void dummy_recv_done_handler(struct ipmi_recv_msg *msg) | |||
2890 | } | 2915 | } |
2891 | 2916 | ||
2892 | #ifdef CONFIG_IPMI_PANIC_STRING | 2917 | #ifdef CONFIG_IPMI_PANIC_STRING |
2893 | static void event_receiver_fetcher(ipmi_smi_t intf, struct ipmi_smi_msg *msg) | 2918 | static void event_receiver_fetcher(ipmi_smi_t intf, struct ipmi_recv_msg *msg) |
2894 | { | 2919 | { |
2895 | if ((msg->rsp[0] == (IPMI_NETFN_SENSOR_EVENT_RESPONSE << 2)) | 2920 | if ((msg->addr.addr_type == IPMI_SYSTEM_INTERFACE_ADDR_TYPE) |
2896 | && (msg->rsp[1] == IPMI_GET_EVENT_RECEIVER_CMD) | 2921 | && (msg->msg.netfn == IPMI_NETFN_SENSOR_EVENT_RESPONSE) |
2897 | && (msg->rsp[2] == IPMI_CC_NO_ERROR)) | 2922 | && (msg->msg.cmd == IPMI_GET_EVENT_RECEIVER_CMD) |
2923 | && (msg->msg.data[0] == IPMI_CC_NO_ERROR)) | ||
2898 | { | 2924 | { |
2899 | /* A get event receiver command, save it. */ | 2925 | /* A get event receiver command, save it. */ |
2900 | intf->event_receiver = msg->rsp[3]; | 2926 | intf->event_receiver = msg->msg.data[1]; |
2901 | intf->event_receiver_lun = msg->rsp[4] & 0x3; | 2927 | intf->event_receiver_lun = msg->msg.data[2] & 0x3; |
2902 | } | 2928 | } |
2903 | } | 2929 | } |
2904 | 2930 | ||
2905 | static void device_id_fetcher(ipmi_smi_t intf, struct ipmi_smi_msg *msg) | 2931 | static void device_id_fetcher(ipmi_smi_t intf, struct ipmi_recv_msg *msg) |
2906 | { | 2932 | { |
2907 | if ((msg->rsp[0] == (IPMI_NETFN_APP_RESPONSE << 2)) | 2933 | if ((msg->addr.addr_type == IPMI_SYSTEM_INTERFACE_ADDR_TYPE) |
2908 | && (msg->rsp[1] == IPMI_GET_DEVICE_ID_CMD) | 2934 | && (msg->msg.netfn == IPMI_NETFN_APP_RESPONSE) |
2909 | && (msg->rsp[2] == IPMI_CC_NO_ERROR)) | 2935 | && (msg->msg.cmd == IPMI_GET_DEVICE_ID_CMD) |
2936 | && (msg->msg.data[0] == IPMI_CC_NO_ERROR)) | ||
2910 | { | 2937 | { |
2911 | /* A get device id command, save if we are an event | 2938 | /* A get device id command, save if we are an event |
2912 | receiver or generator. */ | 2939 | receiver or generator. */ |
2913 | intf->local_sel_device = (msg->rsp[8] >> 2) & 1; | 2940 | intf->local_sel_device = (msg->msg.data[6] >> 2) & 1; |
2914 | intf->local_event_generator = (msg->rsp[8] >> 5) & 1; | 2941 | intf->local_event_generator = (msg->msg.data[6] >> 5) & 1; |
2915 | } | 2942 | } |
2916 | } | 2943 | } |
2917 | #endif | 2944 | #endif |
@@ -2967,7 +2994,7 @@ static void send_panic_events(char *str) | |||
2967 | &addr, | 2994 | &addr, |
2968 | 0, | 2995 | 0, |
2969 | &msg, | 2996 | &msg, |
2970 | NULL, | 2997 | intf, |
2971 | &smi_msg, | 2998 | &smi_msg, |
2972 | &recv_msg, | 2999 | &recv_msg, |
2973 | 0, | 3000 | 0, |
@@ -3013,7 +3040,7 @@ static void send_panic_events(char *str) | |||
3013 | &addr, | 3040 | &addr, |
3014 | 0, | 3041 | 0, |
3015 | &msg, | 3042 | &msg, |
3016 | NULL, | 3043 | intf, |
3017 | &smi_msg, | 3044 | &smi_msg, |
3018 | &recv_msg, | 3045 | &recv_msg, |
3019 | 0, | 3046 | 0, |
@@ -3033,7 +3060,7 @@ static void send_panic_events(char *str) | |||
3033 | &addr, | 3060 | &addr, |
3034 | 0, | 3061 | 0, |
3035 | &msg, | 3062 | &msg, |
3036 | NULL, | 3063 | intf, |
3037 | &smi_msg, | 3064 | &smi_msg, |
3038 | &recv_msg, | 3065 | &recv_msg, |
3039 | 0, | 3066 | 0, |
@@ -3095,7 +3122,7 @@ static void send_panic_events(char *str) | |||
3095 | &addr, | 3122 | &addr, |
3096 | 0, | 3123 | 0, |
3097 | &msg, | 3124 | &msg, |
3098 | NULL, | 3125 | intf, |
3099 | &smi_msg, | 3126 | &smi_msg, |
3100 | &recv_msg, | 3127 | &recv_msg, |
3101 | 0, | 3128 | 0, |
diff --git a/include/linux/ipmi.h b/include/linux/ipmi.h index dd30adedd07d..938d55b813a5 100644 --- a/include/linux/ipmi.h +++ b/include/linux/ipmi.h | |||
@@ -242,7 +242,8 @@ struct ipmi_recv_msg | |||
242 | /* The user_msg_data is the data supplied when a message was | 242 | /* The user_msg_data is the data supplied when a message was |
243 | sent, if this is a response to a sent message. If this is | 243 | sent, if this is a response to a sent message. If this is |
244 | not a response to a sent message, then user_msg_data will | 244 | not a response to a sent message, then user_msg_data will |
245 | be NULL. */ | 245 | be NULL. If the user above is NULL, then this will be the |
246 | intf. */ | ||
246 | void *user_msg_data; | 247 | void *user_msg_data; |
247 | 248 | ||
248 | /* Call this when done with the message. It will presumably free | 249 | /* Call this when done with the message. It will presumably free |