From: Peter Hurley Date: Thu, 16 Oct 2014 19:33:29 +0000 (-0400) Subject: tty: Fix missed wakeup from packet mode status update X-Git-Url: https://git.stricted.de/?a=commitdiff_plain;h=1aa1bf1115272d22fc4c758ee8769b73d8079a79;p=GitHub%2FLineageOS%2FG12%2Fandroid_kernel_amlogic_linux-4.9.git tty: Fix missed wakeup from packet mode status update The pty master read() can miss the wake up for a packet mode status change. For example, CPU 0 | CPU 1 n_tty_read() | n_tty_packet_mode_flush() ... | . if (packet & link->ctrl_status) { | . /* no new ctrl_status ATM */ | . | spin_lock | ctrl_status |= TIOCPKT_FLUSHREAD | spin_unlock | wake_up(link->read_wait) } | set_current_state(TASK_INTERRUPTIBLE) | ... | The pty master read() will now sleep (assuming there is no input) having missed the read_wait wakeup. Set the task state before the condition test. Signed-off-by: Peter Hurley Reviewed-by: Alan Cox Signed-off-by: Greg Kroah-Hartman --- diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index cd725cc6e21e..7f134b977c36 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c @@ -2168,6 +2168,11 @@ static ssize_t n_tty_read(struct tty_struct *tty, struct file *file, add_wait_queue(&tty->read_wait, &wait); while (nr) { + /* This statement must be first before checking for input + so that any interrupt will set the state back to + TASK_RUNNING. */ + set_current_state(TASK_INTERRUPTIBLE); + /* First test for status change. */ if (packet && tty->link->ctrl_status) { unsigned char cs; @@ -2185,10 +2190,6 @@ static ssize_t n_tty_read(struct tty_struct *tty, struct file *file, nr--; break; } - /* This statement must be first before checking for input - so that any interrupt will set the state back to - TASK_RUNNING. */ - set_current_state(TASK_INTERRUPTIBLE); if (((minimum - (b - buf)) < ldata->minimum_to_wake) && ((minimum - (b - buf)) >= 1))