From 71404a2f75c1456d82eda47c3a9699770dc766c9 Mon Sep 17 00:00:00 2001
From: Corey Minyard <cminyard@mvista.com>
Date: Wed, 28 Feb 2018 11:40:16 -0600
Subject: [PATCH] ipmi: Consolidate cleanup code
Git-commit: 71404a2f75c1456d82eda47c3a9699770dc766c9
Patch-mainline: v4.17-rc1
References: FATE#326156
The cleanup code for an init failure and for a device removal were
quite similar, consolidate all that into one function.
Signed-off-by: Corey Minyard <cminyard@mvista.com>
Acked-by: Takashi Iwai <tiwai@suse.de>
---
drivers/char/ipmi/ipmi_si_intf.c | 149 +++++++++++++++++----------------------
1 file changed, 68 insertions(+), 81 deletions(-)
--- a/drivers/char/ipmi/ipmi_si_intf.c
+++ b/drivers/char/ipmi/ipmi_si_intf.c
@@ -232,6 +232,9 @@ struct smi_info {
/* Default driver model device. */
struct platform_device *pdev;
+ /* Have we added the platform device? */
+ bool pdev_registered;
+
/* Counters and things for the proc filesystem. */
atomic_t stats[SI_NUM_STATS];
@@ -255,7 +258,8 @@ static int num_max_busy_us;
static bool unload_when_empty = true;
static int try_smi_init(struct smi_info *smi);
-static void cleanup_one_si(struct smi_info *to_clean);
+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);
#ifdef DEBUG_TIMING
@@ -1914,8 +1918,8 @@ int ipmi_si_add_smi(struct si_sm_io *io)
if (initialized) {
rv = try_smi_init(new_smi);
if (rv) {
- mutex_unlock(&smi_infos_lock);
cleanup_one_si(new_smi);
+ mutex_unlock(&smi_infos_lock);
return rv;
}
}
@@ -1934,7 +1938,6 @@ static int try_smi_init(struct smi_info
int rv = 0;
int i;
char *init_name = NULL;
- bool platform_device_registered = false;
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->io.addr_source),
@@ -2055,7 +2058,7 @@ static int try_smi_init(struct smi_info
atomic_set(&new_smi->req_events, 1);
}
- if (new_smi->pdev) {
+ if (new_smi->pdev && !new_smi->pdev_registered) {
rv = platform_device_add(new_smi->pdev);
if (rv) {
dev_err(new_smi->io.dev,
@@ -2063,9 +2066,11 @@ static int try_smi_init(struct smi_info
rv);
goto out_err;
}
- platform_device_registered = true;
+ new_smi->pdev_registered = true;
}
+ dev_set_drvdata(new_smi->io.dev, new_smi);
+
rv = ipmi_register_smi(&handlers,
new_smi,
new_smi->io.dev,
@@ -2074,7 +2079,7 @@ static int try_smi_init(struct smi_info
dev_err(new_smi->io.dev,
"Unable to register device: error %d\n",
rv);
- goto out_err_stop_timer;
+ goto out_err;
}
rv = ipmi_smi_add_proc_entry(new_smi->intf, "type",
@@ -2083,7 +2088,7 @@ static int try_smi_init(struct smi_info
if (rv) {
dev_err(new_smi->io.dev,
"Unable to create proc entry: %d\n", rv);
- goto out_err_stop_timer;
+ goto out_err;
}
rv = ipmi_smi_add_proc_entry(new_smi->intf, "si_stats",
@@ -2092,7 +2097,7 @@ static int try_smi_init(struct smi_info
if (rv) {
dev_err(new_smi->io.dev,
"Unable to create proc entry: %d\n", rv);
- goto out_err_stop_timer;
+ goto out_err;
}
rv = ipmi_smi_add_proc_entry(new_smi->intf, "params",
@@ -2101,7 +2106,7 @@ static int try_smi_init(struct smi_info
if (rv) {
dev_err(new_smi->io.dev,
"Unable to create proc entry: %d\n", rv);
- goto out_err_stop_timer;
+ goto out_err;
}
/* Don't increment till we know we have succeeded. */
@@ -2115,52 +2120,8 @@ static int try_smi_init(struct smi_info
return 0;
-out_err_stop_timer:
- stop_timer_and_thread(new_smi);
-
out_err:
- new_smi->interrupt_disabled = true;
-
- if (new_smi->intf) {
- ipmi_smi_t intf = new_smi->intf;
- new_smi->intf = NULL;
- ipmi_unregister_smi(intf);
- }
-
- if (new_smi->io.irq_cleanup) {
- new_smi->io.irq_cleanup(&new_smi->io);
- new_smi->io.irq_cleanup = NULL;
- }
-
- /*
- * Wait until we know that we are out of any interrupt
- * handlers might have been running before we freed the
- * interrupt.
- */
- synchronize_sched();
-
- if (new_smi->si_sm) {
- if (new_smi->handlers)
- new_smi->handlers->cleanup(new_smi->si_sm);
- kfree(new_smi->si_sm);
- new_smi->si_sm = NULL;
- }
- if (new_smi->io.addr_source_cleanup) {
- new_smi->io.addr_source_cleanup(&new_smi->io);
- new_smi->io.addr_source_cleanup = NULL;
- }
- if (new_smi->io.io_cleanup) {
- new_smi->io.io_cleanup(&new_smi->io);
- new_smi->io.io_cleanup = NULL;
- }
-
- if (new_smi->pdev) {
- if (platform_device_registered)
- platform_device_unregister(new_smi->pdev);
- else
- platform_device_put(new_smi->pdev);
- new_smi->pdev = NULL;
- }
+ shutdown_one_si(new_smi);
kfree(init_name);
@@ -2238,17 +2199,14 @@ skip_fallback_noirq:
}
module_init(init_ipmi_si);
-static void cleanup_one_si(struct smi_info *to_clean)
+static void shutdown_one_si(struct smi_info *smi_info)
{
int rv = 0;
- if (!to_clean)
- return;
-
- if (to_clean->intf) {
- ipmi_smi_t intf = to_clean->intf;
+ if (smi_info->intf) {
+ ipmi_smi_t intf = smi_info->intf;
- to_clean->intf = NULL;
+ smi_info->intf = NULL;
rv = ipmi_unregister_smi(intf);
if (rv) {
pr_err(PFX "Unable to unregister device: errno=%d\n",
@@ -2256,46 +2214,75 @@ static void cleanup_one_si(struct smi_in
}
}
- list_del(&to_clean->link);
+ if (smi_info->io.dev)
+ dev_set_drvdata(smi_info->io.dev, NULL);
/*
* Make sure that interrupts, the timer and the thread are
* stopped and will not run again.
*/
- if (to_clean->io.irq_cleanup)
- to_clean->io.irq_cleanup(&to_clean->io);
- stop_timer_and_thread(to_clean);
+ smi_info->interrupt_disabled = true;
+ if (smi_info->io.irq_cleanup) {
+ smi_info->io.irq_cleanup(&smi_info->io);
+ smi_info->io.irq_cleanup = NULL;
+ }
+ stop_timer_and_thread(smi_info);
+
+ /*
+ * Wait until we know that we are out of any interrupt
+ * handlers might have been running before we freed the
+ * interrupt.
+ */
+ synchronize_sched();
/*
* Timeouts are stopped, now make sure the interrupts are off
* in the BMC. Note that timers and CPU interrupts are off,
* so no need for locks.
*/
- while (to_clean->curr_msg || (to_clean->si_state != SI_NORMAL)) {
- poll(to_clean);
+ while (smi_info->curr_msg || (smi_info->si_state != SI_NORMAL)) {
+ poll(smi_info);
schedule_timeout_uninterruptible(1);
}
- if (to_clean->handlers)
- disable_si_irq(to_clean);
- while (to_clean->curr_msg || (to_clean->si_state != SI_NORMAL)) {
- poll(to_clean);
+ if (smi_info->handlers)
+ disable_si_irq(smi_info);
+ while (smi_info->curr_msg || (smi_info->si_state != SI_NORMAL)) {
+ poll(smi_info);
schedule_timeout_uninterruptible(1);
}
+ if (smi_info->handlers)
+ smi_info->handlers->cleanup(smi_info->si_sm);
+
+ if (smi_info->io.addr_source_cleanup) {
+ smi_info->io.addr_source_cleanup(&smi_info->io);
+ smi_info->io.addr_source_cleanup = NULL;
+ }
+ if (smi_info->io.io_cleanup) {
+ smi_info->io.io_cleanup(&smi_info->io);
+ smi_info->io.io_cleanup = NULL;
+ }
+
+ kfree(smi_info->si_sm);
+ smi_info->si_sm = NULL;
+}
- if (to_clean->handlers)
- to_clean->handlers->cleanup(to_clean->si_sm);
+static void cleanup_one_si(struct smi_info *smi_info)
+{
+ if (!smi_info)
+ return;
- kfree(to_clean->si_sm);
+ list_del(&smi_info->link);
- if (to_clean->io.addr_source_cleanup)
- to_clean->io.addr_source_cleanup(&to_clean->io);
- if (to_clean->io.io_cleanup)
- to_clean->io.io_cleanup(&to_clean->io);
+ shutdown_one_si(smi_info);
- if (to_clean->pdev)
- platform_device_unregister(to_clean->pdev);
+ if (smi_info->pdev) {
+ if (smi_info->pdev_registered)
+ platform_device_unregister(smi_info->pdev);
+ else
+ platform_device_put(smi_info->pdev);
+ }
- kfree(to_clean);
+ kfree(smi_info);
}
int ipmi_si_remove_by_dev(struct device *dev)