diff options
author | Linus Torvalds | 2019-01-14 05:47:48 +1200 |
---|---|---|
committer | Linus Torvalds | 2019-01-14 05:47:48 +1200 |
commit | 437e878a6c48028273e4b06be7e09d235b189e62 (patch) | |
tree | fb82649e83fe4d0489c2c51207927e66f6c4b54e | |
parent | 1dd8a3f6c619723ab442d6a27247d2f2153f3b11 (diff) | |
parent | d3736d82e8169768218ee0ef68718875918091a0 (diff) |
Merge tag 'tty-5.0-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty
Pull tty/serial fixes from Greg KH:
"Here are 2 tty and serial fixes for 5.0-rc2 that resolve some reported
issues.
The first is a simple serial driver fix for a regression that showed
up in 5.0-rc1. The second one resolves a number of reported issues
with the recent tty locking fixes that went into 5.0-rc1. Lots of
people have tested the second one and say it resolves their issues.
Both have been in linux-next with no reported issues"
* tag 'tty-5.0-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty:
tty: Don't hold ldisc lock in tty_reopen() if ldisc present
serial: lantiq: Do not swap register read/writes
-rw-r--r-- | drivers/tty/serial/lantiq.c | 36 | ||||
-rw-r--r-- | drivers/tty/tty_io.c | 20 |
2 files changed, 32 insertions, 24 deletions
diff --git a/drivers/tty/serial/lantiq.c b/drivers/tty/serial/lantiq.c index e052b69ceb98..9de9f0f239a1 100644 --- a/drivers/tty/serial/lantiq.c +++ b/drivers/tty/serial/lantiq.c @@ -114,9 +114,9 @@ struct ltq_uart_port { static inline void asc_update_bits(u32 clear, u32 set, void __iomem *reg) { - u32 tmp = readl(reg); + u32 tmp = __raw_readl(reg); - writel((tmp & ~clear) | set, reg); + __raw_writel((tmp & ~clear) | set, reg); } static inline struct @@ -144,7 +144,7 @@ lqasc_start_tx(struct uart_port *port) static void lqasc_stop_rx(struct uart_port *port) { - writel(ASCWHBSTATE_CLRREN, port->membase + LTQ_ASC_WHBSTATE); + __raw_writel(ASCWHBSTATE_CLRREN, port->membase + LTQ_ASC_WHBSTATE); } static int @@ -153,11 +153,12 @@ lqasc_rx_chars(struct uart_port *port) struct tty_port *tport = &port->state->port; unsigned int ch = 0, rsr = 0, fifocnt; - fifocnt = readl(port->membase + LTQ_ASC_FSTAT) & ASCFSTAT_RXFFLMASK; + fifocnt = __raw_readl(port->membase + LTQ_ASC_FSTAT) & + ASCFSTAT_RXFFLMASK; while (fifocnt--) { u8 flag = TTY_NORMAL; ch = readb(port->membase + LTQ_ASC_RBUF); - rsr = (readl(port->membase + LTQ_ASC_STATE) + rsr = (__raw_readl(port->membase + LTQ_ASC_STATE) & ASCSTATE_ANY) | UART_DUMMY_UER_RX; tty_flip_buffer_push(tport); port->icount.rx++; @@ -217,7 +218,7 @@ lqasc_tx_chars(struct uart_port *port) return; } - while (((readl(port->membase + LTQ_ASC_FSTAT) & + while (((__raw_readl(port->membase + LTQ_ASC_FSTAT) & ASCFSTAT_TXFREEMASK) >> ASCFSTAT_TXFREEOFF) != 0) { if (port->x_char) { writeb(port->x_char, port->membase + LTQ_ASC_TBUF); @@ -245,7 +246,7 @@ lqasc_tx_int(int irq, void *_port) unsigned long flags; struct uart_port *port = (struct uart_port *)_port; spin_lock_irqsave(<q_asc_lock, flags); - writel(ASC_IRNCR_TIR, port->membase + LTQ_ASC_IRNCR); + __raw_writel(ASC_IRNCR_TIR, port->membase + LTQ_ASC_IRNCR); spin_unlock_irqrestore(<q_asc_lock, flags); lqasc_start_tx(port); return IRQ_HANDLED; @@ -270,7 +271,7 @@ lqasc_rx_int(int irq, void *_port) unsigned long flags; struct uart_port *port = (struct uart_port *)_port; spin_lock_irqsave(<q_asc_lock, flags); - writel(ASC_IRNCR_RIR, port->membase + LTQ_ASC_IRNCR); + __raw_writel(ASC_IRNCR_RIR, port->membase + LTQ_ASC_IRNCR); lqasc_rx_chars(port); spin_unlock_irqrestore(<q_asc_lock, flags); return IRQ_HANDLED; @@ -280,7 +281,8 @@ static unsigned int lqasc_tx_empty(struct uart_port *port) { int status; - status = readl(port->membase + LTQ_ASC_FSTAT) & ASCFSTAT_TXFFLMASK; + status = __raw_readl(port->membase + LTQ_ASC_FSTAT) & + ASCFSTAT_TXFFLMASK; return status ? 0 : TIOCSER_TEMT; } @@ -313,12 +315,12 @@ lqasc_startup(struct uart_port *port) asc_update_bits(ASCCLC_DISS | ASCCLC_RMCMASK, (1 << ASCCLC_RMCOFFSET), port->membase + LTQ_ASC_CLC); - writel(0, port->membase + LTQ_ASC_PISEL); - writel( + __raw_writel(0, port->membase + LTQ_ASC_PISEL); + __raw_writel( ((TXFIFO_FL << ASCTXFCON_TXFITLOFF) & ASCTXFCON_TXFITLMASK) | ASCTXFCON_TXFEN | ASCTXFCON_TXFFLU, port->membase + LTQ_ASC_TXFCON); - writel( + __raw_writel( ((RXFIFO_FL << ASCRXFCON_RXFITLOFF) & ASCRXFCON_RXFITLMASK) | ASCRXFCON_RXFEN | ASCRXFCON_RXFFLU, port->membase + LTQ_ASC_RXFCON); @@ -350,7 +352,7 @@ lqasc_startup(struct uart_port *port) goto err2; } - writel(ASC_IRNREN_RX | ASC_IRNREN_ERR | ASC_IRNREN_TX, + __raw_writel(ASC_IRNREN_RX | ASC_IRNREN_ERR | ASC_IRNREN_TX, port->membase + LTQ_ASC_IRNREN); return 0; @@ -369,7 +371,7 @@ lqasc_shutdown(struct uart_port *port) free_irq(ltq_port->rx_irq, port); free_irq(ltq_port->err_irq, port); - writel(0, port->membase + LTQ_ASC_CON); + __raw_writel(0, port->membase + LTQ_ASC_CON); asc_update_bits(ASCRXFCON_RXFEN, ASCRXFCON_RXFFLU, port->membase + LTQ_ASC_RXFCON); asc_update_bits(ASCTXFCON_TXFEN, ASCTXFCON_TXFFLU, @@ -461,13 +463,13 @@ lqasc_set_termios(struct uart_port *port, asc_update_bits(ASCCON_BRS, 0, port->membase + LTQ_ASC_CON); /* now we can write the new baudrate into the register */ - writel(divisor, port->membase + LTQ_ASC_BG); + __raw_writel(divisor, port->membase + LTQ_ASC_BG); /* turn the baudrate generator back on */ asc_update_bits(0, ASCCON_R, port->membase + LTQ_ASC_CON); /* enable rx */ - writel(ASCWHBSTATE_SETREN, port->membase + LTQ_ASC_WHBSTATE); + __raw_writel(ASCWHBSTATE_SETREN, port->membase + LTQ_ASC_WHBSTATE); spin_unlock_irqrestore(<q_asc_lock, flags); @@ -578,7 +580,7 @@ lqasc_console_putchar(struct uart_port *port, int ch) return; do { - fifofree = (readl(port->membase + LTQ_ASC_FSTAT) + fifofree = (__raw_readl(port->membase + LTQ_ASC_FSTAT) & ASCFSTAT_TXFREEMASK) >> ASCFSTAT_TXFREEOFF; } while (fifofree == 0); writeb(ch, port->membase + LTQ_ASC_TBUF); diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index bfe9ad85b362..23c6fd238422 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c @@ -1256,7 +1256,8 @@ static void tty_driver_remove_tty(struct tty_driver *driver, struct tty_struct * static int tty_reopen(struct tty_struct *tty) { struct tty_driver *driver = tty->driver; - int retval; + struct tty_ldisc *ld; + int retval = 0; if (driver->type == TTY_DRIVER_TYPE_PTY && driver->subtype == PTY_TYPE_MASTER) @@ -1268,13 +1269,18 @@ static int tty_reopen(struct tty_struct *tty) if (test_bit(TTY_EXCLUSIVE, &tty->flags) && !capable(CAP_SYS_ADMIN)) return -EBUSY; - retval = tty_ldisc_lock(tty, 5 * HZ); - if (retval) - return retval; + ld = tty_ldisc_ref_wait(tty); + if (ld) { + tty_ldisc_deref(ld); + } else { + retval = tty_ldisc_lock(tty, 5 * HZ); + if (retval) + return retval; - if (!tty->ldisc) - retval = tty_ldisc_reinit(tty, tty->termios.c_line); - tty_ldisc_unlock(tty); + if (!tty->ldisc) + retval = tty_ldisc_reinit(tty, tty->termios.c_line); + tty_ldisc_unlock(tty); + } if (retval == 0) tty->count++; |