Commit 437e878a authored by Linus Torvalds's avatar Linus Torvalds

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
parents 1dd8a3f6 d3736d82
...@@ -114,9 +114,9 @@ struct ltq_uart_port { ...@@ -114,9 +114,9 @@ struct ltq_uart_port {
static inline void asc_update_bits(u32 clear, u32 set, void __iomem *reg) 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 static inline struct
...@@ -144,7 +144,7 @@ lqasc_start_tx(struct uart_port *port) ...@@ -144,7 +144,7 @@ lqasc_start_tx(struct uart_port *port)
static void static void
lqasc_stop_rx(struct uart_port *port) 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 static int
...@@ -153,11 +153,12 @@ lqasc_rx_chars(struct uart_port *port) ...@@ -153,11 +153,12 @@ lqasc_rx_chars(struct uart_port *port)
struct tty_port *tport = &port->state->port; struct tty_port *tport = &port->state->port;
unsigned int ch = 0, rsr = 0, fifocnt; 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--) { while (fifocnt--) {
u8 flag = TTY_NORMAL; u8 flag = TTY_NORMAL;
ch = readb(port->membase + LTQ_ASC_RBUF); 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; & ASCSTATE_ANY) | UART_DUMMY_UER_RX;
tty_flip_buffer_push(tport); tty_flip_buffer_push(tport);
port->icount.rx++; port->icount.rx++;
...@@ -217,7 +218,7 @@ lqasc_tx_chars(struct uart_port *port) ...@@ -217,7 +218,7 @@ lqasc_tx_chars(struct uart_port *port)
return; return;
} }
while (((readl(port->membase + LTQ_ASC_FSTAT) & while (((__raw_readl(port->membase + LTQ_ASC_FSTAT) &
ASCFSTAT_TXFREEMASK) >> ASCFSTAT_TXFREEOFF) != 0) { ASCFSTAT_TXFREEMASK) >> ASCFSTAT_TXFREEOFF) != 0) {
if (port->x_char) { if (port->x_char) {
writeb(port->x_char, port->membase + LTQ_ASC_TBUF); writeb(port->x_char, port->membase + LTQ_ASC_TBUF);
...@@ -245,7 +246,7 @@ lqasc_tx_int(int irq, void *_port) ...@@ -245,7 +246,7 @@ lqasc_tx_int(int irq, void *_port)
unsigned long flags; unsigned long flags;
struct uart_port *port = (struct uart_port *)_port; struct uart_port *port = (struct uart_port *)_port;
spin_lock_irqsave(&ltq_asc_lock, flags); spin_lock_irqsave(&ltq_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(&ltq_asc_lock, flags); spin_unlock_irqrestore(&ltq_asc_lock, flags);
lqasc_start_tx(port); lqasc_start_tx(port);
return IRQ_HANDLED; return IRQ_HANDLED;
...@@ -270,7 +271,7 @@ lqasc_rx_int(int irq, void *_port) ...@@ -270,7 +271,7 @@ lqasc_rx_int(int irq, void *_port)
unsigned long flags; unsigned long flags;
struct uart_port *port = (struct uart_port *)_port; struct uart_port *port = (struct uart_port *)_port;
spin_lock_irqsave(&ltq_asc_lock, flags); spin_lock_irqsave(&ltq_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); lqasc_rx_chars(port);
spin_unlock_irqrestore(&ltq_asc_lock, flags); spin_unlock_irqrestore(&ltq_asc_lock, flags);
return IRQ_HANDLED; return IRQ_HANDLED;
...@@ -280,7 +281,8 @@ static unsigned int ...@@ -280,7 +281,8 @@ static unsigned int
lqasc_tx_empty(struct uart_port *port) lqasc_tx_empty(struct uart_port *port)
{ {
int status; 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; return status ? 0 : TIOCSER_TEMT;
} }
...@@ -313,12 +315,12 @@ lqasc_startup(struct uart_port *port) ...@@ -313,12 +315,12 @@ lqasc_startup(struct uart_port *port)
asc_update_bits(ASCCLC_DISS | ASCCLC_RMCMASK, (1 << ASCCLC_RMCOFFSET), asc_update_bits(ASCCLC_DISS | ASCCLC_RMCMASK, (1 << ASCCLC_RMCOFFSET),
port->membase + LTQ_ASC_CLC); port->membase + LTQ_ASC_CLC);
writel(0, port->membase + LTQ_ASC_PISEL); __raw_writel(0, port->membase + LTQ_ASC_PISEL);
writel( __raw_writel(
((TXFIFO_FL << ASCTXFCON_TXFITLOFF) & ASCTXFCON_TXFITLMASK) | ((TXFIFO_FL << ASCTXFCON_TXFITLOFF) & ASCTXFCON_TXFITLMASK) |
ASCTXFCON_TXFEN | ASCTXFCON_TXFFLU, ASCTXFCON_TXFEN | ASCTXFCON_TXFFLU,
port->membase + LTQ_ASC_TXFCON); port->membase + LTQ_ASC_TXFCON);
writel( __raw_writel(
((RXFIFO_FL << ASCRXFCON_RXFITLOFF) & ASCRXFCON_RXFITLMASK) ((RXFIFO_FL << ASCRXFCON_RXFITLOFF) & ASCRXFCON_RXFITLMASK)
| ASCRXFCON_RXFEN | ASCRXFCON_RXFFLU, | ASCRXFCON_RXFEN | ASCRXFCON_RXFFLU,
port->membase + LTQ_ASC_RXFCON); port->membase + LTQ_ASC_RXFCON);
...@@ -350,7 +352,7 @@ lqasc_startup(struct uart_port *port) ...@@ -350,7 +352,7 @@ lqasc_startup(struct uart_port *port)
goto err2; 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); port->membase + LTQ_ASC_IRNREN);
return 0; return 0;
...@@ -369,7 +371,7 @@ lqasc_shutdown(struct uart_port *port) ...@@ -369,7 +371,7 @@ lqasc_shutdown(struct uart_port *port)
free_irq(ltq_port->rx_irq, port); free_irq(ltq_port->rx_irq, port);
free_irq(ltq_port->err_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, asc_update_bits(ASCRXFCON_RXFEN, ASCRXFCON_RXFFLU,
port->membase + LTQ_ASC_RXFCON); port->membase + LTQ_ASC_RXFCON);
asc_update_bits(ASCTXFCON_TXFEN, ASCTXFCON_TXFFLU, asc_update_bits(ASCTXFCON_TXFEN, ASCTXFCON_TXFFLU,
...@@ -461,13 +463,13 @@ lqasc_set_termios(struct uart_port *port, ...@@ -461,13 +463,13 @@ lqasc_set_termios(struct uart_port *port,
asc_update_bits(ASCCON_BRS, 0, port->membase + LTQ_ASC_CON); asc_update_bits(ASCCON_BRS, 0, port->membase + LTQ_ASC_CON);
/* now we can write the new baudrate into the register */ /* 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 */ /* turn the baudrate generator back on */
asc_update_bits(0, ASCCON_R, port->membase + LTQ_ASC_CON); asc_update_bits(0, ASCCON_R, port->membase + LTQ_ASC_CON);
/* enable rx */ /* enable rx */
writel(ASCWHBSTATE_SETREN, port->membase + LTQ_ASC_WHBSTATE); __raw_writel(ASCWHBSTATE_SETREN, port->membase + LTQ_ASC_WHBSTATE);
spin_unlock_irqrestore(&ltq_asc_lock, flags); spin_unlock_irqrestore(&ltq_asc_lock, flags);
...@@ -578,7 +580,7 @@ lqasc_console_putchar(struct uart_port *port, int ch) ...@@ -578,7 +580,7 @@ lqasc_console_putchar(struct uart_port *port, int ch)
return; return;
do { do {
fifofree = (readl(port->membase + LTQ_ASC_FSTAT) fifofree = (__raw_readl(port->membase + LTQ_ASC_FSTAT)
& ASCFSTAT_TXFREEMASK) >> ASCFSTAT_TXFREEOFF; & ASCFSTAT_TXFREEMASK) >> ASCFSTAT_TXFREEOFF;
} while (fifofree == 0); } while (fifofree == 0);
writeb(ch, port->membase + LTQ_ASC_TBUF); writeb(ch, port->membase + LTQ_ASC_TBUF);
......
...@@ -1256,7 +1256,8 @@ static void tty_driver_remove_tty(struct tty_driver *driver, struct tty_struct * ...@@ -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) static int tty_reopen(struct tty_struct *tty)
{ {
struct tty_driver *driver = tty->driver; struct tty_driver *driver = tty->driver;
int retval; struct tty_ldisc *ld;
int retval = 0;
if (driver->type == TTY_DRIVER_TYPE_PTY && if (driver->type == TTY_DRIVER_TYPE_PTY &&
driver->subtype == PTY_TYPE_MASTER) driver->subtype == PTY_TYPE_MASTER)
...@@ -1268,13 +1269,18 @@ static int tty_reopen(struct tty_struct *tty) ...@@ -1268,13 +1269,18 @@ static int tty_reopen(struct tty_struct *tty)
if (test_bit(TTY_EXCLUSIVE, &tty->flags) && !capable(CAP_SYS_ADMIN)) if (test_bit(TTY_EXCLUSIVE, &tty->flags) && !capable(CAP_SYS_ADMIN))
return -EBUSY; return -EBUSY;
retval = tty_ldisc_lock(tty, 5 * HZ); ld = tty_ldisc_ref_wait(tty);
if (retval) if (ld) {
return retval; tty_ldisc_deref(ld);
} else {
retval = tty_ldisc_lock(tty, 5 * HZ);
if (retval)
return retval;
if (!tty->ldisc) if (!tty->ldisc)
retval = tty_ldisc_reinit(tty, tty->termios.c_line); retval = tty_ldisc_reinit(tty, tty->termios.c_line);
tty_ldisc_unlock(tty); tty_ldisc_unlock(tty);
}
if (retval == 0) if (retval == 0)
tty->count++; tty->count++;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment