diff options
Diffstat (limited to 'drivers/char/tty_io.c')
| -rw-r--r-- | drivers/char/tty_io.c | 68 |
1 files changed, 30 insertions, 38 deletions
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index bd74e82d8a72..8d19f7281f0b 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c | |||
| @@ -267,7 +267,6 @@ static struct tty_buffer *tty_buffer_alloc(size_t size) | |||
| 267 | p->used = 0; | 267 | p->used = 0; |
| 268 | p->size = size; | 268 | p->size = size; |
| 269 | p->next = NULL; | 269 | p->next = NULL; |
| 270 | p->active = 0; | ||
| 271 | p->commit = 0; | 270 | p->commit = 0; |
| 272 | p->read = 0; | 271 | p->read = 0; |
| 273 | p->char_buf_ptr = (char *)(p->data); | 272 | p->char_buf_ptr = (char *)(p->data); |
| @@ -327,10 +326,9 @@ int tty_buffer_request_room(struct tty_struct *tty, size_t size) | |||
| 327 | /* OPTIMISATION: We could keep a per tty "zero" sized buffer to | 326 | /* OPTIMISATION: We could keep a per tty "zero" sized buffer to |
| 328 | remove this conditional if its worth it. This would be invisible | 327 | remove this conditional if its worth it. This would be invisible |
| 329 | to the callers */ | 328 | to the callers */ |
| 330 | if ((b = tty->buf.tail) != NULL) { | 329 | if ((b = tty->buf.tail) != NULL) |
| 331 | left = b->size - b->used; | 330 | left = b->size - b->used; |
| 332 | b->active = 1; | 331 | else |
| 333 | } else | ||
| 334 | left = 0; | 332 | left = 0; |
| 335 | 333 | ||
| 336 | if (left < size) { | 334 | if (left < size) { |
| @@ -338,12 +336,10 @@ int tty_buffer_request_room(struct tty_struct *tty, size_t size) | |||
| 338 | if ((n = tty_buffer_find(tty, size)) != NULL) { | 336 | if ((n = tty_buffer_find(tty, size)) != NULL) { |
| 339 | if (b != NULL) { | 337 | if (b != NULL) { |
| 340 | b->next = n; | 338 | b->next = n; |
| 341 | b->active = 0; | ||
| 342 | b->commit = b->used; | 339 | b->commit = b->used; |
| 343 | } else | 340 | } else |
| 344 | tty->buf.head = n; | 341 | tty->buf.head = n; |
| 345 | tty->buf.tail = n; | 342 | tty->buf.tail = n; |
| 346 | n->active = 1; | ||
| 347 | } else | 343 | } else |
| 348 | size = left; | 344 | size = left; |
| 349 | } | 345 | } |
| @@ -404,10 +400,8 @@ void tty_schedule_flip(struct tty_struct *tty) | |||
| 404 | { | 400 | { |
| 405 | unsigned long flags; | 401 | unsigned long flags; |
| 406 | spin_lock_irqsave(&tty->buf.lock, flags); | 402 | spin_lock_irqsave(&tty->buf.lock, flags); |
| 407 | if (tty->buf.tail != NULL) { | 403 | if (tty->buf.tail != NULL) |
| 408 | tty->buf.tail->active = 0; | ||
| 409 | tty->buf.tail->commit = tty->buf.tail->used; | 404 | tty->buf.tail->commit = tty->buf.tail->used; |
| 410 | } | ||
| 411 | spin_unlock_irqrestore(&tty->buf.lock, flags); | 405 | spin_unlock_irqrestore(&tty->buf.lock, flags); |
| 412 | schedule_delayed_work(&tty->buf.work, 1); | 406 | schedule_delayed_work(&tty->buf.work, 1); |
| 413 | } | 407 | } |
| @@ -784,11 +778,8 @@ restart: | |||
| 784 | } | 778 | } |
| 785 | 779 | ||
| 786 | clear_bit(TTY_LDISC, &tty->flags); | 780 | clear_bit(TTY_LDISC, &tty->flags); |
| 787 | clear_bit(TTY_DONT_FLIP, &tty->flags); | 781 | if (o_tty) |
| 788 | if (o_tty) { | ||
| 789 | clear_bit(TTY_LDISC, &o_tty->flags); | 782 | clear_bit(TTY_LDISC, &o_tty->flags); |
| 790 | clear_bit(TTY_DONT_FLIP, &o_tty->flags); | ||
| 791 | } | ||
| 792 | spin_unlock_irqrestore(&tty_ldisc_lock, flags); | 783 | spin_unlock_irqrestore(&tty_ldisc_lock, flags); |
| 793 | 784 | ||
| 794 | /* | 785 | /* |
| @@ -1955,7 +1946,6 @@ static void release_dev(struct file * filp) | |||
| 1955 | * race with the set_ldisc code path. | 1946 | * race with the set_ldisc code path. |
| 1956 | */ | 1947 | */ |
| 1957 | clear_bit(TTY_LDISC, &tty->flags); | 1948 | clear_bit(TTY_LDISC, &tty->flags); |
| 1958 | clear_bit(TTY_DONT_FLIP, &tty->flags); | ||
| 1959 | cancel_delayed_work(&tty->buf.work); | 1949 | cancel_delayed_work(&tty->buf.work); |
| 1960 | 1950 | ||
| 1961 | /* | 1951 | /* |
| @@ -2775,8 +2765,7 @@ static void flush_to_ldisc(void *private_) | |||
| 2775 | struct tty_struct *tty = (struct tty_struct *) private_; | 2765 | struct tty_struct *tty = (struct tty_struct *) private_; |
| 2776 | unsigned long flags; | 2766 | unsigned long flags; |
| 2777 | struct tty_ldisc *disc; | 2767 | struct tty_ldisc *disc; |
| 2778 | struct tty_buffer *tbuf; | 2768 | struct tty_buffer *tbuf, *head; |
| 2779 | int count; | ||
| 2780 | char *char_buf; | 2769 | char *char_buf; |
| 2781 | unsigned char *flag_buf; | 2770 | unsigned char *flag_buf; |
| 2782 | 2771 | ||
| @@ -2784,32 +2773,37 @@ static void flush_to_ldisc(void *private_) | |||
| 2784 | if (disc == NULL) /* !TTY_LDISC */ | 2773 | if (disc == NULL) /* !TTY_LDISC */ |
| 2785 | return; | 2774 | return; |
| 2786 | 2775 | ||
| 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); | 2776 | spin_lock_irqsave(&tty->buf.lock, flags); |
| 2795 | while((tbuf = tty->buf.head) != NULL) { | 2777 | head = tty->buf.head; |
| 2796 | while ((count = tbuf->commit - tbuf->read) != 0) { | 2778 | if (head != NULL) { |
| 2797 | char_buf = tbuf->char_buf_ptr + tbuf->read; | 2779 | tty->buf.head = NULL; |
| 2798 | flag_buf = tbuf->flag_buf_ptr + tbuf->read; | 2780 | for (;;) { |
| 2799 | tbuf->read += count; | 2781 | int count = head->commit - head->read; |
| 2782 | if (!count) { | ||
| 2783 | if (head->next == NULL) | ||
| 2784 | break; | ||
| 2785 | tbuf = head; | ||
| 2786 | head = head->next; | ||
| 2787 | tty_buffer_free(tty, tbuf); | ||
| 2788 | continue; | ||
| 2789 | } | ||
| 2790 | if (!tty->receive_room) { | ||
| 2791 | schedule_delayed_work(&tty->buf.work, 1); | ||
| 2792 | break; | ||
| 2793 | } | ||
| 2794 | if (count > tty->receive_room) | ||
| 2795 | count = tty->receive_room; | ||
| 2796 | char_buf = head->char_buf_ptr + head->read; | ||
| 2797 | flag_buf = head->flag_buf_ptr + head->read; | ||
| 2798 | head->read += count; | ||
| 2800 | spin_unlock_irqrestore(&tty->buf.lock, flags); | 2799 | spin_unlock_irqrestore(&tty->buf.lock, flags); |
| 2801 | disc->receive_buf(tty, char_buf, flag_buf, count); | 2800 | disc->receive_buf(tty, char_buf, flag_buf, count); |
| 2802 | spin_lock_irqsave(&tty->buf.lock, flags); | 2801 | spin_lock_irqsave(&tty->buf.lock, flags); |
| 2803 | } | 2802 | } |
| 2804 | if (tbuf->active) | 2803 | 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 | } | 2804 | } |
| 2811 | spin_unlock_irqrestore(&tty->buf.lock, flags); | 2805 | spin_unlock_irqrestore(&tty->buf.lock, flags); |
| 2812 | out: | 2806 | |
| 2813 | tty_ldisc_deref(disc); | 2807 | tty_ldisc_deref(disc); |
| 2814 | } | 2808 | } |
| 2815 | 2809 | ||
| @@ -2902,10 +2896,8 @@ void tty_flip_buffer_push(struct tty_struct *tty) | |||
| 2902 | { | 2896 | { |
| 2903 | unsigned long flags; | 2897 | unsigned long flags; |
| 2904 | spin_lock_irqsave(&tty->buf.lock, flags); | 2898 | spin_lock_irqsave(&tty->buf.lock, flags); |
| 2905 | if (tty->buf.tail != NULL) { | 2899 | if (tty->buf.tail != NULL) |
| 2906 | tty->buf.tail->active = 0; | ||
| 2907 | tty->buf.tail->commit = tty->buf.tail->used; | 2900 | tty->buf.tail->commit = tty->buf.tail->used; |
| 2908 | } | ||
| 2909 | spin_unlock_irqrestore(&tty->buf.lock, flags); | 2901 | spin_unlock_irqrestore(&tty->buf.lock, flags); |
| 2910 | 2902 | ||
| 2911 | if (tty->low_latency) | 2903 | if (tty->low_latency) |
