mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-09-27 12:57:53 +00:00
TTY/Serial fixes for 6.8-rc8 (or -final)
Here are some small remaining tty/serial driver fixes for 6.8-rc8. 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. Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> -----BEGIN PGP SIGNATURE----- iG0EABECAC0WIQT0tgzFv3jCIUoxPcsxR9QN2y37KQUCZetKOg8cZ3JlZ0Brcm9h aC5jb20ACgkQMUfUDdst+ylrgACg1Ro50Xu8pgExHSDbTwoPPybjJrcAoJtpv3/f EN3V+fWc4o0+RVT9JNnM =iG2L -----END PGP SIGNATURE----- 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
This commit is contained in:
commit
563c5b02f2
6 changed files with 57 additions and 15 deletions
|
@ -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);
|
||||
}
|
||||
clk_prepare_enable(d->clk);
|
||||
|
||||
dw8250_do_set_termios(p, termios, old);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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];
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue