aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/IPMI.txt25
-rw-r--r--drivers/char/ipmi/ipmi_si_intf.c320
2 files changed, 322 insertions, 23 deletions
diff --git a/Documentation/IPMI.txt b/Documentation/IPMI.txt
index 9101cbf2d883..24dc3fcf1594 100644
--- a/Documentation/IPMI.txt
+++ b/Documentation/IPMI.txt
@@ -365,6 +365,7 @@ You can change this at module load time (for a module) with:
365 regshifts=<shift1>,<shift2>,... 365 regshifts=<shift1>,<shift2>,...
366 slave_addrs=<addr1>,<addr2>,... 366 slave_addrs=<addr1>,<addr2>,...
367 force_kipmid=<enable1>,<enable2>,... 367 force_kipmid=<enable1>,<enable2>,...
368 unload_when_empty=[0|1]
368 369
369Each of these except si_trydefaults is a list, the first item for the 370Each of these except si_trydefaults is a list, the first item for the
370first interface, second item for the second interface, etc. 371first interface, second item for the second interface, etc.
@@ -416,6 +417,11 @@ by the driver, but systems with broken interrupts might need an enable,
416or users that don't want the daemon (don't need the performance, don't 417or users that don't want the daemon (don't need the performance, don't
417want the CPU hit) can disable it. 418want the CPU hit) can disable it.
418 419
420If unload_when_empty is set to 1, the driver will be unloaded if it
421doesn't find any interfaces or all the interfaces fail to work. The
422default is one. Setting to 0 is useful with the hotmod, but is
423obviously only useful for modules.
424
419When compiled into the kernel, the parameters can be specified on the 425When compiled into the kernel, the parameters can be specified on the
420kernel command line as: 426kernel command line as:
421 427
@@ -441,6 +447,25 @@ have high-res timers enabled in the kernel and you don't have
441interrupts enabled, the driver will run VERY slowly. Don't blame me, 447interrupts enabled, the driver will run VERY slowly. Don't blame me,
442these interfaces suck. 448these interfaces suck.
443 449
450The driver supports a hot add and remove of interfaces. This way,
451interfaces can be added or removed after the kernel is up and running.
452This is done using /sys/modules/ipmi_si/hotmod, which is a write-only
453parameter. You write a string to this interface. The string has the
454format:
455 <op1>[:op2[:op3...]]
456The "op"s are:
457 add|remove,kcs|bt|smic,mem|i/o,<address>[,<opt1>[,<opt2>[,...]]]
458You can specify more than one interface on the line. The "opt"s are:
459 rsp=<regspacing>
460 rsi=<regsize>
461 rsh=<regshift>
462 irq=<irq>
463 ipmb=<ipmb slave addr>
464and these have the same meanings as discussed above. Note that you
465can also use this on the kernel command line for a more compact format
466for specifying an interface. Note that when removing an interface,
467only the first three parameters (si type, address type, and address)
468are used for the comparison. Any options are ignored for removing.
444 469
445The SMBus Driver 470The SMBus Driver
446---------------- 471----------------
diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c
index bedd76310045..8b36b5036391 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 {
92enum si_type { 96enum si_type {
93 SI_KCS, SI_SMIC, SI_BT 97 SI_KCS, SI_SMIC, SI_BT
94}; 98};
95static char *si_to_str[] = { "KCS", "SMIC", "BT" }; 99static 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
222static int force_kipmid[SI_MAX_PARMS]; 226static int force_kipmid[SI_MAX_PARMS];
223static int num_force_kipmid; 227static int num_force_kipmid;
224 228
229static int unload_when_empty = 1;
230
225static int try_smi_init(struct smi_info *smi); 231static int try_smi_init(struct smi_info *smi);
232static void cleanup_one_si(struct smi_info *to_clean);
226 233
227static ATOMIC_NOTIFIER_HEAD(xaction_notifier_list); 234static ATOMIC_NOTIFIER_HEAD(xaction_notifier_list);
228static int register_xaction_notifier(struct notifier_block * nb) 235static int register_xaction_notifier(struct notifier_block * nb)
@@ -247,7 +254,7 @@ static void return_hosed_msg(struct smi_info *smi_info)
247 /* Make it a reponse */ 254 /* Make it a reponse */
248 msg->rsp[0] = msg->data[0] | 4; 255 msg->rsp[0] = msg->data[0] | 4;
249 msg->rsp[1] = msg->data[1]; 256 msg->rsp[1] = msg->data[1];
250 msg->rsp[2] = 0xFF; /* Unknown error. */ 257 msg->rsp[2] = IPMI_ERR_UNSPECIFIED;
251 msg->rsp_size = 3; 258 msg->rsp_size = 3;
252 259
253 smi_info->curr_msg = NULL; 260 smi_info->curr_msg = NULL;
@@ -716,6 +723,15 @@ static void sender(void *send_info,
716 struct timeval t; 723 struct timeval t;
717#endif 724#endif
718 725
726 if (atomic_read(&smi_info->stop_operation)) {
727 msg->rsp[0] = msg->data[0] | 4;
728 msg->rsp[1] = msg->data[1];
729 msg->rsp[2] = IPMI_ERR_UNSPECIFIED;
730 msg->rsp_size = 3;
731 deliver_recv_msg(smi_info, msg);
732 return;
733 }
734
719 spin_lock_irqsave(&(smi_info->msg_lock), flags); 735 spin_lock_irqsave(&(smi_info->msg_lock), flags);
720#ifdef DEBUG_TIMING 736#ifdef DEBUG_TIMING
721 do_gettimeofday(&t); 737 do_gettimeofday(&t);
@@ -819,6 +835,9 @@ static void request_events(void *send_info)
819{ 835{
820 struct smi_info *smi_info = send_info; 836 struct smi_info *smi_info = send_info;
821 837
838 if (atomic_read(&smi_info->stop_operation))
839 return;
840
822 atomic_set(&smi_info->req_events, 1); 841 atomic_set(&smi_info->req_events, 1);
823} 842}
824 843
@@ -1003,6 +1022,16 @@ static int num_regshifts = 0;
1003static int slave_addrs[SI_MAX_PARMS]; 1022static int slave_addrs[SI_MAX_PARMS];
1004static int num_slave_addrs = 0; 1023static int num_slave_addrs = 0;
1005 1024
1025#define IPMI_IO_ADDR_SPACE 0
1026#define IPMI_MEM_ADDR_SPACE 1
1027static char *addr_space_to_str[] = { "I/O", "mem" };
1028
1029static int hotmod_handler(const char *val, struct kernel_param *kp);
1030
1031module_param_call(hotmod, hotmod_handler, NULL, NULL, 0200);
1032MODULE_PARM_DESC(hotmod, "Add and remove interfaces. See"
1033 " Documentation/IPMI.txt in the kernel sources for the"
1034 " gory details.");
1006 1035
1007module_param_named(trydefaults, si_trydefaults, bool, 0); 1036module_param_named(trydefaults, si_trydefaults, bool, 0);
1008MODULE_PARM_DESC(trydefaults, "Setting this to 'false' will disable the" 1037MODULE_PARM_DESC(trydefaults, "Setting this to 'false' will disable the"
@@ -1054,12 +1083,12 @@ module_param_array(force_kipmid, int, &num_force_kipmid, 0);
1054MODULE_PARM_DESC(force_kipmid, "Force the kipmi daemon to be enabled (1) or" 1083MODULE_PARM_DESC(force_kipmid, "Force the kipmi daemon to be enabled (1) or"
1055 " disabled(0). Normally the IPMI driver auto-detects" 1084 " disabled(0). Normally the IPMI driver auto-detects"
1056 " this, but the value may be overridden by this parm."); 1085 " this, but the value may be overridden by this parm.");
1086module_param(unload_when_empty, int, 0);
1087MODULE_PARM_DESC(unload_when_empty, "Unload the module if no interfaces are"
1088 " specified or found, default is 1. Setting to 0"
1089 " is useful for hot add of devices using hotmod.");
1057 1090
1058 1091
1059#define IPMI_IO_ADDR_SPACE 0
1060#define IPMI_MEM_ADDR_SPACE 1
1061static char *addr_space_to_str[] = { "I/O", "memory" };
1062
1063static void std_irq_cleanup(struct smi_info *info) 1092static void std_irq_cleanup(struct smi_info *info)
1064{ 1093{
1065 if (info->si_type == SI_BT) 1094 if (info->si_type == SI_BT)
@@ -1333,6 +1362,234 @@ static int mem_setup(struct smi_info *info)
1333 return 0; 1362 return 0;
1334} 1363}
1335 1364
1365/*
1366 * Parms come in as <op1>[:op2[:op3...]]. ops are:
1367 * add|remove,kcs|bt|smic,mem|i/o,<address>[,<opt1>[,<opt2>[,...]]]
1368 * Options are:
1369 * rsp=<regspacing>
1370 * rsi=<regsize>
1371 * rsh=<regshift>
1372 * irq=<irq>
1373 * ipmb=<ipmb addr>
1374 */
1375enum hotmod_op { HM_ADD, HM_REMOVE };
1376struct hotmod_vals {
1377 char *name;
1378 int val;
1379};
1380static struct hotmod_vals hotmod_ops[] = {
1381 { "add", HM_ADD },
1382 { "remove", HM_REMOVE },
1383 { NULL }
1384};
1385static struct hotmod_vals hotmod_si[] = {
1386 { "kcs", SI_KCS },
1387 { "smic", SI_SMIC },
1388 { "bt", SI_BT },
1389 { NULL }
1390};
1391static struct hotmod_vals hotmod_as[] = {
1392 { "mem", IPMI_MEM_ADDR_SPACE },
1393 { "i/o", IPMI_IO_ADDR_SPACE },
1394 { NULL }
1395};
1396static int ipmi_strcasecmp(const char *s1, const char *s2)
1397{
1398 while (*s1 || *s2) {
1399 if (!*s1)
1400 return -1;
1401 if (!*s2)
1402 return 1;
1403 if (*s1 != *s2)
1404 return *s1 - *s2;
1405 s1++;
1406 s2++;
1407 }
1408 return 0;
1409}
1410static int parse_str(struct hotmod_vals *v, int *val, char *name, char **curr)
1411{
1412 char *s;
1413 int i;
1414
1415 s = strchr(*curr, ',');
1416 if (!s) {
1417 printk(KERN_WARNING PFX "No hotmod %s given.\n", name);
1418 return -EINVAL;
1419 }
1420 *s = '\0';
1421 s++;
1422 for (i = 0; hotmod_ops[i].name; i++) {
1423 if (ipmi_strcasecmp(*curr, v[i].name) == 0) {
1424 *val = v[i].val;
1425 *curr = s;
1426 return 0;
1427 }
1428 }
1429
1430 printk(KERN_WARNING PFX "Invalid hotmod %s '%s'\n", name, *curr);
1431 return -EINVAL;
1432}
1433
1434static int hotmod_handler(const char *val, struct kernel_param *kp)
1435{
1436 char *str = kstrdup(val, GFP_KERNEL);
1437 int rv = -EINVAL;
1438 char *next, *curr, *s, *n, *o;
1439 enum hotmod_op op;
1440 enum si_type si_type;
1441 int addr_space;
1442 unsigned long addr;
1443 int regspacing;
1444 int regsize;
1445 int regshift;
1446 int irq;
1447 int ipmb;
1448 int ival;
1449 struct smi_info *info;
1450
1451 if (!str)
1452 return -ENOMEM;
1453
1454 /* Kill any trailing spaces, as we can get a "\n" from echo. */
1455 ival = strlen(str) - 1;
1456 while ((ival >= 0) && isspace(str[ival])) {
1457 str[ival] = '\0';
1458 ival--;
1459 }
1460
1461 for (curr = str; curr; curr = next) {
1462 regspacing = 1;
1463 regsize = 1;
1464 regshift = 0;
1465 irq = 0;
1466 ipmb = 0x20;
1467
1468 next = strchr(curr, ':');
1469 if (next) {
1470 *next = '\0';
1471 next++;
1472 }
1473
1474 rv = parse_str(hotmod_ops, &ival, "operation", &curr);
1475 if (rv)
1476 break;
1477 op = ival;
1478
1479 rv = parse_str(hotmod_si, &ival, "interface type", &curr);
1480 if (rv)
1481 break;
1482 si_type = ival;
1483
1484 rv = parse_str(hotmod_as, &addr_space, "address space", &curr);
1485 if (rv)
1486 break;
1487
1488 s = strchr(curr, ',');
1489 if (s) {
1490 *s = '\0';
1491 s++;
1492 }
1493 addr = simple_strtoul(curr, &n, 0);
1494 if ((*n != '\0') || (*curr == '\0')) {
1495 printk(KERN_WARNING PFX "Invalid hotmod address"
1496 " '%s'\n", curr);
1497 break;
1498 }
1499
1500 while (s) {
1501 curr = s;
1502 s = strchr(curr, ',');
1503 if (s) {
1504 *s = '\0';
1505 s++;
1506 }
1507 o = strchr(curr, '=');
1508 if (o) {
1509 *o = '\0';
1510 o++;
1511 }
1512#define HOTMOD_INT_OPT(name, val) \
1513 if (ipmi_strcasecmp(curr, name) == 0) { \
1514 if (!o) { \
1515 printk(KERN_WARNING PFX \
1516 "No option given for '%s'\n", \
1517 curr); \
1518 goto out; \
1519 } \
1520 val = simple_strtoul(o, &n, 0); \
1521 if ((*n != '\0') || (*o == '\0')) { \
1522 printk(KERN_WARNING PFX \
1523 "Bad option given for '%s'\n", \
1524 curr); \
1525 goto out; \
1526 } \
1527 }
1528
1529 HOTMOD_INT_OPT("rsp", regspacing)
1530 else HOTMOD_INT_OPT("rsi", regsize)
1531 else HOTMOD_INT_OPT("rsh", regshift)
1532 else HOTMOD_INT_OPT("irq", irq)
1533 else HOTMOD_INT_OPT("ipmb", ipmb)
1534 else {
1535 printk(KERN_WARNING PFX
1536 "Invalid hotmod option '%s'\n",
1537 curr);
1538 goto out;
1539 }
1540#undef HOTMOD_INT_OPT
1541 }
1542
1543 if (op == HM_ADD) {
1544 info = kzalloc(sizeof(*info), GFP_KERNEL);
1545 if (!info) {
1546 rv = -ENOMEM;
1547 goto out;
1548 }
1549
1550 info->addr_source = "hotmod";
1551 info->si_type = si_type;
1552 info->io.addr_data = addr;
1553 info->io.addr_type = addr_space;
1554 if (addr_space == IPMI_MEM_ADDR_SPACE)
1555 info->io_setup = mem_setup;
1556 else
1557 info->io_setup = port_setup;
1558
1559 info->io.addr = NULL;
1560 info->io.regspacing = regspacing;
1561 if (!info->io.regspacing)
1562 info->io.regspacing = DEFAULT_REGSPACING;
1563 info->io.regsize = regsize;
1564 if (!info->io.regsize)
1565 info->io.regsize = DEFAULT_REGSPACING;
1566 info->io.regshift = regshift;
1567 info->irq = irq;
1568 if (info->irq)
1569 info->irq_setup = std_irq_setup;
1570 info->slave_addr = ipmb;
1571
1572 try_smi_init(info);
1573 } else {
1574 /* remove */
1575 struct smi_info *e, *tmp_e;
1576
1577 mutex_lock(&smi_infos_lock);
1578 list_for_each_entry_safe(e, tmp_e, &smi_infos, link) {
1579 if (e->io.addr_type != addr_space)
1580 continue;
1581 if (e->si_type != si_type)
1582 continue;
1583 if (e->io.addr_data == addr)
1584 cleanup_one_si(e);
1585 }
1586 mutex_unlock(&smi_infos_lock);
1587 }
1588 }
1589 out:
1590 kfree(str);
1591 return rv;
1592}
1336 1593
1337static __devinit void hardcode_find_bmc(void) 1594static __devinit void hardcode_find_bmc(void)
1338{ 1595{
@@ -1349,11 +1606,11 @@ static __devinit void hardcode_find_bmc(void)
1349 1606
1350 info->addr_source = "hardcoded"; 1607 info->addr_source = "hardcoded";
1351 1608
1352 if (!si_type[i] || strcmp(si_type[i], "kcs") == 0) { 1609 if (!si_type[i] || ipmi_strcasecmp(si_type[i], "kcs") == 0) {
1353 info->si_type = SI_KCS; 1610 info->si_type = SI_KCS;
1354 } else if (strcmp(si_type[i], "smic") == 0) { 1611 } else if (ipmi_strcasecmp(si_type[i], "smic") == 0) {
1355 info->si_type = SI_SMIC; 1612 info->si_type = SI_SMIC;
1356 } else if (strcmp(si_type[i], "bt") == 0) { 1613 } else if (ipmi_strcasecmp(si_type[i], "bt") == 0) {
1357 info->si_type = SI_BT; 1614 info->si_type = SI_BT;
1358 } else { 1615 } else {
1359 printk(KERN_WARNING 1616 printk(KERN_WARNING
@@ -1968,19 +2225,9 @@ static int try_get_dev_id(struct smi_info *smi_info)
1968static int type_file_read_proc(char *page, char **start, off_t off, 2225static int type_file_read_proc(char *page, char **start, off_t off,
1969 int count, int *eof, void *data) 2226 int count, int *eof, void *data)
1970{ 2227{
1971 char *out = (char *) page;
1972 struct smi_info *smi = data; 2228 struct smi_info *smi = data;
1973 2229
1974 switch (smi->si_type) { 2230 return sprintf(page, "%s\n", si_to_str[smi->si_type]);
1975 case SI_KCS:
1976 return sprintf(out, "kcs\n");
1977 case SI_SMIC:
1978 return sprintf(out, "smic\n");
1979 case SI_BT:
1980 return sprintf(out, "bt\n");
1981 default:
1982 return 0;
1983 }
1984} 2231}
1985 2232
1986static int stat_file_read_proc(char *page, char **start, off_t off, 2233static int stat_file_read_proc(char *page, char **start, off_t off,
@@ -2016,7 +2263,24 @@ static int stat_file_read_proc(char *page, char **start, off_t off,
2016 out += sprintf(out, "incoming_messages: %ld\n", 2263 out += sprintf(out, "incoming_messages: %ld\n",
2017 smi->incoming_messages); 2264 smi->incoming_messages);
2018 2265
2019 return (out - ((char *) page)); 2266 return out - page;
2267}
2268
2269static int param_read_proc(char *page, char **start, off_t off,
2270 int count, int *eof, void *data)
2271{
2272 struct smi_info *smi = data;
2273
2274 return sprintf(page,
2275 "%s,%s,0x%lx,rsp=%d,rsi=%d,rsh=%d,irq=%d,ipmb=%d\n",
2276 si_to_str[smi->si_type],
2277 addr_space_to_str[smi->io.addr_type],
2278 smi->io.addr_data,
2279 smi->io.regspacing,
2280 smi->io.regsize,
2281 smi->io.regshift,
2282 smi->irq,
2283 smi->slave_addr);
2020} 2284}
2021 2285
2022/* 2286/*
@@ -2407,6 +2671,16 @@ static int try_smi_init(struct smi_info *new_smi)
2407 goto out_err_stop_timer; 2671 goto out_err_stop_timer;
2408 } 2672 }
2409 2673
2674 rv = ipmi_smi_add_proc_entry(new_smi->intf, "params",
2675 param_read_proc, NULL,
2676 new_smi, THIS_MODULE);
2677 if (rv) {
2678 printk(KERN_ERR
2679 "ipmi_si: Unable to create proc entry: %d\n",
2680 rv);
2681 goto out_err_stop_timer;
2682 }
2683
2410 list_add_tail(&new_smi->link, &smi_infos); 2684 list_add_tail(&new_smi->link, &smi_infos);
2411 2685
2412 mutex_unlock(&smi_infos_lock); 2686 mutex_unlock(&smi_infos_lock);
@@ -2515,7 +2789,7 @@ static __devinit int init_ipmi_si(void)
2515 } 2789 }
2516 2790
2517 mutex_lock(&smi_infos_lock); 2791 mutex_lock(&smi_infos_lock);
2518 if (list_empty(&smi_infos)) { 2792 if (unload_when_empty && list_empty(&smi_infos)) {
2519 mutex_unlock(&smi_infos_lock); 2793 mutex_unlock(&smi_infos_lock);
2520#ifdef CONFIG_PCI 2794#ifdef CONFIG_PCI
2521 pci_unregister_driver(&ipmi_pci_driver); 2795 pci_unregister_driver(&ipmi_pci_driver);
@@ -2530,7 +2804,7 @@ static __devinit int init_ipmi_si(void)
2530} 2804}
2531module_init(init_ipmi_si); 2805module_init(init_ipmi_si);
2532 2806
2533static void __devexit cleanup_one_si(struct smi_info *to_clean) 2807static void cleanup_one_si(struct smi_info *to_clean)
2534{ 2808{
2535 int rv; 2809 int rv;
2536 unsigned long flags; 2810 unsigned long flags;