pty: Rework the pty layer to use the normal buffering logic
[pandora-kernel.git] / drivers / char / pty.c
index 5acd29e..9d1b4f5 100644 (file)
@@ -75,94 +75,88 @@ static void pty_close(struct tty_struct *tty, struct file *filp)
  */
 static void pty_unthrottle(struct tty_struct *tty)
 {
-       struct tty_struct *o_tty = tty->link;
+       tty_wakeup(tty->link);
+       set_bit(TTY_THROTTLED, &tty->flags);
+}
 
-       if (!o_tty)
-               return;
+/**
+ *     pty_space       -       report space left for writing
+ *     @to: tty we are writing into
+ *
+ *     The tty buffers allow 64K but we sneak a peak and clip at 8K this
+ *     allows a lot of overspill room for echo and other fun messes to
+ *     be handled properly
+ */
 
-       tty_wakeup(o_tty);
-       set_bit(TTY_THROTTLED, &tty->flags);
+static int pty_space(struct tty_struct *to)
+{
+       int n = 8192 - to->buf.memory_used;
+       if (n < 0)
+               return 0;
+       return n;
 }
 
-/*
- * WSH 05/24/97: modified to
- *   (1) use space in tty->flip instead of a shared temp buffer
- *      The flip buffers aren't being used for a pty, so there's lots
- *      of space available.  The buffer is protected by a per-pty
- *      semaphore that should almost never come under contention.
- *   (2) avoid redundant copying for cases where count >> receive_room
- * N.B. Calls from user space may now return an error code instead of
- * a count.
+/**
+ *     pty_write               -       write to a pty
+ *     @tty: the tty we write from
+ *     @buf: kernel buffer of data
+ *     @count: bytes to write
  *
- * FIXME: Our pty_write method is called with our ldisc lock held but
- * not our partners. We can't just take the other one blindly without
- * risking deadlocks.
+ *     Our "hardware" write method. Data is coming from the ldisc which
+ *     may be in a non sleeping state. We simply throw this at the other
+ *     end of the link as if we were an IRQ handler receiving stuff for
+ *     the other side of the pty/tty pair.
  */
+
 static int pty_write(struct tty_struct *tty, const unsigned char *buf,
                                                                int count)
 {
        struct tty_struct *to = tty->link;
-       int     c;
+       int c;
 
-       if (!to || tty->stopped)
+       if (tty->stopped)
                return 0;
 
-       c = to->receive_room;
+       /* This isn't locked but our 8K is quite sloppy so no
+          big deal */
+
+       c = pty_space(to);
        if (c > count)
                c = count;
-       to->ldisc->ops->receive_buf(to, buf, NULL, c);
-
+       if (c > 0) {
+               /* Stuff the data into the input queue of the other end */
+               c = tty_insert_flip_string(to, buf, c);
+               /* And shovel */
+               tty_flip_buffer_push(to);
+               tty_wakeup(tty);
+       }
        return c;
 }
 
+/**
+ *     pty_write_room  -       write space
+ *     @tty: tty we are writing from
+ *
+ *     Report how many bytes the ldisc can send into the queue for
+ *     the other device.
+ */
+
 static int pty_write_room(struct tty_struct *tty)
 {
-       struct tty_struct *to = tty->link;
-
-       if (!to || tty->stopped)
-               return 0;
-
-       return to->receive_room;
+       return pty_space(tty->link);
 }
 
-/*
- *     WSH 05/24/97:  Modified for asymmetric MASTER/SLAVE behavior
- *     The chars_in_buffer() value is used by the ldisc select() function
- *     to hold off writing when chars_in_buffer > WAKEUP_CHARS (== 256).
- *     The pty driver chars_in_buffer() Master/Slave must behave differently:
- *
- *      The Master side needs to allow typed-ahead commands to accumulate
- *      while being canonicalized, so we report "our buffer" as empty until
- *     some threshold is reached, and then report the count. (Any count >
- *     WAKEUP_CHARS is regarded by select() as "full".)  To avoid deadlock
- *     the count returned must be 0 if no canonical data is available to be
- *     read. (The N_TTY ldisc.chars_in_buffer now knows this.)
+/**
+ *     pty_chars_in_buffer     -       characters currently in our tx queue
+ *     @tty: our tty
  *
- *     The Slave side passes all characters in raw mode to the Master side's
- *     buffer where they can be read immediately, so in this case we can
- *     return the true count in the buffer.
+ *     Report how much we have in the transmit queue. As everything is
+ *     instantly at the other end this is easy to implement.
  */
+
 static int pty_chars_in_buffer(struct tty_struct *tty)
 {
-       struct tty_struct *to = tty->link;
-       int count;
-
-       /* We should get the line discipline lock for "tty->link" */
-       if (!to || !to->ldisc->ops->chars_in_buffer)
-               return 0;
-
-       /* The ldisc must report 0 if no characters available to be read */
-       count = to->ldisc->ops->chars_in_buffer(to);
-
-       if (tty->driver->subtype == PTY_TYPE_SLAVE)
-               return count;
-
-       /* Master side driver ... if the other side's read buffer is less than
-        * half full, return 0 to allow writers to proceed; otherwise return
-        * the count.  This leaves a comfortable margin to avoid overflow,
-        * and still allows half a buffer's worth of typed-ahead commands.
-        */
-       return (count < N_TTY_BUF_SIZE/2) ? 0 : count;
+       return 0;
 }
 
 /* Set the lock flag on a pty */
@@ -185,10 +179,7 @@ static void pty_flush_buffer(struct tty_struct *tty)
 
        if (!to)
                return;
-
-       if (to->ldisc->ops->flush_buffer)
-               to->ldisc->ops->flush_buffer(to);
-
+       /* tty_buffer_flush(to); FIXME */
        if (to->packet) {
                spin_lock_irqsave(&tty->ctrl_lock, flags);
                tty->ctrl_status |= TIOCPKT_FLUSHWRITE;