aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/tty/n_tty.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/tty/n_tty.c')
-rw-r--r--drivers/tty/n_tty.c27
1 files changed, 19 insertions, 8 deletions
diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c
index 7cdd1eb9406c..34aacaaae14a 100644
--- a/drivers/tty/n_tty.c
+++ b/drivers/tty/n_tty.c
@@ -93,6 +93,7 @@ struct n_tty_data {
93 size_t canon_head; 93 size_t canon_head;
94 size_t echo_head; 94 size_t echo_head;
95 size_t echo_commit; 95 size_t echo_commit;
96 size_t echo_mark;
96 DECLARE_BITMAP(char_map, 256); 97 DECLARE_BITMAP(char_map, 256);
97 98
98 /* private to n_tty_receive_overrun (single-threaded) */ 99 /* private to n_tty_receive_overrun (single-threaded) */
@@ -336,6 +337,7 @@ static void reset_buffer_flags(struct n_tty_data *ldata)
336{ 337{
337 ldata->read_head = ldata->canon_head = ldata->read_tail = 0; 338 ldata->read_head = ldata->canon_head = ldata->read_tail = 0;
338 ldata->echo_head = ldata->echo_tail = ldata->echo_commit = 0; 339 ldata->echo_head = ldata->echo_tail = ldata->echo_commit = 0;
340 ldata->echo_mark = 0;
339 ldata->line_start = 0; 341 ldata->line_start = 0;
340 342
341 ldata->erasing = 0; 343 ldata->erasing = 0;
@@ -768,7 +770,7 @@ static size_t __process_echoes(struct tty_struct *tty)
768 * data at the tail to prevent a subsequent overrun */ 770 * data at the tail to prevent a subsequent overrun */
769 while (ldata->echo_commit - tail >= ECHO_DISCARD_WATERMARK) { 771 while (ldata->echo_commit - tail >= ECHO_DISCARD_WATERMARK) {
770 if (echo_buf(ldata, tail) == ECHO_OP_START) { 772 if (echo_buf(ldata, tail) == ECHO_OP_START) {
771 if (echo_buf(ldata, tail) == ECHO_OP_ERASE_TAB) 773 if (echo_buf(ldata, tail + 1) == ECHO_OP_ERASE_TAB)
772 tail += 3; 774 tail += 3;
773 else 775 else
774 tail += 2; 776 tail += 2;
@@ -787,6 +789,7 @@ static void commit_echoes(struct tty_struct *tty)
787 size_t head; 789 size_t head;
788 790
789 head = ldata->echo_head; 791 head = ldata->echo_head;
792 ldata->echo_mark = head;
790 old = ldata->echo_commit - ldata->echo_tail; 793 old = ldata->echo_commit - ldata->echo_tail;
791 794
792 /* Process committed echoes if the accumulated # of bytes 795 /* Process committed echoes if the accumulated # of bytes
@@ -810,10 +813,12 @@ static void process_echoes(struct tty_struct *tty)
810 struct n_tty_data *ldata = tty->disc_data; 813 struct n_tty_data *ldata = tty->disc_data;
811 size_t echoed; 814 size_t echoed;
812 815
813 if (!L_ECHO(tty) || ldata->echo_commit == ldata->echo_tail) 816 if ((!L_ECHO(tty) && !L_ECHONL(tty)) ||
817 ldata->echo_mark == ldata->echo_tail)
814 return; 818 return;
815 819
816 mutex_lock(&ldata->output_lock); 820 mutex_lock(&ldata->output_lock);
821 ldata->echo_commit = ldata->echo_mark;
817 echoed = __process_echoes(tty); 822 echoed = __process_echoes(tty);
818 mutex_unlock(&ldata->output_lock); 823 mutex_unlock(&ldata->output_lock);
819 824
@@ -821,11 +826,13 @@ static void process_echoes(struct tty_struct *tty)
821 tty->ops->flush_chars(tty); 826 tty->ops->flush_chars(tty);
822} 827}
823 828
829/* NB: echo_mark and echo_head should be equivalent here */
824static void flush_echoes(struct tty_struct *tty) 830static void flush_echoes(struct tty_struct *tty)
825{ 831{
826 struct n_tty_data *ldata = tty->disc_data; 832 struct n_tty_data *ldata = tty->disc_data;
827 833
828 if (!L_ECHO(tty) || ldata->echo_commit == ldata->echo_head) 834 if ((!L_ECHO(tty) && !L_ECHONL(tty)) ||
835 ldata->echo_commit == ldata->echo_head)
829 return; 836 return;
830 837
831 mutex_lock(&ldata->output_lock); 838 mutex_lock(&ldata->output_lock);
@@ -1998,7 +2005,10 @@ static int canon_copy_from_read_buf(struct tty_struct *tty,
1998 found = 1; 2005 found = 1;
1999 2006
2000 size = N_TTY_BUF_SIZE - tail; 2007 size = N_TTY_BUF_SIZE - tail;
2001 n = (found + eol + size) & (N_TTY_BUF_SIZE - 1); 2008 n = eol - tail;
2009 if (n > 4096)
2010 n += 4096;
2011 n += found;
2002 c = n; 2012 c = n;
2003 2013
2004 if (found && read_buf(ldata, eol) == __DISABLED_CHAR) { 2014 if (found && read_buf(ldata, eol) == __DISABLED_CHAR) {
@@ -2243,18 +2253,19 @@ static ssize_t n_tty_read(struct tty_struct *tty, struct file *file,
2243 if (time) 2253 if (time)
2244 timeout = time; 2254 timeout = time;
2245 } 2255 }
2246 mutex_unlock(&ldata->atomic_read_lock); 2256 n_tty_set_room(tty);
2247 remove_wait_queue(&tty->read_wait, &wait); 2257 up_read(&tty->termios_rwsem);
2248 2258
2259 remove_wait_queue(&tty->read_wait, &wait);
2249 if (!waitqueue_active(&tty->read_wait)) 2260 if (!waitqueue_active(&tty->read_wait))
2250 ldata->minimum_to_wake = minimum; 2261 ldata->minimum_to_wake = minimum;
2251 2262
2263 mutex_unlock(&ldata->atomic_read_lock);
2264
2252 __set_current_state(TASK_RUNNING); 2265 __set_current_state(TASK_RUNNING);
2253 if (b - buf) 2266 if (b - buf)
2254 retval = b - buf; 2267 retval = b - buf;
2255 2268
2256 n_tty_set_room(tty);
2257 up_read(&tty->termios_rwsem);
2258 return retval; 2269 return retval;
2259} 2270}
2260 2271