| From e1ca3ff28ab1e2c1e70713ef3fa7943c725742c3 Mon Sep 17 00:00:00 2001 |
| From: Ryo Takakura <ryotkkr98@gmail.com> |
| Date: Sat, 12 Apr 2025 09:18:47 +0900 |
| Subject: serial: sifive: lock port in startup()/shutdown() callbacks |
| |
| From: Ryo Takakura <ryotkkr98@gmail.com> |
| |
| commit e1ca3ff28ab1e2c1e70713ef3fa7943c725742c3 upstream. |
| |
| startup()/shutdown() callbacks access SIFIVE_SERIAL_IE_OFFS. |
| The register is also accessed from write() callback. |
| |
| If console were printing and startup()/shutdown() callback |
| gets called, its access to the register could be overwritten. |
| |
| Add port->lock to startup()/shutdown() callbacks to make sure |
| their access to SIFIVE_SERIAL_IE_OFFS is synchronized against |
| write() callback. |
| |
| Fixes: 45c054d0815b ("tty: serial: add driver for the SiFive UART") |
| Signed-off-by: Ryo Takakura <ryotkkr98@gmail.com> |
| Reviewed-by: Petr Mladek <pmladek@suse.com> |
| Cc: stable@vger.kernel.org |
| Reviewed-by: John Ogness <john.ogness@linutronix.de> |
| Rule: add |
| Link: https://lore.kernel.org/stable/20250330003522.386632-1-ryotkkr98%40gmail.com |
| Link: https://lore.kernel.org/r/20250412001847.183221-1-ryotkkr98@gmail.com |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| drivers/tty/serial/sifive.c | 6 ++++++ |
| 1 file changed, 6 insertions(+) |
| |
| --- a/drivers/tty/serial/sifive.c |
| +++ b/drivers/tty/serial/sifive.c |
| @@ -596,8 +596,11 @@ static void sifive_serial_break_ctl(stru |
| static int sifive_serial_startup(struct uart_port *port) |
| { |
| struct sifive_serial_port *ssp = port_to_sifive_serial_port(port); |
| + unsigned long flags; |
| |
| + uart_port_lock_irqsave(&ssp->port, &flags); |
| __ssp_enable_rxwm(ssp); |
| + uart_port_unlock_irqrestore(&ssp->port, flags); |
| |
| return 0; |
| } |
| @@ -605,9 +608,12 @@ static int sifive_serial_startup(struct |
| static void sifive_serial_shutdown(struct uart_port *port) |
| { |
| struct sifive_serial_port *ssp = port_to_sifive_serial_port(port); |
| + unsigned long flags; |
| |
| + uart_port_lock_irqsave(&ssp->port, &flags); |
| __ssp_disable_rxwm(ssp); |
| __ssp_disable_txwm(ssp); |
| + uart_port_unlock_irqrestore(&ssp->port, flags); |
| } |
| |
| /** |