patch "tty/serial: atmel: RS485 HD w/DMA: enable RX after TX is stopped" added to tty-linus
Subsystems (4)
This is a note to let you know that I've just added the patch titled
tty/serial: atmel: RS485 HD w/DMA: enable RX after TX is stopped
to my tty git tree which can be found at
git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty.git
in the tty-linus branch.
The patch will show up in the next release of the linux-next tree (usually sometime within the next 24 hours during the week.)
The patch will hopefully also be merged in Linus's tree for the next -rc kernel release.
If you have any questions about this process, please let me know.
From 69646d7a3689fbe1a65ae90397d22ac3f1b8d40f Mon Sep 17 00:00:00 2001
From: Razvan Stefanescu <[email protected]>
Date: Tue, 19 Mar 2019 15:20:35 +0200
Subject: 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 | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-)
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); } }
Signature · 1 line
2.21.0