]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
4.4-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 15 Nov 2016 19:49:19 +0000 (20:49 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 15 Nov 2016 19:49:19 +0000 (20:49 +0100)
added patches:
dmaengine-at_xdmac-fix-spurious-flag-status-for-mem2mem-transfers.patch
tty-serial-at91-fix-hardware-handshake-on-atmel-platforms.patch

queue-4.4/dmaengine-at_xdmac-fix-spurious-flag-status-for-mem2mem-transfers.patch [new file with mode: 0644]
queue-4.4/series
queue-4.4/tty-serial-at91-fix-hardware-handshake-on-atmel-platforms.patch [new file with mode: 0644]

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 (file)
index 0000000..0fe2669
--- /dev/null
@@ -0,0 +1,69 @@
+From 95da0c19d164f6df0b71a5187950f47d4b746e91 Mon Sep 17 00:00:00 2001
+From: Ludovic Desroches <ludovic.desroches@atmel.com>
+Date: Mon, 23 Nov 2015 14:09:39 +0100
+Subject: dmaengine: at_xdmac: fix spurious flag status for mem2mem transfers
+
+From: Ludovic Desroches <ludovic.desroches@atmel.com>
+
+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 <ludovic.desroches@atmel.com>
+Acked-by: Nicolas Ferre <nicolas.ferre@atmel.com>
+Signed-off-by: Vinod Koul <vinod.koul@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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)
index e29583a32c12dab380d228c928752853ea6fa8d7..34366eefc24f948f17ebad800a867f7ebea943f9 100644 (file)
@@ -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 (file)
index 0000000..aa99545
--- /dev/null
@@ -0,0 +1,134 @@
+From 9bcffe7575b721d7b6d9b3090fe18809d9806e78 Mon Sep 17 00:00:00 2001
+From: Richard Genoud <richard.genoud@gmail.com>
+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 <richard.genoud@gmail.com>
+
+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 <richard.genoud@gmail.com>
+Acked-by: Alexandre Belloni <alexandre.belloni@free-electrons.com>
+Acked-by: Cyrille Pitchen <cyrille.pitchen@atmel.com>
+Acked-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
+[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 <nicolas.ferre@atmel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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 */