diff options
| -rw-r--r-- | drivers/char/pty.c | 154 |
1 files changed, 59 insertions, 95 deletions
diff --git a/drivers/char/pty.c b/drivers/char/pty.c index daebe1ba43d4..9d1b4f548f67 100644 --- a/drivers/char/pty.c +++ b/drivers/char/pty.c | |||
| @@ -75,114 +75,88 @@ static void pty_close(struct tty_struct *tty, struct file *filp) | |||
| 75 | */ | 75 | */ |
| 76 | static void pty_unthrottle(struct tty_struct *tty) | 76 | static void pty_unthrottle(struct tty_struct *tty) |
| 77 | { | 77 | { |
| 78 | struct tty_struct *o_tty = tty->link; | 78 | tty_wakeup(tty->link); |
| 79 | |||
| 80 | if (!o_tty) | ||
| 81 | return; | ||
| 82 | |||
| 83 | tty_wakeup(o_tty); | ||
| 84 | set_bit(TTY_THROTTLED, &tty->flags); | 79 | set_bit(TTY_THROTTLED, &tty->flags); |
| 85 | } | 80 | } |
| 86 | 81 | ||
| 87 | /* | 82 | /** |
| 88 | * WSH 05/24/97: modified to | 83 | * pty_space - report space left for writing |
| 89 | * (1) use space in tty->flip instead of a shared temp buffer | 84 | * @to: tty we are writing into |
| 90 | * The flip buffers aren't being used for a pty, so there's lots | ||
| 91 | * of space available. The buffer is protected by a per-pty | ||
| 92 | * semaphore that should almost never come under contention. | ||
| 93 | * (2) avoid redundant copying for cases where count >> receive_room | ||
| 94 | * N.B. Calls from user space may now return an error code instead of | ||
| 95 | * a count. | ||
| 96 | * | 85 | * |
| 97 | * FIXME: Our pty_write method is called with our ldisc lock held but | 86 | * The tty buffers allow 64K but we sneak a peak and clip at 8K this |
| 98 | * not our partners. We can't just wait on the other one blindly without | 87 | * allows a lot of overspill room for echo and other fun messes to |
| 99 | * risking deadlocks. At some point when everything has settled down we need | 88 | * be handled properly |
| 100 | * to look into making pty_write at least able to sleep over an ldisc change. | 89 | */ |
| 90 | |||
| 91 | static int pty_space(struct tty_struct *to) | ||
| 92 | { | ||
| 93 | int n = 8192 - to->buf.memory_used; | ||
| 94 | if (n < 0) | ||
| 95 | return 0; | ||
| 96 | return n; | ||
| 97 | } | ||
| 98 | |||
| 99 | /** | ||
| 100 | * pty_write - write to a pty | ||
| 101 | * @tty: the tty we write from | ||
| 102 | * @buf: kernel buffer of data | ||
| 103 | * @count: bytes to write | ||
| 101 | * | 104 | * |
| 102 | * The return on no ldisc is a bit counter intuitive but the logic works | 105 | * Our "hardware" write method. Data is coming from the ldisc which |
| 103 | * like this. During an ldisc change the other end will flush its buffers. We | 106 | * may be in a non sleeping state. We simply throw this at the other |
| 104 | * thus return the full length which is identical to the case where we had | 107 | * end of the link as if we were an IRQ handler receiving stuff for |
| 105 | * proper locking and happened to queue the bytes just before the flush during | 108 | * the other side of the pty/tty pair. |
| 106 | * the ldisc change. | ||
| 107 | */ | 109 | */ |
| 110 | |||
| 108 | static int pty_write(struct tty_struct *tty, const unsigned char *buf, | 111 | static int pty_write(struct tty_struct *tty, const unsigned char *buf, |
| 109 | int count) | 112 | int count) |
| 110 | { | 113 | { |
| 111 | struct tty_struct *to = tty->link; | 114 | struct tty_struct *to = tty->link; |
| 112 | struct tty_ldisc *ld; | 115 | int c; |
| 113 | int c = count; | ||
| 114 | 116 | ||
| 115 | if (!to || tty->stopped) | 117 | if (tty->stopped) |
| 116 | return 0; | 118 | return 0; |
| 117 | ld = tty_ldisc_ref(to); | 119 | |
| 118 | 120 | /* This isn't locked but our 8K is quite sloppy so no | |
| 119 | if (ld) { | 121 | big deal */ |
| 120 | c = to->receive_room; | 122 | |
| 121 | if (c > count) | 123 | c = pty_space(to); |
| 122 | c = count; | 124 | if (c > count) |
| 123 | ld->ops->receive_buf(to, buf, NULL, c); | 125 | c = count; |
| 124 | tty_ldisc_deref(ld); | 126 | if (c > 0) { |
| 127 | /* Stuff the data into the input queue of the other end */ | ||
| 128 | c = tty_insert_flip_string(to, buf, c); | ||
| 129 | /* And shovel */ | ||
| 130 | tty_flip_buffer_push(to); | ||
| 131 | tty_wakeup(tty); | ||
| 125 | } | 132 | } |
| 126 | return c; | 133 | return c; |
| 127 | } | 134 | } |
| 128 | 135 | ||
| 136 | /** | ||
| 137 | * pty_write_room - write space | ||
| 138 | * @tty: tty we are writing from | ||
| 139 | * | ||
| 140 | * Report how many bytes the ldisc can send into the queue for | ||
| 141 | * the other device. | ||
| 142 | */ | ||
| 143 | |||
| 129 | static int pty_write_room(struct tty_struct *tty) | 144 | static int pty_write_room(struct tty_struct *tty) |
| 130 | { | 145 | { |
| 131 | struct tty_struct *to = tty->link; | 146 | return pty_space(tty->link); |
| 132 | |||
| 133 | if (!to || tty->stopped) | ||
| 134 | return 0; | ||
| 135 | |||
| 136 | return to->receive_room; | ||
| 137 | } | 147 | } |
| 138 | 148 | ||
| 139 | /* | 149 | /** |
| 140 | * WSH 05/24/97: Modified for asymmetric MASTER/SLAVE behavior | 150 | * pty_chars_in_buffer - characters currently in our tx queue |
| 141 | * The chars_in_buffer() value is used by the ldisc select() function | 151 | * @tty: our tty |
| 142 | * to hold off writing when chars_in_buffer > WAKEUP_CHARS (== 256). | ||
| 143 | * The pty driver chars_in_buffer() Master/Slave must behave differently: | ||
| 144 | * | ||
| 145 | * The Master side needs to allow typed-ahead commands to accumulate | ||
| 146 | * while being canonicalized, so we report "our buffer" as empty until | ||
| 147 | * some threshold is reached, and then report the count. (Any count > | ||
| 148 | * WAKEUP_CHARS is regarded by select() as "full".) To avoid deadlock | ||
| 149 | * the count returned must be 0 if no canonical data is available to be | ||
| 150 | * read. (The N_TTY ldisc.chars_in_buffer now knows this.) | ||
| 151 | * | 152 | * |
| 152 | * The Slave side passes all characters in raw mode to the Master side's | 153 | * Report how much we have in the transmit queue. As everything is |
| 153 | * buffer where they can be read immediately, so in this case we can | 154 | * instantly at the other end this is easy to implement. |
| 154 | * return the true count in the buffer. | ||
| 155 | */ | 155 | */ |
| 156 | |||
| 156 | static int pty_chars_in_buffer(struct tty_struct *tty) | 157 | static int pty_chars_in_buffer(struct tty_struct *tty) |
| 157 | { | 158 | { |
| 158 | struct tty_struct *to = tty->link; | 159 | return 0; |
| 159 | struct tty_ldisc *ld; | ||
| 160 | int count = 0; | ||
| 161 | |||
| 162 | /* We should get the line discipline lock for "tty->link" */ | ||
| 163 | if (!to) | ||
| 164 | return 0; | ||
| 165 | /* We cannot take a sleeping reference here without deadlocking with | ||
| 166 | an ldisc change - but it doesn't really matter */ | ||
| 167 | ld = tty_ldisc_ref(to); | ||
| 168 | if (ld == NULL) | ||
| 169 | return 0; | ||
| 170 | |||
| 171 | /* The ldisc must report 0 if no characters available to be read */ | ||
| 172 | if (ld->ops->chars_in_buffer) | ||
| 173 | count = ld->ops->chars_in_buffer(to); | ||
| 174 | |||
| 175 | tty_ldisc_deref(ld); | ||
| 176 | |||
| 177 | if (tty->driver->subtype == PTY_TYPE_SLAVE) | ||
| 178 | return count; | ||
| 179 | |||
| 180 | /* Master side driver ... if the other side's read buffer is less than | ||
| 181 | * half full, return 0 to allow writers to proceed; otherwise return | ||
| 182 | * the count. This leaves a comfortable margin to avoid overflow, | ||
| 183 | * and still allows half a buffer's worth of typed-ahead commands. | ||
| 184 | */ | ||
| 185 | return (count < N_TTY_BUF_SIZE/2) ? 0 : count; | ||
| 186 | } | 160 | } |
| 187 | 161 | ||
| 188 | /* Set the lock flag on a pty */ | 162 | /* Set the lock flag on a pty */ |
| @@ -202,20 +176,10 @@ static void pty_flush_buffer(struct tty_struct *tty) | |||
| 202 | { | 176 | { |
| 203 | struct tty_struct *to = tty->link; | 177 | struct tty_struct *to = tty->link; |
| 204 | unsigned long flags; | 178 | unsigned long flags; |
| 205 | struct tty_ldisc *ld; | ||
| 206 | 179 | ||
| 207 | if (!to) | 180 | if (!to) |
| 208 | return; | 181 | return; |
| 209 | ld = tty_ldisc_ref(to); | 182 | /* tty_buffer_flush(to); FIXME */ |
| 210 | |||
| 211 | /* The other end is changing discipline */ | ||
| 212 | if (!ld) | ||
| 213 | return; | ||
| 214 | |||
| 215 | if (ld->ops->flush_buffer) | ||
| 216 | to->ldisc->ops->flush_buffer(to); | ||
| 217 | tty_ldisc_deref(ld); | ||
| 218 | |||
| 219 | if (to->packet) { | 183 | if (to->packet) { |
| 220 | spin_lock_irqsave(&tty->ctrl_lock, flags); | 184 | spin_lock_irqsave(&tty->ctrl_lock, flags); |
| 221 | tty->ctrl_status |= TIOCPKT_FLUSHWRITE; | 185 | tty->ctrl_status |= TIOCPKT_FLUSHWRITE; |
