Various small fixes for IPMI. Cleanups in the documentation and

convertion printk() to pr_xxx() and removal of an unused module
 parameter.  Some small bug fixes and enhancements.
 
 This also adds a post softdep from the IPMI core module to the
 IPMI device interface.  Many people have complained that the device
 interface isn't automatically avaiable when IPMI is loaded.  I don't
 want to make the device interface mandatory, though, plenty of people
 use IPMI internally (like with ACPI) and don't need a device interface
 or the added possible security entry.  A softdep should make it work
 "out of the box" but allow people to not have it if they don't want it.
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1
 
 iEYEABECAAYFAlhSE9cACgkQIXnXXONXERe6iACgsiU5/LG4tbKu9EyZXp5isRw6
 AdsAn1dT08aobOzJhFI3dVx6oTnJQDDC
 =ifi5
 -----END PGP SIGNATURE-----

Merge tag 'for-linus-4.10' of git://git.code.sf.net/p/openipmi/linux-ipmi

Pull IPMI updates from Corey Minyard:
 "Various small fixes for IPMI. Cleanups in the documentation and
  convertion printk() to pr_xxx() and removal of an unused module
  parameter. Some small bug fixes and enhancements.

  This also adds a post softdep from the IPMI core module to the IPMI
  device interface. Many people have complained that the device
  interface isn't automatically avaiable when IPMI is loaded. I don't
  want to make the device interface mandatory, though, plenty of people
  use IPMI internally (like with ACPI) and don't need a device interface
  or the added possible security entry. A softdep should make it work
  'out of the box' but allow people to not have it if they don't want
  it"

* tag 'for-linus-4.10' of git://git.code.sf.net/p/openipmi/linux-ipmi:
  ipmi: create hardware-independent softdep for ipmi_devintf
  ipmi: Fix sequence number handling
  ipmi: Pick up slave address from SMBIOS on an ACPI device
  ipmi_si: Clean up printks
  Move platform device creation earlier in the initialization
  ipmi: Update documentation
  ipmi_ssif: Remove an unused module parameter
  ipmi: Periodically check for events, not messages
This commit is contained in:
Linus Torvalds 2016-12-14 20:54:33 -08:00
commit 196202be3c
5 changed files with 165 additions and 130 deletions

View File

@ -111,6 +111,8 @@ ipmi_ssif - A driver for accessing BMCs on the SMBus. It uses the
I2C kernel driver's SMBus interfaces to send and receive IPMI messages I2C kernel driver's SMBus interfaces to send and receive IPMI messages
over the SMBus. over the SMBus.
ipmi_powernv - A driver for access BMCs on POWERNV systems.
ipmi_watchdog - IPMI requires systems to have a very capable watchdog ipmi_watchdog - IPMI requires systems to have a very capable watchdog
timer. This driver implements the standard Linux watchdog timer timer. This driver implements the standard Linux watchdog timer
interface on top of the IPMI message handler. interface on top of the IPMI message handler.
@ -118,17 +120,15 @@ interface on top of the IPMI message handler.
ipmi_poweroff - Some systems support the ability to be turned off via ipmi_poweroff - Some systems support the ability to be turned off via
IPMI commands. IPMI commands.
These are all individually selectable via configuration options. bt-bmc - This is not part of the main driver, but instead a driver for
accessing a BMC-side interface of a BT interface. It is used on BMCs
running Linux to provide an interface to the host.
Note that the KCS-only interface has been removed. The af_ipmi driver These are all individually selectable via configuration options.
is no longer supported and has been removed because it was impossible
to do 32 bit emulation on 64-bit kernels with it.
Much documentation for the interface is in the include files. The Much documentation for the interface is in the include files. The
IPMI include files are: IPMI include files are:
net/af_ipmi.h - Contains the socket interface.
linux/ipmi.h - Contains the user interface and IOCTL interface for IPMI. linux/ipmi.h - Contains the user interface and IOCTL interface for IPMI.
linux/ipmi_smi.h - Contains the interface for system management interfaces linux/ipmi_smi.h - Contains the interface for system management interfaces
@ -245,6 +245,16 @@ addressed (because some boards actually have multiple BMCs on them)
and the user should not have to care what type of SMI is below them. and the user should not have to care what type of SMI is below them.
Watching For Interfaces
When your code comes up, the IPMI driver may or may not have detected
if IPMI devices exist. So you might have to defer your setup until
the device is detected, or you might be able to do it immediately.
To handle this, and to allow for discovery, you register an SMI
watcher with ipmi_smi_watcher_register() to iterate over interfaces
and tell you when they come and go.
Creating the User Creating the User
To user the message handler, you must first create a user using To user the message handler, you must first create a user using
@ -263,7 +273,7 @@ closing the device automatically destroys the user.
Messaging Messaging
To send a message from kernel-land, the ipmi_request() call does To send a message from kernel-land, the ipmi_request_settime() call does
pretty much all message handling. Most of the parameter are pretty much all message handling. Most of the parameter are
self-explanatory. However, it takes a "msgid" parameter. This is NOT self-explanatory. However, it takes a "msgid" parameter. This is NOT
the sequence number of messages. It is simply a long value that is the sequence number of messages. It is simply a long value that is
@ -352,11 +362,12 @@ that for more details.
The SI Driver The SI Driver
------------- -------------
The SI driver allows up to 4 KCS or SMIC interfaces to be configured The SI driver allows KCS, BT, and SMIC interfaces to be configured
in the system. By default, scan the ACPI tables for interfaces, and in the system. It discovers interfaces through a host of different
if it doesn't find any the driver will attempt to register one KCS methods, depending on the system.
interface at the spec-specified I/O port 0xca2 without interrupts.
You can change this at module load time (for a module) with: You can specify up to four interfaces on the module load line and
control some module parameters:
modprobe ipmi_si.o type=<type1>,<type2>.... modprobe ipmi_si.o type=<type1>,<type2>....
ports=<port1>,<port2>... addrs=<addr1>,<addr2>... ports=<port1>,<port2>... addrs=<addr1>,<addr2>...
@ -367,7 +378,7 @@ You can change this at module load time (for a module) with:
force_kipmid=<enable1>,<enable2>,... force_kipmid=<enable1>,<enable2>,...
kipmid_max_busy_us=<ustime1>,<ustime2>,... kipmid_max_busy_us=<ustime1>,<ustime2>,...
unload_when_empty=[0|1] unload_when_empty=[0|1]
trydefaults=[0|1] trydmi=[0|1] tryacpi=[0|1] trydmi=[0|1] tryacpi=[0|1]
tryplatform=[0|1] trypci=[0|1] tryplatform=[0|1] trypci=[0|1]
Each of these except try... items is a list, the first item for the Each of these except try... items is a list, the first item for the
@ -386,10 +397,6 @@ use the I/O port given as the device address.
If you specify irqs as non-zero for an interface, the driver will If you specify irqs as non-zero for an interface, the driver will
attempt to use the given interrupt for the device. attempt to use the given interrupt for the device.
trydefaults sets whether the standard IPMI interface at 0xca2 and
any interfaces specified by ACPE are tried. By default, the driver
tries it, set this value to zero to turn this off.
The other try... items disable discovery by their corresponding The other try... items disable discovery by their corresponding
names. These are all enabled by default, set them to zero to disable names. These are all enabled by default, set them to zero to disable
them. The tryplatform disables openfirmware. them. The tryplatform disables openfirmware.
@ -434,7 +441,7 @@ kernel command line as:
ipmi_si.type=<type1>,<type2>... ipmi_si.type=<type1>,<type2>...
ipmi_si.ports=<port1>,<port2>... ipmi_si.addrs=<addr1>,<addr2>... ipmi_si.ports=<port1>,<port2>... ipmi_si.addrs=<addr1>,<addr2>...
ipmi_si.irqs=<irq1>,<irq2>... ipmi_si.trydefaults=[0|1] ipmi_si.irqs=<irq1>,<irq2>...
ipmi_si.regspacings=<sp1>,<sp2>,... ipmi_si.regspacings=<sp1>,<sp2>,...
ipmi_si.regsizes=<size1>,<size2>,... ipmi_si.regsizes=<size1>,<size2>,...
ipmi_si.regshifts=<shift1>,<shift2>,... ipmi_si.regshifts=<shift1>,<shift2>,...
@ -444,11 +451,6 @@ kernel command line as:
It works the same as the module parameters of the same names. It works the same as the module parameters of the same names.
By default, the driver will attempt to detect any device specified by
ACPI, and if none of those then a KCS device at the spec-specified
0xca2. If you want to turn this off, set the "trydefaults" option to
false.
If your IPMI interface does not support interrupts and is a KCS or If your IPMI interface does not support interrupts and is a KCS or
SMIC interface, the IPMI driver will start a kernel thread for the SMIC interface, the IPMI driver will start a kernel thread for the
interface to help speed things up. This is a low-priority kernel interface to help speed things up. This is a low-priority kernel
@ -500,7 +502,8 @@ at module load time (for a module) with:
addr=<i2caddr1>[,<i2caddr2>[,...]] addr=<i2caddr1>[,<i2caddr2>[,...]]
adapter=<adapter1>[,<adapter2>[...]] adapter=<adapter1>[,<adapter2>[...]]
dbg=<flags1>,<flags2>... dbg=<flags1>,<flags2>...
slave_addrs=<addr1>,<addr2>,... slave_addrs=<addr1>,<addr2>,...
tryacpi=[0|1] trydmi=[0|1]
[dbg_probe=1] [dbg_probe=1]
The addresses are normal I2C addresses. The adapter is the string The addresses are normal I2C addresses. The adapter is the string
@ -513,6 +516,9 @@ spaces in kernel parameters.
The debug flags are bit flags for each BMC found, they are: The debug flags are bit flags for each BMC found, they are:
IPMI messages: 1, driver state: 2, timing: 4, I2C probe: 8 IPMI messages: 1, driver state: 2, timing: 4, I2C probe: 8
The tryxxx parameters can be used to disable detecting interfaces
from various sources.
Setting dbg_probe to 1 will enable debugging of the probing and Setting dbg_probe to 1 will enable debugging of the probing and
detection process for BMCs on the SMBusses. detection process for BMCs on the SMBusses.
@ -535,7 +541,8 @@ kernel command line as:
ipmi_ssif.adapter=<adapter1>[,<adapter2>[...]] ipmi_ssif.adapter=<adapter1>[,<adapter2>[...]]
ipmi_ssif.dbg=<flags1>[,<flags2>[...]] ipmi_ssif.dbg=<flags1>[,<flags2>[...]]
ipmi_ssif.dbg_probe=1 ipmi_ssif.dbg_probe=1
ipmi_ssif.slave_addrs=<addr1>[,<addr2>[...]] ipmi_ssif.slave_addrs=<addr1>[,<addr2>[...]]
ipmi_ssif.tryacpi=[0|1] ipmi_ssif.trydmi=[0|1]
These are the same options as on the module command line. These are the same options as on the module command line.

View File

@ -989,4 +989,3 @@ module_exit(cleanup_ipmi);
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
MODULE_AUTHOR("Corey Minyard <minyard@mvista.com>"); MODULE_AUTHOR("Corey Minyard <minyard@mvista.com>");
MODULE_DESCRIPTION("Linux device interface for the IPMI message handler."); MODULE_DESCRIPTION("Linux device interface for the IPMI message handler.");
MODULE_ALIAS("platform:ipmi_si");

View File

@ -158,15 +158,16 @@ struct seq_table {
* Store the information in a msgid (long) to allow us to find a * Store the information in a msgid (long) to allow us to find a
* sequence table entry from the msgid. * sequence table entry from the msgid.
*/ */
#define STORE_SEQ_IN_MSGID(seq, seqid) (((seq&0xff)<<26) | (seqid&0x3ffffff)) #define STORE_SEQ_IN_MSGID(seq, seqid) \
((((seq) & 0x3f) << 26) | ((seqid) & 0x3ffffff))
#define GET_SEQ_FROM_MSGID(msgid, seq, seqid) \ #define GET_SEQ_FROM_MSGID(msgid, seq, seqid) \
do { \ do { \
seq = ((msgid >> 26) & 0x3f); \ seq = (((msgid) >> 26) & 0x3f); \
seqid = (msgid & 0x3fffff); \ seqid = ((msgid) & 0x3ffffff); \
} while (0) } while (0)
#define NEXT_SEQID(seqid) (((seqid) + 1) & 0x3fffff) #define NEXT_SEQID(seqid) (((seqid) + 1) & 0x3ffffff)
struct ipmi_channel { struct ipmi_channel {
unsigned char medium; unsigned char medium;
@ -4645,3 +4646,4 @@ MODULE_AUTHOR("Corey Minyard <minyard@mvista.com>");
MODULE_DESCRIPTION("Incoming and outgoing message routing for an IPMI" MODULE_DESCRIPTION("Incoming and outgoing message routing for an IPMI"
" interface."); " interface.");
MODULE_VERSION(IPMI_DRIVER_VERSION); MODULE_VERSION(IPMI_DRIVER_VERSION);
MODULE_SOFTDEP("post: ipmi_devintf");

View File

@ -789,7 +789,7 @@ static void handle_transaction_done(struct smi_info *smi_info)
smi_info->si_state = SI_NORMAL; smi_info->si_state = SI_NORMAL;
break; break;
} }
start_getting_msg_queue(smi_info); start_getting_events(smi_info);
} else { } else {
smi_info->si_state = SI_NORMAL; smi_info->si_state = SI_NORMAL;
} }
@ -812,7 +812,7 @@ static void handle_transaction_done(struct smi_info *smi_info)
smi_info->si_state = SI_NORMAL; smi_info->si_state = SI_NORMAL;
break; break;
} }
start_getting_msg_queue(smi_info); start_getting_events(smi_info);
} else { } else {
smi_info->si_state = SI_NORMAL; smi_info->si_state = SI_NORMAL;
} }
@ -1764,7 +1764,7 @@ static int parse_str(const struct hotmod_vals *v, int *val, char *name,
s = strchr(*curr, ','); s = strchr(*curr, ',');
if (!s) { if (!s) {
printk(KERN_WARNING PFX "No hotmod %s given.\n", name); pr_warn(PFX "No hotmod %s given.\n", name);
return -EINVAL; return -EINVAL;
} }
*s = '\0'; *s = '\0';
@ -1777,7 +1777,7 @@ static int parse_str(const struct hotmod_vals *v, int *val, char *name,
} }
} }
printk(KERN_WARNING PFX "Invalid hotmod %s '%s'\n", name, *curr); pr_warn(PFX "Invalid hotmod %s '%s'\n", name, *curr);
return -EINVAL; return -EINVAL;
} }
@ -1788,16 +1788,12 @@ static int check_hotmod_int_op(const char *curr, const char *option,
if (strcmp(curr, name) == 0) { if (strcmp(curr, name) == 0) {
if (!option) { if (!option) {
printk(KERN_WARNING PFX pr_warn(PFX "No option given for '%s'\n", curr);
"No option given for '%s'\n",
curr);
return -EINVAL; return -EINVAL;
} }
*val = simple_strtoul(option, &n, 0); *val = simple_strtoul(option, &n, 0);
if ((*n != '\0') || (*option == '\0')) { if ((*n != '\0') || (*option == '\0')) {
printk(KERN_WARNING PFX pr_warn(PFX "Bad option given for '%s'\n", curr);
"Bad option given for '%s'\n",
curr);
return -EINVAL; return -EINVAL;
} }
return 1; return 1;
@ -1877,8 +1873,7 @@ static int hotmod_handler(const char *val, struct kernel_param *kp)
} }
addr = simple_strtoul(curr, &n, 0); addr = simple_strtoul(curr, &n, 0);
if ((*n != '\0') || (*curr == '\0')) { if ((*n != '\0') || (*curr == '\0')) {
printk(KERN_WARNING PFX "Invalid hotmod address" pr_warn(PFX "Invalid hotmod address '%s'\n", curr);
" '%s'\n", curr);
break; break;
} }
@ -1921,9 +1916,7 @@ static int hotmod_handler(const char *val, struct kernel_param *kp)
continue; continue;
rv = -EINVAL; rv = -EINVAL;
printk(KERN_WARNING PFX pr_warn(PFX "Invalid hotmod option '%s'\n", curr);
"Invalid hotmod option '%s'\n",
curr);
goto out; goto out;
} }
@ -2003,7 +1996,7 @@ static int hardcode_find_bmc(void)
return -ENOMEM; return -ENOMEM;
info->addr_source = SI_HARDCODED; info->addr_source = SI_HARDCODED;
printk(KERN_INFO PFX "probing via hardcoded address\n"); pr_info(PFX "probing via hardcoded address\n");
if (!si_type[i] || strcmp(si_type[i], "kcs") == 0) { if (!si_type[i] || strcmp(si_type[i], "kcs") == 0) {
info->si_type = SI_KCS; info->si_type = SI_KCS;
@ -2012,9 +2005,8 @@ static int hardcode_find_bmc(void)
} else if (strcmp(si_type[i], "bt") == 0) { } else if (strcmp(si_type[i], "bt") == 0) {
info->si_type = SI_BT; info->si_type = SI_BT;
} else { } else {
printk(KERN_WARNING PFX "Interface type specified " pr_warn(PFX "Interface type specified for interface %d, was invalid: %s\n",
"for interface %d, was invalid: %s\n", i, si_type[i]);
i, si_type[i]);
kfree(info); kfree(info);
continue; continue;
} }
@ -2030,9 +2022,8 @@ static int hardcode_find_bmc(void)
info->io.addr_data = addrs[i]; info->io.addr_data = addrs[i];
info->io.addr_type = IPMI_MEM_ADDR_SPACE; info->io.addr_type = IPMI_MEM_ADDR_SPACE;
} else { } else {
printk(KERN_WARNING PFX "Interface type specified " pr_warn(PFX "Interface type specified for interface %d, but port and address were not set or set to zero.\n",
"for interface %d, but port and address were " i);
"not set or set to zero.\n", i);
kfree(info); kfree(info);
continue; continue;
} }
@ -2173,18 +2164,18 @@ static int try_init_spmi(struct SPMITable *spmi)
int rv; int rv;
if (spmi->IPMIlegacy != 1) { if (spmi->IPMIlegacy != 1) {
printk(KERN_INFO PFX "Bad SPMI legacy %d\n", spmi->IPMIlegacy); pr_info(PFX "Bad SPMI legacy %d\n", spmi->IPMIlegacy);
return -ENODEV; return -ENODEV;
} }
info = smi_info_alloc(); info = smi_info_alloc();
if (!info) { if (!info) {
printk(KERN_ERR PFX "Could not allocate SI data (3)\n"); pr_err(PFX "Could not allocate SI data (3)\n");
return -ENOMEM; return -ENOMEM;
} }
info->addr_source = SI_SPMI; info->addr_source = SI_SPMI;
printk(KERN_INFO PFX "probing via SPMI\n"); pr_info(PFX "probing via SPMI\n");
/* Figure out the interface type. */ /* Figure out the interface type. */
switch (spmi->InterfaceType) { switch (spmi->InterfaceType) {
@ -2201,8 +2192,8 @@ static int try_init_spmi(struct SPMITable *spmi)
kfree(info); kfree(info);
return -EIO; return -EIO;
default: default:
printk(KERN_INFO PFX "Unknown ACPI/SPMI SI type %d\n", pr_info(PFX "Unknown ACPI/SPMI SI type %d\n",
spmi->InterfaceType); spmi->InterfaceType);
kfree(info); kfree(info);
return -EIO; return -EIO;
} }
@ -2238,15 +2229,15 @@ static int try_init_spmi(struct SPMITable *spmi)
info->io.addr_type = IPMI_IO_ADDR_SPACE; info->io.addr_type = IPMI_IO_ADDR_SPACE;
} else { } else {
kfree(info); kfree(info);
printk(KERN_WARNING PFX "Unknown ACPI I/O Address type\n"); pr_warn(PFX "Unknown ACPI I/O Address type\n");
return -EIO; return -EIO;
} }
info->io.addr_data = spmi->addr.address; info->io.addr_data = spmi->addr.address;
pr_info("ipmi_si: SPMI: %s %#lx regsize %d spacing %d irq %d\n", pr_info("ipmi_si: SPMI: %s %#lx regsize %d spacing %d irq %d\n",
(info->io.addr_type == IPMI_IO_ADDR_SPACE) ? "io" : "mem", (info->io.addr_type == IPMI_IO_ADDR_SPACE) ? "io" : "mem",
info->io.addr_data, info->io.regsize, info->io.regspacing, info->io.addr_data, info->io.regsize, info->io.regspacing,
info->irq); info->irq);
rv = add_smi(info); rv = add_smi(info);
if (rv) if (rv)
@ -2356,12 +2347,12 @@ static void try_init_dmi(struct dmi_ipmi_data *ipmi_data)
info = smi_info_alloc(); info = smi_info_alloc();
if (!info) { if (!info) {
printk(KERN_ERR PFX "Could not allocate SI data\n"); pr_err(PFX "Could not allocate SI data\n");
return; return;
} }
info->addr_source = SI_SMBIOS; info->addr_source = SI_SMBIOS;
printk(KERN_INFO PFX "probing via SMBIOS\n"); pr_info(PFX "probing via SMBIOS\n");
switch (ipmi_data->type) { switch (ipmi_data->type) {
case 0x01: /* KCS */ case 0x01: /* KCS */
@ -2391,8 +2382,8 @@ static void try_init_dmi(struct dmi_ipmi_data *ipmi_data)
default: default:
kfree(info); kfree(info);
printk(KERN_WARNING PFX "Unknown SMBIOS I/O Address type: %d\n", pr_warn(PFX "Unknown SMBIOS I/O Address type: %d\n",
ipmi_data->addr_space); ipmi_data->addr_space);
return; return;
} }
info->io.addr_data = ipmi_data->base_addr; info->io.addr_data = ipmi_data->base_addr;
@ -2410,9 +2401,9 @@ static void try_init_dmi(struct dmi_ipmi_data *ipmi_data)
info->irq_setup = std_irq_setup; info->irq_setup = std_irq_setup;
pr_info("ipmi_si: SMBIOS: %s %#lx regsize %d spacing %d irq %d\n", pr_info("ipmi_si: SMBIOS: %s %#lx regsize %d spacing %d irq %d\n",
(info->io.addr_type == IPMI_IO_ADDR_SPACE) ? "io" : "mem", (info->io.addr_type == IPMI_IO_ADDR_SPACE) ? "io" : "mem",
info->io.addr_data, info->io.regsize, info->io.regspacing, info->io.addr_data, info->io.regsize, info->io.regspacing,
info->irq); info->irq);
if (add_smi(info)) if (add_smi(info))
kfree(info); kfree(info);
@ -3141,9 +3132,7 @@ static int try_enable_event_buffer(struct smi_info *smi_info)
rv = wait_for_msg_done(smi_info); rv = wait_for_msg_done(smi_info);
if (rv) { if (rv) {
printk(KERN_WARNING PFX "Error getting response from get" pr_warn(PFX "Error getting response from get global enables command, the event buffer is not enabled.\n");
" global enables command, the event buffer is not"
" enabled.\n");
goto out; goto out;
} }
@ -3154,8 +3143,7 @@ static int try_enable_event_buffer(struct smi_info *smi_info)
resp[0] != (IPMI_NETFN_APP_REQUEST | 1) << 2 || resp[0] != (IPMI_NETFN_APP_REQUEST | 1) << 2 ||
resp[1] != IPMI_GET_BMC_GLOBAL_ENABLES_CMD || resp[1] != IPMI_GET_BMC_GLOBAL_ENABLES_CMD ||
resp[2] != 0) { resp[2] != 0) {
printk(KERN_WARNING PFX "Invalid return from get global" pr_warn(PFX "Invalid return from get global enables command, cannot enable the event buffer.\n");
" enables command, cannot enable the event buffer.\n");
rv = -EINVAL; rv = -EINVAL;
goto out; goto out;
} }
@ -3173,9 +3161,7 @@ static int try_enable_event_buffer(struct smi_info *smi_info)
rv = wait_for_msg_done(smi_info); rv = wait_for_msg_done(smi_info);
if (rv) { if (rv) {
printk(KERN_WARNING PFX "Error getting response from set" pr_warn(PFX "Error getting response from set global, enables command, the event buffer is not enabled.\n");
" global, enables command, the event buffer is not"
" enabled.\n");
goto out; goto out;
} }
@ -3185,8 +3171,7 @@ static int try_enable_event_buffer(struct smi_info *smi_info)
if (resp_len < 3 || if (resp_len < 3 ||
resp[0] != (IPMI_NETFN_APP_REQUEST | 1) << 2 || resp[0] != (IPMI_NETFN_APP_REQUEST | 1) << 2 ||
resp[1] != IPMI_SET_BMC_GLOBAL_ENABLES_CMD) { resp[1] != IPMI_SET_BMC_GLOBAL_ENABLES_CMD) {
printk(KERN_WARNING PFX "Invalid return from get global," pr_warn(PFX "Invalid return from get global, enables command, not enable the event buffer.\n");
"enables command, not enable the event buffer.\n");
rv = -EINVAL; rv = -EINVAL;
goto out; goto out;
} }
@ -3463,8 +3448,16 @@ static int is_new_interface(struct smi_info *info)
list_for_each_entry(e, &smi_infos, link) { list_for_each_entry(e, &smi_infos, link) {
if (e->io.addr_type != info->io.addr_type) if (e->io.addr_type != info->io.addr_type)
continue; continue;
if (e->io.addr_data == info->io.addr_data) if (e->io.addr_data == info->io.addr_data) {
/*
* This is a cheap hack, ACPI doesn't have a defined
* slave address but SMBIOS does. Pick it up from
* any source that has it available.
*/
if (info->slave_addr && !e->slave_addr)
e->slave_addr = info->slave_addr;
return 0; return 0;
}
} }
return 1; return 1;
@ -3474,17 +3467,18 @@ static int add_smi(struct smi_info *new_smi)
{ {
int rv = 0; int rv = 0;
printk(KERN_INFO PFX "Adding %s-specified %s state machine",
ipmi_addr_src_to_str(new_smi->addr_source),
si_to_str[new_smi->si_type]);
mutex_lock(&smi_infos_lock); mutex_lock(&smi_infos_lock);
if (!is_new_interface(new_smi)) { if (!is_new_interface(new_smi)) {
printk(KERN_CONT " duplicate interface\n"); pr_info(PFX "%s-specified %s state machine: duplicate\n",
ipmi_addr_src_to_str(new_smi->addr_source),
si_to_str[new_smi->si_type]);
rv = -EBUSY; rv = -EBUSY;
goto out_err; goto out_err;
} }
printk(KERN_CONT "\n"); pr_info(PFX "Adding %s-specified %s state machine\n",
ipmi_addr_src_to_str(new_smi->addr_source),
si_to_str[new_smi->si_type]);
/* So we know not to free it unless we have allocated one. */ /* So we know not to free it unless we have allocated one. */
new_smi->intf = NULL; new_smi->intf = NULL;
@ -3502,15 +3496,14 @@ static int try_smi_init(struct smi_info *new_smi)
{ {
int rv = 0; int rv = 0;
int i; int i;
char *init_name = NULL;
printk(KERN_INFO PFX "Trying %s-specified %s state" pr_info(PFX "Trying %s-specified %s state machine at %s address 0x%lx, slave address 0x%x, irq %d\n",
" machine at %s address 0x%lx, slave address 0x%x," ipmi_addr_src_to_str(new_smi->addr_source),
" irq %d\n", si_to_str[new_smi->si_type],
ipmi_addr_src_to_str(new_smi->addr_source), addr_space_to_str[new_smi->io.addr_type],
si_to_str[new_smi->si_type], new_smi->io.addr_data,
addr_space_to_str[new_smi->io.addr_type], new_smi->slave_addr, new_smi->irq);
new_smi->io.addr_data,
new_smi->slave_addr, new_smi->irq);
switch (new_smi->si_type) { switch (new_smi->si_type) {
case SI_KCS: case SI_KCS:
@ -3531,11 +3524,30 @@ static int try_smi_init(struct smi_info *new_smi)
goto out_err; goto out_err;
} }
/* Do this early so it's available for logs. */
if (!new_smi->dev) {
init_name = kasprintf(GFP_KERNEL, "ipmi_si.%d", 0);
/*
* If we don't already have a device from something
* else (like PCI), then register a new one.
*/
new_smi->pdev = platform_device_alloc("ipmi_si",
new_smi->intf_num);
if (!new_smi->pdev) {
pr_err(PFX "Unable to allocate platform device\n");
goto out_err;
}
new_smi->dev = &new_smi->pdev->dev;
new_smi->dev->driver = &ipmi_driver.driver;
/* Nulled by device_add() */
new_smi->dev->init_name = init_name;
}
/* Allocate the state machine's data and initialize it. */ /* Allocate the state machine's data and initialize it. */
new_smi->si_sm = kmalloc(new_smi->handlers->size(), GFP_KERNEL); new_smi->si_sm = kmalloc(new_smi->handlers->size(), GFP_KERNEL);
if (!new_smi->si_sm) { if (!new_smi->si_sm) {
printk(KERN_ERR PFX pr_err(PFX "Could not allocate state machine memory\n");
"Could not allocate state machine memory\n");
rv = -ENOMEM; rv = -ENOMEM;
goto out_err; goto out_err;
} }
@ -3545,14 +3557,14 @@ static int try_smi_init(struct smi_info *new_smi)
/* Now that we know the I/O size, we can set up the I/O. */ /* Now that we know the I/O size, we can set up the I/O. */
rv = new_smi->io_setup(new_smi); rv = new_smi->io_setup(new_smi);
if (rv) { if (rv) {
printk(KERN_ERR PFX "Could not set up I/O space\n"); dev_err(new_smi->dev, "Could not set up I/O space\n");
goto out_err; goto out_err;
} }
/* Do low-level detection first. */ /* Do low-level detection first. */
if (new_smi->handlers->detect(new_smi->si_sm)) { if (new_smi->handlers->detect(new_smi->si_sm)) {
if (new_smi->addr_source) if (new_smi->addr_source)
printk(KERN_INFO PFX "Interface detection failed\n"); dev_err(new_smi->dev, "Interface detection failed\n");
rv = -ENODEV; rv = -ENODEV;
goto out_err; goto out_err;
} }
@ -3564,8 +3576,7 @@ static int try_smi_init(struct smi_info *new_smi)
rv = try_get_dev_id(new_smi); rv = try_get_dev_id(new_smi);
if (rv) { if (rv) {
if (new_smi->addr_source) if (new_smi->addr_source)
printk(KERN_INFO PFX "There appears to be no BMC" dev_err(new_smi->dev, "There appears to be no BMC at this location\n");
" at this location\n");
goto out_err; goto out_err;
} }
@ -3604,27 +3615,12 @@ static int try_smi_init(struct smi_info *new_smi)
atomic_set(&new_smi->req_events, 1); atomic_set(&new_smi->req_events, 1);
} }
if (!new_smi->dev) { if (new_smi->pdev) {
/*
* If we don't already have a device from something
* else (like PCI), then register a new one.
*/
new_smi->pdev = platform_device_alloc("ipmi_si",
new_smi->intf_num);
if (!new_smi->pdev) {
printk(KERN_ERR PFX
"Unable to allocate platform device\n");
goto out_err;
}
new_smi->dev = &new_smi->pdev->dev;
new_smi->dev->driver = &ipmi_driver.driver;
rv = platform_device_add(new_smi->pdev); rv = platform_device_add(new_smi->pdev);
if (rv) { if (rv) {
printk(KERN_ERR PFX dev_err(new_smi->dev,
"Unable to register system interface device:" "Unable to register system interface device: %d\n",
" %d\n", rv);
rv);
goto out_err; goto out_err;
} }
new_smi->dev_registered = true; new_smi->dev_registered = true;
@ -3668,6 +3664,9 @@ static int try_smi_init(struct smi_info *new_smi)
dev_info(new_smi->dev, "IPMI %s interface initialized\n", dev_info(new_smi->dev, "IPMI %s interface initialized\n",
si_to_str[new_smi->si_type]); si_to_str[new_smi->si_type]);
WARN_ON(new_smi->dev->init_name != NULL);
kfree(init_name);
return 0; return 0;
out_err_stop_timer: out_err_stop_timer:
@ -3712,8 +3711,14 @@ out_err:
if (new_smi->dev_registered) { if (new_smi->dev_registered) {
platform_device_unregister(new_smi->pdev); platform_device_unregister(new_smi->pdev);
new_smi->dev_registered = false; new_smi->dev_registered = false;
new_smi->pdev = NULL;
} else if (new_smi->pdev) {
platform_device_put(new_smi->pdev);
new_smi->pdev = NULL;
} }
kfree(init_name);
return rv; return rv;
} }
@ -3732,8 +3737,7 @@ static int init_ipmi_si(void)
if (si_tryplatform) { if (si_tryplatform) {
rv = platform_driver_register(&ipmi_driver); rv = platform_driver_register(&ipmi_driver);
if (rv) { if (rv) {
printk(KERN_ERR PFX "Unable to register " pr_err(PFX "Unable to register driver: %d\n", rv);
"driver: %d\n", rv);
return rv; return rv;
} }
} }
@ -3753,7 +3757,7 @@ static int init_ipmi_si(void)
} }
} }
printk(KERN_INFO "IPMI System Interface driver.\n"); pr_info("IPMI System Interface driver.\n");
/* If the user gave us a device, they presumably want us to use it */ /* If the user gave us a device, they presumably want us to use it */
if (!hardcode_find_bmc()) if (!hardcode_find_bmc())
@ -3763,8 +3767,7 @@ static int init_ipmi_si(void)
if (si_trypci) { if (si_trypci) {
rv = pci_register_driver(&ipmi_pci_driver); rv = pci_register_driver(&ipmi_pci_driver);
if (rv) if (rv)
printk(KERN_ERR PFX "Unable to register " pr_err(PFX "Unable to register PCI driver: %d\n", rv);
"PCI driver: %d\n", rv);
else else
pci_registered = true; pci_registered = true;
} }
@ -3826,8 +3829,7 @@ static int init_ipmi_si(void)
if (unload_when_empty && list_empty(&smi_infos)) { if (unload_when_empty && list_empty(&smi_infos)) {
mutex_unlock(&smi_infos_lock); mutex_unlock(&smi_infos_lock);
cleanup_ipmi_si(); cleanup_ipmi_si();
printk(KERN_WARNING PFX pr_warn(PFX "Unable to find any System Interface(s)\n");
"Unable to find any System Interface(s)\n");
return -ENODEV; return -ENODEV;
} else { } else {
mutex_unlock(&smi_infos_lock); mutex_unlock(&smi_infos_lock);

View File

@ -174,7 +174,6 @@ enum ssif_stat_indexes {
}; };
struct ssif_addr_info { struct ssif_addr_info {
unsigned short addr;
struct i2c_board_info binfo; struct i2c_board_info binfo;
char *adapter_name; char *adapter_name;
int debug; int debug;
@ -1154,10 +1153,6 @@ static bool ssif_dbg_probe;
module_param_named(dbg_probe, ssif_dbg_probe, bool, 0); module_param_named(dbg_probe, ssif_dbg_probe, bool, 0);
MODULE_PARM_DESC(dbg_probe, "Enable debugging of probing of adapters."); MODULE_PARM_DESC(dbg_probe, "Enable debugging of probing of adapters.");
static int use_thread;
module_param(use_thread, int, 0);
MODULE_PARM_DESC(use_thread, "Use the thread interface.");
static bool ssif_tryacpi = true; static bool ssif_tryacpi = true;
module_param_named(tryacpi, ssif_tryacpi, bool, 0); module_param_named(tryacpi, ssif_tryacpi, bool, 0);
MODULE_PARM_DESC(tryacpi, "Setting this to zero will disable the default scan of the interfaces identified via ACPI"); MODULE_PARM_DESC(tryacpi, "Setting this to zero will disable the default scan of the interfaces identified via ACPI");
@ -1405,6 +1400,34 @@ static bool check_acpi(struct ssif_info *ssif_info, struct device *dev)
return false; return false;
} }
static int find_slave_address(struct i2c_client *client, int slave_addr)
{
struct ssif_addr_info *info;
if (slave_addr)
return slave_addr;
/*
* Came in without a slave address, search around to see if
* the other sources have a slave address. This lets us pick
* up an SMBIOS slave address when using ACPI.
*/
list_for_each_entry(info, &ssif_infos, link) {
if (info->binfo.addr != client->addr)
continue;
if (info->adapter_name && client->adapter->name &&
strcmp_nospace(info->adapter_name,
client->adapter->name))
continue;
if (info->slave_addr) {
slave_addr = info->slave_addr;
break;
}
}
return slave_addr;
}
/* /*
* Global enables we care about. * Global enables we care about.
*/ */
@ -1447,6 +1470,8 @@ static int ssif_probe(struct i2c_client *client, const struct i2c_device_id *id)
} }
} }
slave_addr = find_slave_address(client, slave_addr);
pr_info(PFX "Trying %s-specified SSIF interface at i2c address 0x%x, adapter %s, slave address 0x%x\n", pr_info(PFX "Trying %s-specified SSIF interface at i2c address 0x%x, adapter %s, slave address 0x%x\n",
ipmi_addr_src_to_str(ssif_info->addr_source), ipmi_addr_src_to_str(ssif_info->addr_source),
client->addr, client->adapter->name, slave_addr); client->addr, client->adapter->name, slave_addr);
@ -1935,7 +1960,7 @@ static int decode_dmi(const struct dmi_device *dmi_dev)
slave_addr = data[6]; slave_addr = data[6];
} }
return new_ssif_client(myaddr, NULL, 0, 0, SI_SMBIOS); return new_ssif_client(myaddr, NULL, 0, slave_addr, SI_SMBIOS);
} }
static void dmi_iterator(void) static void dmi_iterator(void)