Skip to content

Commit 1aa4ad4

Browse files
tmlindgregkh
authored andcommitted
serial: core: Fix missing shutdown and startup for serial base port
We are seeing start_tx being called after port shutdown as noted by Jiri. This happens because we are missing the startup and shutdown related functions for the serial base port. Let's fix the issue by adding startup and shutdown functions for the serial base port to block tx flushing for the serial base port when the port is not in use. Fixes: 84a9582 ("serial: core: Start managing serial controllers to enable runtime PM") Cc: stable <stable@kernel.org> Reported-by: Jiri Slaby <jirislaby@kernel.org> Signed-off-by: Tony Lindgren <tony@atomide.com> Link: https://lore.kernel.org/r/20240411055848.38190-1-tony@atomide.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent 9cf7ea2 commit 1aa4ad4

File tree

3 files changed

+55
-3
lines changed

3 files changed

+55
-3
lines changed

drivers/tty/serial/serial_base.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ struct serial_ctrl_device {
2222
struct serial_port_device {
2323
struct device dev;
2424
struct uart_port *port;
25+
unsigned int tx_enabled:1;
2526
};
2627

2728
int serial_base_ctrl_init(void);
@@ -30,6 +31,9 @@ void serial_base_ctrl_exit(void);
3031
int serial_base_port_init(void);
3132
void serial_base_port_exit(void);
3233

34+
void serial_base_port_startup(struct uart_port *port);
35+
void serial_base_port_shutdown(struct uart_port *port);
36+
3337
int serial_base_driver_register(struct device_driver *driver);
3438
void serial_base_driver_unregister(struct device_driver *driver);
3539

drivers/tty/serial/serial_core.c

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -323,16 +323,26 @@ static int uart_startup(struct tty_struct *tty, struct uart_state *state,
323323
bool init_hw)
324324
{
325325
struct tty_port *port = &state->port;
326+
struct uart_port *uport;
326327
int retval;
327328

328329
if (tty_port_initialized(port))
329-
return 0;
330+
goto out_base_port_startup;
330331

331332
retval = uart_port_startup(tty, state, init_hw);
332-
if (retval)
333+
if (retval) {
333334
set_bit(TTY_IO_ERROR, &tty->flags);
335+
return retval;
336+
}
334337

335-
return retval;
338+
out_base_port_startup:
339+
uport = uart_port_check(state);
340+
if (!uport)
341+
return -EIO;
342+
343+
serial_base_port_startup(uport);
344+
345+
return 0;
336346
}
337347

338348
/*
@@ -355,6 +365,9 @@ static void uart_shutdown(struct tty_struct *tty, struct uart_state *state)
355365
if (tty)
356366
set_bit(TTY_IO_ERROR, &tty->flags);
357367

368+
if (uport)
369+
serial_base_port_shutdown(uport);
370+
358371
if (tty_port_initialized(port)) {
359372
tty_port_set_initialized(port, false);
360373

@@ -1775,6 +1788,7 @@ static void uart_tty_port_shutdown(struct tty_port *port)
17751788
uport->ops->stop_rx(uport);
17761789
uart_port_unlock_irq(uport);
17771790

1791+
serial_base_port_shutdown(uport);
17781792
uart_port_shutdown(port);
17791793

17801794
/*

drivers/tty/serial/serial_port.c

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,12 @@ static int serial_port_runtime_resume(struct device *dev)
3939

4040
/* Flush any pending TX for the port */
4141
uart_port_lock_irqsave(port, &flags);
42+
if (!port_dev->tx_enabled)
43+
goto unlock;
4244
if (__serial_port_busy(port))
4345
port->ops->start_tx(port);
46+
47+
unlock:
4448
uart_port_unlock_irqrestore(port, flags);
4549

4650
out:
@@ -60,6 +64,11 @@ static int serial_port_runtime_suspend(struct device *dev)
6064
return 0;
6165

6266
uart_port_lock_irqsave(port, &flags);
67+
if (!port_dev->tx_enabled) {
68+
uart_port_unlock_irqrestore(port, flags);
69+
return 0;
70+
}
71+
6372
busy = __serial_port_busy(port);
6473
if (busy)
6574
port->ops->start_tx(port);
@@ -71,6 +80,31 @@ static int serial_port_runtime_suspend(struct device *dev)
7180
return busy ? -EBUSY : 0;
7281
}
7382

83+
static void serial_base_port_set_tx(struct uart_port *port,
84+
struct serial_port_device *port_dev,
85+
bool enabled)
86+
{
87+
unsigned long flags;
88+
89+
uart_port_lock_irqsave(port, &flags);
90+
port_dev->tx_enabled = enabled;
91+
uart_port_unlock_irqrestore(port, flags);
92+
}
93+
94+
void serial_base_port_startup(struct uart_port *port)
95+
{
96+
struct serial_port_device *port_dev = port->port_dev;
97+
98+
serial_base_port_set_tx(port, port_dev, true);
99+
}
100+
101+
void serial_base_port_shutdown(struct uart_port *port)
102+
{
103+
struct serial_port_device *port_dev = port->port_dev;
104+
105+
serial_base_port_set_tx(port, port_dev, false);
106+
}
107+
74108
static DEFINE_RUNTIME_DEV_PM_OPS(serial_port_pm,
75109
serial_port_runtime_suspend,
76110
serial_port_runtime_resume, NULL);

0 commit comments

Comments
 (0)