Message ID | 20240509141549.63704-1-hdegoede@redhat.com (mailing list archive) |
---|---|
State | Handled Elsewhere, archived |
Headers | show |
Series | serial: Clear UPF_DEAD before calling tty_port_register_device_attr_serdev() | expand |
On Thu, May 09, 2024 at 04:15:49PM +0200, Hans de Goede wrote: > If a serdev_device_driver is already loaded for a serdev_tty_port when it > gets registered by tty_port_register_device_attr_serdev() then that > driver's probe() method will be called immediately. > > The serdev_device_driver's probe() method should then be able to call > serdev_device_open() successfully, but because UPF_DEAD is still dead > serdev_device_open() will fail with -ENXIO in this scenario: > > serdev_device_open() > ctrl->ops->open() /* this callback being ttyport_open() */ > tty->ops->open() /* this callback being uart_open() */ > tty_port_open() > port->ops->activate() /* this callback being uart_port_activate() */ > Find bit UPF_DEAD is set in uport->flags and fail with errno -ENXIO. > > Fix this be clearing UPF_DEAD before tty_port_register_device_attr_serdev() Looks OK to me: Reviewed-by: Tony Lindgren <tony.lindgren@linux.intel.com>
On Thu, May 9, 2024 at 5:16 PM Hans de Goede <hdegoede@redhat.com> wrote: > > If a serdev_device_driver is already loaded for a serdev_tty_port when it > gets registered by tty_port_register_device_attr_serdev() then that > driver's probe() method will be called immediately. > > The serdev_device_driver's probe() method should then be able to call > serdev_device_open() successfully, but because UPF_DEAD is still dead > serdev_device_open() will fail with -ENXIO in this scenario: > > serdev_device_open() > ctrl->ops->open() /* this callback being ttyport_open() */ > tty->ops->open() /* this callback being uart_open() */ > tty_port_open() > port->ops->activate() /* this callback being uart_port_activate() */ > Find bit UPF_DEAD is set in uport->flags and fail with errno -ENXIO. > > Fix this be clearing UPF_DEAD before tty_port_register_device_attr_serdev() > note this only moves up the UPD_DEAD clearing a small bit, before: > > tty_port_register_device_attr_serdev(); > mutex_unlock(&tty_port.mutex); > uart_port.flags &= ~UPF_DEAD; > mutex_unlock(&port_mutex); > > after: > > uart_port.flags &= ~UPF_DEAD; > tty_port_register_device_attr_serdev(); > mutex_unlock(&tty_port.mutex); > mutex_unlock(&port_mutex); I guess I have given the tag, anyway since Tony OK with this, no more questions: Reviewed-by: Andy Shevchenko <andy@kernel.org>
diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index c476d884356d..b47a277978a0 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c @@ -3211,6 +3211,9 @@ static int serial_core_add_one_port(struct uart_driver *drv, struct uart_port *u if (uport->attr_group) uport->tty_groups[1] = uport->attr_group; + /* Ensure serdev drivers can call serdev_device_open() right away */ + uport->flags &= ~UPF_DEAD; + /* * Register the port whether it's detected or not. This allows * setserial to be used to alter this port's parameters. @@ -3221,6 +3224,7 @@ static int serial_core_add_one_port(struct uart_driver *drv, struct uart_port *u if (!IS_ERR(tty_dev)) { device_set_wakeup_capable(tty_dev, 1); } else { + uport->flags |= UPF_DEAD; dev_err(uport->dev, "Cannot register tty device on line %d\n", uport->line); } @@ -3426,8 +3430,6 @@ int serial_core_register_port(struct uart_driver *drv, struct uart_port *port) if (ret) goto err_unregister_port_dev; - port->flags &= ~UPF_DEAD; - mutex_unlock(&port_mutex); return 0;