FAILED: patch "[PATCH] tty/serial: atmel: RS485 HD w/DMA: enable RX after TX is" failed to apply to 4.19-stable tree
Subsystems (4)
[email protected]
maintainerThe patch below does not apply to the 4.19-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From 69646d7a3689fbe1a65ae90397d22ac3f1b8d40f Mon Sep 17 00:00:00 2001
From: Razvan Stefanescu <[email protected]>
Date: Tue, 19 Mar 2019 15:20:35 +0200
Subject: [PATCH] tty/serial: atmel: RS485 HD w/DMA: enable RX after TX is
stopped
In half-duplex operation, RX should be started after TX completes.
If DMA is used, there is a case when the DMA transfer completes but the TX FIFO is not emptied, so the RX cannot be restarted just yet.
Use a boolean variable to store this state and rearm TX interrupt mask to be signaled again that the transfer finished. In interrupt transmit handler this variable is used to start RX. A warning message is generated if RX is activated before TX fifo is cleared.
RX after TX is done")
drivers/tty/serial/atmel_serial.c +21 -3
@@ -166,6 +166,8 @@ struct atmel_uart_port {unsigned int pending_status;spinlock_t lock_suspended; +bool hd_start_rx;/* can start RX during half-duplex operation */ +/* ISO7816 */ unsigned int fidi_min;unsigned int fidi_max;
@@ -933,8 +935,13 @@ static void atmel_complete_tx_dma(void *arg)if (!uart_circ_empty (xmit))atmel_tasklet_schedule (atmel_port, &atmel_port->tasklet_tx);else if (atmel_uart_is_half_duplex (port)) { -/* DMA done, stop TX, start RX for RS485 */ -atmel_start_rx (port); +/* +* DMA done, re-enable TXEMPTY and signal that we can stop +* TX and start RX for RS485 +*/ + atmel_port->hd_start_rx = true; +atmel_uart_writel (port,ATMEL_US_IER , + atmel_port->tx_done_mask); }spin_unlock_irqrestore (&port->lock, flags);
@@ -1382,9 +1389,20 @@ atmel_handle_transmit(struct uart_port *port, unsigned int pending)struct atmel_uart_port *atmel_port =to_atmel_uart_port (port);if (pending & atmel_port->tx_done_mask) { -/* Either PDC or interrupt transmission */ atmel_uart_writel (port,ATMEL_US_IDR , atmel_port->tx_done_mask); + +/* Start RX if flag was set and FIFO is empty */ +if (atmel_port->hd_start_rx) { +if (!(atmel_uart_readl (port,ATMEL_US_CSR ) + &ATMEL_US_TXEMPTY )) +dev_warn (port->dev,"Should start RX, but TX fifo is not empty\n" ); + + atmel_port->hd_start_rx = false; +atmel_start_rx (port); +return ; + } +atmel_tasklet_schedule (atmel_port, &atmel_port->tasklet_tx); } }