Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

tty: serial: meson: fix hard LOCKUP on crtscts mode

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: ff7693d079e5 ("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>

v6: stable tag added
v5: https://lore.kernel.org/lkml/OF43DA36FF.2BD3BB21-ON00258A47.005A8125-00258A47.005A9513@gdc.ru/
added missed Reviewed-by tags, Fixes tag added according to Dmitry and Neil notes
v4: https://lore.kernel.org/lkml/OF55521400.7512350F-ON00258A47.003F7254-00258A47.0040E15C@gdc.ru/
More correct patch subject according to Jiri's note
v3: https://lore.kernel.org/lkml/OF6CF5FFA0.CCFD0E8E-ON00258A46.00549EDF-00258A46.0054BB62@gdc.ru/
"From:" line added to the mail
v2: https://lore.kernel.org/lkml/OF950BEF72.7F425944-ON00258A46.00488A76-00258A46.00497D44@gdc.ru/
braces for single statement removed according to Dmitry's note
v1: https://lore.kernel.org/lkml/OF28B2B8C9.5BC0CD28-ON00258A46.0037688F-00258A46.0039155B@gdc.ru/
Link: https://lore.kernel.org/r/OF66360032.51C36182-ON00258A48.003F656B-00258A48.0040092C@gdc.ru

Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Pavel Krasavin and committed by
Greg Kroah-Hartman
2a1d728f b0c9a045

+11 -3
+11 -3
drivers/tty/serial/meson_uart.c
··· 380 380 else 381 381 val |= AML_UART_STOP_BIT_1SB; 382 382 383 - if (cflags & CRTSCTS) 384 - val &= ~AML_UART_TWO_WIRE_EN; 385 - else 383 + if (cflags & CRTSCTS) { 384 + if (port->flags & UPF_HARD_FLOW) 385 + val &= ~AML_UART_TWO_WIRE_EN; 386 + else 387 + termios->c_cflag &= ~CRTSCTS; 388 + } else { 386 389 val |= AML_UART_TWO_WIRE_EN; 390 + } 387 391 388 392 writel(val, port->membase + AML_UART_CONTROL); 389 393 ··· 709 705 u32 fifosize = 64; /* Default is 64, 128 for EE UART_0 */ 710 706 int ret = 0; 711 707 int irq; 708 + bool has_rtscts; 712 709 713 710 if (pdev->dev.of_node) 714 711 pdev->id = of_alias_get_id(pdev->dev.of_node, "serial"); ··· 737 732 return irq; 738 733 739 734 of_property_read_u32(pdev->dev.of_node, "fifo-size", &fifosize); 735 + has_rtscts = of_property_read_bool(pdev->dev.of_node, "uart-has-rtscts"); 740 736 741 737 if (meson_ports[pdev->id]) { 742 738 return dev_err_probe(&pdev->dev, -EBUSY, ··· 768 762 port->mapsize = resource_size(res_mem); 769 763 port->irq = irq; 770 764 port->flags = UPF_BOOT_AUTOCONF | UPF_LOW_LATENCY; 765 + if (has_rtscts) 766 + port->flags |= UPF_HARD_FLOW; 771 767 port->has_sysrq = IS_ENABLED(CONFIG_SERIAL_MESON_CONSOLE); 772 768 port->dev = &pdev->dev; 773 769 port->line = pdev->id;