diff options
author | Paul Mundt <lethal@linux-sh.org> | 2010-11-18 03:35:56 -0500 |
---|---|---|
committer | Paul Mundt <lethal@linux-sh.org> | 2010-11-18 03:35:56 -0500 |
commit | 0421860a5a75b59a76b7a864a172eb090e3d0785 (patch) | |
tree | df22f28abfa4c8bb77d650b674a44e0aedc586be /drivers/tty/tty_buffer.c | |
parent | cf655c36fad7b6488a56f18ab56f7d608ca6552b (diff) | |
parent | 89ba4d12fca24d373e1b10fce498d68157bafaf0 (diff) |
Merge branch 'rmobile/ag5' into rmobile-latest
Diffstat (limited to 'drivers/tty/tty_buffer.c')
-rw-r--r-- | drivers/tty/tty_buffer.c | 14 |
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 | } |