tty: n_smux: Add support for ldisc removal during SSR

If subsystem restart (SSR) is in progress and the line discipline is
removed, then the platform devices may get removed twice leading to a
kernel panic.

Add conditional logic to properly handle platform device removal if line
discipline is removed while a subsystem restart is in progress.

CRs-Fixed: 386491
Change-Id: I1ddc89175509e333098f849b0f76e09660644573
Signed-off-by: Eric Holmberg <eholmber@codeaurora.org>
diff --git a/drivers/tty/n_smux.c b/drivers/tty/n_smux.c
index 32e52d0..1385e08 100644
--- a/drivers/tty/n_smux.c
+++ b/drivers/tty/n_smux.c
@@ -274,6 +274,7 @@
 	struct mutex mutex_lha0;
 
 	int is_initialized;
+	int platform_devs_registered;
 	int in_reset;
 	int ld_open_count;
 	struct tty_struct *tty;
@@ -3377,14 +3378,18 @@
 		/* re-register platform devices */
 		SMUX_DBG("%s: ssr - after power-up\n", __func__);
 		mutex_lock(&smux.mutex_lha0);
-		for (i = 0; i < ARRAY_SIZE(smux_devs); ++i) {
-			SMUX_DBG("%s: register pdev '%s'\n",
+		if (smux.ld_open_count > 0
+				&& !smux.platform_devs_registered) {
+			for (i = 0; i < ARRAY_SIZE(smux_devs); ++i) {
+				SMUX_DBG("%s: register pdev '%s'\n",
 					__func__, smux_devs[i].name);
-			smux_devs[i].dev.release = smux_pdev_release;
-			tmp = platform_device_register(&smux_devs[i]);
-			if (tmp)
-				pr_err("%s: error %d registering device %s\n",
+				smux_devs[i].dev.release = smux_pdev_release;
+				tmp = platform_device_register(&smux_devs[i]);
+				if (tmp)
+					pr_err("%s: error %d registering device %s\n",
 					   __func__, tmp, smux_devs[i].name);
+			}
+			smux.platform_devs_registered = 1;
 		}
 		mutex_unlock(&smux.mutex_lha0);
 		return NOTIFY_DONE;
@@ -3396,30 +3401,34 @@
 	/* Cleanup channels */
 	smux_flush_workqueues();
 	mutex_lock(&smux.mutex_lha0);
-	smux_lch_purge();
-	if (smux.tty)
-		tty_driver_flush_buffer(smux.tty);
+	if (smux.ld_open_count > 0) {
+		smux_lch_purge();
+		if (smux.tty)
+			tty_driver_flush_buffer(smux.tty);
 
-	/* Unregister platform devices */
-	for (i = 0; i < ARRAY_SIZE(smux_devs); ++i) {
-		SMUX_DBG("%s: unregister pdev '%s'\n",
-				__func__, smux_devs[i].name);
-		platform_device_unregister(&smux_devs[i]);
+		/* Unregister platform devices */
+		if (smux.platform_devs_registered) {
+			for (i = 0; i < ARRAY_SIZE(smux_devs); ++i) {
+				SMUX_DBG("%s: unregister pdev '%s'\n",
+						__func__, smux_devs[i].name);
+				platform_device_unregister(&smux_devs[i]);
+			}
+			smux.platform_devs_registered = 0;
+		}
+
+		/* Power-down UART */
+		spin_lock_irqsave(&smux.tx_lock_lha2, flags);
+		if (smux.power_state != SMUX_PWR_OFF) {
+			SMUX_PWR("%s: SSR - turning off UART\n", __func__);
+			smux.power_state = SMUX_PWR_OFF;
+			power_off_uart = 1;
+		}
+		smux.powerdown_enabled = 0;
+		spin_unlock_irqrestore(&smux.tx_lock_lha2, flags);
+
+		if (power_off_uart)
+			smux_uart_power_off_atomic();
 	}
-
-	/* Power-down UART */
-	spin_lock_irqsave(&smux.tx_lock_lha2, flags);
-	if (smux.power_state != SMUX_PWR_OFF) {
-		SMUX_PWR("%s: SSR - turning off UART\n", __func__);
-		smux.power_state = SMUX_PWR_OFF;
-		power_off_uart = 1;
-	}
-	smux.powerdown_enabled = 0;
-	spin_unlock_irqrestore(&smux.tx_lock_lha2, flags);
-
-	if (power_off_uart)
-		smux_uart_power_off_atomic();
-
 	smux.tx_activity_flag = 0;
 	smux.rx_activity_flag = 0;
 	smux.rx_state = SMUX_RX_IDLE;
@@ -3493,6 +3502,7 @@
 			pr_err("%s: error %d registering device %s\n",
 				   __func__, tmp, smux_devs[i].name);
 	}
+	smux.platform_devs_registered = 1;
 	mutex_unlock(&smux.mutex_lha0);
 	return 0;
 }
@@ -3519,10 +3529,13 @@
 	smux_lch_purge();
 
 	/* Unregister platform devices */
-	for (i = 0; i < ARRAY_SIZE(smux_devs); ++i) {
-		SMUX_DBG("%s: unregister pdev '%s'\n",
-				__func__, smux_devs[i].name);
-		platform_device_unregister(&smux_devs[i]);
+	if (smux.platform_devs_registered) {
+		for (i = 0; i < ARRAY_SIZE(smux_devs); ++i) {
+			SMUX_DBG("%s: unregister pdev '%s'\n",
+					__func__, smux_devs[i].name);
+			platform_device_unregister(&smux_devs[i]);
+		}
+		smux.platform_devs_registered = 0;
 	}
 
 	/* Schedule UART power-up if it's down */
@@ -3668,6 +3681,7 @@
 	smux.ld_open_count = 0;
 	smux.in_reset = 0;
 	smux.is_initialized = 1;
+	smux.platform_devs_registered = 0;
 	smux_byte_loopback = 0;
 
 	spin_lock_init(&smux.tx_lock_lha2);