Skip to content

Commit

Permalink
tty: serial: meson: fix hard LOCKUP on crtscts mode
Browse files Browse the repository at this point in the history
commit 2a1d728 upstream.

There might be hard lockup if we set crtscts mode on port without RTS/CTS configured:

# stty -F /dev/ttyAML6 crtscts; echo 1 > /dev/ttyAML6; echo 2 > /dev/ttyAML6
[   95.890386] rcu: INFO: rcu_preempt detected stalls on CPUs/tasks:
[   95.890857] rcu:     3-...0: (201 ticks this GP) idle=e33c/1/0x4000000000000000 softirq=5844/5846 fqs=4984
[   95.900212] rcu:     (detected by 2, t=21016 jiffies, g=7753, q=296 ncpus=4)
[   95.906972] Task dump for CPU 3:
[   95.910178] task:bash            state:R  running task     stack:0     pid:205   ppid:1      flags:0x00000202
[   95.920059] Call trace:
[   95.922485]  __switch_to+0xe4/0x168
[   95.925951]  0xffffff8003477508
[   95.974379] watchdog: Watchdog detected hard LOCKUP on cpu 3
[   95.974424] Modules linked in: 88x2cs(O) rtc_meson_vrtc

Possible solution would be to not allow to setup crtscts on such port.

Tested on S905X3 based board.

Fixes: ff7693d ("ARM: meson: serial: add MesonX SoC on-chip uart driver")
Cc: stable@vger.kernel.org
Signed-off-by: Pavel Krasavin <pkrasavin@imaqliq.com>
Reviewed-by: Neil Armstrong <neil.armstrong@linaro.org>
Reviewed-by: Dmitry Rokosov <ddrokosov@salutedevices.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
  • Loading branch information
Pavel Krasavin authored and gregkh committed Nov 28, 2023
1 parent 82ed328 commit fa71a72
Showing 1 changed file with 11 additions and 3 deletions.
14 changes: 11 additions & 3 deletions drivers/tty/serial/meson_uart.c
Original file line number Diff line number Diff line change
Expand Up @@ -379,10 +379,14 @@ static void meson_uart_set_termios(struct uart_port *port,
else
val |= AML_UART_STOP_BIT_1SB;

if (cflags & CRTSCTS)
val &= ~AML_UART_TWO_WIRE_EN;
else
if (cflags & CRTSCTS) {
if (port->flags & UPF_HARD_FLOW)
val &= ~AML_UART_TWO_WIRE_EN;
else
termios->c_cflag &= ~CRTSCTS;
} else {
val |= AML_UART_TWO_WIRE_EN;
}

writel(val, port->membase + AML_UART_CONTROL);

Expand Down Expand Up @@ -697,6 +701,7 @@ static int meson_uart_probe(struct platform_device *pdev)
u32 fifosize = 64; /* Default is 64, 128 for EE UART_0 */
int ret = 0;
int irq;
bool has_rtscts;

if (pdev->dev.of_node)
pdev->id = of_alias_get_id(pdev->dev.of_node, "serial");
Expand Down Expand Up @@ -724,6 +729,7 @@ static int meson_uart_probe(struct platform_device *pdev)
return irq;

of_property_read_u32(pdev->dev.of_node, "fifo-size", &fifosize);
has_rtscts = of_property_read_bool(pdev->dev.of_node, "uart-has-rtscts");

if (meson_ports[pdev->id]) {
dev_err(&pdev->dev, "port %d already allocated\n", pdev->id);
Expand All @@ -743,6 +749,8 @@ static int meson_uart_probe(struct platform_device *pdev)
port->mapsize = resource_size(res_mem);
port->irq = irq;
port->flags = UPF_BOOT_AUTOCONF | UPF_LOW_LATENCY;
if (has_rtscts)
port->flags |= UPF_HARD_FLOW;
port->has_sysrq = IS_ENABLED(CONFIG_SERIAL_MESON_CONSOLE);
port->dev = &pdev->dev;
port->line = pdev->id;
Expand Down

0 comments on commit fa71a72

Please sign in to comment.