Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > linux.kernel > #1534887 > unrolled thread

[PATCH 0/2] serial: sh-sci: Assorted flow control fixes

Started byGeert Uytterhoeven <geert+renesas@glider.be>
First post2016-12-02 13:40 +0100
Last post2016-12-02 13:40 +0100
Articles 3 — 1 participant

Back to article view | Back to linux.kernel


Contents

  [PATCH 0/2] serial: sh-sci: Assorted flow control fixes Geert Uytterhoeven <geert+renesas@glider.be> - 2016-12-02 13:40 +0100
    [PATCH 2/2] serial: sh-sci: Fix hang in sci_reset() Geert Uytterhoeven <geert+renesas@glider.be> - 2016-12-02 13:40 +0100
    [PATCH 1/2] serial: sh-sci: Fix early deassertion of dedicated RTS Geert Uytterhoeven <geert+renesas@glider.be> - 2016-12-02 13:40 +0100

#1534887 — [PATCH 0/2] serial: sh-sci: Assorted flow control fixes

FromGeert Uytterhoeven <geert+renesas@glider.be>
Date2016-12-02 13:40 +0100
Subject[PATCH 0/2] serial: sh-sci: Assorted flow control fixes
Message-ID<sJVia-3Rc-5@gated-at.bofh.it>
	Hi Greg, Jiri,

This patch series fixes two issues related to hardware flow control on
Renesas SCIF UARTs.

Thanks!

Geert Uytterhoeven (2):
  serial: sh-sci: Fix early deassertion of dedicated RTS
  serial: sh-sci: Fix hang in sci_reset()

 drivers/tty/serial/sh-sci.c | 12 +++++++++---
 1 file changed, 9 insertions(+), 3 deletions(-)

-- 
1.9.1

Gr{oetje,eeting}s,

						Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
							    -- Linus Torvalds

[toc] | [next] | [standalone]


#1534888 — [PATCH 2/2] serial: sh-sci: Fix hang in sci_reset()

FromGeert Uytterhoeven <geert+renesas@glider.be>
Date2016-12-02 13:40 +0100
Subject[PATCH 2/2] serial: sh-sci: Fix hang in sci_reset()
Message-ID<sJVia-3Rc-15@gated-at.bofh.it>
In reply to#1534887
When the .set_termios() callback resets the UART, it first waits until
all characters in the transmit FIFO have been transmitted, to prevent a
port configuration change from impacting these characters.

However, if the previous user of the UART had dedicated RTS/CTS hardware
flow control enabled, these characters may have been stuck in the FIFO
due to CTS not being asserted. When the new user opens the port,
.set_termios() is called while transmission is still disabled, leading
to an infinite loop:

    NMI watchdog: BUG: soft lockup - CPU#0 stuck for 22s!

This has been observed with SCIFA (on r8a7740/armadillo) and SCIFB (on
r8a7791/koelsch).

The issue does not seem to happen when using:
  - GPIO RTS/CTS hardware flow control,
  - No hardware flow control,
  - HSCIF (on r8a7791/koelsch).

To fix this, wait for the draining of the transmit FIFO only if
transmission is already enabled.

Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
---
To reproduce:

    stty -echo < /dev/scifb0
    stty crtscts < /dev/scifb0
    echo hello > /dev/scifb0	# returns early (wrote to FIFO)
    echo hello > /dev/scifb0	# hangs

 drivers/tty/serial/sh-sci.c | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c
index c503db1900f003ed..db5de80c5399a7bd 100644
--- a/drivers/tty/serial/sh-sci.c
+++ b/drivers/tty/serial/sh-sci.c
@@ -2137,9 +2137,11 @@ static void sci_reset(struct uart_port *port)
 	const struct plat_sci_reg *reg;
 	unsigned int status;
 
-	do {
-		status = serial_port_in(port, SCxSR);
-	} while (!(status & SCxSR_TEND(port)));
+	if (serial_port_in(port, SCSCR) & SCSCR_TE) {
+		do {
+			status = serial_port_in(port, SCxSR);
+		} while (!(status & SCxSR_TEND(port)));
+	}
 
 	serial_port_out(port, SCSCR, 0x00);	/* TE=0, RE=0, CKE1=0 */
 
-- 
1.9.1

[toc] | [prev] | [next] | [standalone]


#1534889 — [PATCH 1/2] serial: sh-sci: Fix early deassertion of dedicated RTS

FromGeert Uytterhoeven <geert+renesas@glider.be>
Date2016-12-02 13:40 +0100
Subject[PATCH 1/2] serial: sh-sci: Fix early deassertion of dedicated RTS
Message-ID<sJVia-3Rc-21@gated-at.bofh.it>
In reply to#1534887
If a UART has dedicated RTS/CTS pins, there are some issues:

1. When changing hardware control flow, the new AUTORTS state is not
   immediately reflected in the hardware, but only when RTS is raised.
   However, the serial core doesn't call .set_mctrl() after
   .set_termios(), hence AUTORTS may only become effective when the port
   is closed, and reopened later.
   Note that this problem does not happen when manually using stty to
   change CRTSCTS, as AUTORTS will work fine on next open.

2. When hardware control flow is disabled (or AUTORTS is not yet
   effective), changing any serial port configuration deasserts RTS, as
   .set_termios() calls sci_init_pins().

To fix both issues, call .set_mctrl() from .set_termios() when dedicated
RTS/CTS pins are present, to refresh the AUTORTS or RTS state.
This is similar to what other drivers supporting AUTORTS do (e.g.
omap-serial).

Reported-by: Baumann, Christoph (C.) <cbaumann@visteon.com> (issue 1)
Fixes: 33f50ffc253854cf ("serial: sh-sci: Fix support for hardware-assisted RTS/CTS")
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
---
Tested on r8a7791/koelsch with HSCIF1 (GPIO hardware flow control),
and HSCIF2 and SCIFB0 (dedicated hardware flow control).

A simple test program (basically "cat" with CRTSCTS configuration
capability) can be found at https://github.com/geertu/sercat

Without this patch the following will fail:

  1. sercat -f /dev/hscif2 &
     seq 100 120 | sercat -f -w /dev/hscif1 # hangs

  2. seq 200 220 | sercat -f -w /dev/hscif2 &
     sercat -f /dev/hscif1 # no data received
---
 drivers/tty/serial/sh-sci.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c
index 91e7dddbf72cd3de..c503db1900f003ed 100644
--- a/drivers/tty/serial/sh-sci.c
+++ b/drivers/tty/serial/sh-sci.c
@@ -2340,6 +2340,10 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios,
 
 		serial_port_out(port, SCFCR, ctrl);
 	}
+	if (port->flags & UPF_HARD_FLOW) {
+		/* Refresh (Auto) RTS */
+		sci_set_mctrl(port, port->mctrl);
+	}
 
 	scr_val |= s->cfg->scscr & ~(SCSCR_CKE1 | SCSCR_CKE0);
 	dev_dbg(port->dev, "SCSCR 0x%x\n", scr_val);
-- 
1.9.1

[toc] | [prev] | [standalone]


Back to top | Article view | linux.kernel


csiph-web