serial: core: Add serial_base_match_and_update_preferred_console()
authorTony Lindgren <tony.lindgren@linux.intel.com>
Wed, 3 Jul 2024 10:06:09 +0000 (13:06 +0300)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 4 Jul 2024 13:41:44 +0000 (15:41 +0200)
Let's add serial_base_match_and_update_preferred_console() for consoles
using DEVNAME:0.0 style naming.

The earlier approach to add it caused issues in the kernel command line
ordering as we were calling __add_preferred_console() again for the
deferred consoles.

Signed-off-by: Tony Lindgren <tony.lindgren@linux.intel.com>
Reviewed-by: Petr Mladek <pmladek@suse.com>
Tested-by: Petr Mladek <pmladek@suse.com>
Link: https://lore.kernel.org/r/20240703100615.118762-3-tony.lindgren@linux.intel.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/tty/serial/serial_base.h
drivers/tty/serial/serial_base_bus.c
drivers/tty/serial/serial_core.c

index b6c38d2edfd401a79a937c0d149cbbb77ee3b342..0d50db5b660b0338bd49d7583a2ce61484482298 100644 (file)
@@ -49,3 +49,19 @@ void serial_ctrl_unregister_port(struct uart_driver *drv, struct uart_port *port
 
 int serial_core_register_port(struct uart_driver *drv, struct uart_port *port);
 void serial_core_unregister_port(struct uart_driver *drv, struct uart_port *port);
+
+#ifdef CONFIG_SERIAL_CORE_CONSOLE
+
+int serial_base_match_and_update_preferred_console(struct uart_driver *drv,
+                                                  struct uart_port *port);
+
+#else
+
+static inline
+int serial_base_match_and_update_preferred_console(struct uart_driver *drv,
+                                                  struct uart_port *port)
+{
+       return 0;
+}
+
+#endif
index 4df2a4b10445adde43e83d4b8bd8543a132a1872..d822499ba9d689665b0986ba0f0636920b9c5db4 100644 (file)
@@ -8,6 +8,7 @@
  * The serial core bus manages the serial core controller instances.
  */
 
+#include <linux/cleanup.h>
 #include <linux/container_of.h>
 #include <linux/device.h>
 #include <linux/idr.h>
@@ -204,6 +205,42 @@ void serial_base_port_device_remove(struct serial_port_device *port_dev)
        put_device(&port_dev->dev);
 }
 
+#ifdef CONFIG_SERIAL_CORE_CONSOLE
+
+/**
+ * serial_base_match_and_update_preferred_console - Match and update a preferred console
+ * @drv: Serial port device driver
+ * @port: Serial port instance
+ *
+ * Tries to match and update the preferred console for a serial port for
+ * the kernel command line option console=DEVNAME:0.0.
+ *
+ * Cannot be called early for ISA ports, depends on struct device.
+ *
+ * Return: 0 on success, negative error code on failure.
+ */
+int serial_base_match_and_update_preferred_console(struct uart_driver *drv,
+                                                  struct uart_port *port)
+{
+       const char *port_match __free(kfree) = NULL;
+       int ret;
+
+       port_match = kasprintf(GFP_KERNEL, "%s:%d.%d", dev_name(port->dev),
+                              port->ctrl_id, port->port_id);
+       if (!port_match)
+               return -ENOMEM;
+
+       ret = match_devname_and_update_preferred_console(port_match,
+                                                        drv->dev_name,
+                                                        port->line);
+       if (ret == -ENOENT)
+               return 0;
+
+       return ret;
+}
+
+#endif
+
 static int serial_base_init(void)
 {
        int ret;
index 2a8006e3d68786af3b9f5a6d067541f960d4d5fb..9a18d0b95a41909d2dfdc758ae464b611aecf4d7 100644 (file)
@@ -3422,6 +3422,10 @@ int serial_core_register_port(struct uart_driver *drv, struct uart_port *port)
        if (ret)
                goto err_unregister_ctrl_dev;
 
+       ret = serial_base_match_and_update_preferred_console(drv, port);
+       if (ret)
+               goto err_unregister_port_dev;
+
        ret = serial_core_add_one_port(drv, port);
        if (ret)
                goto err_unregister_port_dev;