diff options
Diffstat (limited to 'drivers/char/tty_io.c')
-rw-r--r-- | drivers/char/tty_io.c | 75 |
1 files changed, 33 insertions, 42 deletions
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index 6c79ff3030fa..a1143238feca 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c | |||
@@ -266,7 +266,6 @@ static struct tty_buffer *tty_buffer_alloc(size_t size) | |||
266 | p->used = 0; | 266 | p->used = 0; |
267 | p->size = size; | 267 | p->size = size; |
268 | p->next = NULL; | 268 | p->next = NULL; |
269 | p->active = 0; | ||
270 | p->commit = 0; | 269 | p->commit = 0; |
271 | p->read = 0; | 270 | p->read = 0; |
272 | p->char_buf_ptr = (char *)(p->data); | 271 | p->char_buf_ptr = (char *)(p->data); |
@@ -326,10 +325,9 @@ int tty_buffer_request_room(struct tty_struct *tty, size_t size) | |||
326 | /* OPTIMISATION: We could keep a per tty "zero" sized buffer to | 325 | /* OPTIMISATION: We could keep a per tty "zero" sized buffer to |
327 | remove this conditional if its worth it. This would be invisible | 326 | remove this conditional if its worth it. This would be invisible |
328 | to the callers */ | 327 | to the callers */ |
329 | if ((b = tty->buf.tail) != NULL) { | 328 | if ((b = tty->buf.tail) != NULL) |
330 | left = b->size - b->used; | 329 | left = b->size - b->used; |
331 | b->active = 1; | 330 | else |
332 | } else | ||
333 | left = 0; | 331 | left = 0; |
334 | 332 | ||
335 | if (left < size) { | 333 | if (left < size) { |
@@ -337,12 +335,10 @@ int tty_buffer_request_room(struct tty_struct *tty, size_t size) | |||
337 | if ((n = tty_buffer_find(tty, size)) != NULL) { | 335 | if ((n = tty_buffer_find(tty, size)) != NULL) { |
338 | if (b != NULL) { | 336 | if (b != NULL) { |
339 | b->next = n; | 337 | b->next = n; |
340 | b->active = 0; | ||
341 | b->commit = b->used; | 338 | b->commit = b->used; |
342 | } else | 339 | } else |
343 | tty->buf.head = n; | 340 | tty->buf.head = n; |
344 | tty->buf.tail = n; | 341 | tty->buf.tail = n; |
345 | n->active = 1; | ||
346 | } else | 342 | } else |
347 | size = left; | 343 | size = left; |
348 | } | 344 | } |
@@ -403,10 +399,8 @@ void tty_schedule_flip(struct tty_struct *tty) | |||
403 | { | 399 | { |
404 | unsigned long flags; | 400 | unsigned long flags; |
405 | spin_lock_irqsave(&tty->buf.lock, flags); | 401 | spin_lock_irqsave(&tty->buf.lock, flags); |
406 | if (tty->buf.tail != NULL) { | 402 | if (tty->buf.tail != NULL) |
407 | tty->buf.tail->active = 0; | ||
408 | tty->buf.tail->commit = tty->buf.tail->used; | 403 | tty->buf.tail->commit = tty->buf.tail->used; |
409 | } | ||
410 | spin_unlock_irqrestore(&tty->buf.lock, flags); | 404 | spin_unlock_irqrestore(&tty->buf.lock, flags); |
411 | schedule_delayed_work(&tty->buf.work, 1); | 405 | schedule_delayed_work(&tty->buf.work, 1); |
412 | } | 406 | } |
@@ -783,11 +777,8 @@ restart: | |||
783 | } | 777 | } |
784 | 778 | ||
785 | clear_bit(TTY_LDISC, &tty->flags); | 779 | clear_bit(TTY_LDISC, &tty->flags); |
786 | clear_bit(TTY_DONT_FLIP, &tty->flags); | 780 | if (o_tty) |
787 | if (o_tty) { | ||
788 | clear_bit(TTY_LDISC, &o_tty->flags); | 781 | clear_bit(TTY_LDISC, &o_tty->flags); |
789 | clear_bit(TTY_DONT_FLIP, &o_tty->flags); | ||
790 | } | ||
791 | spin_unlock_irqrestore(&tty_ldisc_lock, flags); | 782 | spin_unlock_irqrestore(&tty_ldisc_lock, flags); |
792 | 783 | ||
793 | /* | 784 | /* |
@@ -1954,7 +1945,6 @@ static void release_dev(struct file * filp) | |||
1954 | * race with the set_ldisc code path. | 1945 | * race with the set_ldisc code path. |
1955 | */ | 1946 | */ |
1956 | clear_bit(TTY_LDISC, &tty->flags); | 1947 | clear_bit(TTY_LDISC, &tty->flags); |
1957 | clear_bit(TTY_DONT_FLIP, &tty->flags); | ||
1958 | cancel_delayed_work(&tty->buf.work); | 1948 | cancel_delayed_work(&tty->buf.work); |
1959 | 1949 | ||
1960 | /* | 1950 | /* |
@@ -2620,10 +2610,9 @@ int tty_ioctl(struct inode * inode, struct file * file, | |||
2620 | tty->driver->break_ctl(tty, 0); | 2610 | tty->driver->break_ctl(tty, 0); |
2621 | return 0; | 2611 | return 0; |
2622 | case TCSBRK: /* SVID version: non-zero arg --> no break */ | 2612 | case TCSBRK: /* SVID version: non-zero arg --> no break */ |
2623 | /* | 2613 | /* non-zero arg means wait for all output data |
2624 | * XXX is the above comment correct, or the | 2614 | * to be sent (performed above) but don't send break. |
2625 | * code below correct? Is this ioctl used at | 2615 | * This is used by the tcdrain() termios function. |
2626 | * all by anyone? | ||
2627 | */ | 2616 | */ |
2628 | if (!arg) | 2617 | if (!arg) |
2629 | return send_break(tty, 250); | 2618 | return send_break(tty, 250); |
@@ -2775,8 +2764,7 @@ static void flush_to_ldisc(void *private_) | |||
2775 | struct tty_struct *tty = (struct tty_struct *) private_; | 2764 | struct tty_struct *tty = (struct tty_struct *) private_; |
2776 | unsigned long flags; | 2765 | unsigned long flags; |
2777 | struct tty_ldisc *disc; | 2766 | struct tty_ldisc *disc; |
2778 | struct tty_buffer *tbuf; | 2767 | struct tty_buffer *tbuf, *head; |
2779 | int count; | ||
2780 | char *char_buf; | 2768 | char *char_buf; |
2781 | unsigned char *flag_buf; | 2769 | unsigned char *flag_buf; |
2782 | 2770 | ||
@@ -2784,32 +2772,37 @@ static void flush_to_ldisc(void *private_) | |||
2784 | if (disc == NULL) /* !TTY_LDISC */ | 2772 | if (disc == NULL) /* !TTY_LDISC */ |
2785 | return; | 2773 | return; |
2786 | 2774 | ||
2787 | if (test_bit(TTY_DONT_FLIP, &tty->flags)) { | ||
2788 | /* | ||
2789 | * Do it after the next timer tick: | ||
2790 | */ | ||
2791 | schedule_delayed_work(&tty->buf.work, 1); | ||
2792 | goto out; | ||
2793 | } | ||
2794 | spin_lock_irqsave(&tty->buf.lock, flags); | 2775 | spin_lock_irqsave(&tty->buf.lock, flags); |
2795 | while((tbuf = tty->buf.head) != NULL) { | 2776 | head = tty->buf.head; |
2796 | while ((count = tbuf->commit - tbuf->read) != 0) { | 2777 | if (head != NULL) { |
2797 | char_buf = tbuf->char_buf_ptr + tbuf->read; | 2778 | tty->buf.head = NULL; |
2798 | flag_buf = tbuf->flag_buf_ptr + tbuf->read; | 2779 | for (;;) { |
2799 | tbuf->read += count; | 2780 | int count = head->commit - head->read; |
2781 | if (!count) { | ||
2782 | if (head->next == NULL) | ||
2783 | break; | ||
2784 | tbuf = head; | ||
2785 | head = head->next; | ||
2786 | tty_buffer_free(tty, tbuf); | ||
2787 | continue; | ||
2788 | } | ||
2789 | if (!tty->receive_room) { | ||
2790 | schedule_delayed_work(&tty->buf.work, 1); | ||
2791 | break; | ||
2792 | } | ||
2793 | if (count > tty->receive_room) | ||
2794 | count = tty->receive_room; | ||
2795 | char_buf = head->char_buf_ptr + head->read; | ||
2796 | flag_buf = head->flag_buf_ptr + head->read; | ||
2797 | head->read += count; | ||
2800 | spin_unlock_irqrestore(&tty->buf.lock, flags); | 2798 | spin_unlock_irqrestore(&tty->buf.lock, flags); |
2801 | disc->receive_buf(tty, char_buf, flag_buf, count); | 2799 | disc->receive_buf(tty, char_buf, flag_buf, count); |
2802 | spin_lock_irqsave(&tty->buf.lock, flags); | 2800 | spin_lock_irqsave(&tty->buf.lock, flags); |
2803 | } | 2801 | } |
2804 | if (tbuf->active) | 2802 | tty->buf.head = head; |
2805 | break; | ||
2806 | tty->buf.head = tbuf->next; | ||
2807 | if (tty->buf.head == NULL) | ||
2808 | tty->buf.tail = NULL; | ||
2809 | tty_buffer_free(tty, tbuf); | ||
2810 | } | 2803 | } |
2811 | spin_unlock_irqrestore(&tty->buf.lock, flags); | 2804 | spin_unlock_irqrestore(&tty->buf.lock, flags); |
2812 | out: | 2805 | |
2813 | tty_ldisc_deref(disc); | 2806 | tty_ldisc_deref(disc); |
2814 | } | 2807 | } |
2815 | 2808 | ||
@@ -2902,10 +2895,8 @@ void tty_flip_buffer_push(struct tty_struct *tty) | |||
2902 | { | 2895 | { |
2903 | unsigned long flags; | 2896 | unsigned long flags; |
2904 | spin_lock_irqsave(&tty->buf.lock, flags); | 2897 | spin_lock_irqsave(&tty->buf.lock, flags); |
2905 | if (tty->buf.tail != NULL) { | 2898 | if (tty->buf.tail != NULL) |
2906 | tty->buf.tail->active = 0; | ||
2907 | tty->buf.tail->commit = tty->buf.tail->used; | 2899 | tty->buf.tail->commit = tty->buf.tail->used; |
2908 | } | ||
2909 | spin_unlock_irqrestore(&tty->buf.lock, flags); | 2900 | spin_unlock_irqrestore(&tty->buf.lock, flags); |
2910 | 2901 | ||
2911 | if (tty->low_latency) | 2902 | if (tty->low_latency) |