diff options
Diffstat (limited to 'drivers/tty/n_tty.c')
-rw-r--r-- | drivers/tty/n_tty.c | 81 |
1 files changed, 37 insertions, 44 deletions
diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index 26f097f60b10..d2b496750d59 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c | |||
@@ -321,7 +321,8 @@ static void n_tty_check_unthrottle(struct tty_struct *tty) | |||
321 | 321 | ||
322 | static inline void put_tty_queue(unsigned char c, struct n_tty_data *ldata) | 322 | static inline void put_tty_queue(unsigned char c, struct n_tty_data *ldata) |
323 | { | 323 | { |
324 | *read_buf_addr(ldata, ldata->read_head++) = c; | 324 | *read_buf_addr(ldata, ldata->read_head) = c; |
325 | ldata->read_head++; | ||
325 | } | 326 | } |
326 | 327 | ||
327 | /** | 328 | /** |
@@ -351,13 +352,13 @@ static void n_tty_packet_mode_flush(struct tty_struct *tty) | |||
351 | { | 352 | { |
352 | unsigned long flags; | 353 | unsigned long flags; |
353 | 354 | ||
354 | spin_lock_irqsave(&tty->ctrl_lock, flags); | ||
355 | if (tty->link->packet) { | 355 | if (tty->link->packet) { |
356 | spin_lock_irqsave(&tty->ctrl_lock, flags); | ||
356 | tty->ctrl_status |= TIOCPKT_FLUSHREAD; | 357 | tty->ctrl_status |= TIOCPKT_FLUSHREAD; |
358 | spin_unlock_irqrestore(&tty->ctrl_lock, flags); | ||
357 | if (waitqueue_active(&tty->link->read_wait)) | 359 | if (waitqueue_active(&tty->link->read_wait)) |
358 | wake_up_interruptible(&tty->link->read_wait); | 360 | wake_up_interruptible(&tty->link->read_wait); |
359 | } | 361 | } |
360 | spin_unlock_irqrestore(&tty->ctrl_lock, flags); | ||
361 | } | 362 | } |
362 | 363 | ||
363 | /** | 364 | /** |
@@ -2128,7 +2129,6 @@ static ssize_t n_tty_read(struct tty_struct *tty, struct file *file, | |||
2128 | int minimum, time; | 2129 | int minimum, time; |
2129 | ssize_t retval = 0; | 2130 | ssize_t retval = 0; |
2130 | long timeout; | 2131 | long timeout; |
2131 | unsigned long flags; | ||
2132 | int packet; | 2132 | int packet; |
2133 | 2133 | ||
2134 | c = job_control(tty, file); | 2134 | c = job_control(tty, file); |
@@ -2174,10 +2174,10 @@ static ssize_t n_tty_read(struct tty_struct *tty, struct file *file, | |||
2174 | unsigned char cs; | 2174 | unsigned char cs; |
2175 | if (b != buf) | 2175 | if (b != buf) |
2176 | break; | 2176 | break; |
2177 | spin_lock_irqsave(&tty->link->ctrl_lock, flags); | 2177 | spin_lock_irq(&tty->link->ctrl_lock); |
2178 | cs = tty->link->ctrl_status; | 2178 | cs = tty->link->ctrl_status; |
2179 | tty->link->ctrl_status = 0; | 2179 | tty->link->ctrl_status = 0; |
2180 | spin_unlock_irqrestore(&tty->link->ctrl_lock, flags); | 2180 | spin_unlock_irq(&tty->link->ctrl_lock); |
2181 | if (tty_put_user(tty, cs, b++)) { | 2181 | if (tty_put_user(tty, cs, b++)) { |
2182 | retval = -EFAULT; | 2182 | retval = -EFAULT; |
2183 | b--; | 2183 | b--; |
@@ -2193,45 +2193,29 @@ static ssize_t n_tty_read(struct tty_struct *tty, struct file *file, | |||
2193 | 2193 | ||
2194 | if (!input_available_p(tty, 0)) { | 2194 | if (!input_available_p(tty, 0)) { |
2195 | if (test_bit(TTY_OTHER_CLOSED, &tty->flags)) { | 2195 | if (test_bit(TTY_OTHER_CLOSED, &tty->flags)) { |
2196 | up_read(&tty->termios_rwsem); | 2196 | retval = -EIO; |
2197 | tty_flush_to_ldisc(tty); | 2197 | break; |
2198 | down_read(&tty->termios_rwsem); | ||
2199 | if (!input_available_p(tty, 0)) { | ||
2200 | retval = -EIO; | ||
2201 | break; | ||
2202 | } | ||
2203 | } else { | ||
2204 | if (tty_hung_up_p(file)) | ||
2205 | break; | ||
2206 | if (!timeout) | ||
2207 | break; | ||
2208 | if (file->f_flags & O_NONBLOCK) { | ||
2209 | retval = -EAGAIN; | ||
2210 | break; | ||
2211 | } | ||
2212 | if (signal_pending(current)) { | ||
2213 | retval = -ERESTARTSYS; | ||
2214 | break; | ||
2215 | } | ||
2216 | n_tty_set_room(tty); | ||
2217 | up_read(&tty->termios_rwsem); | ||
2218 | |||
2219 | timeout = wait_woken(&wait, TASK_INTERRUPTIBLE, | ||
2220 | timeout); | ||
2221 | |||
2222 | down_read(&tty->termios_rwsem); | ||
2223 | continue; | ||
2224 | } | 2198 | } |
2225 | } | 2199 | if (tty_hung_up_p(file)) |
2226 | 2200 | break; | |
2227 | /* Deal with packet mode. */ | 2201 | if (!timeout) |
2228 | if (packet && b == buf) { | 2202 | break; |
2229 | if (tty_put_user(tty, TIOCPKT_DATA, b++)) { | 2203 | if (file->f_flags & O_NONBLOCK) { |
2230 | retval = -EFAULT; | 2204 | retval = -EAGAIN; |
2231 | b--; | ||
2232 | break; | 2205 | break; |
2233 | } | 2206 | } |
2234 | nr--; | 2207 | if (signal_pending(current)) { |
2208 | retval = -ERESTARTSYS; | ||
2209 | break; | ||
2210 | } | ||
2211 | n_tty_set_room(tty); | ||
2212 | up_read(&tty->termios_rwsem); | ||
2213 | |||
2214 | timeout = wait_woken(&wait, TASK_INTERRUPTIBLE, | ||
2215 | timeout); | ||
2216 | |||
2217 | down_read(&tty->termios_rwsem); | ||
2218 | continue; | ||
2235 | } | 2219 | } |
2236 | 2220 | ||
2237 | if (ldata->icanon && !L_EXTPROC(tty)) { | 2221 | if (ldata->icanon && !L_EXTPROC(tty)) { |
@@ -2243,8 +2227,17 @@ static ssize_t n_tty_read(struct tty_struct *tty, struct file *file, | |||
2243 | break; | 2227 | break; |
2244 | } else { | 2228 | } else { |
2245 | int uncopied; | 2229 | int uncopied; |
2246 | /* The copy function takes the read lock and handles | 2230 | |
2247 | locking internally for this case */ | 2231 | /* Deal with packet mode. */ |
2232 | if (packet && b == buf) { | ||
2233 | if (tty_put_user(tty, TIOCPKT_DATA, b++)) { | ||
2234 | retval = -EFAULT; | ||
2235 | b--; | ||
2236 | break; | ||
2237 | } | ||
2238 | nr--; | ||
2239 | } | ||
2240 | |||
2248 | uncopied = copy_from_read_buf(tty, &b, &nr); | 2241 | uncopied = copy_from_read_buf(tty, &b, &nr); |
2249 | uncopied += copy_from_read_buf(tty, &b, &nr); | 2242 | uncopied += copy_from_read_buf(tty, &b, &nr); |
2250 | if (uncopied) { | 2243 | if (uncopied) { |