Skip to content

Commit 563c5b0

Browse files
committed
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
2 parents e536e0d + 3d9319c commit 563c5b0

File tree

6 files changed

+57
-15
lines changed

6 files changed

+57
-15
lines changed

drivers/tty/serial/8250/8250_dw.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -357,18 +357,18 @@ static void dw8250_set_termios(struct uart_port *p, struct ktermios *termios,
357357
long rate;
358358
int ret;
359359

360-
clk_disable_unprepare(d->clk);
361360
rate = clk_round_rate(d->clk, newrate);
362-
if (rate > 0) {
361+
if (rate > 0 && p->uartclk != rate) {
362+
clk_disable_unprepare(d->clk);
363363
/*
364364
* Note that any clock-notifer worker will block in
365365
* serial8250_update_uartclk() until we are done.
366366
*/
367367
ret = clk_set_rate(d->clk, newrate);
368368
if (!ret)
369369
p->uartclk = rate;
370+
clk_prepare_enable(d->clk);
370371
}
371-
clk_prepare_enable(d->clk);
372372

373373
dw8250_do_set_termios(p, termios, old);
374374
}

drivers/tty/serial/fsl_lpuart.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2345,9 +2345,12 @@ lpuart32_set_termios(struct uart_port *port, struct ktermios *termios,
23452345

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

23522355
if ((ctrl & (UARTCTRL_PE | UARTCTRL_M)) == UARTCTRL_PE)
23532356
sport->is_cs7 = true;

drivers/tty/serial/imx.c

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -462,8 +462,7 @@ static void imx_uart_stop_tx(struct uart_port *port)
462462
}
463463
}
464464

465-
/* called with port.lock taken and irqs off */
466-
static void imx_uart_stop_rx(struct uart_port *port)
465+
static void imx_uart_stop_rx_with_loopback_ctrl(struct uart_port *port, bool loopback)
467466
{
468467
struct imx_port *sport = (struct imx_port *)port;
469468
u32 ucr1, ucr2, ucr4, uts;
@@ -485,7 +484,7 @@ static void imx_uart_stop_rx(struct uart_port *port)
485484
/* See SER_RS485_ENABLED/UTS_LOOP comment in imx_uart_probe() */
486485
if (port->rs485.flags & SER_RS485_ENABLED &&
487486
port->rs485.flags & SER_RS485_RTS_ON_SEND &&
488-
sport->have_rtscts && !sport->have_rtsgpio) {
487+
sport->have_rtscts && !sport->have_rtsgpio && loopback) {
489488
uts = imx_uart_readl(sport, imx_uart_uts_reg(sport));
490489
uts |= UTS_LOOP;
491490
imx_uart_writel(sport, uts, imx_uart_uts_reg(sport));
@@ -497,6 +496,16 @@ static void imx_uart_stop_rx(struct uart_port *port)
497496
imx_uart_writel(sport, ucr2, UCR2);
498497
}
499498

499+
/* called with port.lock taken and irqs off */
500+
static void imx_uart_stop_rx(struct uart_port *port)
501+
{
502+
/*
503+
* Stop RX and enable loopback in order to make sure RS485 bus
504+
* is not blocked. Se comment in imx_uart_probe().
505+
*/
506+
imx_uart_stop_rx_with_loopback_ctrl(port, true);
507+
}
508+
500509
/* called with port.lock taken and irqs off */
501510
static void imx_uart_enable_ms(struct uart_port *port)
502511
{
@@ -682,9 +691,14 @@ static void imx_uart_start_tx(struct uart_port *port)
682691
imx_uart_rts_inactive(sport, &ucr2);
683692
imx_uart_writel(sport, ucr2, UCR2);
684693

694+
/*
695+
* Since we are about to transmit we can not stop RX
696+
* with loopback enabled because that will make our
697+
* transmitted data being just looped to RX.
698+
*/
685699
if (!(port->rs485.flags & SER_RS485_RX_DURING_TX) &&
686700
!port->rs485_rx_during_tx_gpio)
687-
imx_uart_stop_rx(port);
701+
imx_uart_stop_rx_with_loopback_ctrl(port, false);
688702

689703
sport->tx_state = WAIT_AFTER_RTS;
690704

drivers/tty/serial/qcom_geni_serial.c

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -851,19 +851,21 @@ static void qcom_geni_serial_stop_tx(struct uart_port *uport)
851851
}
852852

853853
static void qcom_geni_serial_send_chunk_fifo(struct uart_port *uport,
854-
unsigned int remaining)
854+
unsigned int chunk)
855855
{
856856
struct qcom_geni_serial_port *port = to_dev_port(uport);
857857
struct circ_buf *xmit = &uport->state->xmit;
858-
unsigned int tx_bytes;
858+
unsigned int tx_bytes, c, remaining = chunk;
859859
u8 buf[BYTES_PER_FIFO_WORD];
860860

861861
while (remaining) {
862862
memset(buf, 0, sizeof(buf));
863863
tx_bytes = min(remaining, BYTES_PER_FIFO_WORD);
864864

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

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

drivers/tty/serial/serial_port.c

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,31 @@ static int serial_port_runtime_resume(struct device *dev)
4646
return 0;
4747
}
4848

49+
static int serial_port_runtime_suspend(struct device *dev)
50+
{
51+
struct serial_port_device *port_dev = to_serial_base_port_device(dev);
52+
struct uart_port *port = port_dev->port;
53+
unsigned long flags;
54+
bool busy;
55+
56+
if (port->flags & UPF_DEAD)
57+
return 0;
58+
59+
uart_port_lock_irqsave(port, &flags);
60+
busy = __serial_port_busy(port);
61+
if (busy)
62+
port->ops->start_tx(port);
63+
uart_port_unlock_irqrestore(port, flags);
64+
65+
if (busy)
66+
pm_runtime_mark_last_busy(dev);
67+
68+
return busy ? -EBUSY : 0;
69+
}
70+
4971
static DEFINE_RUNTIME_DEV_PM_OPS(serial_port_pm,
50-
NULL, serial_port_runtime_resume, NULL);
72+
serial_port_runtime_suspend,
73+
serial_port_runtime_resume, NULL);
5174

5275
static int serial_port_probe(struct device *dev)
5376
{

drivers/tty/vt/vt.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -381,7 +381,7 @@ static void vc_uniscr_delete(struct vc_data *vc, unsigned int nr)
381381
u32 *ln = vc->vc_uni_lines[vc->state.y];
382382
unsigned int x = vc->state.x, cols = vc->vc_cols;
383383

384-
memcpy(&ln[x], &ln[x + nr], (cols - x - nr) * sizeof(*ln));
384+
memmove(&ln[x], &ln[x + nr], (cols - x - nr) * sizeof(*ln));
385385
memset32(&ln[cols - nr], ' ', nr);
386386
}
387387
}

0 commit comments

Comments
 (0)