Commit 563c5b02 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull tty / serial fixes from Greg KH:
 "Here are some small remaining tty/serial driver fixes. Included in
  here is fixes for:

   - vt unicode buffer corruption fix

   - imx serial driver fixes, again

   - port suspend fix

   - 8250_dw driver fix

   - fsl_lpuart driver fix

   - revert for the qcom_geni_serial driver to fix a reported regression

  All of these have been in linux-next with no reported issues"

* tag 'tty-6.8-rc8' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty:
  Revert "tty: serial: simplify qcom_geni_serial_send_chunk_fifo()"
  tty: serial: fsl_lpuart: avoid idle preamble pending if CTS is enabled
  vt: fix unicode buffer corruption when deleting characters
  serial: port: Don't suspend if the port is still busy
  serial: 8250_dw: Do not reclock if already at correct rate
  tty: serial: imx: Fix broken RS485
parents e536e0d4 3d9319c2
Loading
Loading
Loading
Loading
+3 −3
Original line number Diff line number Diff line
@@ -357,9 +357,9 @@ static void dw8250_set_termios(struct uart_port *p, struct ktermios *termios,
	long rate;
	int ret;

	clk_disable_unprepare(d->clk);
	rate = clk_round_rate(d->clk, newrate);
	if (rate > 0) {
	if (rate > 0 && p->uartclk != rate) {
		clk_disable_unprepare(d->clk);
		/*
		 * Note that any clock-notifer worker will block in
		 * serial8250_update_uartclk() until we are done.
@@ -367,8 +367,8 @@ static void dw8250_set_termios(struct uart_port *p, struct ktermios *termios,
		ret = clk_set_rate(d->clk, newrate);
		if (!ret)
			p->uartclk = rate;
	}
		clk_prepare_enable(d->clk);
	}

	dw8250_do_set_termios(p, termios, old);
}
+5 −2
Original line number Diff line number Diff line
@@ -2345,9 +2345,12 @@ lpuart32_set_termios(struct uart_port *port, struct ktermios *termios,

	lpuart32_write(&sport->port, bd, UARTBAUD);
	lpuart32_serial_setbrg(sport, baud);
	lpuart32_write(&sport->port, modem, UARTMODIR);
	lpuart32_write(&sport->port, ctrl, UARTCTRL);
	/* disable CTS before enabling UARTCTRL_TE to avoid pending idle preamble */
	lpuart32_write(&sport->port, modem & ~UARTMODIR_TXCTSE, UARTMODIR);
	/* restore control register */
	lpuart32_write(&sport->port, ctrl, UARTCTRL);
	/* re-enable the CTS if needed */
	lpuart32_write(&sport->port, modem, UARTMODIR);

	if ((ctrl & (UARTCTRL_PE | UARTCTRL_M)) == UARTCTRL_PE)
		sport->is_cs7 = true;
+18 −4
Original line number Diff line number Diff line
@@ -462,8 +462,7 @@ static void imx_uart_stop_tx(struct uart_port *port)
	}
}

/* called with port.lock taken and irqs off */
static void imx_uart_stop_rx(struct uart_port *port)
static void imx_uart_stop_rx_with_loopback_ctrl(struct uart_port *port, bool loopback)
{
	struct imx_port *sport = (struct imx_port *)port;
	u32 ucr1, ucr2, ucr4, uts;
@@ -485,7 +484,7 @@ static void imx_uart_stop_rx(struct uart_port *port)
	/* See SER_RS485_ENABLED/UTS_LOOP comment in imx_uart_probe() */
	if (port->rs485.flags & SER_RS485_ENABLED &&
	    port->rs485.flags & SER_RS485_RTS_ON_SEND &&
	    sport->have_rtscts && !sport->have_rtsgpio) {
	    sport->have_rtscts && !sport->have_rtsgpio && loopback) {
		uts = imx_uart_readl(sport, imx_uart_uts_reg(sport));
		uts |= UTS_LOOP;
		imx_uart_writel(sport, uts, imx_uart_uts_reg(sport));
@@ -497,6 +496,16 @@ static void imx_uart_stop_rx(struct uart_port *port)
	imx_uart_writel(sport, ucr2, UCR2);
}

/* called with port.lock taken and irqs off */
static void imx_uart_stop_rx(struct uart_port *port)
{
	/*
	 * Stop RX and enable loopback in order to make sure RS485 bus
	 * is not blocked. Se comment in imx_uart_probe().
	 */
	imx_uart_stop_rx_with_loopback_ctrl(port, true);
}

/* called with port.lock taken and irqs off */
static void imx_uart_enable_ms(struct uart_port *port)
{
@@ -682,9 +691,14 @@ static void imx_uart_start_tx(struct uart_port *port)
				imx_uart_rts_inactive(sport, &ucr2);
			imx_uart_writel(sport, ucr2, UCR2);

			/*
			 * Since we are about to transmit we can not stop RX
			 * with loopback enabled because that will make our
			 * transmitted data being just looped to RX.
			 */
			if (!(port->rs485.flags & SER_RS485_RX_DURING_TX) &&
			    !port->rs485_rx_during_tx_gpio)
				imx_uart_stop_rx(port);
				imx_uart_stop_rx_with_loopback_ctrl(port, false);

			sport->tx_state = WAIT_AFTER_RTS;

+6 −4
Original line number Diff line number Diff line
@@ -851,19 +851,21 @@ static void qcom_geni_serial_stop_tx(struct uart_port *uport)
}

static void qcom_geni_serial_send_chunk_fifo(struct uart_port *uport,
					     unsigned int remaining)
					     unsigned int chunk)
{
	struct qcom_geni_serial_port *port = to_dev_port(uport);
	struct circ_buf *xmit = &uport->state->xmit;
	unsigned int tx_bytes;
	unsigned int tx_bytes, c, remaining = chunk;
	u8 buf[BYTES_PER_FIFO_WORD];

	while (remaining) {
		memset(buf, 0, sizeof(buf));
		tx_bytes = min(remaining, BYTES_PER_FIFO_WORD);

		memcpy(buf, &xmit->buf[xmit->tail], tx_bytes);
		uart_xmit_advance(uport, tx_bytes);
		for (c = 0; c < tx_bytes ; c++) {
			buf[c] = xmit->buf[xmit->tail];
			uart_xmit_advance(uport, 1);
		}

		iowrite32_rep(uport->membase + SE_GENI_TX_FIFOn, buf, 1);

+24 −1
Original line number Diff line number Diff line
@@ -46,8 +46,31 @@ static int serial_port_runtime_resume(struct device *dev)
	return 0;
}

static int serial_port_runtime_suspend(struct device *dev)
{
	struct serial_port_device *port_dev = to_serial_base_port_device(dev);
	struct uart_port *port = port_dev->port;
	unsigned long flags;
	bool busy;

	if (port->flags & UPF_DEAD)
		return 0;

	uart_port_lock_irqsave(port, &flags);
	busy = __serial_port_busy(port);
	if (busy)
		port->ops->start_tx(port);
	uart_port_unlock_irqrestore(port, flags);

	if (busy)
		pm_runtime_mark_last_busy(dev);

	return busy ? -EBUSY : 0;
}

static DEFINE_RUNTIME_DEV_PM_OPS(serial_port_pm,
				 NULL, serial_port_runtime_resume, NULL);
				 serial_port_runtime_suspend,
				 serial_port_runtime_resume, NULL);

static int serial_port_probe(struct device *dev)
{
Loading