Skip to content

Commit

Permalink
tty/serial: atmel: RS485 half duplex w/DMA: enable RX after TX is done
Browse files Browse the repository at this point in the history
commit b389f17 upstream.

When using RS485 in half duplex, RX should be enabled when TX is
finished, and stopped when TX starts.

Before commit 0058f08 ("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 0058f08
("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: 0058f08
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>
  • Loading branch information
Richard Genoud authored and Greg Kroah-Hartman committed Apr 21, 2017
1 parent 8dc821b commit 990a142
Showing 1 changed file with 5 additions and 6 deletions.
11 changes: 5 additions & 6 deletions drivers/tty/serial/atmel_serial.c
Original file line number Diff line number Diff line change
@@ -810,6 +810,11 @@ static void atmel_complete_tx_dma(void *arg)
*/
if (!uart_circ_empty(xmit))
tasklet_schedule(&atmel_port->tasklet);
else if ((port->rs485.flags & SER_RS485_ENABLED) &&
!(port->rs485.flags & SER_RS485_RX_DURING_TX)) {
/* DMA done, stop TX, start RX for RS485 */
atmel_start_rx(port);
}

spin_unlock_irqrestore(&port->lock, flags);
}
@@ -912,12 +917,6 @@ static void atmel_tx_dma(struct uart_port *port)
desc->callback = atmel_complete_tx_dma;
desc->callback_param = atmel_port;
atmel_port->cookie_tx = dmaengine_submit(desc);

} else {
if (port->rs485.flags & SER_RS485_ENABLED) {
/* DMA done, stop TX, start RX for RS485 */
atmel_start_rx(port);
}
}

if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)

0 comments on commit 990a142

Please sign in to comment.