[PATCH] serial: 8250_dw: Improve dw8250_tx_wait_empty implementation

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



The previous implementation has had a detrimental effect on devices using
high bitrates (bluetooth), as the fifo being non-empty for a single check
would result in a 10 µs delay.

This patch updates the code such that it will allow 1000 retries to fail
before delaying by 1 µs for the remaining retry limit.

In addition, the maximum number of retries has been increased, both to
cover the decreased delay length, and to cover a new worst-case seen on
the Armada 385 SoC. "dmesg ; resize", filling the buffer with text to
output before reconfiguring, required 13 ms to empty the buffer and avoid
losing characters.

Signed-off-by: Joshua Scott <joshua.scott@xxxxxxxxxxxxxxxxxxx>
---
 drivers/tty/serial/8250/8250_dw.c | 11 +++++++++--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c
index 823c1dc..843c2a2 100644
--- a/drivers/tty/serial/8250/8250_dw.c
+++ b/drivers/tty/serial/8250/8250_dw.c
@@ -127,13 +127,20 @@ static void dw8250_check_lcr(struct uart_port *p, int value)
 /* Returns once the transmitter is empty or we run out of retries */
 static void dw8250_tx_wait_empty(struct uart_port *p, int tries)
 {
+	unsigned int delay_threshold = tries - 1000;
 	unsigned int lsr;
 
 	while (tries--) {
 		lsr = readb (p->membase + (UART_LSR << p->regshift));
 		if (lsr & UART_LSR_TEMT)
 			break;
-		udelay (10);
+
+		/* The device is first given a chance to empty without delay,
+		 * to avoid slowdowns at high bitrates. If after 1000 tries
+		 * the buffer has still not emptied, allow more time for low-
+		 * speed links. */
+		if (tries < delay_threshold)
+			udelay (1);
 	}
 }
 
@@ -143,7 +150,7 @@ static void dw8250_serial_out(struct uart_port *p, int offset, int value)
 
 	/* Allow the TX to drain before we reconfigure */
 	if (offset == UART_LCR)
-		dw8250_tx_wait_empty(p, 1000);
+		dw8250_tx_wait_empty(p, 20000);
 
 	writeb(value, p->membase + (offset << p->regshift));
 
-- 
2.16.2

--
To unsubscribe from this list: send the line "unsubscribe linux-serial" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Kernel Newbies]     [Security]     [Netfilter]     [Bugtraq]     [Linux PPP]     [Linux FS]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Samba]     [Video 4 Linux]     [Linmodem]     [Device Mapper]     [Linux Kernel for ARM]

  Powered by Linux