Re: [PATCH] serial: 8250_dw: Improve dw8250_tx_wait_empty implementation

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

 



On Mon, 2018-03-12 at 09:43 +1300, Joshua Scott wrote:
> 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.

I gave a thought about this patch and initial approach. I think we need
a kind of quirk depending on which the workaround would be enabled or
disabled.

> 
> 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));
>  

-- 
Andy Shevchenko <andriy.shevchenko@xxxxxxxxxxxxxxx>
Intel Finland Oy
--
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