aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char/tty_io.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/char/tty_io.c')
-rw-r--r--drivers/char/tty_io.c75
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);
2812out: 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)