From: Greg Kroah-Hartman Date: Wed, 3 Apr 2019 15:24:39 +0000 (+0200) Subject: 4.4-stable patches X-Git-Tag: v4.9.168~12 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=acc69f12c47c65b4242d5082e505927f4f0366c5;p=thirdparty%2Fkernel%2Fstable-queue.git 4.4-stable patches added patches: tty-serial-atmel-rs485-hd-w-dma-enable-rx-after-tx-is-stopped.patch --- diff --git a/queue-4.4/series b/queue-4.4/series index de8a1428251..0a92b3271f6 100644 --- a/queue-4.4/series +++ b/queue-4.4/series @@ -6,3 +6,4 @@ tty-serial-atmel-add-is_half_duplex-helper.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 bluetooth-fix-decrementing-reference-count-twice-in-releasing-socket.patch +tty-serial-atmel-rs485-hd-w-dma-enable-rx-after-tx-is-stopped.patch diff --git a/queue-4.4/tty-serial-atmel-add-is_half_duplex-helper.patch b/queue-4.4/tty-serial-atmel-add-is_half_duplex-helper.patch index a9fea76bdc8..988287f59ce 100644 --- a/queue-4.4/tty-serial-atmel-add-is_half_duplex-helper.patch +++ b/queue-4.4/tty-serial-atmel-add-is_half_duplex-helper.patch @@ -18,8 +18,8 @@ Signed-off-by: Greg Kroah-Hartman --- - drivers/tty/serial/atmel_serial.c | 17 +++++++++++------ - 1 file changed, 11 insertions(+), 6 deletions(-) + drivers/tty/serial/atmel_serial.c | 19 +++++++++++-------- + 1 file changed, 11 insertions(+), 8 deletions(-) --- a/drivers/tty/serial/atmel_serial.c +++ b/drivers/tty/serial/atmel_serial.c @@ -58,15 +58,17 @@ Signed-off-by: Greg Kroah-Hartman atmel_stop_rx(port); if (atmel_use_pdc_tx(port)) -@@ -812,6 +817,7 @@ static void atmel_complete_tx_dma(void * +@@ -810,8 +815,7 @@ static void atmel_complete_tx_dma(void * + */ + 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)) { +- else if ((port->rs485.flags & SER_RS485_ENABLED) && +- !(port->rs485.flags & SER_RS485_RX_DURING_TX)) { + else if (atmel_uart_is_half_duplex(port)) { /* DMA done, stop TX, start RX for RS485 */ atmel_start_rx(port); } -@@ -1388,8 +1394,7 @@ static void atmel_tx_pdc(struct uart_por +@@ -1388,8 +1392,7 @@ static void atmel_tx_pdc(struct uart_por atmel_uart_writel(port, ATMEL_US_IER, atmel_port->tx_done_mask); } else { diff --git a/queue-4.4/tty-serial-atmel-rs485-hd-w-dma-enable-rx-after-tx-is-stopped.patch b/queue-4.4/tty-serial-atmel-rs485-hd-w-dma-enable-rx-after-tx-is-stopped.patch new file mode 100644 index 00000000000..1ab9b0d2139 --- /dev/null +++ b/queue-4.4/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 +@@ -169,6 +169,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); +@@ -816,8 +818,13 @@ static void atmel_complete_tx_dma(void * + if (!uart_circ_empty(xmit)) + tasklet_schedule(&atmel_port->tasklet); + 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); +@@ -1257,9 +1264,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; ++ } ++ + tasklet_schedule(&atmel_port->tasklet); + } + }