tty: n_smux: Add/remove platform devices for SSR

Subsystem restart is handled by sending DISCONNECT notifications to
clients.  In addition, a subsystem restart may trigger the mdm helper to
unload the line discipline to capture a memory dump before reloading the
line discipline.  This requires SMUX clients to handle two different
disconnect cases properly.

To converge the two use cases and simplify client code, both a subsystem
restart and line discipline unload will result in removing the platform
devices.  The platform devices are re-added after the line discipline is
loaded or the subsystem restart has been completed.

CRs-Fixed: 386186
Change-Id: Ic61c97acef2a9909f180ac4c81e944351ba9d348
Signed-off-by: Eric Holmberg <eholmber@codeaurora.org>
diff --git a/drivers/tty/n_smux.c b/drivers/tty/n_smux.c
index cb09de3..32e52d0 100644
--- a/drivers/tty/n_smux.c
+++ b/drivers/tty/n_smux.c
@@ -359,6 +359,7 @@
 static void smux_uart_power_on_atomic(void);
 static int smux_rx_flow_control_updated(struct smux_lch_t *ch);
 static void smux_flush_workqueues(void);
+static void smux_pdev_release(struct device *dev);
 
 /**
  * Convert TTY Error Flags to string for logging purposes.
@@ -3362,6 +3363,8 @@
 				void *data)
 {
 	unsigned long flags;
+	int i;
+	int tmp;
 	int power_off_uart = 0;
 
 	if (code == SUBSYS_BEFORE_SHUTDOWN) {
@@ -3370,6 +3373,21 @@
 		smux.in_reset = 1;
 		mutex_unlock(&smux.mutex_lha0);
 		return NOTIFY_DONE;
+	} else if (code == SUBSYS_AFTER_POWERUP) {
+		/* 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",
+					__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",
+					   __func__, tmp, smux_devs[i].name);
+		}
+		mutex_unlock(&smux.mutex_lha0);
+		return NOTIFY_DONE;
 	} else if (code != SUBSYS_AFTER_SHUTDOWN) {
 		return NOTIFY_DONE;
 	}
@@ -3382,6 +3400,13 @@
 	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]);
+	}
+
 	/* Power-down UART */
 	spin_lock_irqsave(&smux.tx_lock_lha2, flags);
 	if (smux.power_state != SMUX_PWR_OFF) {