summaryrefslogtreecommitdiff
path: root/drivers/tty/serial/msm_smd_tty.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/tty/serial/msm_smd_tty.c')
-rw-r--r--drivers/tty/serial/msm_smd_tty.c44
1 files changed, 44 insertions, 0 deletions
diff --git a/drivers/tty/serial/msm_smd_tty.c b/drivers/tty/serial/msm_smd_tty.c
index 67edaf557a43..179fcef767cc 100644
--- a/drivers/tty/serial/msm_smd_tty.c
+++ b/drivers/tty/serial/msm_smd_tty.c
@@ -27,6 +27,7 @@
#include <linux/slab.h>
#include <linux/ipc_logging.h>
#include <linux/of.h>
+#include <linux/suspend.h>
#include <linux/tty.h>
#include <linux/tty_driver.h>
@@ -40,6 +41,7 @@
#define MAX_SMD_TTYS 37
#define MAX_TTY_BUF_SIZE 2048
#define TTY_PUSH_WS_DELAY 500
+#define TTY_PUSH_WS_POST_SUSPEND_DELAY 100
#define MAX_RA_WAKE_LOCK_NAME_LEN 32
#define SMD_TTY_PROBE_WAIT_TIMEOUT 3000
#define SMD_TTY_LOG_PAGES 2
@@ -63,6 +65,10 @@ static void *smd_tty_log_ctx;
static struct delayed_work smd_tty_probe_work;
static int smd_tty_probe_done;
+static bool smd_tty_in_suspend;
+static bool smd_tty_read_in_suspend;
+static struct wakeup_source read_in_suspend_ws;
+
/**
* struct smd_tty_info - context for an individual SMD TTY device
*
@@ -312,6 +318,9 @@ static void smd_tty_read(unsigned long param)
*/
__pm_wakeup_event(&info->pending_ws, TTY_PUSH_WS_DELAY);
+ if (smd_tty_in_suspend)
+ smd_tty_read_in_suspend = true;
+
tty_flip_buffer_push(tty->port);
}
@@ -834,6 +843,31 @@ static const struct tty_operations smd_tty_ops = {
.tiocmset = smd_tty_tiocmset,
};
+static int smd_tty_pm_notifier(struct notifier_block *nb,
+ unsigned long event, void *unused)
+{
+ switch (event) {
+ case PM_SUSPEND_PREPARE:
+ smd_tty_read_in_suspend = false;
+ smd_tty_in_suspend = true;
+ break;
+
+ case PM_POST_SUSPEND:
+ smd_tty_in_suspend = false;
+ if (smd_tty_read_in_suspend) {
+ smd_tty_read_in_suspend = false;
+ __pm_wakeup_event(&read_in_suspend_ws,
+ TTY_PUSH_WS_POST_SUSPEND_DELAY);
+ }
+ break;
+ }
+ return NOTIFY_DONE;
+}
+
+static struct notifier_block smd_tty_pm_nb = {
+ .notifier_call = smd_tty_pm_notifier,
+ .priority = 0,
+};
/**
* smd_tty_log_init()- Init function for IPC logging
@@ -938,6 +972,11 @@ static int smd_tty_core_init(void)
smd_tty_device_init(idx);
}
INIT_DELAYED_WORK(&loopback_work, loopback_probe_worker);
+
+ ret = register_pm_notifier(&smd_tty_pm_nb);
+ if (ret)
+ pr_err("%s: power state notif error %d\n", __func__, ret);
+
return 0;
}
@@ -999,6 +1038,10 @@ static int smd_tty_devicetree_init(struct platform_device *pdev)
}
INIT_DELAYED_WORK(&loopback_work, loopback_probe_worker);
+ ret = register_pm_notifier(&smd_tty_pm_nb);
+ if (ret)
+ pr_err("%s: power state notif error %d\n", __func__, ret);
+
return 0;
error:
@@ -1080,6 +1123,7 @@ static int __init smd_tty_init(void)
schedule_delayed_work(&smd_tty_probe_work,
msecs_to_jiffies(SMD_TTY_PROBE_WAIT_TIMEOUT));
+ wakeup_source_init(&read_in_suspend_ws, "SMDTTY_READ_IN_SUSPEND");
return 0;
}