aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/tty/tty_buffer.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2010-11-12 19:02:30 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2010-11-12 19:02:30 -0500
commitedaa4d668babd65e98e1452043996bbefc0285b0 (patch)
treea6cf4c6083ae49e8d1b7a4efc92a32864a79e534 /drivers/tty/tty_buffer.c
parent891cbd30ef456664e50bbd28436ef3006a81cf7c (diff)
parent40e3465db2cffd64e069ca82ee981025554bc159 (diff)
Merge branch 'tty-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty-2.6
* 'tty-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty-2.6: n_gsm: Fix length handling n_gsm: Copy n2 over when configuring via ioctl interface serial: bfin_5xx: grab port lock before making port termios changes serial: bfin_5xx: disable CON_PRINTBUFFER for consoles serial: bfin_5xx: remove redundant SSYNC to improve TX speed serial: bfin_5xx: always include DMA headers vcs: make proper usage of the poll flags amiserial: Remove unused variable icount 8250: Fix tcsetattr to avoid ioctl(TIOCMIWAIT) hang tty_ldisc: Fix BUG() on hangup TTY: restore tty_ldisc_wait_idle SERIAL: blacklist si3052 chip drivers/serial/bfin_5xx.c: Fix line continuation defects tty: prevent DOS in the flush_to_ldisc 8250: add support for Kouwell KW-L221N-2 nozomi: Fix warning from the previous TIOCGCOUNT changes tty: fix warning in synclink driver tty: Fix formatting in tty.h tty: the development tree is now done in git
Diffstat (limited to 'drivers/tty/tty_buffer.c')
-rw-r--r--drivers/tty/tty_buffer.c14
1 files changed, 12 insertions, 2 deletions
diff --git a/drivers/tty/tty_buffer.c b/drivers/tty/tty_buffer.c
index cc1e9850d655..d8210ca00720 100644
--- a/drivers/tty/tty_buffer.c
+++ b/drivers/tty/tty_buffer.c
@@ -413,7 +413,8 @@ static void flush_to_ldisc(struct work_struct *work)
413 spin_lock_irqsave(&tty->buf.lock, flags); 413 spin_lock_irqsave(&tty->buf.lock, flags);
414 414
415 if (!test_and_set_bit(TTY_FLUSHING, &tty->flags)) { 415 if (!test_and_set_bit(TTY_FLUSHING, &tty->flags)) {
416 struct tty_buffer *head; 416 struct tty_buffer *head, *tail = tty->buf.tail;
417 int seen_tail = 0;
417 while ((head = tty->buf.head) != NULL) { 418 while ((head = tty->buf.head) != NULL) {
418 int count; 419 int count;
419 char *char_buf; 420 char *char_buf;
@@ -423,6 +424,15 @@ static void flush_to_ldisc(struct work_struct *work)
423 if (!count) { 424 if (!count) {
424 if (head->next == NULL) 425 if (head->next == NULL)
425 break; 426 break;
427 /*
428 There's a possibility tty might get new buffer
429 added during the unlock window below. We could
430 end up spinning in here forever hogging the CPU
431 completely. To avoid this let's have a rest each
432 time we processed the tail buffer.
433 */
434 if (tail == head)
435 seen_tail = 1;
426 tty->buf.head = head->next; 436 tty->buf.head = head->next;
427 tty_buffer_free(tty, head); 437 tty_buffer_free(tty, head);
428 continue; 438 continue;
@@ -432,7 +442,7 @@ static void flush_to_ldisc(struct work_struct *work)
432 line discipline as we want to empty the queue */ 442 line discipline as we want to empty the queue */
433 if (test_bit(TTY_FLUSHPENDING, &tty->flags)) 443 if (test_bit(TTY_FLUSHPENDING, &tty->flags))
434 break; 444 break;
435 if (!tty->receive_room) { 445 if (!tty->receive_room || seen_tail) {
436 schedule_delayed_work(&tty->buf.work, 1); 446 schedule_delayed_work(&tty->buf.work, 1);
437 break; 447 break;
438 } 448 }