From: Greg Kroah-Hartman Date: Wed, 3 Apr 2019 15:25:04 +0000 (+0200) Subject: 4.9-stable patches X-Git-Tag: v4.9.168~11 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=ab86d63b1412eadd62455e8b78e328de4a985fda;p=thirdparty%2Fkernel%2Fstable-queue.git 4.9-stable patches added patches: tty-serial-atmel-rs485-hd-w-dma-enable-rx-after-tx-is-stopped.patch --- diff --git a/queue-4.9/series b/queue-4.9/series index c16607f74df..c07d3025d78 100644 --- a/queue-4.9/series +++ b/queue-4.9/series @@ -3,5 +3,6 @@ arm64-debug-ensure-debug-handlers-check-triggering-exception-level.patch ext4-cleanup-bh-release-code-in-ext4_ind_remove_space.patch lib-int_sqrt-optimize-initial-value-compute.patch tty-serial-atmel-add-is_half_duplex-helper.patch +tty-serial-atmel-rs485-hd-w-dma-enable-rx-after-tx-is-stopped.patch mm-mempolicy-make-mbind-return-eio-when-mpol_mf_strict-is-specified.patch i2c-core-smbus-prevent-stack-corruption-on-read-i2c_block_data.patch diff --git a/queue-4.9/tty-serial-atmel-rs485-hd-w-dma-enable-rx-after-tx-is-stopped.patch b/queue-4.9/tty-serial-atmel-rs485-hd-w-dma-enable-rx-after-tx-is-stopped.patch new file mode 100644 index 00000000000..483e3d81c81 --- /dev/null +++ b/queue-4.9/tty-serial-atmel-rs485-hd-w-dma-enable-rx-after-tx-is-stopped.patch @@ -0,0 +1,79 @@ +From 69646d7a3689fbe1a65ae90397d22ac3f1b8d40f Mon Sep 17 00:00:00 2001 +From: Razvan Stefanescu +Date: Tue, 19 Mar 2019 15:20:35 +0200 +Subject: tty/serial: atmel: RS485 HD w/DMA: enable RX after TX is stopped + +From: Razvan Stefanescu + +commit 69646d7a3689fbe1a65ae90397d22ac3f1b8d40f upstream. + +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. + +Fixes: b389f173aaa1 ("tty/serial: atmel: RS485 half duplex w/DMA: enable +RX after TX is done") +Signed-off-by: Razvan Stefanescu +Acked-by: Richard Genoud +Cc: stable +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/tty/serial/atmel_serial.c | 24 +++++++++++++++++++++--- + 1 file changed, 21 insertions(+), 3 deletions(-) + +--- a/drivers/tty/serial/atmel_serial.c ++++ b/drivers/tty/serial/atmel_serial.c +@@ -175,6 +175,8 @@ struct atmel_uart_port { + unsigned int pending_status; + spinlock_t lock_suspended; + ++ bool hd_start_rx; /* can start RX during half-duplex operation */ ++ + int (*prepare_rx)(struct uart_port *port); + int (*prepare_tx)(struct uart_port *port); + void (*schedule_rx)(struct uart_port *port); +@@ -815,8 +817,13 @@ static void atmel_complete_tx_dma(void * + 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); +@@ -1261,9 +1268,20 @@ atmel_handle_transmit(struct uart_port * + 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); + } + }