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) {