]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
3.10-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 7 Jul 2014 21:03:17 +0000 (14:03 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 7 Jul 2014 21:03:17 +0000 (14:03 -0700)
added patches:
serial-8250_dw-report-cts-asserted-for-auto-flow.patch

queue-3.10/serial-8250_dw-report-cts-asserted-for-auto-flow.patch [new file with mode: 0644]
queue-3.10/series

diff --git a/queue-3.10/serial-8250_dw-report-cts-asserted-for-auto-flow.patch b/queue-3.10/serial-8250_dw-report-cts-asserted-for-auto-flow.patch
new file mode 100644 (file)
index 0000000..6383e53
--- /dev/null
@@ -0,0 +1,106 @@
+From 33acbb82695f84e9429c1f7fbdeb4588dea12ffa Mon Sep 17 00:00:00 2001
+From: Tim Kryger <tim.kryger@linaro.org>
+Date: Fri, 16 Aug 2013 13:50:15 -0700
+Subject: serial: 8250_dw: Report CTS asserted for auto flow
+
+From: Tim Kryger <tim.kryger@linaro.org>
+
+commit 33acbb82695f84e9429c1f7fbdeb4588dea12ffa upstream.
+
+When a serial port is configured for RTS/CTS flow control, serial core
+will disable the transmitter if it observes CTS is de-asserted. This is
+perfectly reasonable and appropriate when the UART lacks the ability to
+automatically perform CTS flow control.
+
+However, if the UART hardware can manage flow control automatically, it
+is important that software not get involved.  When the DesignWare UART
+enables 16C750 style auto-RTS/CTS it stops generating interrupts for
+changes in CTS state so software mostly stays out of the way.  However,
+it does report the true state of CTS in the MSR so software may notice
+it is de-asserted and respond by improperly disabling the transmitter.
+Once this happens the transmitter will be blocked forever.
+
+To avoid this situation, we simply lie to the 8250 and serial core by
+reporting that CTS is asserted whenever auto-RTS/CTS mode is enabled.
+
+Signed-off-by: Tim Kryger <tim.kryger@linaro.org>
+Reviewed-by: Matt Porter <matt.porter@linaro.org>
+Reviewed-by: Markus Mayer <markus.mayer@linaro.org>
+Cc: Wang Nan <wangnan0@huawei.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/tty/serial/8250/8250_dw.c |   34 ++++++++++++++++++++++++++--------
+ 1 file changed, 26 insertions(+), 8 deletions(-)
+
+--- a/drivers/tty/serial/8250/8250_dw.c
++++ b/drivers/tty/serial/8250/8250_dw.c
+@@ -55,10 +55,24 @@
+ struct dw8250_data {
+       int             last_lcr;
++      int             last_mcr;
+       int             line;
+       struct clk      *clk;
+ };
++static inline int dw8250_modify_msr(struct uart_port *p, int offset, int value)
++{
++      struct dw8250_data *d = p->private_data;
++
++      /* If reading MSR, report CTS asserted when auto-CTS/RTS enabled */
++      if (offset == UART_MSR && d->last_mcr & UART_MCR_AFE) {
++              value |= UART_MSR_CTS;
++              value &= ~UART_MSR_DCTS;
++      }
++
++      return value;
++}
++
+ static void dw8250_serial_out(struct uart_port *p, int offset, int value)
+ {
+       struct dw8250_data *d = p->private_data;
+@@ -66,15 +80,17 @@ static void dw8250_serial_out(struct uar
+       if (offset == UART_LCR)
+               d->last_lcr = value;
+-      offset <<= p->regshift;
+-      writeb(value, p->membase + offset);
++      if (offset == UART_MCR)
++              d->last_mcr = value;
++
++      writeb(value, p->membase + (offset << p->regshift));
+ }
+ static unsigned int dw8250_serial_in(struct uart_port *p, int offset)
+ {
+-      offset <<= p->regshift;
++      unsigned int value = readb(p->membase + (offset << p->regshift));
+-      return readb(p->membase + offset);
++      return dw8250_modify_msr(p, offset, value);
+ }
+ static void dw8250_serial_out32(struct uart_port *p, int offset, int value)
+@@ -84,15 +100,17 @@ static void dw8250_serial_out32(struct u
+       if (offset == UART_LCR)
+               d->last_lcr = value;
+-      offset <<= p->regshift;
+-      writel(value, p->membase + offset);
++      if (offset == UART_MCR)
++              d->last_mcr = value;
++
++      writel(value, p->membase + (offset << p->regshift));
+ }
+ static unsigned int dw8250_serial_in32(struct uart_port *p, int offset)
+ {
+-      offset <<= p->regshift;
++      unsigned int value = readl(p->membase + (offset << p->regshift));
+-      return readl(p->membase + offset);
++      return dw8250_modify_msr(p, offset, value);
+ }
+ static int dw8250_handle_irq(struct uart_port *p)
index 0e8edcfa10aa65e56a9e79a6ac1234cac7ce6f75..c706c2908c2f56acac267429018fea87b1fb3365 100644 (file)
@@ -44,3 +44,4 @@ md-flush-writes-before-starting-a-recovery.patch
 md-make-sure-get_array_info-ioctl-reports-correct-clean-status.patch
 irqchip-spear_shirq-fix-interrupt-offset.patch
 mmc-rtsx-add-r1-no-crc-mmc-command-type-handle.patch
+serial-8250_dw-report-cts-asserted-for-auto-flow.patch