diff options
Diffstat (limited to 'drivers/char/ipmi/ipmi_msghandler.c')
-rw-r--r-- | drivers/char/ipmi/ipmi_msghandler.c | 211 |
1 files changed, 184 insertions, 27 deletions
diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c index e93fc8d22fb2..aa83a0865ec1 100644 --- a/drivers/char/ipmi/ipmi_msghandler.c +++ b/drivers/char/ipmi/ipmi_msghandler.c | |||
@@ -285,6 +285,11 @@ enum ipmi_stat_indexes { | |||
285 | /* Events that were received with the proper format. */ | 285 | /* Events that were received with the proper format. */ |
286 | IPMI_STAT_events, | 286 | IPMI_STAT_events, |
287 | 287 | ||
288 | /* Retransmissions on IPMB that failed. */ | ||
289 | IPMI_STAT_dropped_rexmit_ipmb_commands, | ||
290 | |||
291 | /* Retransmissions on LAN that failed. */ | ||
292 | IPMI_STAT_dropped_rexmit_lan_commands, | ||
288 | 293 | ||
289 | /* This *must* remain last, add new values above this. */ | 294 | /* This *must* remain last, add new values above this. */ |
290 | IPMI_NUM_STATS | 295 | IPMI_NUM_STATS |
@@ -445,6 +450,20 @@ static DEFINE_MUTEX(smi_watchers_mutex); | |||
445 | #define ipmi_get_stat(intf, stat) \ | 450 | #define ipmi_get_stat(intf, stat) \ |
446 | ((unsigned int) atomic_read(&(intf)->stats[IPMI_STAT_ ## stat])) | 451 | ((unsigned int) atomic_read(&(intf)->stats[IPMI_STAT_ ## stat])) |
447 | 452 | ||
453 | static int is_lan_addr(struct ipmi_addr *addr) | ||
454 | { | ||
455 | return addr->addr_type == IPMI_LAN_ADDR_TYPE; | ||
456 | } | ||
457 | |||
458 | static int is_ipmb_addr(struct ipmi_addr *addr) | ||
459 | { | ||
460 | return addr->addr_type == IPMI_IPMB_ADDR_TYPE; | ||
461 | } | ||
462 | |||
463 | static int is_ipmb_bcast_addr(struct ipmi_addr *addr) | ||
464 | { | ||
465 | return addr->addr_type == IPMI_IPMB_BROADCAST_ADDR_TYPE; | ||
466 | } | ||
448 | 467 | ||
449 | static void free_recv_msg_list(struct list_head *q) | 468 | static void free_recv_msg_list(struct list_head *q) |
450 | { | 469 | { |
@@ -601,8 +620,7 @@ ipmi_addr_equal(struct ipmi_addr *addr1, struct ipmi_addr *addr2) | |||
601 | return (smi_addr1->lun == smi_addr2->lun); | 620 | return (smi_addr1->lun == smi_addr2->lun); |
602 | } | 621 | } |
603 | 622 | ||
604 | if ((addr1->addr_type == IPMI_IPMB_ADDR_TYPE) | 623 | if (is_ipmb_addr(addr1) || is_ipmb_bcast_addr(addr1)) { |
605 | || (addr1->addr_type == IPMI_IPMB_BROADCAST_ADDR_TYPE)) { | ||
606 | struct ipmi_ipmb_addr *ipmb_addr1 | 624 | struct ipmi_ipmb_addr *ipmb_addr1 |
607 | = (struct ipmi_ipmb_addr *) addr1; | 625 | = (struct ipmi_ipmb_addr *) addr1; |
608 | struct ipmi_ipmb_addr *ipmb_addr2 | 626 | struct ipmi_ipmb_addr *ipmb_addr2 |
@@ -612,7 +630,7 @@ ipmi_addr_equal(struct ipmi_addr *addr1, struct ipmi_addr *addr2) | |||
612 | && (ipmb_addr1->lun == ipmb_addr2->lun)); | 630 | && (ipmb_addr1->lun == ipmb_addr2->lun)); |
613 | } | 631 | } |
614 | 632 | ||
615 | if (addr1->addr_type == IPMI_LAN_ADDR_TYPE) { | 633 | if (is_lan_addr(addr1)) { |
616 | struct ipmi_lan_addr *lan_addr1 | 634 | struct ipmi_lan_addr *lan_addr1 |
617 | = (struct ipmi_lan_addr *) addr1; | 635 | = (struct ipmi_lan_addr *) addr1; |
618 | struct ipmi_lan_addr *lan_addr2 | 636 | struct ipmi_lan_addr *lan_addr2 |
@@ -644,14 +662,13 @@ int ipmi_validate_addr(struct ipmi_addr *addr, int len) | |||
644 | || (addr->channel < 0)) | 662 | || (addr->channel < 0)) |
645 | return -EINVAL; | 663 | return -EINVAL; |
646 | 664 | ||
647 | if ((addr->addr_type == IPMI_IPMB_ADDR_TYPE) | 665 | if (is_ipmb_addr(addr) || is_ipmb_bcast_addr(addr)) { |
648 | || (addr->addr_type == IPMI_IPMB_BROADCAST_ADDR_TYPE)) { | ||
649 | if (len < sizeof(struct ipmi_ipmb_addr)) | 666 | if (len < sizeof(struct ipmi_ipmb_addr)) |
650 | return -EINVAL; | 667 | return -EINVAL; |
651 | return 0; | 668 | return 0; |
652 | } | 669 | } |
653 | 670 | ||
654 | if (addr->addr_type == IPMI_LAN_ADDR_TYPE) { | 671 | if (is_lan_addr(addr)) { |
655 | if (len < sizeof(struct ipmi_lan_addr)) | 672 | if (len < sizeof(struct ipmi_lan_addr)) |
656 | return -EINVAL; | 673 | return -EINVAL; |
657 | return 0; | 674 | return 0; |
@@ -1503,8 +1520,7 @@ static int i_ipmi_request(ipmi_user_t user, | |||
1503 | memcpy(&(smi_msg->data[2]), msg->data, msg->data_len); | 1520 | memcpy(&(smi_msg->data[2]), msg->data, msg->data_len); |
1504 | smi_msg->data_size = msg->data_len + 2; | 1521 | smi_msg->data_size = msg->data_len + 2; |
1505 | ipmi_inc_stat(intf, sent_local_commands); | 1522 | ipmi_inc_stat(intf, sent_local_commands); |
1506 | } else if ((addr->addr_type == IPMI_IPMB_ADDR_TYPE) | 1523 | } else if (is_ipmb_addr(addr) || is_ipmb_bcast_addr(addr)) { |
1507 | || (addr->addr_type == IPMI_IPMB_BROADCAST_ADDR_TYPE)) { | ||
1508 | struct ipmi_ipmb_addr *ipmb_addr; | 1524 | struct ipmi_ipmb_addr *ipmb_addr; |
1509 | unsigned char ipmb_seq; | 1525 | unsigned char ipmb_seq; |
1510 | long seqid; | 1526 | long seqid; |
@@ -1583,8 +1599,6 @@ static int i_ipmi_request(ipmi_user_t user, | |||
1583 | 1599 | ||
1584 | spin_lock_irqsave(&(intf->seq_lock), flags); | 1600 | spin_lock_irqsave(&(intf->seq_lock), flags); |
1585 | 1601 | ||
1586 | ipmi_inc_stat(intf, sent_ipmb_commands); | ||
1587 | |||
1588 | /* | 1602 | /* |
1589 | * Create a sequence number with a 1 second | 1603 | * Create a sequence number with a 1 second |
1590 | * timeout and 4 retries. | 1604 | * timeout and 4 retries. |
@@ -1606,6 +1620,8 @@ static int i_ipmi_request(ipmi_user_t user, | |||
1606 | goto out_err; | 1620 | goto out_err; |
1607 | } | 1621 | } |
1608 | 1622 | ||
1623 | ipmi_inc_stat(intf, sent_ipmb_commands); | ||
1624 | |||
1609 | /* | 1625 | /* |
1610 | * Store the sequence number in the message, | 1626 | * Store the sequence number in the message, |
1611 | * so that when the send message response | 1627 | * so that when the send message response |
@@ -1635,7 +1651,7 @@ static int i_ipmi_request(ipmi_user_t user, | |||
1635 | */ | 1651 | */ |
1636 | spin_unlock_irqrestore(&(intf->seq_lock), flags); | 1652 | spin_unlock_irqrestore(&(intf->seq_lock), flags); |
1637 | } | 1653 | } |
1638 | } else if (addr->addr_type == IPMI_LAN_ADDR_TYPE) { | 1654 | } else if (is_lan_addr(addr)) { |
1639 | struct ipmi_lan_addr *lan_addr; | 1655 | struct ipmi_lan_addr *lan_addr; |
1640 | unsigned char ipmb_seq; | 1656 | unsigned char ipmb_seq; |
1641 | long seqid; | 1657 | long seqid; |
@@ -1696,8 +1712,6 @@ static int i_ipmi_request(ipmi_user_t user, | |||
1696 | 1712 | ||
1697 | spin_lock_irqsave(&(intf->seq_lock), flags); | 1713 | spin_lock_irqsave(&(intf->seq_lock), flags); |
1698 | 1714 | ||
1699 | ipmi_inc_stat(intf, sent_lan_commands); | ||
1700 | |||
1701 | /* | 1715 | /* |
1702 | * Create a sequence number with a 1 second | 1716 | * Create a sequence number with a 1 second |
1703 | * timeout and 4 retries. | 1717 | * timeout and 4 retries. |
@@ -1719,6 +1733,8 @@ static int i_ipmi_request(ipmi_user_t user, | |||
1719 | goto out_err; | 1733 | goto out_err; |
1720 | } | 1734 | } |
1721 | 1735 | ||
1736 | ipmi_inc_stat(intf, sent_lan_commands); | ||
1737 | |||
1722 | /* | 1738 | /* |
1723 | * Store the sequence number in the message, | 1739 | * Store the sequence number in the message, |
1724 | * so that when the send message response | 1740 | * so that when the send message response |
@@ -1937,6 +1953,10 @@ static int stat_file_read_proc(char *page, char **start, off_t off, | |||
1937 | ipmi_get_stat(intf, invalid_events)); | 1953 | ipmi_get_stat(intf, invalid_events)); |
1938 | out += sprintf(out, "events: %u\n", | 1954 | out += sprintf(out, "events: %u\n", |
1939 | ipmi_get_stat(intf, events)); | 1955 | ipmi_get_stat(intf, events)); |
1956 | out += sprintf(out, "failed rexmit LAN msgs: %u\n", | ||
1957 | ipmi_get_stat(intf, dropped_rexmit_lan_commands)); | ||
1958 | out += sprintf(out, "failed rexmit IPMB msgs: %u\n", | ||
1959 | ipmi_get_stat(intf, dropped_rexmit_ipmb_commands)); | ||
1940 | 1960 | ||
1941 | return (out - ((char *) page)); | 1961 | return (out - ((char *) page)); |
1942 | } | 1962 | } |
@@ -3264,6 +3284,114 @@ static int handle_lan_get_msg_cmd(ipmi_smi_t intf, | |||
3264 | return rv; | 3284 | return rv; |
3265 | } | 3285 | } |
3266 | 3286 | ||
3287 | /* | ||
3288 | * This routine will handle "Get Message" command responses with | ||
3289 | * channels that use an OEM Medium. The message format belongs to | ||
3290 | * the OEM. See IPMI 2.0 specification, Chapter 6 and | ||
3291 | * Chapter 22, sections 22.6 and 22.24 for more details. | ||
3292 | */ | ||
3293 | static int handle_oem_get_msg_cmd(ipmi_smi_t intf, | ||
3294 | struct ipmi_smi_msg *msg) | ||
3295 | { | ||
3296 | struct cmd_rcvr *rcvr; | ||
3297 | int rv = 0; | ||
3298 | unsigned char netfn; | ||
3299 | unsigned char cmd; | ||
3300 | unsigned char chan; | ||
3301 | ipmi_user_t user = NULL; | ||
3302 | struct ipmi_system_interface_addr *smi_addr; | ||
3303 | struct ipmi_recv_msg *recv_msg; | ||
3304 | |||
3305 | /* | ||
3306 | * We expect the OEM SW to perform error checking | ||
3307 | * so we just do some basic sanity checks | ||
3308 | */ | ||
3309 | if (msg->rsp_size < 4) { | ||
3310 | /* Message not big enough, just ignore it. */ | ||
3311 | ipmi_inc_stat(intf, invalid_commands); | ||
3312 | return 0; | ||
3313 | } | ||
3314 | |||
3315 | if (msg->rsp[2] != 0) { | ||
3316 | /* An error getting the response, just ignore it. */ | ||
3317 | return 0; | ||
3318 | } | ||
3319 | |||
3320 | /* | ||
3321 | * This is an OEM Message so the OEM needs to know how | ||
3322 | * handle the message. We do no interpretation. | ||
3323 | */ | ||
3324 | netfn = msg->rsp[0] >> 2; | ||
3325 | cmd = msg->rsp[1]; | ||
3326 | chan = msg->rsp[3] & 0xf; | ||
3327 | |||
3328 | rcu_read_lock(); | ||
3329 | rcvr = find_cmd_rcvr(intf, netfn, cmd, chan); | ||
3330 | if (rcvr) { | ||
3331 | user = rcvr->user; | ||
3332 | kref_get(&user->refcount); | ||
3333 | } else | ||
3334 | user = NULL; | ||
3335 | rcu_read_unlock(); | ||
3336 | |||
3337 | if (user == NULL) { | ||
3338 | /* We didn't find a user, just give up. */ | ||
3339 | ipmi_inc_stat(intf, unhandled_commands); | ||
3340 | |||
3341 | /* | ||
3342 | * Don't do anything with these messages, just allow | ||
3343 | * them to be freed. | ||
3344 | */ | ||
3345 | |||
3346 | rv = 0; | ||
3347 | } else { | ||
3348 | /* Deliver the message to the user. */ | ||
3349 | ipmi_inc_stat(intf, handled_commands); | ||
3350 | |||
3351 | recv_msg = ipmi_alloc_recv_msg(); | ||
3352 | if (!recv_msg) { | ||
3353 | /* | ||
3354 | * We couldn't allocate memory for the | ||
3355 | * message, so requeue it for handling | ||
3356 | * later. | ||
3357 | */ | ||
3358 | rv = 1; | ||
3359 | kref_put(&user->refcount, free_user); | ||
3360 | } else { | ||
3361 | /* | ||
3362 | * OEM Messages are expected to be delivered via | ||
3363 | * the system interface to SMS software. We might | ||
3364 | * need to visit this again depending on OEM | ||
3365 | * requirements | ||
3366 | */ | ||
3367 | smi_addr = ((struct ipmi_system_interface_addr *) | ||
3368 | &(recv_msg->addr)); | ||
3369 | smi_addr->addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE; | ||
3370 | smi_addr->channel = IPMI_BMC_CHANNEL; | ||
3371 | smi_addr->lun = msg->rsp[0] & 3; | ||
3372 | |||
3373 | recv_msg->user = user; | ||
3374 | recv_msg->user_msg_data = NULL; | ||
3375 | recv_msg->recv_type = IPMI_OEM_RECV_TYPE; | ||
3376 | recv_msg->msg.netfn = msg->rsp[0] >> 2; | ||
3377 | recv_msg->msg.cmd = msg->rsp[1]; | ||
3378 | recv_msg->msg.data = recv_msg->msg_data; | ||
3379 | |||
3380 | /* | ||
3381 | * The message starts at byte 4 which follows the | ||
3382 | * the Channel Byte in the "GET MESSAGE" command | ||
3383 | */ | ||
3384 | recv_msg->msg.data_len = msg->rsp_size - 4; | ||
3385 | memcpy(recv_msg->msg_data, | ||
3386 | &(msg->rsp[4]), | ||
3387 | msg->rsp_size - 4); | ||
3388 | deliver_response(recv_msg); | ||
3389 | } | ||
3390 | } | ||
3391 | |||
3392 | return rv; | ||
3393 | } | ||
3394 | |||
3267 | static void copy_event_into_recv_msg(struct ipmi_recv_msg *recv_msg, | 3395 | static void copy_event_into_recv_msg(struct ipmi_recv_msg *recv_msg, |
3268 | struct ipmi_smi_msg *msg) | 3396 | struct ipmi_smi_msg *msg) |
3269 | { | 3397 | { |
@@ -3519,6 +3647,17 @@ static int handle_new_recv_msg(ipmi_smi_t intf, | |||
3519 | goto out; | 3647 | goto out; |
3520 | } | 3648 | } |
3521 | 3649 | ||
3650 | /* | ||
3651 | ** We need to make sure the channels have been initialized. | ||
3652 | ** The channel_handler routine will set the "curr_channel" | ||
3653 | ** equal to or greater than IPMI_MAX_CHANNELS when all the | ||
3654 | ** channels for this interface have been initialized. | ||
3655 | */ | ||
3656 | if (intf->curr_channel < IPMI_MAX_CHANNELS) { | ||
3657 | requeue = 1; /* Just put the message back for now */ | ||
3658 | goto out; | ||
3659 | } | ||
3660 | |||
3522 | switch (intf->channels[chan].medium) { | 3661 | switch (intf->channels[chan].medium) { |
3523 | case IPMI_CHANNEL_MEDIUM_IPMB: | 3662 | case IPMI_CHANNEL_MEDIUM_IPMB: |
3524 | if (msg->rsp[4] & 0x04) { | 3663 | if (msg->rsp[4] & 0x04) { |
@@ -3554,11 +3693,20 @@ static int handle_new_recv_msg(ipmi_smi_t intf, | |||
3554 | break; | 3693 | break; |
3555 | 3694 | ||
3556 | default: | 3695 | default: |
3557 | /* | 3696 | /* Check for OEM Channels. Clients had better |
3558 | * We don't handle the channel type, so just | 3697 | register for these commands. */ |
3559 | * free the message. | 3698 | if ((intf->channels[chan].medium |
3560 | */ | 3699 | >= IPMI_CHANNEL_MEDIUM_OEM_MIN) |
3561 | requeue = 0; | 3700 | && (intf->channels[chan].medium |
3701 | <= IPMI_CHANNEL_MEDIUM_OEM_MAX)) { | ||
3702 | requeue = handle_oem_get_msg_cmd(intf, msg); | ||
3703 | } else { | ||
3704 | /* | ||
3705 | * We don't handle the channel type, so just | ||
3706 | * free the message. | ||
3707 | */ | ||
3708 | requeue = 0; | ||
3709 | } | ||
3562 | } | 3710 | } |
3563 | 3711 | ||
3564 | } else if ((msg->rsp[0] == ((IPMI_NETFN_APP_REQUEST|1) << 2)) | 3712 | } else if ((msg->rsp[0] == ((IPMI_NETFN_APP_REQUEST|1) << 2)) |
@@ -3730,7 +3878,7 @@ static void check_msg_timeout(ipmi_smi_t intf, struct seq_table *ent, | |||
3730 | list_add_tail(&msg->link, timeouts); | 3878 | list_add_tail(&msg->link, timeouts); |
3731 | if (ent->broadcast) | 3879 | if (ent->broadcast) |
3732 | ipmi_inc_stat(intf, timed_out_ipmb_broadcasts); | 3880 | ipmi_inc_stat(intf, timed_out_ipmb_broadcasts); |
3733 | else if (ent->recv_msg->addr.addr_type == IPMI_LAN_ADDR_TYPE) | 3881 | else if (is_lan_addr(&ent->recv_msg->addr)) |
3734 | ipmi_inc_stat(intf, timed_out_lan_commands); | 3882 | ipmi_inc_stat(intf, timed_out_lan_commands); |
3735 | else | 3883 | else |
3736 | ipmi_inc_stat(intf, timed_out_ipmb_commands); | 3884 | ipmi_inc_stat(intf, timed_out_ipmb_commands); |
@@ -3744,15 +3892,17 @@ static void check_msg_timeout(ipmi_smi_t intf, struct seq_table *ent, | |||
3744 | */ | 3892 | */ |
3745 | ent->timeout = MAX_MSG_TIMEOUT; | 3893 | ent->timeout = MAX_MSG_TIMEOUT; |
3746 | ent->retries_left--; | 3894 | ent->retries_left--; |
3747 | if (ent->recv_msg->addr.addr_type == IPMI_LAN_ADDR_TYPE) | ||
3748 | ipmi_inc_stat(intf, retransmitted_lan_commands); | ||
3749 | else | ||
3750 | ipmi_inc_stat(intf, retransmitted_ipmb_commands); | ||
3751 | |||
3752 | smi_msg = smi_from_recv_msg(intf, ent->recv_msg, slot, | 3895 | smi_msg = smi_from_recv_msg(intf, ent->recv_msg, slot, |
3753 | ent->seqid); | 3896 | ent->seqid); |
3754 | if (!smi_msg) | 3897 | if (!smi_msg) { |
3898 | if (is_lan_addr(&ent->recv_msg->addr)) | ||
3899 | ipmi_inc_stat(intf, | ||
3900 | dropped_rexmit_lan_commands); | ||
3901 | else | ||
3902 | ipmi_inc_stat(intf, | ||
3903 | dropped_rexmit_ipmb_commands); | ||
3755 | return; | 3904 | return; |
3905 | } | ||
3756 | 3906 | ||
3757 | spin_unlock_irqrestore(&intf->seq_lock, *flags); | 3907 | spin_unlock_irqrestore(&intf->seq_lock, *flags); |
3758 | 3908 | ||
@@ -3764,10 +3914,17 @@ static void check_msg_timeout(ipmi_smi_t intf, struct seq_table *ent, | |||
3764 | * resent. | 3914 | * resent. |
3765 | */ | 3915 | */ |
3766 | handlers = intf->handlers; | 3916 | handlers = intf->handlers; |
3767 | if (handlers) | 3917 | if (handlers) { |
3918 | if (is_lan_addr(&ent->recv_msg->addr)) | ||
3919 | ipmi_inc_stat(intf, | ||
3920 | retransmitted_lan_commands); | ||
3921 | else | ||
3922 | ipmi_inc_stat(intf, | ||
3923 | retransmitted_ipmb_commands); | ||
3924 | |||
3768 | intf->handlers->sender(intf->send_info, | 3925 | intf->handlers->sender(intf->send_info, |
3769 | smi_msg, 0); | 3926 | smi_msg, 0); |
3770 | else | 3927 | } else |
3771 | ipmi_free_smi_msg(smi_msg); | 3928 | ipmi_free_smi_msg(smi_msg); |
3772 | 3929 | ||
3773 | spin_lock_irqsave(&intf->seq_lock, *flags); | 3930 | spin_lock_irqsave(&intf->seq_lock, *flags); |