From: Greg Kroah-Hartman Date: Tue, 15 Nov 2016 19:49:19 +0000 (+0100) Subject: 4.4-stable patches X-Git-Tag: v4.4.33~13 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=fab0098fc725ee750fa1ac1c02388a9b18bd871e;p=thirdparty%2Fkernel%2Fstable-queue.git 4.4-stable patches added patches: dmaengine-at_xdmac-fix-spurious-flag-status-for-mem2mem-transfers.patch tty-serial-at91-fix-hardware-handshake-on-atmel-platforms.patch --- diff --git a/queue-4.4/dmaengine-at_xdmac-fix-spurious-flag-status-for-mem2mem-transfers.patch b/queue-4.4/dmaengine-at_xdmac-fix-spurious-flag-status-for-mem2mem-transfers.patch new file mode 100644 index 00000000000..0fe266946f9 --- /dev/null +++ b/queue-4.4/dmaengine-at_xdmac-fix-spurious-flag-status-for-mem2mem-transfers.patch @@ -0,0 +1,69 @@ +From 95da0c19d164f6df0b71a5187950f47d4b746e91 Mon Sep 17 00:00:00 2001 +From: Ludovic Desroches +Date: Mon, 23 Nov 2015 14:09:39 +0100 +Subject: dmaengine: at_xdmac: fix spurious flag status for mem2mem transfers + +From: Ludovic Desroches + +commit 95da0c19d164f6df0b71a5187950f47d4b746e91 upstream. + +When setting the channel configuration register, the perid field is not +set to 0 since it is useless for mem2mem transfers. Unfortunately, a +device has 0 as perid. It could cause spurious flags status because +the controller could mix some events from the two channels. +For that reason, use the highest perid value for mem2mem transfers since it +doesn't match the perid of other devices. + +Signed-off-by: Ludovic Desroches +Acked-by: Nicolas Ferre +Signed-off-by: Vinod Koul +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/dma/at_xdmac.c | 18 +++++++++++++++--- + 1 file changed, 15 insertions(+), 3 deletions(-) + +--- a/drivers/dma/at_xdmac.c ++++ b/drivers/dma/at_xdmac.c +@@ -864,8 +864,12 @@ at_xdmac_interleaved_queue_desc(struct d + * access. Hopefully we can access DDR through both ports (at least on + * SAMA5D4x), so we can use the same interface for source and dest, + * that solves the fact we don't know the direction. ++ * ERRATA: Even if useless for memory transfers, the PERID has to not ++ * match the one of another channel. If not, it could lead to spurious ++ * flag status. + */ +- u32 chan_cc = AT_XDMAC_CC_DIF(0) ++ u32 chan_cc = AT_XDMAC_CC_PERID(0x3f) ++ | AT_XDMAC_CC_DIF(0) + | AT_XDMAC_CC_SIF(0) + | AT_XDMAC_CC_MBSIZE_SIXTEEN + | AT_XDMAC_CC_TYPE_MEM_TRAN; +@@ -1042,8 +1046,12 @@ at_xdmac_prep_dma_memcpy(struct dma_chan + * access DDR through both ports (at least on SAMA5D4x), so we can use + * the same interface for source and dest, that solves the fact we + * don't know the direction. ++ * ERRATA: Even if useless for memory transfers, the PERID has to not ++ * match the one of another channel. If not, it could lead to spurious ++ * flag status. + */ +- u32 chan_cc = AT_XDMAC_CC_DAM_INCREMENTED_AM ++ u32 chan_cc = AT_XDMAC_CC_PERID(0x3f) ++ | AT_XDMAC_CC_DAM_INCREMENTED_AM + | AT_XDMAC_CC_SAM_INCREMENTED_AM + | AT_XDMAC_CC_DIF(0) + | AT_XDMAC_CC_SIF(0) +@@ -1144,8 +1152,12 @@ static struct at_xdmac_desc *at_xdmac_me + * access. Hopefully we can access DDR through both ports (at least on + * SAMA5D4x), so we can use the same interface for source and dest, + * that solves the fact we don't know the direction. ++ * ERRATA: Even if useless for memory transfers, the PERID has to not ++ * match the one of another channel. If not, it could lead to spurious ++ * flag status. + */ +- u32 chan_cc = AT_XDMAC_CC_DAM_UBS_AM ++ u32 chan_cc = AT_XDMAC_CC_PERID(0x3f) ++ | AT_XDMAC_CC_DAM_UBS_AM + | AT_XDMAC_CC_SAM_INCREMENTED_AM + | AT_XDMAC_CC_DIF(0) + | AT_XDMAC_CC_SIF(0) diff --git a/queue-4.4/series b/queue-4.4/series index e29583a32c1..34366eefc24 100644 --- a/queue-4.4/series +++ b/queue-4.4/series @@ -23,3 +23,5 @@ scsi-qla2xxx-fix-scsi-scan-hang-triggered-if-adapter-fails-during-init.patch scsi-mpt3sas-fix-for-block-device-of-raid-exists-even-after-deleting-raid-disk.patch kvm-mips-precalculate-mmio-load-resume-pc.patch drm-i915-respect-alternate_ddc_pin-for-all-ddi-ports.patch +dmaengine-at_xdmac-fix-spurious-flag-status-for-mem2mem-transfers.patch +tty-serial-at91-fix-hardware-handshake-on-atmel-platforms.patch diff --git a/queue-4.4/tty-serial-at91-fix-hardware-handshake-on-atmel-platforms.patch b/queue-4.4/tty-serial-at91-fix-hardware-handshake-on-atmel-platforms.patch new file mode 100644 index 00000000000..aa99545d5e8 --- /dev/null +++ b/queue-4.4/tty-serial-at91-fix-hardware-handshake-on-atmel-platforms.patch @@ -0,0 +1,134 @@ +From 9bcffe7575b721d7b6d9b3090fe18809d9806e78 Mon Sep 17 00:00:00 2001 +From: Richard Genoud +Date: Thu, 27 Oct 2016 18:04:06 +0200 +Subject: tty/serial: at91: fix hardware handshake on Atmel platforms +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Richard Genoud + +commit 9bcffe7575b721d7b6d9b3090fe18809d9806e78 upstream. + +After commit 1cf6e8fc8341 ("tty/serial: at91: fix RTS line management +when hardware handshake is enabled"), the hardware handshake wasn't +functional anymore on Atmel platforms (beside SAMA5D2). + +To understand why, one has to understand the flag ATMEL_US_USMODE_HWHS +first: +Before commit 1cf6e8fc8341 ("tty/serial: at91: fix RTS line management +when hardware handshake is enabled"), this flag was never set. +Thus, the CTS/RTS where only handled by serial_core (and everything +worked just fine). + +This commit introduced the use of the ATMEL_US_USMODE_HWHS flag, +enabling it for all boards when the user space enables flow control. + +When the ATMEL_US_USMODE_HWHS is set, the Atmel USART controller +handles a part of the flow control job: +- disable the transmitter when the CTS pin gets high. +- drive the RTS pin high when the DMA buffer transfer is completed or + PDC RX buffer full or RX FIFO is beyond threshold. (depending on the + controller version). + +NB: This feature is *not* mandatory for the flow control to work. +(Nevertheless, it's very useful if low latencies are needed.) + +Now, the specifics of the ATMEL_US_USMODE_HWHS flag: + +- For platforms with DMAC and no FIFOs (sam9x25, sam9x35, sama5D3, +sama5D4, sam9g15, sam9g25, sam9g35)* this feature simply doesn't work. +( source: https://lkml.org/lkml/2016/9/7/598 ) +Tested it on sam9g35, the RTS pins always stays up, even when RXEN=1 +or a new DMA transfer descriptor is set. +=> ATMEL_US_USMODE_HWHS must not be used for those platforms + +- For platforms with a PDC (sam926{0,1,3}, sam9g10, sam9g20, sam9g45, +sam9g46)*, there's another kind of problem. Once the flag +ATMEL_US_USMODE_HWHS is set, the RTS pin can't be driven anymore via +RTSEN/RTSDIS in USART Control Register. The RTS pin can only be driven +by enabling/disabling the receiver or setting RCR=RNCR=0 in the PDC +(Receive (Next) Counter Register). +=> Doing this is beyond the scope of this patch and could add other +bugs, so the original (and working) behaviour should be set for those +platforms (meaning ATMEL_US_USMODE_HWHS flag should be unset). + +- For platforms with a FIFO (sama5d2)*, the RTS pin is driven according +to the RX FIFO thresholds, and can be also driven by RTSEN/RTSDIS in +USART Control Register. No problem here. +(This was the use case of commit 1cf6e8fc8341 ("tty/serial: at91: fix +RTS line management when hardware handshake is enabled")) +NB: If the CTS pin declared as a GPIO in the DTS, (for instance +cts-gpios = <&pioA PIN_PB31 GPIO_ACTIVE_LOW>), the transmitter will be +disabled. +=> ATMEL_US_USMODE_HWHS flag can be set for this platform ONLY IF the +CTS pin is not a GPIO. + +So, the only case when ATMEL_US_USMODE_HWHS can be enabled is when +(atmel_use_fifo(port) && + !mctrl_gpio_to_gpiod(atmel_port->gpios, UART_GPIO_CTS)) + +Tested on all Atmel USART controller flavours: +AT91SAM9G35-CM (DMAC flavour), AT91SAM9G20-EK (PDC flavour), +SAMA5D2xplained (FIFO flavour). + +* the list may not be exhaustive + +Fixes: 1cf6e8fc8341 ("tty/serial: at91: fix RTS line management when hardware handshake is enabled") +Signed-off-by: Richard Genoud +Acked-by: Alexandre Belloni +Acked-by: Cyrille Pitchen +Acked-by: Uwe Kleine-König +[nicolas.ferre@atmel.com: adapt to 4.4.x kernel for stable by adding +the atmel_port variable declaration which was missing] +Signed-off-by: Nicolas Ferre +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/tty/serial/atmel_serial.c | 27 +++++++++++++++++++++++---- + 1 file changed, 23 insertions(+), 4 deletions(-) + +--- a/drivers/tty/serial/atmel_serial.c ++++ b/drivers/tty/serial/atmel_serial.c +@@ -2075,6 +2075,7 @@ static void atmel_serial_pm(struct uart_ + static void atmel_set_termios(struct uart_port *port, struct ktermios *termios, + struct ktermios *old) + { ++ struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); + unsigned long flags; + unsigned int old_mode, mode, imr, quot, baud; + +@@ -2178,11 +2179,29 @@ static void atmel_set_termios(struct uar + mode |= ATMEL_US_USMODE_RS485; + } else if (termios->c_cflag & CRTSCTS) { + /* RS232 with hardware handshake (RTS/CTS) */ +- if (atmel_use_dma_rx(port) && !atmel_use_fifo(port)) { +- dev_info(port->dev, "not enabling hardware flow control because DMA is used"); +- termios->c_cflag &= ~CRTSCTS; +- } else { ++ if (atmel_use_fifo(port) && ++ !mctrl_gpio_to_gpiod(atmel_port->gpios, UART_GPIO_CTS)) { ++ /* ++ * with ATMEL_US_USMODE_HWHS set, the controller will ++ * be able to drive the RTS pin high/low when the RX ++ * FIFO is above RXFTHRES/below RXFTHRES2. ++ * It will also disable the transmitter when the CTS ++ * pin is high. ++ * This mode is not activated if CTS pin is a GPIO ++ * because in this case, the transmitter is always ++ * disabled (there must be an internal pull-up ++ * responsible for this behaviour). ++ * If the RTS pin is a GPIO, the controller won't be ++ * able to drive it according to the FIFO thresholds, ++ * but it will be handled by the driver. ++ */ + mode |= ATMEL_US_USMODE_HWHS; ++ } else { ++ /* ++ * For platforms without FIFO, the flow control is ++ * handled by the driver. ++ */ ++ mode |= ATMEL_US_USMODE_NORMAL; + } + } else { + /* RS232 without hadware handshake */