summaryrefslogtreecommitdiff
path: root/drivers/char/ipmi/ipmi_si_intf.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/char/ipmi/ipmi_si_intf.c')
-rw-r--r--drivers/char/ipmi/ipmi_si_intf.c198
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)