Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

serial: amba-pl011: do not time out prematurely when draining tx fifo

The current timeout for draining the tx fifo in RS485 mode is calculated by
multiplying the time it takes to transmit one character (with the given
baud rate) with the maximal number of characters in the tx queue.

This timeout is too short for two reasons:
First when calculating the time to transmit one character integer division
is used which may round down the result in case of a remainder of the
division.

Fix this by rounding up the division result.

Second the hardware may need additional time (e.g for first putting the
characters from the fifo into the shift register) before the characters are
actually put onto the wire.

To be on the safe side double the current maximum number of iterations
that are used to wait for the queue draining.

Fixes: 8d479237727c ("serial: amba-pl011: add RS485 support")
Cc: stable@vger.kernel.org
Signed-off-by: Lino Sanfilippo <LinoSanfilippo@gmx.de>
Link: https://lore.kernel.org/r/20220408233503.7251-1-LinoSanfilippo@gmx.de
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Lino Sanfilippo and committed by
Greg Kroah-Hartman
0e4deb56 ff9166c6

+7 -2
+7 -2
drivers/tty/serial/amba-pl011.c
··· 1255 1255 1256 1256 static void pl011_rs485_tx_stop(struct uart_amba_port *uap) 1257 1257 { 1258 + /* 1259 + * To be on the safe side only time out after twice as many iterations 1260 + * as fifo size. 1261 + */ 1262 + const int MAX_TX_DRAIN_ITERS = uap->port.fifosize * 2; 1258 1263 struct uart_port *port = &uap->port; 1259 1264 int i = 0; 1260 1265 u32 cr; 1261 1266 1262 1267 /* Wait until hardware tx queue is empty */ 1263 1268 while (!pl011_tx_empty(port)) { 1264 - if (i == port->fifosize) { 1269 + if (i > MAX_TX_DRAIN_ITERS) { 1265 1270 dev_warn(port->dev, 1266 1271 "timeout while draining hardware tx queue\n"); 1267 1272 break; ··· 2057 2052 * with the given baud rate. We use this as the poll interval when we 2058 2053 * wait for the tx queue to empty. 2059 2054 */ 2060 - uap->rs485_tx_drain_interval = (bits * 1000 * 1000) / baud; 2055 + uap->rs485_tx_drain_interval = DIV_ROUND_UP(bits * 1000 * 1000, baud); 2061 2056 2062 2057 pl011_setup_status_masks(port, termios); 2063 2058