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.c37
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)