Commit 437e878a authored by Linus Torvalds's avatar Linus Torvalds
Browse files
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
Loading
Loading
Loading
Loading
+19 −17
Original line number Diff line number Diff line
@@ -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(&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);
	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(&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);
	spin_unlock_irqrestore(&ltq_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(&ltq_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);
+13 −7
Original line number Diff line number Diff line
@@ -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,6 +1269,10 @@ static int tty_reopen(struct tty_struct *tty)
	if (test_bit(TTY_EXCLUSIVE, &tty->flags) && !capable(CAP_SYS_ADMIN))
		return -EBUSY;

	ld = tty_ldisc_ref_wait(tty);
	if (ld) {
		tty_ldisc_deref(ld);
	} else {
		retval = tty_ldisc_lock(tty, 5 * HZ);
		if (retval)
			return retval;
@@ -1275,6 +1280,7 @@ static int tty_reopen(struct tty_struct *tty)
		if (!tty->ldisc)
			retval = tty_ldisc_reinit(tty, tty->termios.c_line);
		tty_ldisc_unlock(tty);
	}

	if (retval == 0)
		tty->count++;