Blob Blame History Raw
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)