Commit 563c5b02 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'tty-6.8-rc8' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty

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
...@@ -357,9 +357,9 @@ static void dw8250_set_termios(struct uart_port *p, struct ktermios *termios, ...@@ -357,9 +357,9 @@ static void dw8250_set_termios(struct uart_port *p, struct ktermios *termios,
long rate; long rate;
int ret; int ret;
clk_disable_unprepare(d->clk);
rate = clk_round_rate(d->clk, newrate); 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 * Note that any clock-notifer worker will block in
* serial8250_update_uartclk() until we are done. * serial8250_update_uartclk() until we are done.
...@@ -367,8 +367,8 @@ static void dw8250_set_termios(struct uart_port *p, struct ktermios *termios, ...@@ -367,8 +367,8 @@ static void dw8250_set_termios(struct uart_port *p, struct ktermios *termios,
ret = clk_set_rate(d->clk, newrate); ret = clk_set_rate(d->clk, newrate);
if (!ret) if (!ret)
p->uartclk = rate; p->uartclk = rate;
clk_prepare_enable(d->clk);
} }
clk_prepare_enable(d->clk);
dw8250_do_set_termios(p, termios, old); dw8250_do_set_termios(p, termios, old);
} }
......
...@@ -2345,9 +2345,12 @@ lpuart32_set_termios(struct uart_port *port, struct ktermios *termios, ...@@ -2345,9 +2345,12 @@ lpuart32_set_termios(struct uart_port *port, struct ktermios *termios,
lpuart32_write(&sport->port, bd, UARTBAUD); lpuart32_write(&sport->port, bd, UARTBAUD);
lpuart32_serial_setbrg(sport, baud); lpuart32_serial_setbrg(sport, baud);
lpuart32_write(&sport->port, modem, UARTMODIR); /* disable CTS before enabling UARTCTRL_TE to avoid pending idle preamble */
lpuart32_write(&sport->port, ctrl, UARTCTRL); lpuart32_write(&sport->port, modem & ~UARTMODIR_TXCTSE, UARTMODIR);
/* restore control register */ /* 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) if ((ctrl & (UARTCTRL_PE | UARTCTRL_M)) == UARTCTRL_PE)
sport->is_cs7 = true; sport->is_cs7 = true;
......
...@@ -462,8 +462,7 @@ static void imx_uart_stop_tx(struct uart_port *port) ...@@ -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_with_loopback_ctrl(struct uart_port *port, bool loopback)
static void imx_uart_stop_rx(struct uart_port *port)
{ {
struct imx_port *sport = (struct imx_port *)port; struct imx_port *sport = (struct imx_port *)port;
u32 ucr1, ucr2, ucr4, uts; u32 ucr1, ucr2, ucr4, uts;
...@@ -485,7 +484,7 @@ static void imx_uart_stop_rx(struct uart_port *port) ...@@ -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() */ /* See SER_RS485_ENABLED/UTS_LOOP comment in imx_uart_probe() */
if (port->rs485.flags & SER_RS485_ENABLED && if (port->rs485.flags & SER_RS485_ENABLED &&
port->rs485.flags & SER_RS485_RTS_ON_SEND && 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 = imx_uart_readl(sport, imx_uart_uts_reg(sport));
uts |= UTS_LOOP; uts |= UTS_LOOP;
imx_uart_writel(sport, uts, imx_uart_uts_reg(sport)); imx_uart_writel(sport, uts, imx_uart_uts_reg(sport));
...@@ -497,6 +496,16 @@ static void imx_uart_stop_rx(struct uart_port *port) ...@@ -497,6 +496,16 @@ static void imx_uart_stop_rx(struct uart_port *port)
imx_uart_writel(sport, ucr2, UCR2); 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 */ /* called with port.lock taken and irqs off */
static void imx_uart_enable_ms(struct uart_port *port) static void imx_uart_enable_ms(struct uart_port *port)
{ {
...@@ -682,9 +691,14 @@ static void imx_uart_start_tx(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_rts_inactive(sport, &ucr2);
imx_uart_writel(sport, ucr2, 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) && if (!(port->rs485.flags & SER_RS485_RX_DURING_TX) &&
!port->rs485_rx_during_tx_gpio) !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; sport->tx_state = WAIT_AFTER_RTS;
......
...@@ -851,19 +851,21 @@ static void qcom_geni_serial_stop_tx(struct uart_port *uport) ...@@ -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, 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 qcom_geni_serial_port *port = to_dev_port(uport);
struct circ_buf *xmit = &uport->state->xmit; struct circ_buf *xmit = &uport->state->xmit;
unsigned int tx_bytes; unsigned int tx_bytes, c, remaining = chunk;
u8 buf[BYTES_PER_FIFO_WORD]; u8 buf[BYTES_PER_FIFO_WORD];
while (remaining) { while (remaining) {
memset(buf, 0, sizeof(buf)); memset(buf, 0, sizeof(buf));
tx_bytes = min(remaining, BYTES_PER_FIFO_WORD); tx_bytes = min(remaining, BYTES_PER_FIFO_WORD);
memcpy(buf, &xmit->buf[xmit->tail], tx_bytes); for (c = 0; c < tx_bytes ; c++) {
uart_xmit_advance(uport, tx_bytes); buf[c] = xmit->buf[xmit->tail];
uart_xmit_advance(uport, 1);
}
iowrite32_rep(uport->membase + SE_GENI_TX_FIFOn, buf, 1); iowrite32_rep(uport->membase + SE_GENI_TX_FIFOn, buf, 1);
......
...@@ -46,8 +46,31 @@ static int serial_port_runtime_resume(struct device *dev) ...@@ -46,8 +46,31 @@ static int serial_port_runtime_resume(struct device *dev)
return 0; 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, 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) static int serial_port_probe(struct device *dev)
{ {
......
...@@ -381,7 +381,7 @@ static void vc_uniscr_delete(struct vc_data *vc, unsigned int nr) ...@@ -381,7 +381,7 @@ static void vc_uniscr_delete(struct vc_data *vc, unsigned int nr)
u32 *ln = vc->vc_uni_lines[vc->state.y]; u32 *ln = vc->vc_uni_lines[vc->state.y];
unsigned int x = vc->state.x, cols = vc->vc_cols; unsigned int x = vc->state.x, cols = vc->vc_cols;
memcpy(&ln[x], &ln[x + nr], (cols - x - nr) * sizeof(*ln)); memmove(&ln[x], &ln[x + nr], (cols - x - nr) * sizeof(*ln));
memset32(&ln[cols - nr], ' ', nr); memset32(&ln[cols - nr], ' ', nr);
} }
} }
......
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