diff options
Diffstat (limited to 'drivers/char/ipmi/ipmi_si_intf.c')
-rw-r--r-- | drivers/char/ipmi/ipmi_si_intf.c | 198 |
1 files changed, 30 insertions, 168 deletions
diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c index ff870aa91cfe..ad353be871bf 100644 --- a/drivers/char/ipmi/ipmi_si_intf.c +++ b/drivers/char/ipmi/ipmi_si_intf.c @@ -122,8 +122,8 @@ enum si_stat_indexes { }; struct smi_info { - int intf_num; - ipmi_smi_t intf; + int si_num; + struct ipmi_smi *intf; struct si_sm_data *si_sm; const struct si_sm_handlers *handlers; spinlock_t si_lock; @@ -261,7 +261,6 @@ static int num_max_busy_us; static bool unload_when_empty = true; static int try_smi_init(struct smi_info *smi); -static void shutdown_one_si(struct smi_info *smi_info); static void cleanup_one_si(struct smi_info *smi_info); static void cleanup_ipmi_si(void); @@ -287,10 +286,7 @@ static void deliver_recv_msg(struct smi_info *smi_info, struct ipmi_smi_msg *msg) { /* Deliver the message to the upper layer. */ - if (smi_info->intf) - ipmi_smi_msg_received(smi_info->intf, msg); - else - ipmi_free_smi_msg(msg); + ipmi_smi_msg_received(smi_info->intf, msg); } static void return_hosed_msg(struct smi_info *smi_info, int cCode) @@ -471,8 +467,7 @@ retry: start_clear_flags(smi_info); smi_info->msg_flags &= ~WDT_PRE_TIMEOUT_INT; - if (smi_info->intf) - ipmi_smi_watchdog_pretimeout(smi_info->intf); + ipmi_smi_watchdog_pretimeout(smi_info->intf); } else if (smi_info->msg_flags & RECEIVE_MSG_AVAIL) { /* Messages available. */ smi_info->curr_msg = alloc_msg_handle_irq(smi_info); @@ -798,8 +793,7 @@ restart: * We prefer handling attn over new messages. But don't do * this if there is not yet an upper layer to handle anything. */ - if (likely(smi_info->intf) && - (si_sm_result == SI_SM_ATTN || smi_info->got_attn)) { + if (si_sm_result == SI_SM_ATTN || smi_info->got_attn) { unsigned char msg[2]; if (smi_info->si_state != SI_NORMAL) { @@ -962,8 +956,8 @@ static inline int ipmi_thread_busy_wait(enum si_sm_result smi_result, { unsigned int max_busy_us = 0; - if (smi_info->intf_num < num_max_busy_us) - max_busy_us = kipmid_max_busy_us[smi_info->intf_num]; + if (smi_info->si_num < num_max_busy_us) + max_busy_us = kipmid_max_busy_us[smi_info->si_num]; if (max_busy_us == 0 || smi_result != SI_SM_CALL_WITH_DELAY) ipmi_si_set_not_busy(busy_until); else if (!ipmi_si_is_busy(busy_until)) { @@ -1143,8 +1137,8 @@ irqreturn_t ipmi_si_irq_handler(int irq, void *data) return IRQ_HANDLED; } -static int smi_start_processing(void *send_info, - ipmi_smi_t intf) +static int smi_start_processing(void *send_info, + struct ipmi_smi *intf) { struct smi_info *new_smi = send_info; int enable = 0; @@ -1165,8 +1159,8 @@ static int smi_start_processing(void *send_info, /* * Check if the user forcefully enabled the daemon. */ - if (new_smi->intf_num < num_force_kipmid) - enable = force_kipmid[new_smi->intf_num]; + if (new_smi->si_num < num_force_kipmid) + enable = force_kipmid[new_smi->si_num]; /* * The BT interface is efficient enough to not need a thread, * and there is no need for a thread if we have interrupts. @@ -1176,7 +1170,7 @@ static int smi_start_processing(void *send_info, if (enable) { new_smi->thread = kthread_run(ipmi_thread, new_smi, - "kipmi%d", new_smi->intf_num); + "kipmi%d", new_smi->si_num); if (IS_ERR(new_smi->thread)) { dev_notice(new_smi->io.dev, "Could not start" " kernel thread due to error %ld, only using" @@ -1209,9 +1203,11 @@ static void set_maintenance_mode(void *send_info, bool enable) atomic_set(&smi_info->req_events, 0); } +static void shutdown_smi(void *send_info); static const struct ipmi_smi_handlers handlers = { .owner = THIS_MODULE, .start_processing = smi_start_processing, + .shutdown = shutdown_smi, .get_smi_info = get_smi_info, .sender = sender, .request_events = request_events, @@ -1592,102 +1588,6 @@ out: return rv; } -#ifdef CONFIG_IPMI_PROC_INTERFACE -static int smi_type_proc_show(struct seq_file *m, void *v) -{ - struct smi_info *smi = m->private; - - seq_printf(m, "%s\n", si_to_str[smi->io.si_type]); - - return 0; -} - -static int smi_type_proc_open(struct inode *inode, struct file *file) -{ - return single_open(file, smi_type_proc_show, PDE_DATA(inode)); -} - -static const struct file_operations smi_type_proc_ops = { - .open = smi_type_proc_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - -static int smi_si_stats_proc_show(struct seq_file *m, void *v) -{ - struct smi_info *smi = m->private; - - seq_printf(m, "interrupts_enabled: %d\n", - smi->io.irq && !smi->interrupt_disabled); - seq_printf(m, "short_timeouts: %u\n", - smi_get_stat(smi, short_timeouts)); - seq_printf(m, "long_timeouts: %u\n", - smi_get_stat(smi, long_timeouts)); - seq_printf(m, "idles: %u\n", - smi_get_stat(smi, idles)); - seq_printf(m, "interrupts: %u\n", - smi_get_stat(smi, interrupts)); - seq_printf(m, "attentions: %u\n", - smi_get_stat(smi, attentions)); - seq_printf(m, "flag_fetches: %u\n", - smi_get_stat(smi, flag_fetches)); - seq_printf(m, "hosed_count: %u\n", - smi_get_stat(smi, hosed_count)); - seq_printf(m, "complete_transactions: %u\n", - smi_get_stat(smi, complete_transactions)); - seq_printf(m, "events: %u\n", - smi_get_stat(smi, events)); - seq_printf(m, "watchdog_pretimeouts: %u\n", - smi_get_stat(smi, watchdog_pretimeouts)); - seq_printf(m, "incoming_messages: %u\n", - smi_get_stat(smi, incoming_messages)); - return 0; -} - -static int smi_si_stats_proc_open(struct inode *inode, struct file *file) -{ - return single_open(file, smi_si_stats_proc_show, PDE_DATA(inode)); -} - -static const struct file_operations smi_si_stats_proc_ops = { - .open = smi_si_stats_proc_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - -static int smi_params_proc_show(struct seq_file *m, void *v) -{ - struct smi_info *smi = m->private; - - seq_printf(m, - "%s,%s,0x%lx,rsp=%d,rsi=%d,rsh=%d,irq=%d,ipmb=%d\n", - si_to_str[smi->io.si_type], - addr_space_to_str[smi->io.addr_type], - smi->io.addr_data, - smi->io.regspacing, - smi->io.regsize, - smi->io.regshift, - smi->io.irq, - smi->io.slave_addr); - - return 0; -} - -static int smi_params_proc_open(struct inode *inode, struct file *file) -{ - return single_open(file, smi_params_proc_show, PDE_DATA(inode)); -} - -static const struct file_operations smi_params_proc_ops = { - .open = smi_params_proc_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; -#endif - #define IPMI_SI_ATTR(name) \ static ssize_t ipmi_##name##_show(struct device *dev, \ struct device_attribute *attr, \ @@ -2006,14 +1906,8 @@ int ipmi_si_add_smi(struct si_sm_io *io) list_add_tail(&new_smi->link, &smi_infos); - if (initialized) { + if (initialized) rv = try_smi_init(new_smi); - if (rv) { - cleanup_one_si(new_smi); - mutex_unlock(&smi_infos_lock); - return rv; - } - } out_err: mutex_unlock(&smi_infos_lock); return rv; @@ -2056,19 +1950,19 @@ static int try_smi_init(struct smi_info *new_smi) goto out_err; } - new_smi->intf_num = smi_num; + new_smi->si_num = smi_num; /* Do this early so it's available for logs. */ if (!new_smi->io.dev) { init_name = kasprintf(GFP_KERNEL, "ipmi_si.%d", - new_smi->intf_num); + new_smi->si_num); /* * 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); + new_smi->si_num); if (!new_smi->pdev) { pr_err(PFX "Unable to allocate platform device\n"); rv = -ENOMEM; @@ -2182,35 +2076,6 @@ static int try_smi_init(struct smi_info *new_smi) goto out_err; } -#ifdef CONFIG_IPMI_PROC_INTERFACE - rv = ipmi_smi_add_proc_entry(new_smi->intf, "type", - &smi_type_proc_ops, - new_smi); - if (rv) { - dev_err(new_smi->io.dev, - "Unable to create proc entry: %d\n", rv); - goto out_err; - } - - rv = ipmi_smi_add_proc_entry(new_smi->intf, "si_stats", - &smi_si_stats_proc_ops, - new_smi); - if (rv) { - dev_err(new_smi->io.dev, - "Unable to create proc entry: %d\n", rv); - goto out_err; - } - - rv = ipmi_smi_add_proc_entry(new_smi->intf, "params", - &smi_params_proc_ops, - new_smi); - if (rv) { - dev_err(new_smi->io.dev, - "Unable to create proc entry: %d\n", rv); - goto out_err; - } -#endif - /* Don't increment till we know we have succeeded. */ smi_num++; @@ -2223,7 +2088,8 @@ static int try_smi_init(struct smi_info *new_smi) return 0; out_err: - shutdown_one_si(new_smi); + ipmi_unregister_smi(new_smi->intf); + new_smi->intf = NULL; kfree(init_name); @@ -2301,20 +2167,9 @@ skip_fallback_noirq: } module_init(init_ipmi_si); -static void shutdown_one_si(struct smi_info *smi_info) +static void shutdown_smi(void *send_info) { - int rv = 0; - - if (smi_info->intf) { - ipmi_smi_t intf = smi_info->intf; - - smi_info->intf = NULL; - rv = ipmi_unregister_smi(intf); - if (rv) { - pr_err(PFX "Unable to unregister device: errno=%d\n", - rv); - } - } + struct smi_info *smi_info = send_info; if (smi_info->dev_group_added) { device_remove_group(smi_info->io.dev, &ipmi_si_dev_attr_group); @@ -2372,6 +2227,10 @@ static void shutdown_one_si(struct smi_info *smi_info) smi_info->si_sm = NULL; } +/* + * Must be called with smi_infos_lock held, to serialize the + * smi_info->intf check. + */ static void cleanup_one_si(struct smi_info *smi_info) { if (!smi_info) @@ -2379,7 +2238,10 @@ static void cleanup_one_si(struct smi_info *smi_info) list_del(&smi_info->link); - shutdown_one_si(smi_info); + if (smi_info->intf) { + ipmi_unregister_smi(smi_info->intf); + smi_info->intf = NULL; + } if (smi_info->pdev) { if (smi_info->pdev_registered) |