aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char/ipmi
diff options
context:
space:
mode:
authorCorey Minyard <minyard@acm.org>2005-09-06 18:18:38 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2005-09-07 19:57:47 -0400
commitc14979b993021377228958498937bcdd9539cbce (patch)
treee30638df99aa69f707e7549e4e990e9e92d477ae /drivers/char/ipmi
parentb224cd3a0ca376dd52f382905c1aaf5a83a54692 (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')
-rw-r--r--drivers/char/ipmi/ipmi_devintf.c94
-rw-r--r--drivers/char/ipmi/ipmi_msghandler.c137
2 files changed, 178 insertions, 53 deletions
diff --git a/drivers/char/ipmi/ipmi_devintf.c b/drivers/char/ipmi/ipmi_devintf.c
index e0a53570fea1..5571e92c520f 100644
--- a/drivers/char/ipmi/ipmi_devintf.c
+++ b/drivers/char/ipmi/ipmi_devintf.c
@@ -411,6 +411,7 @@ static int ipmi_ioctl(struct inode *inode,
411 break; 411 break;
412 } 412 }
413 413
414 /* The next four are legacy, not per-channel. */
414 case IPMICTL_SET_MY_ADDRESS_CMD: 415 case IPMICTL_SET_MY_ADDRESS_CMD:
415 { 416 {
416 unsigned int val; 417 unsigned int val;
@@ -420,22 +421,25 @@ static int ipmi_ioctl(struct inode *inode,
420 break; 421 break;
421 } 422 }
422 423
423 ipmi_set_my_address(priv->user, val); 424 rv = ipmi_set_my_address(priv->user, 0, val);
424 rv = 0;
425 break; 425 break;
426 } 426 }
427 427
428 case IPMICTL_GET_MY_ADDRESS_CMD: 428 case IPMICTL_GET_MY_ADDRESS_CMD:
429 { 429 {
430 unsigned int val; 430 unsigned int val;
431 unsigned char rval;
432
433 rv = ipmi_get_my_address(priv->user, 0, &rval);
434 if (rv)
435 break;
431 436
432 val = ipmi_get_my_address(priv->user); 437 val = rval;
433 438
434 if (copy_to_user(arg, &val, sizeof(val))) { 439 if (copy_to_user(arg, &val, sizeof(val))) {
435 rv = -EFAULT; 440 rv = -EFAULT;
436 break; 441 break;
437 } 442 }
438 rv = 0;
439 break; 443 break;
440 } 444 }
441 445
@@ -448,24 +452,94 @@ static int ipmi_ioctl(struct inode *inode,
448 break; 452 break;
449 } 453 }
450 454
451 ipmi_set_my_LUN(priv->user, val); 455 rv = ipmi_set_my_LUN(priv->user, 0, val);
452 rv = 0;
453 break; 456 break;
454 } 457 }
455 458
456 case IPMICTL_GET_MY_LUN_CMD: 459 case IPMICTL_GET_MY_LUN_CMD:
457 { 460 {
458 unsigned int val; 461 unsigned int val;
462 unsigned char rval;
463
464 rv = ipmi_get_my_LUN(priv->user, 0, &rval);
465 if (rv)
466 break;
459 467
460 val = ipmi_get_my_LUN(priv->user); 468 val = rval;
461 469
462 if (copy_to_user(arg, &val, sizeof(val))) { 470 if (copy_to_user(arg, &val, sizeof(val))) {
463 rv = -EFAULT; 471 rv = -EFAULT;
464 break; 472 break;
465 } 473 }
466 rv = 0;
467 break; 474 break;
468 } 475 }
476
477 case IPMICTL_SET_MY_CHANNEL_ADDRESS_CMD:
478 {
479 struct ipmi_channel_lun_address_set val;
480
481 if (copy_from_user(&val, arg, sizeof(val))) {
482 rv = -EFAULT;
483 break;
484 }
485
486 return ipmi_set_my_address(priv->user, val.channel, val.value);
487 break;
488 }
489
490 case IPMICTL_GET_MY_CHANNEL_ADDRESS_CMD:
491 {
492 struct ipmi_channel_lun_address_set val;
493
494 if (copy_from_user(&val, arg, sizeof(val))) {
495 rv = -EFAULT;
496 break;
497 }
498
499 rv = ipmi_get_my_address(priv->user, val.channel, &val.value);
500 if (rv)
501 break;
502
503 if (copy_to_user(arg, &val, sizeof(val))) {
504 rv = -EFAULT;
505 break;
506 }
507 break;
508 }
509
510 case IPMICTL_SET_MY_CHANNEL_LUN_CMD:
511 {
512 struct ipmi_channel_lun_address_set val;
513
514 if (copy_from_user(&val, arg, sizeof(val))) {
515 rv = -EFAULT;
516 break;
517 }
518
519 rv = ipmi_set_my_LUN(priv->user, val.channel, val.value);
520 break;
521 }
522
523 case IPMICTL_GET_MY_CHANNEL_LUN_CMD:
524 {
525 struct ipmi_channel_lun_address_set val;
526
527 if (copy_from_user(&val, arg, sizeof(val))) {
528 rv = -EFAULT;
529 break;
530 }
531
532 rv = ipmi_get_my_LUN(priv->user, val.channel, &val.value);
533 if (rv)
534 break;
535
536 if (copy_to_user(arg, &val, sizeof(val))) {
537 rv = -EFAULT;
538 break;
539 }
540 break;
541 }
542
469 case IPMICTL_SET_TIMING_PARMS_CMD: 543 case IPMICTL_SET_TIMING_PARMS_CMD:
470 { 544 {
471 struct ipmi_timing_parms parms; 545 struct ipmi_timing_parms parms;
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
139struct ipmi_smi 147struct 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
769void ipmi_set_my_address(ipmi_user_t user, 769int 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
775unsigned char ipmi_get_my_address(ipmi_user_t user) 779int 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
780void ipmi_set_my_LUN(ipmi_user_t user, 789int 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
786unsigned char ipmi_get_my_LUN(ipmi_user_t user) 799int 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
791int ipmi_set_gets_events(ipmi_user_t user, int val) 809int 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
1367static 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
1349int ipmi_request_settime(ipmi_user_t user, 1379int 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
1404static int version_file_read_proc(char *page, char **start, off_t off, 1453static 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 }