Skip to content

Commit 990a142

Browse files
rgenoudgregkh
authored andcommitted
tty/serial: atmel: RS485 half duplex w/DMA: enable RX after TX is done
commit b389f173aaa1204d6dc1f299082a162eb0491545 upstream. When using RS485 in half duplex, RX should be enabled when TX is finished, and stopped when TX starts. Before commit 0058f0871efe7b01c6 ("tty/serial: atmel: fix RS485 half duplex with DMA"), RX was not disabled in atmel_start_tx() if the DMA was used. So, collisions could happened. But disabling RX in atmel_start_tx() uncovered another bug: RX was enabled again in the wrong place (in atmel_tx_dma) instead of being enabled when TX is finished (in atmel_complete_tx_dma), so the transmission simply stopped. This bug was not triggered before commit 0058f0871efe7b01c6 ("tty/serial: atmel: fix RS485 half duplex with DMA") because RX was never disabled before. Moving atmel_start_rx() in atmel_complete_tx_dma() corrects the problem. Reported-by: Gil Weber <webergil@gmail.com> Fixes: 0058f0871efe7b01c6 Tested-by: Gil Weber <webergil@gmail.com> Signed-off-by: Richard Genoud <richard.genoud@gmail.com> Acked-by: Alexandre Belloni <alexandre.belloni@free-electrons.com> Signed-off-by: Alexandre Belloni <alexandre.belloni@free-electrons.com> Tested-by: Bryan Evenson <bevenson@melinkcorp.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent 8dc821b commit 990a142

1 file changed

Lines changed: 5 additions & 6 deletions

File tree

drivers/tty/serial/atmel_serial.c

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -810,6 +810,11 @@ static void atmel_complete_tx_dma(void *arg)
810810
*/
811811
if (!uart_circ_empty(xmit))
812812
tasklet_schedule(&atmel_port->tasklet);
813+
else if ((port->rs485.flags & SER_RS485_ENABLED) &&
814+
!(port->rs485.flags & SER_RS485_RX_DURING_TX)) {
815+
/* DMA done, stop TX, start RX for RS485 */
816+
atmel_start_rx(port);
817+
}
813818

814819
spin_unlock_irqrestore(&port->lock, flags);
815820
}
@@ -912,12 +917,6 @@ static void atmel_tx_dma(struct uart_port *port)
912917
desc->callback = atmel_complete_tx_dma;
913918
desc->callback_param = atmel_port;
914919
atmel_port->cookie_tx = dmaengine_submit(desc);
915-
916-
} else {
917-
if (port->rs485.flags & SER_RS485_ENABLED) {
918-
/* DMA done, stop TX, start RX for RS485 */
919-
atmel_start_rx(port);
920-
}
921920
}
922921

923922
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)

0 commit comments

Comments
 (0)