diff options
Diffstat (limited to 'drivers/tty')
| -rw-r--r-- | drivers/tty/hvc/hvc_xen.c | 18 | ||||
| -rw-r--r-- | drivers/tty/n_gsm.c | 5 | ||||
| -rw-r--r-- | drivers/tty/n_hdlc.c | 4 | ||||
| -rw-r--r-- | drivers/tty/n_tty.c | 22 | ||||
| -rw-r--r-- | drivers/tty/pty.c | 5 | ||||
| -rw-r--r-- | drivers/tty/serial/amba-pl011.c | 5 | ||||
| -rw-r--r-- | drivers/tty/serial/earlycon.c | 9 | ||||
| -rw-r--r-- | drivers/tty/serial/omap-serial.c | 2 | ||||
| -rw-r--r-- | drivers/tty/tty_buffer.c | 41 |
9 files changed, 77 insertions, 34 deletions
diff --git a/drivers/tty/hvc/hvc_xen.c b/drivers/tty/hvc/hvc_xen.c index f1e57425e39f..5bab1c684bb1 100644 --- a/drivers/tty/hvc/hvc_xen.c +++ b/drivers/tty/hvc/hvc_xen.c | |||
| @@ -299,11 +299,27 @@ static int xen_initial_domain_console_init(void) | |||
| 299 | return 0; | 299 | return 0; |
| 300 | } | 300 | } |
| 301 | 301 | ||
| 302 | static void xen_console_update_evtchn(struct xencons_info *info) | ||
| 303 | { | ||
| 304 | if (xen_hvm_domain()) { | ||
| 305 | uint64_t v; | ||
| 306 | int err; | ||
| 307 | |||
| 308 | err = hvm_get_parameter(HVM_PARAM_CONSOLE_EVTCHN, &v); | ||
| 309 | if (!err && v) | ||
| 310 | info->evtchn = v; | ||
| 311 | } else | ||
| 312 | info->evtchn = xen_start_info->console.domU.evtchn; | ||
| 313 | } | ||
| 314 | |||
| 302 | void xen_console_resume(void) | 315 | void xen_console_resume(void) |
| 303 | { | 316 | { |
| 304 | struct xencons_info *info = vtermno_to_xencons(HVC_COOKIE); | 317 | struct xencons_info *info = vtermno_to_xencons(HVC_COOKIE); |
| 305 | if (info != NULL && info->irq) | 318 | if (info != NULL && info->irq) { |
| 319 | if (!xen_initial_domain()) | ||
| 320 | xen_console_update_evtchn(info); | ||
| 306 | rebind_evtchn_irq(info->evtchn, info->irq); | 321 | rebind_evtchn_irq(info->evtchn, info->irq); |
| 322 | } | ||
| 307 | } | 323 | } |
| 308 | 324 | ||
| 309 | static void xencons_disconnect_backend(struct xencons_info *info) | 325 | static void xencons_disconnect_backend(struct xencons_info *info) |
diff --git a/drivers/tty/n_gsm.c b/drivers/tty/n_gsm.c index 91abc00aa833..2c34c3249972 100644 --- a/drivers/tty/n_gsm.c +++ b/drivers/tty/n_gsm.c | |||
| @@ -3170,7 +3170,7 @@ static int gsmtty_break_ctl(struct tty_struct *tty, int state) | |||
| 3170 | return gsmtty_modem_update(dlci, encode); | 3170 | return gsmtty_modem_update(dlci, encode); |
| 3171 | } | 3171 | } |
| 3172 | 3172 | ||
| 3173 | static void gsmtty_remove(struct tty_driver *driver, struct tty_struct *tty) | 3173 | static void gsmtty_cleanup(struct tty_struct *tty) |
| 3174 | { | 3174 | { |
| 3175 | struct gsm_dlci *dlci = tty->driver_data; | 3175 | struct gsm_dlci *dlci = tty->driver_data; |
| 3176 | struct gsm_mux *gsm = dlci->gsm; | 3176 | struct gsm_mux *gsm = dlci->gsm; |
| @@ -3178,7 +3178,6 @@ static void gsmtty_remove(struct tty_driver *driver, struct tty_struct *tty) | |||
| 3178 | dlci_put(dlci); | 3178 | dlci_put(dlci); |
| 3179 | dlci_put(gsm->dlci[0]); | 3179 | dlci_put(gsm->dlci[0]); |
| 3180 | mux_put(gsm); | 3180 | mux_put(gsm); |
| 3181 | driver->ttys[tty->index] = NULL; | ||
| 3182 | } | 3181 | } |
| 3183 | 3182 | ||
| 3184 | /* Virtual ttys for the demux */ | 3183 | /* Virtual ttys for the demux */ |
| @@ -3199,7 +3198,7 @@ static const struct tty_operations gsmtty_ops = { | |||
| 3199 | .tiocmget = gsmtty_tiocmget, | 3198 | .tiocmget = gsmtty_tiocmget, |
| 3200 | .tiocmset = gsmtty_tiocmset, | 3199 | .tiocmset = gsmtty_tiocmset, |
| 3201 | .break_ctl = gsmtty_break_ctl, | 3200 | .break_ctl = gsmtty_break_ctl, |
| 3202 | .remove = gsmtty_remove, | 3201 | .cleanup = gsmtty_cleanup, |
| 3203 | }; | 3202 | }; |
| 3204 | 3203 | ||
| 3205 | 3204 | ||
diff --git a/drivers/tty/n_hdlc.c b/drivers/tty/n_hdlc.c index 644ddb841d9f..bbc4ce66c2c1 100644 --- a/drivers/tty/n_hdlc.c +++ b/drivers/tty/n_hdlc.c | |||
| @@ -600,7 +600,7 @@ static ssize_t n_hdlc_tty_read(struct tty_struct *tty, struct file *file, | |||
| 600 | add_wait_queue(&tty->read_wait, &wait); | 600 | add_wait_queue(&tty->read_wait, &wait); |
| 601 | 601 | ||
| 602 | for (;;) { | 602 | for (;;) { |
| 603 | if (test_bit(TTY_OTHER_CLOSED, &tty->flags)) { | 603 | if (test_bit(TTY_OTHER_DONE, &tty->flags)) { |
| 604 | ret = -EIO; | 604 | ret = -EIO; |
| 605 | break; | 605 | break; |
| 606 | } | 606 | } |
| @@ -828,7 +828,7 @@ static unsigned int n_hdlc_tty_poll(struct tty_struct *tty, struct file *filp, | |||
| 828 | /* set bits for operations that won't block */ | 828 | /* set bits for operations that won't block */ |
| 829 | if (n_hdlc->rx_buf_list.head) | 829 | if (n_hdlc->rx_buf_list.head) |
| 830 | mask |= POLLIN | POLLRDNORM; /* readable */ | 830 | mask |= POLLIN | POLLRDNORM; /* readable */ |
| 831 | if (test_bit(TTY_OTHER_CLOSED, &tty->flags)) | 831 | if (test_bit(TTY_OTHER_DONE, &tty->flags)) |
| 832 | mask |= POLLHUP; | 832 | mask |= POLLHUP; |
| 833 | if (tty_hung_up_p(filp)) | 833 | if (tty_hung_up_p(filp)) |
| 834 | mask |= POLLHUP; | 834 | mask |= POLLHUP; |
diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index cf6e0f2e1331..cc57a3a6b02b 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c | |||
| @@ -1949,6 +1949,18 @@ static inline int input_available_p(struct tty_struct *tty, int poll) | |||
| 1949 | return ldata->commit_head - ldata->read_tail >= amt; | 1949 | return ldata->commit_head - ldata->read_tail >= amt; |
| 1950 | } | 1950 | } |
| 1951 | 1951 | ||
| 1952 | static inline int check_other_done(struct tty_struct *tty) | ||
| 1953 | { | ||
| 1954 | int done = test_bit(TTY_OTHER_DONE, &tty->flags); | ||
| 1955 | if (done) { | ||
| 1956 | /* paired with cmpxchg() in check_other_closed(); ensures | ||
| 1957 | * read buffer head index is not stale | ||
| 1958 | */ | ||
| 1959 | smp_mb__after_atomic(); | ||
| 1960 | } | ||
| 1961 | return done; | ||
| 1962 | } | ||
| 1963 | |||
| 1952 | /** | 1964 | /** |
| 1953 | * copy_from_read_buf - copy read data directly | 1965 | * copy_from_read_buf - copy read data directly |
| 1954 | * @tty: terminal device | 1966 | * @tty: terminal device |
| @@ -2167,7 +2179,7 @@ static ssize_t n_tty_read(struct tty_struct *tty, struct file *file, | |||
| 2167 | struct n_tty_data *ldata = tty->disc_data; | 2179 | struct n_tty_data *ldata = tty->disc_data; |
| 2168 | unsigned char __user *b = buf; | 2180 | unsigned char __user *b = buf; |
| 2169 | DEFINE_WAIT_FUNC(wait, woken_wake_function); | 2181 | DEFINE_WAIT_FUNC(wait, woken_wake_function); |
| 2170 | int c; | 2182 | int c, done; |
| 2171 | int minimum, time; | 2183 | int minimum, time; |
| 2172 | ssize_t retval = 0; | 2184 | ssize_t retval = 0; |
| 2173 | long timeout; | 2185 | long timeout; |
| @@ -2235,8 +2247,10 @@ static ssize_t n_tty_read(struct tty_struct *tty, struct file *file, | |||
| 2235 | ((minimum - (b - buf)) >= 1)) | 2247 | ((minimum - (b - buf)) >= 1)) |
| 2236 | ldata->minimum_to_wake = (minimum - (b - buf)); | 2248 | ldata->minimum_to_wake = (minimum - (b - buf)); |
| 2237 | 2249 | ||
| 2250 | done = check_other_done(tty); | ||
| 2251 | |||
| 2238 | if (!input_available_p(tty, 0)) { | 2252 | if (!input_available_p(tty, 0)) { |
| 2239 | if (test_bit(TTY_OTHER_CLOSED, &tty->flags)) { | 2253 | if (done) { |
| 2240 | retval = -EIO; | 2254 | retval = -EIO; |
| 2241 | break; | 2255 | break; |
| 2242 | } | 2256 | } |
| @@ -2443,12 +2457,12 @@ static unsigned int n_tty_poll(struct tty_struct *tty, struct file *file, | |||
| 2443 | 2457 | ||
| 2444 | poll_wait(file, &tty->read_wait, wait); | 2458 | poll_wait(file, &tty->read_wait, wait); |
| 2445 | poll_wait(file, &tty->write_wait, wait); | 2459 | poll_wait(file, &tty->write_wait, wait); |
| 2460 | if (check_other_done(tty)) | ||
| 2461 | mask |= POLLHUP; | ||
| 2446 | if (input_available_p(tty, 1)) | 2462 | if (input_available_p(tty, 1)) |
| 2447 | mask |= POLLIN | POLLRDNORM; | 2463 | mask |= POLLIN | POLLRDNORM; |
| 2448 | if (tty->packet && tty->link->ctrl_status) | 2464 | if (tty->packet && tty->link->ctrl_status) |
| 2449 | mask |= POLLPRI | POLLIN | POLLRDNORM; | 2465 | mask |= POLLPRI | POLLIN | POLLRDNORM; |
| 2450 | if (test_bit(TTY_OTHER_CLOSED, &tty->flags)) | ||
| 2451 | mask |= POLLHUP; | ||
| 2452 | if (tty_hung_up_p(file)) | 2466 | if (tty_hung_up_p(file)) |
| 2453 | mask |= POLLHUP; | 2467 | mask |= POLLHUP; |
| 2454 | if (!(mask & (POLLHUP | POLLIN | POLLRDNORM))) { | 2468 | if (!(mask & (POLLHUP | POLLIN | POLLRDNORM))) { |
diff --git a/drivers/tty/pty.c b/drivers/tty/pty.c index e72ee629cead..4d5e8409769c 100644 --- a/drivers/tty/pty.c +++ b/drivers/tty/pty.c | |||
| @@ -53,9 +53,8 @@ static void pty_close(struct tty_struct *tty, struct file *filp) | |||
| 53 | /* Review - krefs on tty_link ?? */ | 53 | /* Review - krefs on tty_link ?? */ |
| 54 | if (!tty->link) | 54 | if (!tty->link) |
| 55 | return; | 55 | return; |
| 56 | tty_flush_to_ldisc(tty->link); | ||
| 57 | set_bit(TTY_OTHER_CLOSED, &tty->link->flags); | 56 | set_bit(TTY_OTHER_CLOSED, &tty->link->flags); |
| 58 | wake_up_interruptible(&tty->link->read_wait); | 57 | tty_flip_buffer_push(tty->link->port); |
| 59 | wake_up_interruptible(&tty->link->write_wait); | 58 | wake_up_interruptible(&tty->link->write_wait); |
| 60 | if (tty->driver->subtype == PTY_TYPE_MASTER) { | 59 | if (tty->driver->subtype == PTY_TYPE_MASTER) { |
| 61 | set_bit(TTY_OTHER_CLOSED, &tty->flags); | 60 | set_bit(TTY_OTHER_CLOSED, &tty->flags); |
| @@ -243,7 +242,9 @@ static int pty_open(struct tty_struct *tty, struct file *filp) | |||
| 243 | goto out; | 242 | goto out; |
| 244 | 243 | ||
| 245 | clear_bit(TTY_IO_ERROR, &tty->flags); | 244 | clear_bit(TTY_IO_ERROR, &tty->flags); |
| 245 | /* TTY_OTHER_CLOSED must be cleared before TTY_OTHER_DONE */ | ||
| 246 | clear_bit(TTY_OTHER_CLOSED, &tty->link->flags); | 246 | clear_bit(TTY_OTHER_CLOSED, &tty->link->flags); |
| 247 | clear_bit(TTY_OTHER_DONE, &tty->link->flags); | ||
| 247 | set_bit(TTY_THROTTLED, &tty->flags); | 248 | set_bit(TTY_THROTTLED, &tty->flags); |
| 248 | return 0; | 249 | return 0; |
| 249 | 250 | ||
diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c index 5a4e9d579585..6f5a0720a8c8 100644 --- a/drivers/tty/serial/amba-pl011.c +++ b/drivers/tty/serial/amba-pl011.c | |||
| @@ -1639,6 +1639,9 @@ static int pl011_startup(struct uart_port *port) | |||
| 1639 | 1639 | ||
| 1640 | writew(uap->vendor->ifls, uap->port.membase + UART011_IFLS); | 1640 | writew(uap->vendor->ifls, uap->port.membase + UART011_IFLS); |
| 1641 | 1641 | ||
| 1642 | /* Assume that TX IRQ doesn't work until we see one: */ | ||
| 1643 | uap->tx_irq_seen = 0; | ||
| 1644 | |||
| 1642 | spin_lock_irq(&uap->port.lock); | 1645 | spin_lock_irq(&uap->port.lock); |
| 1643 | 1646 | ||
| 1644 | /* restore RTS and DTR */ | 1647 | /* restore RTS and DTR */ |
| @@ -1702,7 +1705,7 @@ static void pl011_shutdown(struct uart_port *port) | |||
| 1702 | spin_lock_irq(&uap->port.lock); | 1705 | spin_lock_irq(&uap->port.lock); |
| 1703 | uap->im = 0; | 1706 | uap->im = 0; |
| 1704 | writew(uap->im, uap->port.membase + UART011_IMSC); | 1707 | writew(uap->im, uap->port.membase + UART011_IMSC); |
| 1705 | writew(0xffff & ~UART011_TXIS, uap->port.membase + UART011_ICR); | 1708 | writew(0xffff, uap->port.membase + UART011_ICR); |
| 1706 | spin_unlock_irq(&uap->port.lock); | 1709 | spin_unlock_irq(&uap->port.lock); |
| 1707 | 1710 | ||
| 1708 | pl011_dma_shutdown(uap); | 1711 | pl011_dma_shutdown(uap); |
diff --git a/drivers/tty/serial/earlycon.c b/drivers/tty/serial/earlycon.c index 5fdc9f3ecd64..6dc471e30e79 100644 --- a/drivers/tty/serial/earlycon.c +++ b/drivers/tty/serial/earlycon.c | |||
| @@ -187,13 +187,8 @@ static int __init param_setup_earlycon(char *buf) | |||
| 187 | return 0; | 187 | return 0; |
| 188 | 188 | ||
| 189 | err = setup_earlycon(buf); | 189 | err = setup_earlycon(buf); |
| 190 | if (err == -ENOENT) { | 190 | if (err == -ENOENT || err == -EALREADY) |
| 191 | pr_warn("no match for %s\n", buf); | 191 | return 0; |
| 192 | err = 0; | ||
| 193 | } else if (err == -EALREADY) { | ||
| 194 | pr_warn("already registered\n"); | ||
| 195 | err = 0; | ||
| 196 | } | ||
| 197 | return err; | 192 | return err; |
| 198 | } | 193 | } |
| 199 | early_param("earlycon", param_setup_earlycon); | 194 | early_param("earlycon", param_setup_earlycon); |
diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c index 211479aa34bb..7f49172ccd86 100644 --- a/drivers/tty/serial/omap-serial.c +++ b/drivers/tty/serial/omap-serial.c | |||
| @@ -1735,6 +1735,8 @@ static int serial_omap_probe(struct platform_device *pdev) | |||
| 1735 | err_add_port: | 1735 | err_add_port: |
| 1736 | pm_runtime_put(&pdev->dev); | 1736 | pm_runtime_put(&pdev->dev); |
| 1737 | pm_runtime_disable(&pdev->dev); | 1737 | pm_runtime_disable(&pdev->dev); |
| 1738 | pm_qos_remove_request(&up->pm_qos_request); | ||
| 1739 | device_init_wakeup(up->dev, false); | ||
| 1738 | err_rs485: | 1740 | err_rs485: |
| 1739 | err_port_line: | 1741 | err_port_line: |
| 1740 | return ret; | 1742 | return ret; |
diff --git a/drivers/tty/tty_buffer.c b/drivers/tty/tty_buffer.c index 75661641f5fe..2f78b77f0f81 100644 --- a/drivers/tty/tty_buffer.c +++ b/drivers/tty/tty_buffer.c | |||
| @@ -37,6 +37,28 @@ | |||
| 37 | 37 | ||
| 38 | #define TTY_BUFFER_PAGE (((PAGE_SIZE - sizeof(struct tty_buffer)) / 2) & ~0xFF) | 38 | #define TTY_BUFFER_PAGE (((PAGE_SIZE - sizeof(struct tty_buffer)) / 2) & ~0xFF) |
| 39 | 39 | ||
| 40 | /* | ||
| 41 | * If all tty flip buffers have been processed by flush_to_ldisc() or | ||
| 42 | * dropped by tty_buffer_flush(), check if the linked pty has been closed. | ||
| 43 | * If so, wake the reader/poll to process | ||
| 44 | */ | ||
| 45 | static inline void check_other_closed(struct tty_struct *tty) | ||
| 46 | { | ||
| 47 | unsigned long flags, old; | ||
| 48 | |||
| 49 | /* transition from TTY_OTHER_CLOSED => TTY_OTHER_DONE must be atomic */ | ||
| 50 | for (flags = ACCESS_ONCE(tty->flags); | ||
| 51 | test_bit(TTY_OTHER_CLOSED, &flags); | ||
| 52 | ) { | ||
| 53 | old = flags; | ||
| 54 | __set_bit(TTY_OTHER_DONE, &flags); | ||
| 55 | flags = cmpxchg(&tty->flags, old, flags); | ||
| 56 | if (old == flags) { | ||
| 57 | wake_up_interruptible(&tty->read_wait); | ||
| 58 | break; | ||
| 59 | } | ||
| 60 | } | ||
| 61 | } | ||
| 40 | 62 | ||
| 41 | /** | 63 | /** |
| 42 | * tty_buffer_lock_exclusive - gain exclusive access to buffer | 64 | * tty_buffer_lock_exclusive - gain exclusive access to buffer |
| @@ -229,6 +251,8 @@ void tty_buffer_flush(struct tty_struct *tty, struct tty_ldisc *ld) | |||
| 229 | if (ld && ld->ops->flush_buffer) | 251 | if (ld && ld->ops->flush_buffer) |
| 230 | ld->ops->flush_buffer(tty); | 252 | ld->ops->flush_buffer(tty); |
| 231 | 253 | ||
| 254 | check_other_closed(tty); | ||
| 255 | |||
| 232 | atomic_dec(&buf->priority); | 256 | atomic_dec(&buf->priority); |
| 233 | mutex_unlock(&buf->lock); | 257 | mutex_unlock(&buf->lock); |
| 234 | } | 258 | } |
| @@ -471,8 +495,10 @@ static void flush_to_ldisc(struct work_struct *work) | |||
| 471 | smp_rmb(); | 495 | smp_rmb(); |
| 472 | count = head->commit - head->read; | 496 | count = head->commit - head->read; |
| 473 | if (!count) { | 497 | if (!count) { |
| 474 | if (next == NULL) | 498 | if (next == NULL) { |
| 499 | check_other_closed(tty); | ||
| 475 | break; | 500 | break; |
| 501 | } | ||
| 476 | buf->head = next; | 502 | buf->head = next; |
| 477 | tty_buffer_free(port, head); | 503 | tty_buffer_free(port, head); |
| 478 | continue; | 504 | continue; |
| @@ -489,19 +515,6 @@ static void flush_to_ldisc(struct work_struct *work) | |||
| 489 | } | 515 | } |
| 490 | 516 | ||
| 491 | /** | 517 | /** |
| 492 | * tty_flush_to_ldisc | ||
| 493 | * @tty: tty to push | ||
| 494 | * | ||
| 495 | * Push the terminal flip buffers to the line discipline. | ||
| 496 | * | ||
| 497 | * Must not be called from IRQ context. | ||
| 498 | */ | ||
| 499 | void tty_flush_to_ldisc(struct tty_struct *tty) | ||
| 500 | { | ||
| 501 | flush_work(&tty->port->buf.work); | ||
| 502 | } | ||
| 503 | |||
| 504 | /** | ||
| 505 | * tty_flip_buffer_push - terminal | 518 | * tty_flip_buffer_push - terminal |
| 506 | * @port: tty port to push | 519 | * @port: tty port to push |
| 507 | * | 520 | * |
