diff options
author | Corey Minyard <minyard@acm.org> | 2005-09-06 18:18:38 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2005-09-07 19:57:47 -0400 |
commit | c14979b993021377228958498937bcdd9539cbce (patch) | |
tree | e30638df99aa69f707e7549e4e990e9e92d477ae /drivers/char/ipmi/ipmi_msghandler.c | |
parent | b224cd3a0ca376dd52f382905c1aaf5a83a54692 (diff) |
[PATCH] ipmi: add per-channel IPMB addresses
IPMI allows multiple IPMB channels on a single interface, and each channel
might have a different IPMB address. However, the driver has only one IPMB
address that it uses for everything. This patch adds new IOCTLS and a new
internal interface for setting per-channel IPMB addresses and LUNs. New
systems are coming out with support for multiple IPMB channels, and they are
broken without this patch.
Signed-off-by: Corey Minyard <minyard@acm.org>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'drivers/char/ipmi/ipmi_msghandler.c')
-rw-r--r-- | drivers/char/ipmi/ipmi_msghandler.c | 137 |
1 files changed, 94 insertions, 43 deletions
diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c index e16c13fe698d..84d477c6f925 100644 --- a/drivers/char/ipmi/ipmi_msghandler.c +++ b/drivers/char/ipmi/ipmi_msghandler.c | |||
@@ -124,6 +124,14 @@ struct ipmi_channel | |||
124 | { | 124 | { |
125 | unsigned char medium; | 125 | unsigned char medium; |
126 | unsigned char protocol; | 126 | unsigned char protocol; |
127 | |||
128 | /* My slave address. This is initialized to IPMI_BMC_SLAVE_ADDR, | ||
129 | but may be changed by the user. */ | ||
130 | unsigned char address; | ||
131 | |||
132 | /* My LUN. This should generally stay the SMS LUN, but just in | ||
133 | case... */ | ||
134 | unsigned char lun; | ||
127 | }; | 135 | }; |
128 | 136 | ||
129 | #ifdef CONFIG_PROC_FS | 137 | #ifdef CONFIG_PROC_FS |
@@ -135,7 +143,7 @@ struct ipmi_proc_entry | |||
135 | #endif | 143 | #endif |
136 | 144 | ||
137 | #define IPMI_IPMB_NUM_SEQ 64 | 145 | #define IPMI_IPMB_NUM_SEQ 64 |
138 | #define IPMI_MAX_CHANNELS 8 | 146 | #define IPMI_MAX_CHANNELS 16 |
139 | struct ipmi_smi | 147 | struct ipmi_smi |
140 | { | 148 | { |
141 | /* What interface number are we? */ | 149 | /* What interface number are we? */ |
@@ -199,14 +207,6 @@ struct ipmi_smi | |||
199 | this is registered. */ | 207 | this is registered. */ |
200 | ipmi_user_t all_cmd_rcvr; | 208 | ipmi_user_t all_cmd_rcvr; |
201 | 209 | ||
202 | /* My slave address. This is initialized to IPMI_BMC_SLAVE_ADDR, | ||
203 | but may be changed by the user. */ | ||
204 | unsigned char my_address; | ||
205 | |||
206 | /* My LUN. This should generally stay the SMS LUN, but just in | ||
207 | case... */ | ||
208 | unsigned char my_lun; | ||
209 | |||
210 | /* The event receiver for my BMC, only really used at panic | 210 | /* The event receiver for my BMC, only really used at panic |
211 | shutdown as a place to store this. */ | 211 | shutdown as a place to store this. */ |
212 | unsigned char event_receiver; | 212 | unsigned char event_receiver; |
@@ -766,26 +766,44 @@ void ipmi_get_version(ipmi_user_t user, | |||
766 | *minor = user->intf->version_minor; | 766 | *minor = user->intf->version_minor; |
767 | } | 767 | } |
768 | 768 | ||
769 | void ipmi_set_my_address(ipmi_user_t user, | 769 | int ipmi_set_my_address(ipmi_user_t user, |
770 | unsigned char address) | 770 | unsigned int channel, |
771 | unsigned char address) | ||
771 | { | 772 | { |
772 | user->intf->my_address = address; | 773 | if (channel >= IPMI_MAX_CHANNELS) |
774 | return -EINVAL; | ||
775 | user->intf->channels[channel].address = address; | ||
776 | return 0; | ||
773 | } | 777 | } |
774 | 778 | ||
775 | unsigned char ipmi_get_my_address(ipmi_user_t user) | 779 | int ipmi_get_my_address(ipmi_user_t user, |
780 | unsigned int channel, | ||
781 | unsigned char *address) | ||
776 | { | 782 | { |
777 | return user->intf->my_address; | 783 | if (channel >= IPMI_MAX_CHANNELS) |
784 | return -EINVAL; | ||
785 | *address = user->intf->channels[channel].address; | ||
786 | return 0; | ||
778 | } | 787 | } |
779 | 788 | ||
780 | void ipmi_set_my_LUN(ipmi_user_t user, | 789 | int ipmi_set_my_LUN(ipmi_user_t user, |
781 | unsigned char LUN) | 790 | unsigned int channel, |
791 | unsigned char LUN) | ||
782 | { | 792 | { |
783 | user->intf->my_lun = LUN & 0x3; | 793 | if (channel >= IPMI_MAX_CHANNELS) |
794 | return -EINVAL; | ||
795 | user->intf->channels[channel].lun = LUN & 0x3; | ||
796 | return 0; | ||
784 | } | 797 | } |
785 | 798 | ||
786 | unsigned char ipmi_get_my_LUN(ipmi_user_t user) | 799 | int ipmi_get_my_LUN(ipmi_user_t user, |
800 | unsigned int channel, | ||
801 | unsigned char *address) | ||
787 | { | 802 | { |
788 | return user->intf->my_lun; | 803 | if (channel >= IPMI_MAX_CHANNELS) |
804 | return -EINVAL; | ||
805 | *address = user->intf->channels[channel].lun; | ||
806 | return 0; | ||
789 | } | 807 | } |
790 | 808 | ||
791 | int ipmi_set_gets_events(ipmi_user_t user, int val) | 809 | int ipmi_set_gets_events(ipmi_user_t user, int val) |
@@ -1213,7 +1231,7 @@ static inline int i_ipmi_request(ipmi_user_t user, | |||
1213 | unsigned char ipmb_seq; | 1231 | unsigned char ipmb_seq; |
1214 | long seqid; | 1232 | long seqid; |
1215 | 1233 | ||
1216 | if (addr->channel > IPMI_NUM_CHANNELS) { | 1234 | if (addr->channel >= IPMI_NUM_CHANNELS) { |
1217 | spin_lock_irqsave(&intf->counter_lock, flags); | 1235 | spin_lock_irqsave(&intf->counter_lock, flags); |
1218 | intf->sent_invalid_commands++; | 1236 | intf->sent_invalid_commands++; |
1219 | spin_unlock_irqrestore(&intf->counter_lock, flags); | 1237 | spin_unlock_irqrestore(&intf->counter_lock, flags); |
@@ -1346,6 +1364,18 @@ static inline int i_ipmi_request(ipmi_user_t user, | |||
1346 | return rv; | 1364 | return rv; |
1347 | } | 1365 | } |
1348 | 1366 | ||
1367 | static int check_addr(ipmi_smi_t intf, | ||
1368 | struct ipmi_addr *addr, | ||
1369 | unsigned char *saddr, | ||
1370 | unsigned char *lun) | ||
1371 | { | ||
1372 | if (addr->channel >= IPMI_MAX_CHANNELS) | ||
1373 | return -EINVAL; | ||
1374 | *lun = intf->channels[addr->channel].lun; | ||
1375 | *saddr = intf->channels[addr->channel].address; | ||
1376 | return 0; | ||
1377 | } | ||
1378 | |||
1349 | int ipmi_request_settime(ipmi_user_t user, | 1379 | int ipmi_request_settime(ipmi_user_t user, |
1350 | struct ipmi_addr *addr, | 1380 | struct ipmi_addr *addr, |
1351 | long msgid, | 1381 | long msgid, |
@@ -1355,6 +1385,12 @@ int ipmi_request_settime(ipmi_user_t user, | |||
1355 | int retries, | 1385 | int retries, |
1356 | unsigned int retry_time_ms) | 1386 | unsigned int retry_time_ms) |
1357 | { | 1387 | { |
1388 | unsigned char saddr, lun; | ||
1389 | int rv; | ||
1390 | |||
1391 | rv = check_addr(user->intf, addr, &saddr, &lun); | ||
1392 | if (rv) | ||
1393 | return rv; | ||
1358 | return i_ipmi_request(user, | 1394 | return i_ipmi_request(user, |
1359 | user->intf, | 1395 | user->intf, |
1360 | addr, | 1396 | addr, |
@@ -1363,8 +1399,8 @@ int ipmi_request_settime(ipmi_user_t user, | |||
1363 | user_msg_data, | 1399 | user_msg_data, |
1364 | NULL, NULL, | 1400 | NULL, NULL, |
1365 | priority, | 1401 | priority, |
1366 | user->intf->my_address, | 1402 | saddr, |
1367 | user->intf->my_lun, | 1403 | lun, |
1368 | retries, | 1404 | retries, |
1369 | retry_time_ms); | 1405 | retry_time_ms); |
1370 | } | 1406 | } |
@@ -1378,6 +1414,12 @@ int ipmi_request_supply_msgs(ipmi_user_t user, | |||
1378 | struct ipmi_recv_msg *supplied_recv, | 1414 | struct ipmi_recv_msg *supplied_recv, |
1379 | int priority) | 1415 | int priority) |
1380 | { | 1416 | { |
1417 | unsigned char saddr, lun; | ||
1418 | int rv; | ||
1419 | |||
1420 | rv = check_addr(user->intf, addr, &saddr, &lun); | ||
1421 | if (rv) | ||
1422 | return rv; | ||
1381 | return i_ipmi_request(user, | 1423 | return i_ipmi_request(user, |
1382 | user->intf, | 1424 | user->intf, |
1383 | addr, | 1425 | addr, |
@@ -1387,8 +1429,8 @@ int ipmi_request_supply_msgs(ipmi_user_t user, | |||
1387 | supplied_smi, | 1429 | supplied_smi, |
1388 | supplied_recv, | 1430 | supplied_recv, |
1389 | priority, | 1431 | priority, |
1390 | user->intf->my_address, | 1432 | saddr, |
1391 | user->intf->my_lun, | 1433 | lun, |
1392 | -1, 0); | 1434 | -1, 0); |
1393 | } | 1435 | } |
1394 | 1436 | ||
@@ -1397,8 +1439,15 @@ static int ipmb_file_read_proc(char *page, char **start, off_t off, | |||
1397 | { | 1439 | { |
1398 | char *out = (char *) page; | 1440 | char *out = (char *) page; |
1399 | ipmi_smi_t intf = data; | 1441 | ipmi_smi_t intf = data; |
1442 | int i; | ||
1443 | int rv= 0; | ||
1400 | 1444 | ||
1401 | return sprintf(out, "%x\n", intf->my_address); | 1445 | for (i=0; i<IPMI_MAX_CHANNELS; i++) |
1446 | rv += sprintf(out+rv, "%x ", intf->channels[i].address); | ||
1447 | out[rv-1] = '\n'; /* Replace the final space with a newline */ | ||
1448 | out[rv] = '\0'; | ||
1449 | rv++; | ||
1450 | return rv; | ||
1402 | } | 1451 | } |
1403 | 1452 | ||
1404 | static int version_file_read_proc(char *page, char **start, off_t off, | 1453 | static int version_file_read_proc(char *page, char **start, off_t off, |
@@ -1592,8 +1641,8 @@ send_channel_info_cmd(ipmi_smi_t intf, int chan) | |||
1592 | NULL, | 1641 | NULL, |
1593 | NULL, | 1642 | NULL, |
1594 | 0, | 1643 | 0, |
1595 | intf->my_address, | 1644 | intf->channels[0].address, |
1596 | intf->my_lun, | 1645 | intf->channels[0].lun, |
1597 | -1, 0); | 1646 | -1, 0); |
1598 | } | 1647 | } |
1599 | 1648 | ||
@@ -1696,11 +1745,13 @@ int ipmi_register_smi(struct ipmi_smi_handlers *handlers, | |||
1696 | new_intf->intf_num = i; | 1745 | new_intf->intf_num = i; |
1697 | new_intf->version_major = version_major; | 1746 | new_intf->version_major = version_major; |
1698 | new_intf->version_minor = version_minor; | 1747 | new_intf->version_minor = version_minor; |
1699 | if (slave_addr == 0) | 1748 | for (j=0; j<IPMI_MAX_CHANNELS; j++) { |
1700 | new_intf->my_address = IPMI_BMC_SLAVE_ADDR; | 1749 | new_intf->channels[j].address |
1701 | else | 1750 | = IPMI_BMC_SLAVE_ADDR; |
1702 | new_intf->my_address = slave_addr; | 1751 | new_intf->channels[j].lun = 2; |
1703 | new_intf->my_lun = 2; /* the SMS LUN. */ | 1752 | } |
1753 | if (slave_addr != 0) | ||
1754 | new_intf->channels[0].address = slave_addr; | ||
1704 | rwlock_init(&(new_intf->users_lock)); | 1755 | rwlock_init(&(new_intf->users_lock)); |
1705 | INIT_LIST_HEAD(&(new_intf->users)); | 1756 | INIT_LIST_HEAD(&(new_intf->users)); |
1706 | new_intf->handlers = handlers; | 1757 | new_intf->handlers = handlers; |
@@ -1985,7 +2036,7 @@ static int handle_ipmb_get_msg_cmd(ipmi_smi_t intf, | |||
1985 | msg->data[3] = msg->rsp[6]; | 2036 | msg->data[3] = msg->rsp[6]; |
1986 | msg->data[4] = ((netfn + 1) << 2) | (msg->rsp[7] & 0x3); | 2037 | msg->data[4] = ((netfn + 1) << 2) | (msg->rsp[7] & 0x3); |
1987 | msg->data[5] = ipmb_checksum(&(msg->data[3]), 2); | 2038 | msg->data[5] = ipmb_checksum(&(msg->data[3]), 2); |
1988 | msg->data[6] = intf->my_address; | 2039 | msg->data[6] = intf->channels[msg->rsp[3] & 0xf].address; |
1989 | /* rqseq/lun */ | 2040 | /* rqseq/lun */ |
1990 | msg->data[7] = (msg->rsp[7] & 0xfc) | (msg->rsp[4] & 0x3); | 2041 | msg->data[7] = (msg->rsp[7] & 0xfc) | (msg->rsp[4] & 0x3); |
1991 | msg->data[8] = msg->rsp[8]; /* cmd */ | 2042 | msg->data[8] = msg->rsp[8]; /* cmd */ |
@@ -2919,8 +2970,8 @@ static void send_panic_events(char *str) | |||
2919 | &smi_msg, | 2970 | &smi_msg, |
2920 | &recv_msg, | 2971 | &recv_msg, |
2921 | 0, | 2972 | 0, |
2922 | intf->my_address, | 2973 | intf->channels[0].address, |
2923 | intf->my_lun, | 2974 | intf->channels[0].lun, |
2924 | 0, 1); /* Don't retry, and don't wait. */ | 2975 | 0, 1); /* Don't retry, and don't wait. */ |
2925 | } | 2976 | } |
2926 | 2977 | ||
@@ -2965,8 +3016,8 @@ static void send_panic_events(char *str) | |||
2965 | &smi_msg, | 3016 | &smi_msg, |
2966 | &recv_msg, | 3017 | &recv_msg, |
2967 | 0, | 3018 | 0, |
2968 | intf->my_address, | 3019 | intf->channels[0].address, |
2969 | intf->my_lun, | 3020 | intf->channels[0].lun, |
2970 | 0, 1); /* Don't retry, and don't wait. */ | 3021 | 0, 1); /* Don't retry, and don't wait. */ |
2971 | 3022 | ||
2972 | if (intf->local_event_generator) { | 3023 | if (intf->local_event_generator) { |
@@ -2985,8 +3036,8 @@ static void send_panic_events(char *str) | |||
2985 | &smi_msg, | 3036 | &smi_msg, |
2986 | &recv_msg, | 3037 | &recv_msg, |
2987 | 0, | 3038 | 0, |
2988 | intf->my_address, | 3039 | intf->channels[0].address, |
2989 | intf->my_lun, | 3040 | intf->channels[0].lun, |
2990 | 0, 1); /* no retry, and no wait. */ | 3041 | 0, 1); /* no retry, and no wait. */ |
2991 | } | 3042 | } |
2992 | intf->null_user_handler = NULL; | 3043 | intf->null_user_handler = NULL; |
@@ -2996,7 +3047,7 @@ static void send_panic_events(char *str) | |||
2996 | be zero, and it must not be my address. */ | 3047 | be zero, and it must not be my address. */ |
2997 | if (((intf->event_receiver & 1) == 0) | 3048 | if (((intf->event_receiver & 1) == 0) |
2998 | && (intf->event_receiver != 0) | 3049 | && (intf->event_receiver != 0) |
2999 | && (intf->event_receiver != intf->my_address)) | 3050 | && (intf->event_receiver != intf->channels[0].address)) |
3000 | { | 3051 | { |
3001 | /* The event receiver is valid, send an IPMB | 3052 | /* The event receiver is valid, send an IPMB |
3002 | message. */ | 3053 | message. */ |
@@ -3031,7 +3082,7 @@ static void send_panic_events(char *str) | |||
3031 | data[0] = 0; | 3082 | data[0] = 0; |
3032 | data[1] = 0; | 3083 | data[1] = 0; |
3033 | data[2] = 0xf0; /* OEM event without timestamp. */ | 3084 | data[2] = 0xf0; /* OEM event without timestamp. */ |
3034 | data[3] = intf->my_address; | 3085 | data[3] = intf->channels[0].address; |
3035 | data[4] = j++; /* sequence # */ | 3086 | data[4] = j++; /* sequence # */ |
3036 | /* Always give 11 bytes, so strncpy will fill | 3087 | /* Always give 11 bytes, so strncpy will fill |
3037 | it with zeroes for me. */ | 3088 | it with zeroes for me. */ |
@@ -3047,8 +3098,8 @@ static void send_panic_events(char *str) | |||
3047 | &smi_msg, | 3098 | &smi_msg, |
3048 | &recv_msg, | 3099 | &recv_msg, |
3049 | 0, | 3100 | 0, |
3050 | intf->my_address, | 3101 | intf->channels[0].address, |
3051 | intf->my_lun, | 3102 | intf->channels[0].lun, |
3052 | 0, 1); /* no retry, and no wait. */ | 3103 | 0, 1); /* no retry, and no wait. */ |
3053 | } | 3104 | } |
3054 | } | 3105 | } |