diff options
Diffstat (limited to 'drivers/tty/serial/msm_smd_tty.c')
-rw-r--r-- | drivers/tty/serial/msm_smd_tty.c | 44 |
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; } |