Re: [PATCH] serial: 8250: respect rts_before_send before sending chars

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

 



On Thu, Oct 04, 2018 at 09:23:16AM +0200, Uwe Kleine-König wrote:
> serial8250_tx_chars() is called from several places and the callers don't
> consider that sending might not be allowed yet because the
> rts_before_send delay isn't over yet.
> 
> So teach serial8250_tx_chars() about rts_before_send and delay the
> request accordingly if required.
> 
> Signed-off-by: Uwe Kleine-König <u.kleine-koenig@xxxxxxxxxxxxxx>
> ---
> Cc: Tomas Melin <tomas.melin@xxxxxxxxxxx>
> Cc: Daniel Golle <daniel@xxxxxxxxxxxxxx>
> Cc: Ricardo Ribalda Delgado <ricardo.ribalda@xxxxxxxxx>
> Cc: Lukas Wunner <lukas@xxxxxxxxx>
> Cc: Aaron Sierra <asierra@xxxxxxxxxxx>
> Cc: Rafael Gago <rafael.gago@xxxxxxxxx>
> Cc: Daniel Jedrychowski <avistel@xxxxxxxxx>
> 
> Hello,
> 
> on a powerpc (MPC8313) this patch prevents sending characters too early
> after an edge on CTS is detected. As the 8250 driver is quite "advanced"
> I'd welcome testing feedback for other chip variants, so I added a few
> people to Cc who did rs485 stuff in the past.

You pretty much missed the author of contribution of RS485 emulation
to 8250 driver.

Cc'ed to Matwey.

> 
>  drivers/tty/serial/8250/8250_port.c | 31 +++++++++++++++++++++++++++--
>  1 file changed, 29 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c
> index 3f779d25ec0c..d8d7456f8ec3 100644
> --- a/drivers/tty/serial/8250/8250_port.c
> +++ b/drivers/tty/serial/8250/8250_port.c
> @@ -1548,6 +1548,8 @@ static void serial8250_stop_tx(struct uart_port *port)
>  	serial8250_rpm_put(up);
>  }
>  
> +static void __serial8250_tx_chars(struct uart_8250_port *up);
> +
>  static inline void __start_tx(struct uart_port *port)
>  {
>  	struct uart_8250_port *up = up_to_u8250p(port);
> @@ -1565,7 +1567,7 @@ static inline void __start_tx(struct uart_port *port)
>  			lsr = serial_in(up, UART_LSR);
>  			up->lsr_saved_flags |= lsr & LSR_SAVE_FLAGS;
>  			if (lsr & UART_LSR_THRE)
> -				serial8250_tx_chars(up);
> +				__serial8250_tx_chars(up);
>  		}
>  	}
>  
> @@ -1765,7 +1767,7 @@ unsigned char serial8250_rx_chars(struct uart_8250_port *up, unsigned char lsr)
>  }
>  EXPORT_SYMBOL_GPL(serial8250_rx_chars);
>  
> -void serial8250_tx_chars(struct uart_8250_port *up)
> +static void __serial8250_tx_chars(struct uart_8250_port *up)
>  {
>  	struct uart_port *port = &up->port;
>  	struct circ_buf *xmit = &port->state->xmit;
> @@ -1813,6 +1815,31 @@ void serial8250_tx_chars(struct uart_8250_port *up)
>  	if (uart_circ_empty(xmit) && !(up->capabilities & UART_CAP_RPM))
>  		__stop_tx(up);
>  }
> +
> +/* called with port->lock taken and irqs off */
> +void serial8250_tx_chars(struct uart_8250_port *up)
> +{
> +	struct uart_8250_em485 *em485;
> +
> +	em485 = up->em485;
> +	if (em485) {
> +		if (em485->active_timer == &em485->start_tx_timer)
> +			/*
> +			 * Still waiting for rts_before_send delay. When the
> +			 * timer triggers it will start tx.
> +			 */
> +			return;
> +
> +		/*
> +		 * tx might have finshed before and the driver waits for
> +		 * rts_after_send. Now as there is new data to be sent this
> +		 * is void.
> +		 */
> +		em485->active_timer = NULL;
> +	}
> +
> +	__serial8250_tx_chars(up);
> +}
>  EXPORT_SYMBOL_GPL(serial8250_tx_chars);
>  
>  /* Caller holds uart port lock */
> -- 
> 2.19.0
> 

-- 
With Best Regards,
Andy Shevchenko





[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