diff options
Diffstat (limited to 'drivers/char/tty_io.c')
-rw-r--r-- | drivers/char/tty_io.c | 37 |
1 files changed, 25 insertions, 12 deletions
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index 076e07c1da38..e9bba94fc898 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c | |||
@@ -268,6 +268,8 @@ static struct tty_buffer *tty_buffer_alloc(size_t size) | |||
268 | p->size = size; | 268 | p->size = size; |
269 | p->next = NULL; | 269 | p->next = NULL; |
270 | p->active = 0; | 270 | p->active = 0; |
271 | p->commit = 0; | ||
272 | p->read = 0; | ||
271 | p->char_buf_ptr = (char *)(p->data); | 273 | p->char_buf_ptr = (char *)(p->data); |
272 | p->flag_buf_ptr = (unsigned char *)p->char_buf_ptr + size; | 274 | p->flag_buf_ptr = (unsigned char *)p->char_buf_ptr + size; |
273 | /* printk("Flip create %p\n", p); */ | 275 | /* printk("Flip create %p\n", p); */ |
@@ -298,6 +300,8 @@ static struct tty_buffer *tty_buffer_find(struct tty_struct *tty, size_t size) | |||
298 | *tbh = t->next; | 300 | *tbh = t->next; |
299 | t->next = NULL; | 301 | t->next = NULL; |
300 | t->used = 0; | 302 | t->used = 0; |
303 | t->commit = 0; | ||
304 | t->read = 0; | ||
301 | /* DEBUG ONLY */ | 305 | /* DEBUG ONLY */ |
302 | memset(t->data, '*', size); | 306 | memset(t->data, '*', size); |
303 | /* printk("Flip recycle %p\n", t); */ | 307 | /* printk("Flip recycle %p\n", t); */ |
@@ -335,6 +339,7 @@ int tty_buffer_request_room(struct tty_struct *tty, size_t size) | |||
335 | if (b != NULL) { | 339 | if (b != NULL) { |
336 | b->next = n; | 340 | b->next = n; |
337 | b->active = 0; | 341 | b->active = 0; |
342 | b->commit = b->used; | ||
338 | } else | 343 | } else |
339 | tty->buf.head = n; | 344 | tty->buf.head = n; |
340 | tty->buf.tail = n; | 345 | tty->buf.tail = n; |
@@ -1836,7 +1841,6 @@ static void release_dev(struct file * filp) | |||
1836 | tty_closing = tty->count <= 1; | 1841 | tty_closing = tty->count <= 1; |
1837 | o_tty_closing = o_tty && | 1842 | o_tty_closing = o_tty && |
1838 | (o_tty->count <= (pty_master ? 1 : 0)); | 1843 | (o_tty->count <= (pty_master ? 1 : 0)); |
1839 | up(&tty_sem); | ||
1840 | do_sleep = 0; | 1844 | do_sleep = 0; |
1841 | 1845 | ||
1842 | if (tty_closing) { | 1846 | if (tty_closing) { |
@@ -1864,6 +1868,7 @@ static void release_dev(struct file * filp) | |||
1864 | 1868 | ||
1865 | printk(KERN_WARNING "release_dev: %s: read/write wait queue " | 1869 | printk(KERN_WARNING "release_dev: %s: read/write wait queue " |
1866 | "active!\n", tty_name(tty, buf)); | 1870 | "active!\n", tty_name(tty, buf)); |
1871 | up(&tty_sem); | ||
1867 | schedule(); | 1872 | schedule(); |
1868 | } | 1873 | } |
1869 | 1874 | ||
@@ -1872,8 +1877,6 @@ static void release_dev(struct file * filp) | |||
1872 | * both sides, and we've completed the last operation that could | 1877 | * both sides, and we've completed the last operation that could |
1873 | * block, so it's safe to proceed with closing. | 1878 | * block, so it's safe to proceed with closing. |
1874 | */ | 1879 | */ |
1875 | |||
1876 | down(&tty_sem); | ||
1877 | if (pty_master) { | 1880 | if (pty_master) { |
1878 | if (--o_tty->count < 0) { | 1881 | if (--o_tty->count < 0) { |
1879 | printk(KERN_WARNING "release_dev: bad pty slave count " | 1882 | printk(KERN_WARNING "release_dev: bad pty slave count " |
@@ -1887,7 +1890,6 @@ static void release_dev(struct file * filp) | |||
1887 | tty->count, tty_name(tty, buf)); | 1890 | tty->count, tty_name(tty, buf)); |
1888 | tty->count = 0; | 1891 | tty->count = 0; |
1889 | } | 1892 | } |
1890 | up(&tty_sem); | ||
1891 | 1893 | ||
1892 | /* | 1894 | /* |
1893 | * We've decremented tty->count, so we need to remove this file | 1895 | * We've decremented tty->count, so we need to remove this file |
@@ -1932,6 +1934,8 @@ static void release_dev(struct file * filp) | |||
1932 | read_unlock(&tasklist_lock); | 1934 | read_unlock(&tasklist_lock); |
1933 | } | 1935 | } |
1934 | 1936 | ||
1937 | up(&tty_sem); | ||
1938 | |||
1935 | /* check whether both sides are closing ... */ | 1939 | /* check whether both sides are closing ... */ |
1936 | if (!tty_closing || (o_tty && !o_tty_closing)) | 1940 | if (!tty_closing || (o_tty && !o_tty_closing)) |
1937 | return; | 1941 | return; |
@@ -2752,6 +2756,9 @@ static void flush_to_ldisc(void *private_) | |||
2752 | unsigned long flags; | 2756 | unsigned long flags; |
2753 | struct tty_ldisc *disc; | 2757 | struct tty_ldisc *disc; |
2754 | struct tty_buffer *tbuf; | 2758 | struct tty_buffer *tbuf; |
2759 | int count; | ||
2760 | char *char_buf; | ||
2761 | unsigned char *flag_buf; | ||
2755 | 2762 | ||
2756 | disc = tty_ldisc_ref(tty); | 2763 | disc = tty_ldisc_ref(tty); |
2757 | if (disc == NULL) /* !TTY_LDISC */ | 2764 | if (disc == NULL) /* !TTY_LDISC */ |
@@ -2765,16 +2772,20 @@ static void flush_to_ldisc(void *private_) | |||
2765 | goto out; | 2772 | goto out; |
2766 | } | 2773 | } |
2767 | spin_lock_irqsave(&tty->buf.lock, flags); | 2774 | spin_lock_irqsave(&tty->buf.lock, flags); |
2768 | while((tbuf = tty->buf.head) != NULL && !tbuf->active) { | 2775 | while((tbuf = tty->buf.head) != NULL) { |
2776 | while ((count = tbuf->commit - tbuf->read) != 0) { | ||
2777 | char_buf = tbuf->char_buf_ptr + tbuf->read; | ||
2778 | flag_buf = tbuf->flag_buf_ptr + tbuf->read; | ||
2779 | tbuf->read += count; | ||
2780 | spin_unlock_irqrestore(&tty->buf.lock, flags); | ||
2781 | disc->receive_buf(tty, char_buf, flag_buf, count); | ||
2782 | spin_lock_irqsave(&tty->buf.lock, flags); | ||
2783 | } | ||
2784 | if (tbuf->active) | ||
2785 | break; | ||
2769 | tty->buf.head = tbuf->next; | 2786 | tty->buf.head = tbuf->next; |
2770 | if (tty->buf.head == NULL) | 2787 | if (tty->buf.head == NULL) |
2771 | tty->buf.tail = NULL; | 2788 | tty->buf.tail = NULL; |
2772 | spin_unlock_irqrestore(&tty->buf.lock, flags); | ||
2773 | /* printk("Process buffer %p for %d\n", tbuf, tbuf->used); */ | ||
2774 | disc->receive_buf(tty, tbuf->char_buf_ptr, | ||
2775 | tbuf->flag_buf_ptr, | ||
2776 | tbuf->used); | ||
2777 | spin_lock_irqsave(&tty->buf.lock, flags); | ||
2778 | tty_buffer_free(tty, tbuf); | 2789 | tty_buffer_free(tty, tbuf); |
2779 | } | 2790 | } |
2780 | spin_unlock_irqrestore(&tty->buf.lock, flags); | 2791 | spin_unlock_irqrestore(&tty->buf.lock, flags); |
@@ -2871,8 +2882,10 @@ void tty_flip_buffer_push(struct tty_struct *tty) | |||
2871 | { | 2882 | { |
2872 | unsigned long flags; | 2883 | unsigned long flags; |
2873 | spin_lock_irqsave(&tty->buf.lock, flags); | 2884 | spin_lock_irqsave(&tty->buf.lock, flags); |
2874 | if (tty->buf.tail != NULL) | 2885 | if (tty->buf.tail != NULL) { |
2875 | tty->buf.tail->active = 0; | 2886 | tty->buf.tail->active = 0; |
2887 | tty->buf.tail->commit = tty->buf.tail->used; | ||
2888 | } | ||
2876 | spin_unlock_irqrestore(&tty->buf.lock, flags); | 2889 | spin_unlock_irqrestore(&tty->buf.lock, flags); |
2877 | 2890 | ||
2878 | if (tty->low_latency) | 2891 | if (tty->low_latency) |