Re: [PATCH] serial: 8250_dw: Limit dw8250_tx_wait_empty quirk to armada-38x devices

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

 



On Thu, 2018-03-15 at 10:02 +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.
> 
> Limit the change to devices with the new "marvell,armada-38x-uart"
> compatible string. Also update the code to allow the first 1000
> retries
> to not perform a delay.
> 
> The maximum duration of retries has been increased to cover a worst-
> case
> seen on the Armada 385 SoC. "dmesg ; resize", will fill the buffer
> with
> text to output before doing a resize. At 9600 baud this took up to 13
> ms
> to flush all characters and avoid some getting lost.
> 

Yep, something like this.

Reviewed-by: Andy Shevchenko <andriy.shevchenko@xxxxxxxxxxxxxxx>

Couple of minor comments below.

> Signed-off-by: Joshua Scott <joshua.scott@xxxxxxxxxxxxxxxxxxx>
> ---
>  arch/arm/boot/dts/armada-38x.dtsi |  4 ++--
>  drivers/tty/serial/8250/8250_dw.c | 30 +++++++++++++++++++++++++++---
>  2 files changed, 29 insertions(+), 5 deletions(-)
> 
> diff --git a/arch/arm/boot/dts/armada-38x.dtsi
> b/arch/arm/boot/dts/armada-38x.dtsi
> index 00ff549..4e6d8d6 100644
> --- a/arch/arm/boot/dts/armada-38x.dtsi
> +++ b/arch/arm/boot/dts/armada-38x.dtsi
> @@ -200,7 +200,7 @@
>  			};
>  
>  			uart0: serial@12000 {
> -				compatible = "snps,dw-apb-uart";
> +				compatible = "marvell,armada-38x-
> uart";
>  				reg = <0x12000 0x100>;
>  				reg-shift = <2>;
>  				interrupts = <GIC_SPI 12
> IRQ_TYPE_LEVEL_HIGH>;
> @@ -210,7 +210,7 @@
>  			};
>  
>  			uart1: serial@12100 {
> -				compatible = "snps,dw-apb-uart";
> +				compatible = "marvell,armada-38x-
> uart";
>  				reg = <0x12100 0x100>;
>  				reg-shift = <2>;
>  				interrupts = <GIC_SPI 13
> IRQ_TYPE_LEVEL_HIGH>;
> diff --git a/drivers/tty/serial/8250/8250_dw.c
> b/drivers/tty/serial/8250/8250_dw.c
> index 823c1dc..9656707 100644
> --- a/drivers/tty/serial/8250/8250_dw.c
> +++ b/drivers/tty/serial/8250/8250_dw.c
> @@ -127,23 +127,41 @@ 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);
>  	}
>  }
>  
> -static void dw8250_serial_out(struct uart_port *p, int offset, int
> value)
> +static void dw8250_serial_out38x(struct uart_port *p, int offset, int
> value)
>  {
>  	struct dw8250_data *d = p->private_data;
>  
>  	/* Allow the TX to drain before we reconfigure */
>  	if (offset == UART_LCR)
> -		dw8250_tx_wait_empty(p, 1000);
> +		dw8250_tx_wait_empty(p, 20000);

I would still define tries inside the function in a way how it's done in
_check_lcr().

> +
> +	writeb(value, p->membase + (offset << p->regshift));
> +
> +	if (offset == UART_LCR && !d->uart_16550_compatible)
> +		dw8250_check_lcr(p, value);
> +}
> +
> +
> +static void dw8250_serial_out(struct uart_port *p, int offset, int
> value)
> +{
> +	struct dw8250_data *d = p->private_data;
>  
>  	writeb(value, p->membase + (offset << p->regshift));
>  
> @@ -361,6 +379,11 @@ static void dw8250_quirks(struct uart_port *p,
> struct dw8250_data *data)
>  			p->serial_in = dw8250_serial_in32be;
>  			p->serial_out = dw8250_serial_out32be;
>  		}
> +
> +		if (of_device_is_compatible(np, "marvell,armada-38x-
> uart")) {
> +			p->serial_out = dw8250_serial_out38x;
> +		}

> +

Redundant empty string, and perhaps you don't need curly braces for now.

>  	} else if (has_acpi_companion(p->dev)) {
>  		const struct acpi_device_id *id;
>  
> @@ -675,6 +698,7 @@ static const struct dev_pm_ops dw8250_pm_ops = {
>  static const struct of_device_id dw8250_of_match[] = {
>  	{ .compatible = "snps,dw-apb-uart" },
>  	{ .compatible = "cavium,octeon-3860-uart" },
> +	{ .compatible = "marvell,armada-38x-uart" },
>  	{ /* Sentinel */ }
>  };
>  MODULE_DEVICE_TABLE(of, dw8250_of_match);

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