diff options
Diffstat (limited to 'drivers/char/ipmi')
| -rw-r--r-- | drivers/char/ipmi/Kconfig | 9 | ||||
| -rw-r--r-- | drivers/char/ipmi/ipmb_dev_int.c | 13 | ||||
| -rw-r--r-- | drivers/char/ipmi/ipmi_ipmb.c | 4 | ||||
| -rw-r--r-- | drivers/char/ipmi/ipmi_kcs_sm.c | 2 | ||||
| -rw-r--r-- | drivers/char/ipmi/ipmi_msghandler.c | 29 | ||||
| -rw-r--r-- | drivers/char/ipmi/ipmi_si_intf.c | 149 | ||||
| -rw-r--r-- | drivers/char/ipmi/ipmi_si_platform.c | 15 | ||||
| -rw-r--r-- | drivers/char/ipmi/ipmi_ssif.c | 32 | ||||
| -rw-r--r-- | drivers/char/ipmi/ssif_bmc.c | 2 |
9 files changed, 191 insertions, 64 deletions
diff --git a/drivers/char/ipmi/Kconfig b/drivers/char/ipmi/Kconfig index 669f76000197..538a7d3c65bf 100644 --- a/drivers/char/ipmi/Kconfig +++ b/drivers/char/ipmi/Kconfig @@ -67,6 +67,15 @@ config IPMI_SI Currently, only KCS and SMIC are supported. If you are using IPMI, you should probably say "y" here. +config IPMI_SI_ASYNC_INIT + bool 'Asynchronous initialization of IPMI System Interface' + depends on IPMI_SI + default n + help + Offloads individual SMI inits. It speeds up the boot time. + It also introduces a very small risk that something else might fail + if it depends on synchronous IPMI init. + config IPMI_SSIF tristate 'IPMI SMBus handler (SSIF)' depends on I2C diff --git a/drivers/char/ipmi/ipmb_dev_int.c b/drivers/char/ipmi/ipmb_dev_int.c index 2fe1d205ce4e..eae31ec92382 100644 --- a/drivers/char/ipmi/ipmb_dev_int.c +++ b/drivers/char/ipmi/ipmb_dev_int.c @@ -141,13 +141,14 @@ static ssize_t ipmb_write(struct file *file, const char __user *buf, u8 msg[MAX_MSG_LEN]; ssize_t ret; - if (count > sizeof(msg)) + if (!count || count > sizeof(msg)) return -EINVAL; if (copy_from_user(&msg, buf, count)) return -EFAULT; - if (count < msg[0]) + if (msg[IPMB_MSG_LEN_IDX] < IPMB_REQUEST_LEN_MIN || + count < (size_t)msg[IPMB_MSG_LEN_IDX] + 1) return -EINVAL; rq_sa = GET_7BIT_ADDR(msg[RQ_SA_8BIT_IDX]); @@ -353,15 +354,15 @@ static void ipmb_remove(struct i2c_client *client) } static const struct i2c_device_id ipmb_id[] = { - { "ipmb-dev" }, - {} + { .name = "ipmb-dev" }, + { } }; MODULE_DEVICE_TABLE(i2c, ipmb_id); #ifdef CONFIG_ACPI static const struct acpi_device_id acpi_ipmb_id[] = { - { "IPMB0001", 0 }, - {}, + { .id = "IPMB0001" }, + { } }; MODULE_DEVICE_TABLE(acpi, acpi_ipmb_id); #endif diff --git a/drivers/char/ipmi/ipmi_ipmb.c b/drivers/char/ipmi/ipmi_ipmb.c index 28818952a7a4..1f1e5718f082 100644 --- a/drivers/char/ipmi/ipmi_ipmb.c +++ b/drivers/char/ipmi/ipmi_ipmb.c @@ -566,8 +566,8 @@ MODULE_DEVICE_TABLE(of, of_ipmi_ipmb_match); #endif static const struct i2c_device_id ipmi_ipmb_id[] = { - { DEVICE_NAME }, - {} + { .name = DEVICE_NAME }, + { } }; MODULE_DEVICE_TABLE(i2c, ipmi_ipmb_id); diff --git a/drivers/char/ipmi/ipmi_kcs_sm.c b/drivers/char/ipmi/ipmi_kcs_sm.c index efda90dcf5b3..c89055db39e5 100644 --- a/drivers/char/ipmi/ipmi_kcs_sm.c +++ b/drivers/char/ipmi/ipmi_kcs_sm.c @@ -102,7 +102,7 @@ enum kcs_states { /* Timeouts in microseconds. */ #define IBF_RETRY_TIMEOUT (5*USEC_PER_SEC) #define OBF_RETRY_TIMEOUT (5*USEC_PER_SEC) -#define MAX_ERROR_RETRIES 10 +#define MAX_ERROR_RETRIES 2 #define ERROR0_OBF_WAIT_JIFFIES (2*HZ) struct si_sm_data { diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c index 869ac87a4b6a..152dd6b5bb27 100644 --- a/drivers/char/ipmi/ipmi_msghandler.c +++ b/drivers/char/ipmi/ipmi_msghandler.c @@ -1391,6 +1391,7 @@ static void _ipmi_destroy_user(struct ipmi_user *user) } } mutex_unlock(&intf->cmd_rcvrs_mutex); + synchronize_rcu(); while (rcvrs) { rcvr = rcvrs; rcvrs = rcvr->next; @@ -1610,14 +1611,12 @@ int ipmi_set_gets_events(struct ipmi_user *user, bool val) { struct ipmi_smi *intf = user->intf; struct ipmi_recv_msg *msg, *msg2; - struct list_head msgs; + LIST_HEAD(msgs); user = acquire_ipmi_user(user); if (!user) return -ENODEV; - INIT_LIST_HEAD(&msgs); - mutex_lock(&intf->events_mutex); if (user->gets_events == val) goto out; @@ -2347,6 +2346,10 @@ static int i_ipmi_request(struct ipmi_user *user, if (smi_msg == NULL) { if (!supplied_recv) ipmi_free_recv_msg(recv_msg); + else if (recv_msg->user) { + atomic_dec(&recv_msg->user->nr_msgs); + kref_put(&recv_msg->user->refcount, free_ipmi_user); + } return -ENOMEM; } } @@ -2420,6 +2423,10 @@ out_err: ipmi_free_smi_msg(smi_msg); if (!supplied_recv) ipmi_free_recv_msg(recv_msg); + else if (recv_msg->user) { + atomic_dec(&recv_msg->user->nr_msgs); + kref_put(&recv_msg->user->refcount, free_ipmi_user); + } } return rv; } @@ -3295,6 +3302,7 @@ out_list_del: list_del(&intf->bmc_link); mutex_unlock(&bmc->dyn_mutex); intf->bmc = &intf->tmp_bmc; + ida_free(&ipmi_bmc_ida, bmc->pdev.id); put_device(&bmc->pdev.dev); goto out; } @@ -3734,6 +3742,7 @@ int ipmi_add_smi(struct module *owner, sysfs_attr_init(&intf->maintenance_mode_devattr.attr); rv = device_create_file(intf->si_dev, &intf->maintenance_mode_devattr); if (rv) { + device_remove_file(intf->si_dev, &intf->nr_msgs_devattr); device_remove_file(intf->si_dev, &intf->nr_users_devattr); goto out_err_bmc_reg; } @@ -3751,12 +3760,14 @@ int ipmi_add_smi(struct module *owner, out_err_bmc_reg: ipmi_bmc_unregister(intf); out_err_started: + intf->in_shutdown = true; if (intf->handlers->shutdown) intf->handlers->shutdown(intf->send_info); out_err: list_del(&intf->link); mutex_unlock(&ipmi_interfaces_mutex); mutex_unlock(&smi_watchers_mutex); + cancel_work_sync(&intf->smi_work); kref_put(&intf->refcount, intf_free); return rv; @@ -3785,10 +3796,9 @@ static void cleanup_smi_msgs(struct ipmi_smi *intf) struct seq_table *ent; struct ipmi_smi_msg *msg; struct list_head *entry; - struct list_head tmplist; + LIST_HEAD(tmplist); /* Clear out our transmit queues and hold the messages. */ - INIT_LIST_HEAD(&tmplist); list_splice_tail(&intf->hp_xmit_msgs, &tmplist); list_splice_tail(&intf->xmit_msgs, &tmplist); @@ -4442,7 +4452,7 @@ static int handle_read_event_rsp(struct ipmi_smi *intf, struct ipmi_smi_msg *msg) { struct ipmi_recv_msg *recv_msg, *recv_msg2; - struct list_head msgs; + LIST_HEAD(msgs); struct ipmi_user *user; int rv = 0, deliver_count = 0; @@ -4457,8 +4467,6 @@ static int handle_read_event_rsp(struct ipmi_smi *intf, return 0; } - INIT_LIST_HEAD(&msgs); - mutex_lock(&intf->events_mutex); ipmi_inc_stat(intf, events); @@ -4477,10 +4485,8 @@ static int handle_read_event_rsp(struct ipmi_smi *intf, mutex_unlock(&intf->users_mutex); list_for_each_entry_safe(recv_msg, recv_msg2, &msgs, link) { - user = recv_msg->user; list_del(&recv_msg->link); ipmi_free_recv_msg(recv_msg); - kref_put(&user->refcount, free_ipmi_user); } /* * We couldn't allocate memory for the @@ -5101,7 +5107,7 @@ static void check_msg_timeout(struct ipmi_smi *intf, struct seq_table *ent, static bool ipmi_timeout_handler(struct ipmi_smi *intf, unsigned long timeout_period) { - struct list_head timeouts; + LIST_HEAD(timeouts); struct ipmi_recv_msg *msg, *msg2; unsigned long flags; int i; @@ -5120,7 +5126,6 @@ static bool ipmi_timeout_handler(struct ipmi_smi *intf, * have timed out, putting them in the timeouts * list. */ - INIT_LIST_HEAD(&timeouts); mutex_lock(&intf->seq_lock); if (intf->ipmb_maintenance_mode_timeout) { if (intf->ipmb_maintenance_mode_timeout <= timeout_period) diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c index 4a9e9de4d684..6b95a7581328 100644 --- a/drivers/char/ipmi/ipmi_si_intf.c +++ b/drivers/char/ipmi/ipmi_si_intf.c @@ -39,6 +39,7 @@ #include <linux/rcupdate.h> #include <linux/ipmi.h> #include <linux/ipmi_smi.h> +#include <linux/workqueue.h> #include "ipmi_si.h" #include "ipmi_si_sm.h" #include <linux/string.h> @@ -168,6 +169,10 @@ struct smi_info { OEM2_DATA_AVAIL) unsigned char msg_flags; + /* When requesting events and messages, don't do it forever. */ + unsigned int num_requests_in_a_row; + bool last_was_flag_fetch; + /* Does the BMC have an event buffer? */ bool has_event_buffer; @@ -248,6 +253,8 @@ struct smi_info { struct task_struct *thread; + struct work_struct init_work; + struct list_head link; }; @@ -268,6 +275,7 @@ static bool unload_when_empty = true; static int try_smi_init(struct smi_info *smi); static void cleanup_one_si(struct smi_info *smi_info); static void cleanup_ipmi_si(void); +static void smi_init_work_fn(struct work_struct *work); #ifdef DEBUG_TIMING void debug_timestamp(struct smi_info *smi_info, char *msg) @@ -410,7 +418,10 @@ static void start_getting_msg_queue(struct smi_info *smi_info) start_new_msg(smi_info, smi_info->curr_msg->data, smi_info->curr_msg->data_size); - smi_info->si_state = SI_GETTING_MESSAGES; + if (smi_info->si_state != SI_GETTING_MESSAGES) { + smi_info->num_requests_in_a_row = 0; + smi_info->si_state = SI_GETTING_MESSAGES; + } } static void start_getting_events(struct smi_info *smi_info) @@ -421,7 +432,10 @@ static void start_getting_events(struct smi_info *smi_info) start_new_msg(smi_info, smi_info->curr_msg->data, smi_info->curr_msg->data_size); - smi_info->si_state = SI_GETTING_EVENTS; + if (smi_info->si_state != SI_GETTING_EVENTS) { + smi_info->num_requests_in_a_row = 0; + smi_info->si_state = SI_GETTING_EVENTS; + } } /* @@ -487,15 +501,19 @@ retry: } else if (smi_info->msg_flags & RECEIVE_MSG_AVAIL) { /* Messages available. */ smi_info->curr_msg = alloc_msg_handle_irq(smi_info); - if (!smi_info->curr_msg) + if (!smi_info->curr_msg) { + smi_info->si_state = SI_NORMAL; return; + } start_getting_msg_queue(smi_info); } else if (smi_info->msg_flags & EVENT_MSG_BUFFER_FULL) { /* Events available. */ smi_info->curr_msg = alloc_msg_handle_irq(smi_info); - if (!smi_info->curr_msg) + if (!smi_info->curr_msg) { + smi_info->si_state = SI_NORMAL; return; + } start_getting_events(smi_info); } else if (smi_info->msg_flags & OEM_DATA_AVAIL && @@ -595,6 +613,7 @@ static void handle_transaction_done(struct smi_info *smi_info) smi_info->si_state = SI_NORMAL; } else { smi_info->msg_flags = msg[3]; + smi_info->last_was_flag_fetch = true; handle_flags(smi_info); } break; @@ -630,7 +649,13 @@ static void handle_transaction_done(struct smi_info *smi_info) */ msg = smi_info->curr_msg; smi_info->curr_msg = NULL; - if (msg->rsp[2] != 0) { + /* + * It appears some BMCs, with no event data, return no + * data in the message and not a 0x80 error as the + * spec says they should. Shut down processing if + * the data is not the right length. + */ + if (msg->rsp[2] != 0 || msg->rsp_size != 19) { /* Error getting event, probably done. */ msg->done(msg); @@ -640,6 +665,11 @@ static void handle_transaction_done(struct smi_info *smi_info) } else { smi_inc_stat(smi_info, events); + smi_info->num_requests_in_a_row++; + if (smi_info->num_requests_in_a_row > 10) + /* Stop if we do this too many times. */ + smi_info->msg_flags &= ~EVENT_MSG_BUFFER_FULL; + /* * Do this before we deliver the message * because delivering the message releases the @@ -678,6 +708,11 @@ static void handle_transaction_done(struct smi_info *smi_info) } else { smi_inc_stat(smi_info, incoming_messages); + smi_info->num_requests_in_a_row++; + if (smi_info->num_requests_in_a_row > 10) + /* Stop if we do this too many times. */ + smi_info->msg_flags &= ~RECEIVE_MSG_AVAIL; + /* * Do this before we deliver the message * because delivering the message releases the @@ -820,6 +855,26 @@ restart: } /* + * If we are currently idle, or if the last thing that was + * done was a flag fetch and there is a message pending, try + * to start the next message. + * + * We do the waiting message check to avoid a stuck flag + * completely wedging the driver. Let a message through + * in between flag operations if that happens. + */ + if (si_sm_result == SI_SM_IDLE || + (si_sm_result == SI_SM_ATTN && smi_info->waiting_msg && + smi_info->last_was_flag_fetch)) { + smi_info->last_was_flag_fetch = false; + smi_inc_stat(smi_info, idles); + + si_sm_result = start_next_msg(smi_info); + if (si_sm_result != SI_SM_IDLE) + goto restart; + } + + /* * We prefer handling attn over new messages. But don't do * this if there is not yet an upper layer to handle anything. */ @@ -846,15 +901,6 @@ restart: } } - /* If we are currently idle, try to start the next message. */ - if (si_sm_result == SI_SM_IDLE) { - smi_inc_stat(smi_info, idles); - - si_sm_result = start_next_msg(smi_info); - if (si_sm_result != SI_SM_IDLE) - goto restart; - } - if ((si_sm_result == SI_SM_IDLE) && (atomic_read(&smi_info->req_events))) { /* @@ -1928,6 +1974,7 @@ int ipmi_si_add_smi(struct si_sm_io *io) if (!new_smi) return -ENOMEM; spin_lock_init(&new_smi->si_lock); + INIT_WORK(&new_smi->init_work, smi_init_work_fn); new_smi->io = *io; @@ -1940,7 +1987,12 @@ int ipmi_si_add_smi(struct si_sm_io *io) dev_info(dup->io.dev, "Removing SMBIOS-specified %s state machine in favor of ACPI\n", si_to_str[new_smi->io.si_info->type]); + list_del(&dup->link); + mutex_unlock(&smi_infos_lock); + cleanup_one_si(dup); + + mutex_lock(&smi_infos_lock); } else { dev_info(new_smi->io.dev, "%s-specified %s state machine: duplicate\n", @@ -1958,8 +2010,12 @@ int ipmi_si_add_smi(struct si_sm_io *io) list_add_tail(&new_smi->link, &smi_infos); - if (initialized) - rv = try_smi_init(new_smi); + if (initialized) { + if (IS_ENABLED(CONFIG_IPMI_SI_ASYNC_INIT)) + queue_work(system_dfl_wq, &new_smi->init_work); + else + rv = try_smi_init(new_smi); + } out_err: mutex_unlock(&smi_infos_lock); return rv; @@ -2132,6 +2188,15 @@ static bool __init ipmi_smi_info_same(struct smi_info *e1, struct smi_info *e2) e1->io.addr_data == e2->io.addr_data); } +static void smi_init_work_fn(struct work_struct *work) +{ + struct smi_info *smi = container_of(work, struct smi_info, init_work); + + mutex_lock(&smi_infos_lock); + try_smi_init(smi); + mutex_unlock(&smi_infos_lock); +} + static int __init init_ipmi_si(void) { struct smi_info *e, *e2; @@ -2177,8 +2242,12 @@ static int __init init_ipmi_si(void) break; } } - if (!dup) - try_smi_init(e); + if (!dup) { + if (IS_ENABLED(CONFIG_IPMI_SI_ASYNC_INIT)) + queue_work(system_unbound_wq, &e->init_work); + else + try_smi_init(e); + } } /* @@ -2211,8 +2280,12 @@ static int __init init_ipmi_si(void) break; } } - if (!dup) - try_smi_init(e); + if (!dup) { + if (IS_ENABLED(CONFIG_IPMI_SI_ASYNC_INIT)) + queue_work(system_unbound_wq, &e->init_work); + else + try_smi_init(e); + } } initialized = true; @@ -2302,31 +2375,36 @@ static void shutdown_smi(void *send_info) } /* - * Must be called with smi_infos_lock held, to serialize the - * smi_info->intf check. + * Must be called with smi_info unlinked from smi_infos and smi_infos_lock released. */ static void cleanup_one_si(struct smi_info *smi_info) { if (!smi_info) return; - list_del(&smi_info->link); + if (IS_ENABLED(CONFIG_IPMI_SI_ASYNC_INIT)) + cancel_work_sync(&smi_info->init_work); + ipmi_unregister_smi(smi_info->intf); kfree(smi_info); } void ipmi_si_remove_by_dev(struct device *dev) { - struct smi_info *e; + struct smi_info *e = NULL, *tmp; mutex_lock(&smi_infos_lock); - list_for_each_entry(e, &smi_infos, link) { - if (e->io.dev == dev) { - cleanup_one_si(e); + list_for_each_entry(tmp, &smi_infos, link) { + if (tmp->io.dev == dev) { + e = tmp; + list_del(&e->link); break; } } mutex_unlock(&smi_infos_lock); + + if (e) + cleanup_one_si(e); } struct device *ipmi_si_remove_by_data(int addr_space, enum si_type si_type, @@ -2335,6 +2413,7 @@ struct device *ipmi_si_remove_by_data(int addr_space, enum si_type si_type, /* remove */ struct smi_info *e, *tmp_e; struct device *dev = NULL; + LIST_HEAD(to_clean); mutex_lock(&smi_infos_lock); list_for_each_entry_safe(e, tmp_e, &smi_infos, link) { @@ -2344,17 +2423,23 @@ struct device *ipmi_si_remove_by_data(int addr_space, enum si_type si_type, continue; if (e->io.addr_data == addr) { dev = get_device(e->io.dev); - cleanup_one_si(e); + list_move_tail(&e->link, &to_clean); } } mutex_unlock(&smi_infos_lock); + list_for_each_entry_safe(e, tmp_e, &to_clean, link) { + list_del(&e->link); + cleanup_one_si(e); + } + return dev; } static void cleanup_ipmi_si(void) { struct smi_info *e, *tmp_e; + LIST_HEAD(to_clean); if (!initialized) return; @@ -2368,10 +2453,14 @@ static void cleanup_ipmi_si(void) ipmi_si_platform_shutdown(); mutex_lock(&smi_infos_lock); - list_for_each_entry_safe(e, tmp_e, &smi_infos, link) - cleanup_one_si(e); + list_splice_init(&smi_infos, &to_clean); mutex_unlock(&smi_infos_lock); + list_for_each_entry_safe(e, tmp_e, &to_clean, link) { + list_del(&e->link); + cleanup_one_si(e); + } + ipmi_si_hardcode_exit(); ipmi_si_hotmod_exit(); } diff --git a/drivers/char/ipmi/ipmi_si_platform.c b/drivers/char/ipmi/ipmi_si_platform.c index fb6e359ae494..fa221cbb4b3b 100644 --- a/drivers/char/ipmi/ipmi_si_platform.c +++ b/drivers/char/ipmi/ipmi_si_platform.c @@ -276,7 +276,10 @@ static int of_ipmi_probe(struct platform_device *pdev) io.regspacing = regspacing ? be32_to_cpup(regspacing) : DEFAULT_REGSPACING; io.regshift = regshift ? be32_to_cpup(regshift) : 0; - io.irq = irq_of_parse_and_map(pdev->dev.of_node, 0); + io.irq = platform_get_irq_optional(pdev, 0); + if (io.irq < 0) + io.irq = 0; + io.dev = &pdev->dev; dev_dbg(&pdev->dev, "addr 0x%lx regsize %d spacing %d irq %d\n", @@ -384,8 +387,8 @@ static int acpi_ipmi_probe(struct platform_device *pdev) } static const struct acpi_device_id acpi_ipmi_match[] = { - { "IPI0001", 0 }, - { }, + { .id = "IPI0001" }, + { } }; MODULE_DEVICE_TABLE(acpi, acpi_ipmi_match); #else @@ -433,9 +436,9 @@ void ipmi_remove_platform_device_by_name(char *name) } static const struct platform_device_id si_plat_ids[] = { - { "dmi-ipmi-si", 0 }, - { "hardcode-ipmi-si", 0 }, - { "hotmod-ipmi-si", 0 }, + { .name = "dmi-ipmi-si" }, + { .name = "hardcode-ipmi-si" }, + { .name = "hotmod-ipmi-si" }, { } }; diff --git a/drivers/char/ipmi/ipmi_ssif.c b/drivers/char/ipmi/ipmi_ssif.c index b49500a1bd36..2361103c5edc 100644 --- a/drivers/char/ipmi/ipmi_ssif.c +++ b/drivers/char/ipmi/ipmi_ssif.c @@ -225,6 +225,9 @@ struct ssif_info { bool has_event_buffer; bool supports_alert; + /* When requesting events and messages, don't do it forever. */ + unsigned int num_requests_in_a_row; + /* * Used to tell what we should do with alerts. If we are * waiting on a response, read the data immediately. @@ -413,7 +416,10 @@ static void start_event_fetch(struct ssif_info *ssif_info, unsigned long *flags) } ssif_info->curr_msg = msg; - ssif_info->ssif_state = SSIF_GETTING_EVENTS; + if (ssif_info->ssif_state != SSIF_GETTING_EVENTS) { + ssif_info->num_requests_in_a_row = 0; + ssif_info->ssif_state = SSIF_GETTING_EVENTS; + } ipmi_ssif_unlock_cond(ssif_info, flags); msg->data[0] = (IPMI_NETFN_APP_REQUEST << 2); @@ -436,7 +442,10 @@ static void start_recv_msg_fetch(struct ssif_info *ssif_info, } ssif_info->curr_msg = msg; - ssif_info->ssif_state = SSIF_GETTING_MESSAGES; + if (ssif_info->ssif_state != SSIF_GETTING_MESSAGES) { + ssif_info->num_requests_in_a_row = 0; + ssif_info->ssif_state = SSIF_GETTING_MESSAGES; + } ipmi_ssif_unlock_cond(ssif_info, flags); msg->data[0] = (IPMI_NETFN_APP_REQUEST << 2); @@ -843,6 +852,11 @@ static void msg_done_handler(struct ssif_info *ssif_info, int result, ssif_info->msg_flags &= ~EVENT_MSG_BUFFER_FULL; handle_flags(ssif_info, flags); } else { + ssif_info->num_requests_in_a_row++; + if (ssif_info->num_requests_in_a_row > 10) + /* Stop if we do this too many times. */ + ssif_info->msg_flags &= ~EVENT_MSG_BUFFER_FULL; + handle_flags(ssif_info, flags); ssif_inc_stat(ssif_info, events); deliver_recv_msg(ssif_info, msg); @@ -876,6 +890,11 @@ static void msg_done_handler(struct ssif_info *ssif_info, int result, ssif_info->msg_flags &= ~RECEIVE_MSG_AVAIL; handle_flags(ssif_info, flags); } else { + ssif_info->num_requests_in_a_row++; + if (ssif_info->num_requests_in_a_row > 10) + /* Stop if we do this too many times. */ + ssif_info->msg_flags &= ~RECEIVE_MSG_AVAIL; + ssif_inc_stat(ssif_info, incoming_messages); handle_flags(ssif_info, flags); deliver_recv_msg(ssif_info, msg); @@ -1886,6 +1905,7 @@ static int ssif_probe(struct i2c_client *client) "kssif%4.4x", thread_num); if (IS_ERR(ssif_info->thread)) { rv = PTR_ERR(ssif_info->thread); + ssif_info->thread = NULL; dev_notice(&ssif_info->client->dev, "Could not start kernel thread: error %d\n", rv); @@ -2037,8 +2057,8 @@ static unsigned short *ssif_address_list(void) #ifdef CONFIG_ACPI static const struct acpi_device_id ssif_acpi_match[] = { - { "IPI0001", 0 }, - { }, + { .id = "IPI0001" }, + { } }; MODULE_DEVICE_TABLE(acpi, ssif_acpi_match); #endif @@ -2074,7 +2094,7 @@ static int dmi_ipmi_probe(struct platform_device *pdev) #endif static const struct i2c_device_id ssif_id[] = { - { DEVICE_NAME }, + { .name = DEVICE_NAME }, { } }; MODULE_DEVICE_TABLE(i2c, ssif_id); @@ -2107,7 +2127,7 @@ static void ssif_platform_remove(struct platform_device *dev) } static const struct platform_device_id ssif_plat_ids[] = { - { "dmi-ipmi-ssif", 0 }, + { .name = "dmi-ipmi-ssif" }, { } }; MODULE_DEVICE_TABLE(platform, ssif_plat_ids); diff --git a/drivers/char/ipmi/ssif_bmc.c b/drivers/char/ipmi/ssif_bmc.c index 1df0e9284ad9..6036897725f3 100644 --- a/drivers/char/ipmi/ssif_bmc.c +++ b/drivers/char/ipmi/ssif_bmc.c @@ -874,7 +874,7 @@ static const struct of_device_id ssif_bmc_match[] = { MODULE_DEVICE_TABLE(of, ssif_bmc_match); static const struct i2c_device_id ssif_bmc_id[] = { - { DEVICE_NAME }, + { .name = DEVICE_NAME }, { } }; MODULE_DEVICE_TABLE(i2c, ssif_bmc_id); |
