Message ID | 20240208075216.48915-1-yangyicong@huawei.com |
---|---|
State | New |
Headers | show |
Series | [v3] serial: port: Don't suspend if the port is still busy | expand |
On Thu, Feb 08, 2024 at 09:27:57AM +0100, Jiri Slaby wrote: > On 08. 02. 24, 8:52, Yicong Yang wrote: ... > > static int __serial_port_busy(struct uart_port *port) > > { > > - return !uart_tx_stopped(port) && > > - uart_circ_chars_pending(&port->state->xmit); > > + if (uart_tx_stopped(port)) > > + return 0; > > + > > + if (uart_circ_chars_pending(&port->state->xmit)) > > + return -EBUSY; > > Why do you do this change at all? If anything, __serial_port_busy() should > be made to return a bool and not to return an error. Look how it is named -- > returning EBUSY is sort of unexpected in my eyes. And if this needed to be > done, it should have been in a separate patch anyway. I proposed that with a renaming, so it won't look as boolean. And I also implied (sorry if it was unclear) that this has to be done separately, so we are on the same page about this.
diff --git a/drivers/tty/serial/serial_port.c b/drivers/tty/serial/serial_port.c index 88975a4df306..8d72f7d95009 100644 --- a/drivers/tty/serial/serial_port.c +++ b/drivers/tty/serial/serial_port.c @@ -19,8 +19,13 @@ /* Only considers pending TX for now. Caller must take care of locking */ static int __serial_port_busy(struct uart_port *port) { - return !uart_tx_stopped(port) && - uart_circ_chars_pending(&port->state->xmit); + if (uart_tx_stopped(port)) + return 0; + + if (uart_circ_chars_pending(&port->state->xmit)) + return -EBUSY; + + return 0; } static int serial_port_runtime_resume(struct device *dev) @@ -46,8 +51,33 @@ static int serial_port_runtime_resume(struct device *dev) return 0; } +static int serial_port_runtime_suspend(struct device *dev) +{ + struct serial_port_device *port_dev = to_serial_base_port_device(dev); + struct uart_port *port; + unsigned long flags; + int ret; + + port = port_dev->port; + + if (port->flags & UPF_DEAD) + return 0; + + uart_port_lock_irqsave(port, &flags); + ret = __serial_port_busy(port); + if (ret) + port->ops->start_tx(port); + uart_port_unlock_irqrestore(port, flags); + + if (ret) + pm_runtime_mark_last_busy(dev); + + return ret; +} + static DEFINE_RUNTIME_DEV_PM_OPS(serial_port_pm, - NULL, serial_port_runtime_resume, NULL); + serial_port_runtime_suspend, + serial_port_runtime_resume, NULL); static int serial_port_probe(struct device *dev) {