Message ID | 20250506112321.61710-1-cuiyunhui@bytedance.com |
---|---|
State | Superseded |
Headers | show |
Series | [v5,1/4] serial: 8250: fix panic due to PSLVERR | expand |
Hi Ilpo, On Tue, May 6, 2025 at 8:35 PM Ilpo Järvinen <ilpo.jarvinen@linux.intel.com> wrote: > > On Tue, 6 May 2025, Yunhui Cui wrote: > > > When the PSLVERR_RESP_EN parameter is set to 1, the device generates > > an error response if an attempt is made to read an empty RBR (Receive > > Buffer Register) while the FIFO is enabled. > > > > In serial8250_do_startup(), calling serial_port_out(port, UART_LCR, > > UART_LCR_WLEN8) triggers dw8250_check_lcr(), which invokes > > dw8250_force_idle() and serial8250_clear_and_reinit_fifos(). The latter > > function enables the FIFO via serial_out(p, UART_FCR, p->fcr). > > Execution proceeds to the dont_test_tx_en label: > > Where is dont_test_tx_en label? Oh, I'll rebase the latest code of linux-next. > > > ... > > serial_port_in(port, UART_RX); > > This satisfies the PSLVERR trigger condition. > > > > Because another CPU(e.g., using printk()) is accessing the UART (UART > > Because -> When ? > > missing space before ( > > > is busy), the current CPU fails the check (value & ~UART_LCR_SPAR) == > > (lcr & ~UART_LCR_SPAR) > > Add: > > ... in dw8250_check_lcr() Okay, it will be updated in the next version. > > >, causing it to enter dw8250_force_idle(). > > > > Put serial_port_out(port, UART_LCR, UART_LCR_WLEN8) under the port->lock > > to fix this issue. > > > > Panic backtrace: > > [ 0.442336] Oops - unknown exception [#1] > > [ 0.442343] epc : dw8250_serial_in32+0x1e/0x4a > > [ 0.442351] ra : serial8250_do_startup+0x2c8/0x88e > > ... > > [ 0.442416] console_on_rootfs+0x26/0x70 > > > > Fixes: c49436b657d0 ("serial: 8250_dw: Improve unwritable LCR workaround") > > Link: https://lore.kernel.org/all/84cydt5peu.fsf@jogness.linutronix.de/T/ > > Signed-off-by: Yunhui Cui <cuiyunhui@bytedance.com> > > --- > > drivers/tty/serial/8250/8250_port.c | 3 ++- > > 1 file changed, 2 insertions(+), 1 deletion(-) > > > > diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c > > index 3f256e96c722..a913135d5217 100644 > > --- a/drivers/tty/serial/8250/8250_port.c > > +++ b/drivers/tty/serial/8250/8250_port.c > > @@ -2380,9 +2380,10 @@ int serial8250_do_startup(struct uart_port *port) > > /* > > * Now, initialize the UART > > */ > > - serial_port_out(port, UART_LCR, UART_LCR_WLEN8); > > > > uart_port_lock_irqsave(port, &flags); > > + serial_port_out(port, UART_LCR, UART_LCR_WLEN8); > > + > > if (up->port.flags & UPF_FOURPORT) { > > if (!up->port.irq) > > up->port.mctrl |= TIOCM_OUT1; > > > > -- > i. > Thanks, Yunhui
diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c index 3f256e96c722..a913135d5217 100644 --- a/drivers/tty/serial/8250/8250_port.c +++ b/drivers/tty/serial/8250/8250_port.c @@ -2380,9 +2380,10 @@ int serial8250_do_startup(struct uart_port *port) /* * Now, initialize the UART */ - serial_port_out(port, UART_LCR, UART_LCR_WLEN8); uart_port_lock_irqsave(port, &flags); + serial_port_out(port, UART_LCR, UART_LCR_WLEN8); + if (up->port.flags & UPF_FOURPORT) { if (!up->port.irq) up->port.mctrl |= TIOCM_OUT1;
When the PSLVERR_RESP_EN parameter is set to 1, the device generates an error response if an attempt is made to read an empty RBR (Receive Buffer Register) while the FIFO is enabled. In serial8250_do_startup(), calling serial_port_out(port, UART_LCR, UART_LCR_WLEN8) triggers dw8250_check_lcr(), which invokes dw8250_force_idle() and serial8250_clear_and_reinit_fifos(). The latter function enables the FIFO via serial_out(p, UART_FCR, p->fcr). Execution proceeds to the dont_test_tx_en label: ... serial_port_in(port, UART_RX); This satisfies the PSLVERR trigger condition. Because another CPU(e.g., using printk()) is accessing the UART (UART is busy), the current CPU fails the check (value & ~UART_LCR_SPAR) == (lcr & ~UART_LCR_SPAR), causing it to enter dw8250_force_idle(). Put serial_port_out(port, UART_LCR, UART_LCR_WLEN8) under the port->lock to fix this issue. Panic backtrace: [ 0.442336] Oops - unknown exception [#1] [ 0.442343] epc : dw8250_serial_in32+0x1e/0x4a [ 0.442351] ra : serial8250_do_startup+0x2c8/0x88e ... [ 0.442416] console_on_rootfs+0x26/0x70 Fixes: c49436b657d0 ("serial: 8250_dw: Improve unwritable LCR workaround") Link: https://lore.kernel.org/all/84cydt5peu.fsf@jogness.linutronix.de/T/ Signed-off-by: Yunhui Cui <cuiyunhui@bytedance.com> --- drivers/tty/serial/8250/8250_port.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)