diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-12-14 20:54:33 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-12-14 20:54:33 -0800 |
commit | 196202be3cfc75762b0075e2d69f55cef949c610 (patch) | |
tree | d7844c45fa634caf459eea8d07411b694af6b613 /drivers | |
parent | e3842cbfe0976b014288147b130551d8bf52b96c (diff) | |
parent | 070cbd1d42aa0e359c9957cd73c2a529dec62047 (diff) | |
download | linux-196202be3cfc75762b0075e2d69f55cef949c610.tar.bz2 |
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
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/char/ipmi/ipmi_devintf.c | 1 | ||||
-rw-r--r-- | drivers/char/ipmi/ipmi_msghandler.c | 10 | ||||
-rw-r--r-- | drivers/char/ipmi/ipmi_si_intf.c | 190 | ||||
-rw-r--r-- | drivers/char/ipmi/ipmi_ssif.c | 37 |
4 files changed, 133 insertions, 105 deletions
diff --git a/drivers/char/ipmi/ipmi_devintf.c b/drivers/char/ipmi/ipmi_devintf.c index 1786574536b2..a21407de46ae 100644 --- a/drivers/char/ipmi/ipmi_devintf.c +++ b/drivers/char/ipmi/ipmi_devintf.c @@ -989,4 +989,3 @@ module_exit(cleanup_ipmi); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Corey Minyard <minyard@mvista.com>"); MODULE_DESCRIPTION("Linux device interface for the IPMI message handler."); -MODULE_ALIAS("platform:ipmi_si"); diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c index fcdd886819f5..92e53acf2cd2 100644 --- a/drivers/char/ipmi/ipmi_msghandler.c +++ b/drivers/char/ipmi/ipmi_msghandler.c @@ -158,15 +158,16 @@ struct seq_table { * Store the information in a msgid (long) to allow us to find a * 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) \ do { \ - seq = ((msgid >> 26) & 0x3f); \ - seqid = (msgid & 0x3fffff); \ + seq = (((msgid) >> 26) & 0x3f); \ + seqid = ((msgid) & 0x3ffffff); \ } while (0) -#define NEXT_SEQID(seqid) (((seqid) + 1) & 0x3fffff) +#define NEXT_SEQID(seqid) (((seqid) + 1) & 0x3ffffff) struct ipmi_channel { unsigned char medium; @@ -4645,3 +4646,4 @@ MODULE_AUTHOR("Corey Minyard <minyard@mvista.com>"); MODULE_DESCRIPTION("Incoming and outgoing message routing for an IPMI" " interface."); MODULE_VERSION(IPMI_DRIVER_VERSION); +MODULE_SOFTDEP("post: ipmi_devintf"); diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c index a112c0146012..2a7c425ddfa7 100644 --- a/drivers/char/ipmi/ipmi_si_intf.c +++ b/drivers/char/ipmi/ipmi_si_intf.c @@ -789,7 +789,7 @@ static void handle_transaction_done(struct smi_info *smi_info) smi_info->si_state = SI_NORMAL; break; } - start_getting_msg_queue(smi_info); + start_getting_events(smi_info); } else { 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; break; } - start_getting_msg_queue(smi_info); + start_getting_events(smi_info); } else { 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, ','); if (!s) { - printk(KERN_WARNING PFX "No hotmod %s given.\n", name); + pr_warn(PFX "No hotmod %s given.\n", name); return -EINVAL; } *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; } @@ -1788,16 +1788,12 @@ static int check_hotmod_int_op(const char *curr, const char *option, if (strcmp(curr, name) == 0) { if (!option) { - printk(KERN_WARNING PFX - "No option given for '%s'\n", - curr); + pr_warn(PFX "No option given for '%s'\n", curr); return -EINVAL; } *val = simple_strtoul(option, &n, 0); if ((*n != '\0') || (*option == '\0')) { - printk(KERN_WARNING PFX - "Bad option given for '%s'\n", - curr); + pr_warn(PFX "Bad option given for '%s'\n", curr); return -EINVAL; } return 1; @@ -1877,8 +1873,7 @@ static int hotmod_handler(const char *val, struct kernel_param *kp) } addr = simple_strtoul(curr, &n, 0); if ((*n != '\0') || (*curr == '\0')) { - printk(KERN_WARNING PFX "Invalid hotmod address" - " '%s'\n", curr); + pr_warn(PFX "Invalid hotmod address '%s'\n", curr); break; } @@ -1921,9 +1916,7 @@ static int hotmod_handler(const char *val, struct kernel_param *kp) continue; rv = -EINVAL; - printk(KERN_WARNING PFX - "Invalid hotmod option '%s'\n", - curr); + pr_warn(PFX "Invalid hotmod option '%s'\n", curr); goto out; } @@ -2003,7 +1996,7 @@ static int hardcode_find_bmc(void) return -ENOMEM; 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) { info->si_type = SI_KCS; @@ -2012,9 +2005,8 @@ static int hardcode_find_bmc(void) } else if (strcmp(si_type[i], "bt") == 0) { info->si_type = SI_BT; } else { - printk(KERN_WARNING PFX "Interface type specified " - "for interface %d, was invalid: %s\n", - i, si_type[i]); + pr_warn(PFX "Interface type specified for interface %d, was invalid: %s\n", + i, si_type[i]); kfree(info); continue; } @@ -2030,9 +2022,8 @@ static int hardcode_find_bmc(void) info->io.addr_data = addrs[i]; info->io.addr_type = IPMI_MEM_ADDR_SPACE; } else { - printk(KERN_WARNING PFX "Interface type specified " - "for interface %d, but port and address were " - "not set or set to zero.\n", i); + pr_warn(PFX "Interface type specified for interface %d, but port and address were not set or set to zero.\n", + i); kfree(info); continue; } @@ -2173,18 +2164,18 @@ static int try_init_spmi(struct SPMITable *spmi) int rv; 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; } info = smi_info_alloc(); 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; } 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. */ switch (spmi->InterfaceType) { @@ -2201,8 +2192,8 @@ static int try_init_spmi(struct SPMITable *spmi) kfree(info); return -EIO; default: - printk(KERN_INFO PFX "Unknown ACPI/SPMI SI type %d\n", - spmi->InterfaceType); + pr_info(PFX "Unknown ACPI/SPMI SI type %d\n", + spmi->InterfaceType); kfree(info); return -EIO; } @@ -2238,15 +2229,15 @@ static int try_init_spmi(struct SPMITable *spmi) info->io.addr_type = IPMI_IO_ADDR_SPACE; } else { 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; } info->io.addr_data = spmi->addr.address; 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_data, info->io.regsize, info->io.regspacing, - info->irq); + (info->io.addr_type == IPMI_IO_ADDR_SPACE) ? "io" : "mem", + info->io.addr_data, info->io.regsize, info->io.regspacing, + info->irq); rv = add_smi(info); if (rv) @@ -2356,12 +2347,12 @@ static void try_init_dmi(struct dmi_ipmi_data *ipmi_data) info = smi_info_alloc(); if (!info) { - printk(KERN_ERR PFX "Could not allocate SI data\n"); + pr_err(PFX "Could not allocate SI data\n"); return; } info->addr_source = SI_SMBIOS; - printk(KERN_INFO PFX "probing via SMBIOS\n"); + pr_info(PFX "probing via SMBIOS\n"); switch (ipmi_data->type) { case 0x01: /* KCS */ @@ -2391,8 +2382,8 @@ static void try_init_dmi(struct dmi_ipmi_data *ipmi_data) default: kfree(info); - printk(KERN_WARNING PFX "Unknown SMBIOS I/O Address type: %d\n", - ipmi_data->addr_space); + pr_warn(PFX "Unknown SMBIOS I/O Address type: %d\n", + ipmi_data->addr_space); return; } 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; 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_data, info->io.regsize, info->io.regspacing, - info->irq); + (info->io.addr_type == IPMI_IO_ADDR_SPACE) ? "io" : "mem", + info->io.addr_data, info->io.regsize, info->io.regspacing, + info->irq); if (add_smi(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); if (rv) { - printk(KERN_WARNING PFX "Error getting response from get" - " global enables command, the event buffer is not" - " enabled.\n"); + pr_warn(PFX "Error getting response from get global enables command, the event buffer is not enabled.\n"); 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[1] != IPMI_GET_BMC_GLOBAL_ENABLES_CMD || resp[2] != 0) { - printk(KERN_WARNING PFX "Invalid return from get global" - " enables command, cannot enable the event buffer.\n"); + pr_warn(PFX "Invalid return from get global enables command, cannot enable the event buffer.\n"); rv = -EINVAL; goto out; } @@ -3173,9 +3161,7 @@ static int try_enable_event_buffer(struct smi_info *smi_info) rv = wait_for_msg_done(smi_info); if (rv) { - printk(KERN_WARNING PFX "Error getting response from set" - " global, enables command, the event buffer is not" - " enabled.\n"); + pr_warn(PFX "Error getting response from set global, enables command, the event buffer is not enabled.\n"); goto out; } @@ -3185,8 +3171,7 @@ static int try_enable_event_buffer(struct smi_info *smi_info) if (resp_len < 3 || resp[0] != (IPMI_NETFN_APP_REQUEST | 1) << 2 || resp[1] != IPMI_SET_BMC_GLOBAL_ENABLES_CMD) { - printk(KERN_WARNING PFX "Invalid return from get global," - "enables command, not enable the event buffer.\n"); + pr_warn(PFX "Invalid return from get global, enables command, not enable the event buffer.\n"); rv = -EINVAL; goto out; } @@ -3463,8 +3448,16 @@ static int is_new_interface(struct smi_info *info) list_for_each_entry(e, &smi_infos, link) { if (e->io.addr_type != info->io.addr_type) 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 1; @@ -3474,17 +3467,18 @@ static int add_smi(struct smi_info *new_smi) { 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); 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; 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. */ new_smi->intf = NULL; @@ -3502,15 +3496,14 @@ static int try_smi_init(struct smi_info *new_smi) { int rv = 0; int i; + char *init_name = NULL; - printk(KERN_INFO PFX "Trying %s-specified %s state" - " machine at %s address 0x%lx, slave address 0x%x," - " irq %d\n", - ipmi_addr_src_to_str(new_smi->addr_source), - si_to_str[new_smi->si_type], - addr_space_to_str[new_smi->io.addr_type], - new_smi->io.addr_data, - new_smi->slave_addr, new_smi->irq); + pr_info(PFX "Trying %s-specified %s state machine at %s address 0x%lx, slave address 0x%x, irq %d\n", + ipmi_addr_src_to_str(new_smi->addr_source), + si_to_str[new_smi->si_type], + addr_space_to_str[new_smi->io.addr_type], + new_smi->io.addr_data, + new_smi->slave_addr, new_smi->irq); switch (new_smi->si_type) { case SI_KCS: @@ -3531,11 +3524,30 @@ static int try_smi_init(struct smi_info *new_smi) 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. */ new_smi->si_sm = kmalloc(new_smi->handlers->size(), GFP_KERNEL); if (!new_smi->si_sm) { - printk(KERN_ERR PFX - "Could not allocate state machine memory\n"); + pr_err(PFX "Could not allocate state machine memory\n"); rv = -ENOMEM; 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. */ rv = new_smi->io_setup(new_smi); 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; } /* Do low-level detection first. */ if (new_smi->handlers->detect(new_smi->si_sm)) { if (new_smi->addr_source) - printk(KERN_INFO PFX "Interface detection failed\n"); + dev_err(new_smi->dev, "Interface detection failed\n"); rv = -ENODEV; goto out_err; } @@ -3564,8 +3576,7 @@ static int try_smi_init(struct smi_info *new_smi) rv = try_get_dev_id(new_smi); if (rv) { if (new_smi->addr_source) - printk(KERN_INFO PFX "There appears to be no BMC" - " at this location\n"); + dev_err(new_smi->dev, "There appears to be no BMC at this location\n"); goto out_err; } @@ -3604,27 +3615,12 @@ static int try_smi_init(struct smi_info *new_smi) atomic_set(&new_smi->req_events, 1); } - if (!new_smi->dev) { - /* - * 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; - + if (new_smi->pdev) { rv = platform_device_add(new_smi->pdev); if (rv) { - printk(KERN_ERR PFX - "Unable to register system interface device:" - " %d\n", - rv); + dev_err(new_smi->dev, + "Unable to register system interface device: %d\n", + rv); goto out_err; } 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", si_to_str[new_smi->si_type]); + WARN_ON(new_smi->dev->init_name != NULL); + kfree(init_name); + return 0; out_err_stop_timer: @@ -3712,8 +3711,14 @@ out_err: if (new_smi->dev_registered) { platform_device_unregister(new_smi->pdev); 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; } @@ -3732,8 +3737,7 @@ static int init_ipmi_si(void) if (si_tryplatform) { rv = platform_driver_register(&ipmi_driver); if (rv) { - printk(KERN_ERR PFX "Unable to register " - "driver: %d\n", rv); + pr_err(PFX "Unable to register driver: %d\n", 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 (!hardcode_find_bmc()) @@ -3763,8 +3767,7 @@ static int init_ipmi_si(void) if (si_trypci) { rv = pci_register_driver(&ipmi_pci_driver); if (rv) - printk(KERN_ERR PFX "Unable to register " - "PCI driver: %d\n", rv); + pr_err(PFX "Unable to register PCI driver: %d\n", rv); else pci_registered = true; } @@ -3826,8 +3829,7 @@ static int init_ipmi_si(void) if (unload_when_empty && list_empty(&smi_infos)) { mutex_unlock(&smi_infos_lock); cleanup_ipmi_si(); - printk(KERN_WARNING PFX - "Unable to find any System Interface(s)\n"); + pr_warn(PFX "Unable to find any System Interface(s)\n"); return -ENODEV; } else { mutex_unlock(&smi_infos_lock); diff --git a/drivers/char/ipmi/ipmi_ssif.c b/drivers/char/ipmi/ipmi_ssif.c index 5673ffff00be..cca6e5bc1cea 100644 --- a/drivers/char/ipmi/ipmi_ssif.c +++ b/drivers/char/ipmi/ipmi_ssif.c @@ -174,7 +174,6 @@ enum ssif_stat_indexes { }; struct ssif_addr_info { - unsigned short addr; struct i2c_board_info binfo; char *adapter_name; int debug; @@ -1154,10 +1153,6 @@ static bool ssif_dbg_probe; module_param_named(dbg_probe, ssif_dbg_probe, bool, 0); 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; 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"); @@ -1405,6 +1400,34 @@ static bool check_acpi(struct ssif_info *ssif_info, struct device *dev) 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. */ @@ -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", ipmi_addr_src_to_str(ssif_info->addr_source), 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]; } - 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) |