diff options
Diffstat (limited to 'drivers/char/ipmi/ipmi_si_intf.c')
-rw-r--r-- | drivers/char/ipmi/ipmi_si_intf.c | 376 |
1 files changed, 338 insertions, 38 deletions
diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c index bb1fac104fda..81a0c89598e7 100644 --- a/drivers/char/ipmi/ipmi_si_intf.c +++ b/drivers/char/ipmi/ipmi_si_intf.c | |||
@@ -61,6 +61,10 @@ | |||
61 | #include "ipmi_si_sm.h" | 61 | #include "ipmi_si_sm.h" |
62 | #include <linux/init.h> | 62 | #include <linux/init.h> |
63 | #include <linux/dmi.h> | 63 | #include <linux/dmi.h> |
64 | #include <linux/string.h> | ||
65 | #include <linux/ctype.h> | ||
66 | |||
67 | #define PFX "ipmi_si: " | ||
64 | 68 | ||
65 | /* Measure times between events in the driver. */ | 69 | /* Measure times between events in the driver. */ |
66 | #undef DEBUG_TIMING | 70 | #undef DEBUG_TIMING |
@@ -92,7 +96,7 @@ enum si_intf_state { | |||
92 | enum si_type { | 96 | enum si_type { |
93 | SI_KCS, SI_SMIC, SI_BT | 97 | SI_KCS, SI_SMIC, SI_BT |
94 | }; | 98 | }; |
95 | static char *si_to_str[] = { "KCS", "SMIC", "BT" }; | 99 | static char *si_to_str[] = { "kcs", "smic", "bt" }; |
96 | 100 | ||
97 | #define DEVICE_NAME "ipmi_si" | 101 | #define DEVICE_NAME "ipmi_si" |
98 | 102 | ||
@@ -222,7 +226,10 @@ struct smi_info | |||
222 | static int force_kipmid[SI_MAX_PARMS]; | 226 | static int force_kipmid[SI_MAX_PARMS]; |
223 | static int num_force_kipmid; | 227 | static int num_force_kipmid; |
224 | 228 | ||
229 | static int unload_when_empty = 1; | ||
230 | |||
225 | static int try_smi_init(struct smi_info *smi); | 231 | static int try_smi_init(struct smi_info *smi); |
232 | static void cleanup_one_si(struct smi_info *to_clean); | ||
226 | 233 | ||
227 | static ATOMIC_NOTIFIER_HEAD(xaction_notifier_list); | 234 | static ATOMIC_NOTIFIER_HEAD(xaction_notifier_list); |
228 | static int register_xaction_notifier(struct notifier_block * nb) | 235 | static int register_xaction_notifier(struct notifier_block * nb) |
@@ -240,14 +247,18 @@ static void deliver_recv_msg(struct smi_info *smi_info, | |||
240 | spin_lock(&(smi_info->si_lock)); | 247 | spin_lock(&(smi_info->si_lock)); |
241 | } | 248 | } |
242 | 249 | ||
243 | static void return_hosed_msg(struct smi_info *smi_info) | 250 | static void return_hosed_msg(struct smi_info *smi_info, int cCode) |
244 | { | 251 | { |
245 | struct ipmi_smi_msg *msg = smi_info->curr_msg; | 252 | struct ipmi_smi_msg *msg = smi_info->curr_msg; |
246 | 253 | ||
254 | if (cCode < 0 || cCode > IPMI_ERR_UNSPECIFIED) | ||
255 | cCode = IPMI_ERR_UNSPECIFIED; | ||
256 | /* else use it as is */ | ||
257 | |||
247 | /* Make it a reponse */ | 258 | /* Make it a reponse */ |
248 | msg->rsp[0] = msg->data[0] | 4; | 259 | msg->rsp[0] = msg->data[0] | 4; |
249 | msg->rsp[1] = msg->data[1]; | 260 | msg->rsp[1] = msg->data[1]; |
250 | msg->rsp[2] = 0xFF; /* Unknown error. */ | 261 | msg->rsp[2] = cCode; |
251 | msg->rsp_size = 3; | 262 | msg->rsp_size = 3; |
252 | 263 | ||
253 | smi_info->curr_msg = NULL; | 264 | smi_info->curr_msg = NULL; |
@@ -298,7 +309,7 @@ static enum si_sm_result start_next_msg(struct smi_info *smi_info) | |||
298 | smi_info->curr_msg->data, | 309 | smi_info->curr_msg->data, |
299 | smi_info->curr_msg->data_size); | 310 | smi_info->curr_msg->data_size); |
300 | if (err) { | 311 | if (err) { |
301 | return_hosed_msg(smi_info); | 312 | return_hosed_msg(smi_info, err); |
302 | } | 313 | } |
303 | 314 | ||
304 | rv = SI_SM_CALL_WITHOUT_DELAY; | 315 | rv = SI_SM_CALL_WITHOUT_DELAY; |
@@ -640,7 +651,7 @@ static enum si_sm_result smi_event_handler(struct smi_info *smi_info, | |||
640 | /* If we were handling a user message, format | 651 | /* If we were handling a user message, format |
641 | a response to send to the upper layer to | 652 | a response to send to the upper layer to |
642 | tell it about the error. */ | 653 | tell it about the error. */ |
643 | return_hosed_msg(smi_info); | 654 | return_hosed_msg(smi_info, IPMI_ERR_UNSPECIFIED); |
644 | } | 655 | } |
645 | si_sm_result = smi_info->handlers->event(smi_info->si_sm, 0); | 656 | si_sm_result = smi_info->handlers->event(smi_info->si_sm, 0); |
646 | } | 657 | } |
@@ -684,22 +695,24 @@ static enum si_sm_result smi_event_handler(struct smi_info *smi_info, | |||
684 | { | 695 | { |
685 | /* We are idle and the upper layer requested that I fetch | 696 | /* We are idle and the upper layer requested that I fetch |
686 | events, so do so. */ | 697 | events, so do so. */ |
687 | unsigned char msg[2]; | 698 | atomic_set(&smi_info->req_events, 0); |
688 | 699 | ||
689 | spin_lock(&smi_info->count_lock); | 700 | smi_info->curr_msg = ipmi_alloc_smi_msg(); |
690 | smi_info->flag_fetches++; | 701 | if (!smi_info->curr_msg) |
691 | spin_unlock(&smi_info->count_lock); | 702 | goto out; |
692 | 703 | ||
693 | atomic_set(&smi_info->req_events, 0); | 704 | smi_info->curr_msg->data[0] = (IPMI_NETFN_APP_REQUEST << 2); |
694 | msg[0] = (IPMI_NETFN_APP_REQUEST << 2); | 705 | smi_info->curr_msg->data[1] = IPMI_READ_EVENT_MSG_BUFFER_CMD; |
695 | msg[1] = IPMI_GET_MSG_FLAGS_CMD; | 706 | smi_info->curr_msg->data_size = 2; |
696 | 707 | ||
697 | smi_info->handlers->start_transaction( | 708 | smi_info->handlers->start_transaction( |
698 | smi_info->si_sm, msg, 2); | 709 | smi_info->si_sm, |
699 | smi_info->si_state = SI_GETTING_FLAGS; | 710 | smi_info->curr_msg->data, |
711 | smi_info->curr_msg->data_size); | ||
712 | smi_info->si_state = SI_GETTING_EVENTS; | ||
700 | goto restart; | 713 | goto restart; |
701 | } | 714 | } |
702 | 715 | out: | |
703 | return si_sm_result; | 716 | return si_sm_result; |
704 | } | 717 | } |
705 | 718 | ||
@@ -714,6 +727,15 @@ static void sender(void *send_info, | |||
714 | struct timeval t; | 727 | struct timeval t; |
715 | #endif | 728 | #endif |
716 | 729 | ||
730 | if (atomic_read(&smi_info->stop_operation)) { | ||
731 | msg->rsp[0] = msg->data[0] | 4; | ||
732 | msg->rsp[1] = msg->data[1]; | ||
733 | msg->rsp[2] = IPMI_ERR_UNSPECIFIED; | ||
734 | msg->rsp_size = 3; | ||
735 | deliver_recv_msg(smi_info, msg); | ||
736 | return; | ||
737 | } | ||
738 | |||
717 | spin_lock_irqsave(&(smi_info->msg_lock), flags); | 739 | spin_lock_irqsave(&(smi_info->msg_lock), flags); |
718 | #ifdef DEBUG_TIMING | 740 | #ifdef DEBUG_TIMING |
719 | do_gettimeofday(&t); | 741 | do_gettimeofday(&t); |
@@ -805,13 +827,21 @@ static void poll(void *send_info) | |||
805 | { | 827 | { |
806 | struct smi_info *smi_info = send_info; | 828 | struct smi_info *smi_info = send_info; |
807 | 829 | ||
808 | smi_event_handler(smi_info, 0); | 830 | /* |
831 | * Make sure there is some delay in the poll loop so we can | ||
832 | * drive time forward and timeout things. | ||
833 | */ | ||
834 | udelay(10); | ||
835 | smi_event_handler(smi_info, 10); | ||
809 | } | 836 | } |
810 | 837 | ||
811 | static void request_events(void *send_info) | 838 | static void request_events(void *send_info) |
812 | { | 839 | { |
813 | struct smi_info *smi_info = send_info; | 840 | struct smi_info *smi_info = send_info; |
814 | 841 | ||
842 | if (atomic_read(&smi_info->stop_operation)) | ||
843 | return; | ||
844 | |||
815 | atomic_set(&smi_info->req_events, 1); | 845 | atomic_set(&smi_info->req_events, 1); |
816 | } | 846 | } |
817 | 847 | ||
@@ -949,12 +979,21 @@ static int smi_start_processing(void *send_info, | |||
949 | return 0; | 979 | return 0; |
950 | } | 980 | } |
951 | 981 | ||
982 | static void set_maintenance_mode(void *send_info, int enable) | ||
983 | { | ||
984 | struct smi_info *smi_info = send_info; | ||
985 | |||
986 | if (!enable) | ||
987 | atomic_set(&smi_info->req_events, 0); | ||
988 | } | ||
989 | |||
952 | static struct ipmi_smi_handlers handlers = | 990 | static struct ipmi_smi_handlers handlers = |
953 | { | 991 | { |
954 | .owner = THIS_MODULE, | 992 | .owner = THIS_MODULE, |
955 | .start_processing = smi_start_processing, | 993 | .start_processing = smi_start_processing, |
956 | .sender = sender, | 994 | .sender = sender, |
957 | .request_events = request_events, | 995 | .request_events = request_events, |
996 | .set_maintenance_mode = set_maintenance_mode, | ||
958 | .set_run_to_completion = set_run_to_completion, | 997 | .set_run_to_completion = set_run_to_completion, |
959 | .poll = poll, | 998 | .poll = poll, |
960 | }; | 999 | }; |
@@ -987,6 +1026,16 @@ static int num_regshifts = 0; | |||
987 | static int slave_addrs[SI_MAX_PARMS]; | 1026 | static int slave_addrs[SI_MAX_PARMS]; |
988 | static int num_slave_addrs = 0; | 1027 | static int num_slave_addrs = 0; |
989 | 1028 | ||
1029 | #define IPMI_IO_ADDR_SPACE 0 | ||
1030 | #define IPMI_MEM_ADDR_SPACE 1 | ||
1031 | static char *addr_space_to_str[] = { "I/O", "mem" }; | ||
1032 | |||
1033 | static int hotmod_handler(const char *val, struct kernel_param *kp); | ||
1034 | |||
1035 | module_param_call(hotmod, hotmod_handler, NULL, NULL, 0200); | ||
1036 | MODULE_PARM_DESC(hotmod, "Add and remove interfaces. See" | ||
1037 | " Documentation/IPMI.txt in the kernel sources for the" | ||
1038 | " gory details."); | ||
990 | 1039 | ||
991 | module_param_named(trydefaults, si_trydefaults, bool, 0); | 1040 | module_param_named(trydefaults, si_trydefaults, bool, 0); |
992 | MODULE_PARM_DESC(trydefaults, "Setting this to 'false' will disable the" | 1041 | MODULE_PARM_DESC(trydefaults, "Setting this to 'false' will disable the" |
@@ -1038,12 +1087,12 @@ module_param_array(force_kipmid, int, &num_force_kipmid, 0); | |||
1038 | MODULE_PARM_DESC(force_kipmid, "Force the kipmi daemon to be enabled (1) or" | 1087 | MODULE_PARM_DESC(force_kipmid, "Force the kipmi daemon to be enabled (1) or" |
1039 | " disabled(0). Normally the IPMI driver auto-detects" | 1088 | " disabled(0). Normally the IPMI driver auto-detects" |
1040 | " this, but the value may be overridden by this parm."); | 1089 | " this, but the value may be overridden by this parm."); |
1090 | module_param(unload_when_empty, int, 0); | ||
1091 | MODULE_PARM_DESC(unload_when_empty, "Unload the module if no interfaces are" | ||
1092 | " specified or found, default is 1. Setting to 0" | ||
1093 | " is useful for hot add of devices using hotmod."); | ||
1041 | 1094 | ||
1042 | 1095 | ||
1043 | #define IPMI_IO_ADDR_SPACE 0 | ||
1044 | #define IPMI_MEM_ADDR_SPACE 1 | ||
1045 | static char *addr_space_to_str[] = { "I/O", "memory" }; | ||
1046 | |||
1047 | static void std_irq_cleanup(struct smi_info *info) | 1096 | static void std_irq_cleanup(struct smi_info *info) |
1048 | { | 1097 | { |
1049 | if (info->si_type == SI_BT) | 1098 | if (info->si_type == SI_BT) |
@@ -1317,6 +1366,234 @@ static int mem_setup(struct smi_info *info) | |||
1317 | return 0; | 1366 | return 0; |
1318 | } | 1367 | } |
1319 | 1368 | ||
1369 | /* | ||
1370 | * Parms come in as <op1>[:op2[:op3...]]. ops are: | ||
1371 | * add|remove,kcs|bt|smic,mem|i/o,<address>[,<opt1>[,<opt2>[,...]]] | ||
1372 | * Options are: | ||
1373 | * rsp=<regspacing> | ||
1374 | * rsi=<regsize> | ||
1375 | * rsh=<regshift> | ||
1376 | * irq=<irq> | ||
1377 | * ipmb=<ipmb addr> | ||
1378 | */ | ||
1379 | enum hotmod_op { HM_ADD, HM_REMOVE }; | ||
1380 | struct hotmod_vals { | ||
1381 | char *name; | ||
1382 | int val; | ||
1383 | }; | ||
1384 | static struct hotmod_vals hotmod_ops[] = { | ||
1385 | { "add", HM_ADD }, | ||
1386 | { "remove", HM_REMOVE }, | ||
1387 | { NULL } | ||
1388 | }; | ||
1389 | static struct hotmod_vals hotmod_si[] = { | ||
1390 | { "kcs", SI_KCS }, | ||
1391 | { "smic", SI_SMIC }, | ||
1392 | { "bt", SI_BT }, | ||
1393 | { NULL } | ||
1394 | }; | ||
1395 | static struct hotmod_vals hotmod_as[] = { | ||
1396 | { "mem", IPMI_MEM_ADDR_SPACE }, | ||
1397 | { "i/o", IPMI_IO_ADDR_SPACE }, | ||
1398 | { NULL } | ||
1399 | }; | ||
1400 | static int ipmi_strcasecmp(const char *s1, const char *s2) | ||
1401 | { | ||
1402 | while (*s1 || *s2) { | ||
1403 | if (!*s1) | ||
1404 | return -1; | ||
1405 | if (!*s2) | ||
1406 | return 1; | ||
1407 | if (*s1 != *s2) | ||
1408 | return *s1 - *s2; | ||
1409 | s1++; | ||
1410 | s2++; | ||
1411 | } | ||
1412 | return 0; | ||
1413 | } | ||
1414 | static int parse_str(struct hotmod_vals *v, int *val, char *name, char **curr) | ||
1415 | { | ||
1416 | char *s; | ||
1417 | int i; | ||
1418 | |||
1419 | s = strchr(*curr, ','); | ||
1420 | if (!s) { | ||
1421 | printk(KERN_WARNING PFX "No hotmod %s given.\n", name); | ||
1422 | return -EINVAL; | ||
1423 | } | ||
1424 | *s = '\0'; | ||
1425 | s++; | ||
1426 | for (i = 0; hotmod_ops[i].name; i++) { | ||
1427 | if (ipmi_strcasecmp(*curr, v[i].name) == 0) { | ||
1428 | *val = v[i].val; | ||
1429 | *curr = s; | ||
1430 | return 0; | ||
1431 | } | ||
1432 | } | ||
1433 | |||
1434 | printk(KERN_WARNING PFX "Invalid hotmod %s '%s'\n", name, *curr); | ||
1435 | return -EINVAL; | ||
1436 | } | ||
1437 | |||
1438 | static int hotmod_handler(const char *val, struct kernel_param *kp) | ||
1439 | { | ||
1440 | char *str = kstrdup(val, GFP_KERNEL); | ||
1441 | int rv = -EINVAL; | ||
1442 | char *next, *curr, *s, *n, *o; | ||
1443 | enum hotmod_op op; | ||
1444 | enum si_type si_type; | ||
1445 | int addr_space; | ||
1446 | unsigned long addr; | ||
1447 | int regspacing; | ||
1448 | int regsize; | ||
1449 | int regshift; | ||
1450 | int irq; | ||
1451 | int ipmb; | ||
1452 | int ival; | ||
1453 | struct smi_info *info; | ||
1454 | |||
1455 | if (!str) | ||
1456 | return -ENOMEM; | ||
1457 | |||
1458 | /* Kill any trailing spaces, as we can get a "\n" from echo. */ | ||
1459 | ival = strlen(str) - 1; | ||
1460 | while ((ival >= 0) && isspace(str[ival])) { | ||
1461 | str[ival] = '\0'; | ||
1462 | ival--; | ||
1463 | } | ||
1464 | |||
1465 | for (curr = str; curr; curr = next) { | ||
1466 | regspacing = 1; | ||
1467 | regsize = 1; | ||
1468 | regshift = 0; | ||
1469 | irq = 0; | ||
1470 | ipmb = 0x20; | ||
1471 | |||
1472 | next = strchr(curr, ':'); | ||
1473 | if (next) { | ||
1474 | *next = '\0'; | ||
1475 | next++; | ||
1476 | } | ||
1477 | |||
1478 | rv = parse_str(hotmod_ops, &ival, "operation", &curr); | ||
1479 | if (rv) | ||
1480 | break; | ||
1481 | op = ival; | ||
1482 | |||
1483 | rv = parse_str(hotmod_si, &ival, "interface type", &curr); | ||
1484 | if (rv) | ||
1485 | break; | ||
1486 | si_type = ival; | ||
1487 | |||
1488 | rv = parse_str(hotmod_as, &addr_space, "address space", &curr); | ||
1489 | if (rv) | ||
1490 | break; | ||
1491 | |||
1492 | s = strchr(curr, ','); | ||
1493 | if (s) { | ||
1494 | *s = '\0'; | ||
1495 | s++; | ||
1496 | } | ||
1497 | addr = simple_strtoul(curr, &n, 0); | ||
1498 | if ((*n != '\0') || (*curr == '\0')) { | ||
1499 | printk(KERN_WARNING PFX "Invalid hotmod address" | ||
1500 | " '%s'\n", curr); | ||
1501 | break; | ||
1502 | } | ||
1503 | |||
1504 | while (s) { | ||
1505 | curr = s; | ||
1506 | s = strchr(curr, ','); | ||
1507 | if (s) { | ||
1508 | *s = '\0'; | ||
1509 | s++; | ||
1510 | } | ||
1511 | o = strchr(curr, '='); | ||
1512 | if (o) { | ||
1513 | *o = '\0'; | ||
1514 | o++; | ||
1515 | } | ||
1516 | #define HOTMOD_INT_OPT(name, val) \ | ||
1517 | if (ipmi_strcasecmp(curr, name) == 0) { \ | ||
1518 | if (!o) { \ | ||
1519 | printk(KERN_WARNING PFX \ | ||
1520 | "No option given for '%s'\n", \ | ||
1521 | curr); \ | ||
1522 | goto out; \ | ||
1523 | } \ | ||
1524 | val = simple_strtoul(o, &n, 0); \ | ||
1525 | if ((*n != '\0') || (*o == '\0')) { \ | ||
1526 | printk(KERN_WARNING PFX \ | ||
1527 | "Bad option given for '%s'\n", \ | ||
1528 | curr); \ | ||
1529 | goto out; \ | ||
1530 | } \ | ||
1531 | } | ||
1532 | |||
1533 | HOTMOD_INT_OPT("rsp", regspacing) | ||
1534 | else HOTMOD_INT_OPT("rsi", regsize) | ||
1535 | else HOTMOD_INT_OPT("rsh", regshift) | ||
1536 | else HOTMOD_INT_OPT("irq", irq) | ||
1537 | else HOTMOD_INT_OPT("ipmb", ipmb) | ||
1538 | else { | ||
1539 | printk(KERN_WARNING PFX | ||
1540 | "Invalid hotmod option '%s'\n", | ||
1541 | curr); | ||
1542 | goto out; | ||
1543 | } | ||
1544 | #undef HOTMOD_INT_OPT | ||
1545 | } | ||
1546 | |||
1547 | if (op == HM_ADD) { | ||
1548 | info = kzalloc(sizeof(*info), GFP_KERNEL); | ||
1549 | if (!info) { | ||
1550 | rv = -ENOMEM; | ||
1551 | goto out; | ||
1552 | } | ||
1553 | |||
1554 | info->addr_source = "hotmod"; | ||
1555 | info->si_type = si_type; | ||
1556 | info->io.addr_data = addr; | ||
1557 | info->io.addr_type = addr_space; | ||
1558 | if (addr_space == IPMI_MEM_ADDR_SPACE) | ||
1559 | info->io_setup = mem_setup; | ||
1560 | else | ||
1561 | info->io_setup = port_setup; | ||
1562 | |||
1563 | info->io.addr = NULL; | ||
1564 | info->io.regspacing = regspacing; | ||
1565 | if (!info->io.regspacing) | ||
1566 | info->io.regspacing = DEFAULT_REGSPACING; | ||
1567 | info->io.regsize = regsize; | ||
1568 | if (!info->io.regsize) | ||
1569 | info->io.regsize = DEFAULT_REGSPACING; | ||
1570 | info->io.regshift = regshift; | ||
1571 | info->irq = irq; | ||
1572 | if (info->irq) | ||
1573 | info->irq_setup = std_irq_setup; | ||
1574 | info->slave_addr = ipmb; | ||
1575 | |||
1576 | try_smi_init(info); | ||
1577 | } else { | ||
1578 | /* remove */ | ||
1579 | struct smi_info *e, *tmp_e; | ||
1580 | |||
1581 | mutex_lock(&smi_infos_lock); | ||
1582 | list_for_each_entry_safe(e, tmp_e, &smi_infos, link) { | ||
1583 | if (e->io.addr_type != addr_space) | ||
1584 | continue; | ||
1585 | if (e->si_type != si_type) | ||
1586 | continue; | ||
1587 | if (e->io.addr_data == addr) | ||
1588 | cleanup_one_si(e); | ||
1589 | } | ||
1590 | mutex_unlock(&smi_infos_lock); | ||
1591 | } | ||
1592 | } | ||
1593 | out: | ||
1594 | kfree(str); | ||
1595 | return rv; | ||
1596 | } | ||
1320 | 1597 | ||
1321 | static __devinit void hardcode_find_bmc(void) | 1598 | static __devinit void hardcode_find_bmc(void) |
1322 | { | 1599 | { |
@@ -1333,11 +1610,11 @@ static __devinit void hardcode_find_bmc(void) | |||
1333 | 1610 | ||
1334 | info->addr_source = "hardcoded"; | 1611 | info->addr_source = "hardcoded"; |
1335 | 1612 | ||
1336 | if (!si_type[i] || strcmp(si_type[i], "kcs") == 0) { | 1613 | if (!si_type[i] || ipmi_strcasecmp(si_type[i], "kcs") == 0) { |
1337 | info->si_type = SI_KCS; | 1614 | info->si_type = SI_KCS; |
1338 | } else if (strcmp(si_type[i], "smic") == 0) { | 1615 | } else if (ipmi_strcasecmp(si_type[i], "smic") == 0) { |
1339 | info->si_type = SI_SMIC; | 1616 | info->si_type = SI_SMIC; |
1340 | } else if (strcmp(si_type[i], "bt") == 0) { | 1617 | } else if (ipmi_strcasecmp(si_type[i], "bt") == 0) { |
1341 | info->si_type = SI_BT; | 1618 | info->si_type = SI_BT; |
1342 | } else { | 1619 | } else { |
1343 | printk(KERN_WARNING | 1620 | printk(KERN_WARNING |
@@ -1952,19 +2229,9 @@ static int try_get_dev_id(struct smi_info *smi_info) | |||
1952 | static int type_file_read_proc(char *page, char **start, off_t off, | 2229 | static int type_file_read_proc(char *page, char **start, off_t off, |
1953 | int count, int *eof, void *data) | 2230 | int count, int *eof, void *data) |
1954 | { | 2231 | { |
1955 | char *out = (char *) page; | ||
1956 | struct smi_info *smi = data; | 2232 | struct smi_info *smi = data; |
1957 | 2233 | ||
1958 | switch (smi->si_type) { | 2234 | return sprintf(page, "%s\n", si_to_str[smi->si_type]); |
1959 | case SI_KCS: | ||
1960 | return sprintf(out, "kcs\n"); | ||
1961 | case SI_SMIC: | ||
1962 | return sprintf(out, "smic\n"); | ||
1963 | case SI_BT: | ||
1964 | return sprintf(out, "bt\n"); | ||
1965 | default: | ||
1966 | return 0; | ||
1967 | } | ||
1968 | } | 2235 | } |
1969 | 2236 | ||
1970 | static int stat_file_read_proc(char *page, char **start, off_t off, | 2237 | static int stat_file_read_proc(char *page, char **start, off_t off, |
@@ -2000,7 +2267,24 @@ static int stat_file_read_proc(char *page, char **start, off_t off, | |||
2000 | out += sprintf(out, "incoming_messages: %ld\n", | 2267 | out += sprintf(out, "incoming_messages: %ld\n", |
2001 | smi->incoming_messages); | 2268 | smi->incoming_messages); |
2002 | 2269 | ||
2003 | return (out - ((char *) page)); | 2270 | return out - page; |
2271 | } | ||
2272 | |||
2273 | static int param_read_proc(char *page, char **start, off_t off, | ||
2274 | int count, int *eof, void *data) | ||
2275 | { | ||
2276 | struct smi_info *smi = data; | ||
2277 | |||
2278 | return sprintf(page, | ||
2279 | "%s,%s,0x%lx,rsp=%d,rsi=%d,rsh=%d,irq=%d,ipmb=%d\n", | ||
2280 | si_to_str[smi->si_type], | ||
2281 | addr_space_to_str[smi->io.addr_type], | ||
2282 | smi->io.addr_data, | ||
2283 | smi->io.regspacing, | ||
2284 | smi->io.regsize, | ||
2285 | smi->io.regshift, | ||
2286 | smi->irq, | ||
2287 | smi->slave_addr); | ||
2004 | } | 2288 | } |
2005 | 2289 | ||
2006 | /* | 2290 | /* |
@@ -2362,6 +2646,7 @@ static int try_smi_init(struct smi_info *new_smi) | |||
2362 | new_smi, | 2646 | new_smi, |
2363 | &new_smi->device_id, | 2647 | &new_smi->device_id, |
2364 | new_smi->dev, | 2648 | new_smi->dev, |
2649 | "bmc", | ||
2365 | new_smi->slave_addr); | 2650 | new_smi->slave_addr); |
2366 | if (rv) { | 2651 | if (rv) { |
2367 | printk(KERN_ERR | 2652 | printk(KERN_ERR |
@@ -2390,6 +2675,16 @@ static int try_smi_init(struct smi_info *new_smi) | |||
2390 | goto out_err_stop_timer; | 2675 | goto out_err_stop_timer; |
2391 | } | 2676 | } |
2392 | 2677 | ||
2678 | rv = ipmi_smi_add_proc_entry(new_smi->intf, "params", | ||
2679 | param_read_proc, NULL, | ||
2680 | new_smi, THIS_MODULE); | ||
2681 | if (rv) { | ||
2682 | printk(KERN_ERR | ||
2683 | "ipmi_si: Unable to create proc entry: %d\n", | ||
2684 | rv); | ||
2685 | goto out_err_stop_timer; | ||
2686 | } | ||
2687 | |||
2393 | list_add_tail(&new_smi->link, &smi_infos); | 2688 | list_add_tail(&new_smi->link, &smi_infos); |
2394 | 2689 | ||
2395 | mutex_unlock(&smi_infos_lock); | 2690 | mutex_unlock(&smi_infos_lock); |
@@ -2483,7 +2778,12 @@ static __devinit int init_ipmi_si(void) | |||
2483 | #endif | 2778 | #endif |
2484 | 2779 | ||
2485 | #ifdef CONFIG_PCI | 2780 | #ifdef CONFIG_PCI |
2486 | pci_module_init(&ipmi_pci_driver); | 2781 | rv = pci_register_driver(&ipmi_pci_driver); |
2782 | if (rv){ | ||
2783 | printk(KERN_ERR | ||
2784 | "init_ipmi_si: Unable to register PCI driver: %d\n", | ||
2785 | rv); | ||
2786 | } | ||
2487 | #endif | 2787 | #endif |
2488 | 2788 | ||
2489 | if (si_trydefaults) { | 2789 | if (si_trydefaults) { |
@@ -2498,7 +2798,7 @@ static __devinit int init_ipmi_si(void) | |||
2498 | } | 2798 | } |
2499 | 2799 | ||
2500 | mutex_lock(&smi_infos_lock); | 2800 | mutex_lock(&smi_infos_lock); |
2501 | if (list_empty(&smi_infos)) { | 2801 | if (unload_when_empty && list_empty(&smi_infos)) { |
2502 | mutex_unlock(&smi_infos_lock); | 2802 | mutex_unlock(&smi_infos_lock); |
2503 | #ifdef CONFIG_PCI | 2803 | #ifdef CONFIG_PCI |
2504 | pci_unregister_driver(&ipmi_pci_driver); | 2804 | pci_unregister_driver(&ipmi_pci_driver); |
@@ -2513,7 +2813,7 @@ static __devinit int init_ipmi_si(void) | |||
2513 | } | 2813 | } |
2514 | module_init(init_ipmi_si); | 2814 | module_init(init_ipmi_si); |
2515 | 2815 | ||
2516 | static void __devexit cleanup_one_si(struct smi_info *to_clean) | 2816 | static void cleanup_one_si(struct smi_info *to_clean) |
2517 | { | 2817 | { |
2518 | int rv; | 2818 | int rv; |
2519 | unsigned long flags; | 2819 | unsigned long flags; |