From nobody Thu Dec 18 00:32:49 2025 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id ABAFFC54FB9 for ; Tue, 21 Nov 2023 11:32:58 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234111AbjKULc7 (ORCPT ); Tue, 21 Nov 2023 06:32:59 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:59040 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234198AbjKULcz (ORCPT ); Tue, 21 Nov 2023 06:32:55 -0500 Received: from muru.com (muru.com [72.249.23.125]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 2A79CD1; Tue, 21 Nov 2023 03:32:50 -0800 (PST) Received: from hillo.muru.com (localhost [127.0.0.1]) by muru.com (Postfix) with ESMTP id D5C8380E2; Tue, 21 Nov 2023 11:32:47 +0000 (UTC) From: Tony Lindgren To: Greg Kroah-Hartman , Jiri Slaby , Petr Mladek , Steven Rostedt , John Ogness , Sergey Senozhatsky Cc: "David S . Miller" , Andy Shevchenko , Dhruva Gole , =?UTF-8?q?Ilpo=20J=C3=A4rvinen?= , Johan Hovold , Sebastian Andrzej Siewior , Vignesh Raghavendra , linux-kernel@vger.kernel.org, linux-serial@vger.kernel.org Subject: [PATCH v3 1/3] printk: Save console options for add_preferred_console_match() Date: Tue, 21 Nov 2023 13:31:55 +0200 Message-ID: <20231121113203.61341-2-tony@atomide.com> X-Mailer: git-send-email 2.42.1 In-Reply-To: <20231121113203.61341-1-tony@atomide.com> References: <20231121113203.61341-1-tony@atomide.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" Driver subsystems may need to translate the preferred console name to the character device name used. We already do some of this in console_setup() with a few hardcoded names, but that does not scale well. The console options are parsed early in console_setup(), and the consoles are added with __add_preferred_console(). At this point we don't know much about the character device names and device drivers getting probed. To allow drivers subsystems to set up a preferred console, let's save the kernel command line console options. To add a preferred console, let's add a new function add_preferred_console_match(). This allows the serial core layer to support console=3DDEVNAME:0.0 style hardware based addressing in addition to the current console=3DttyS0 style naming. And we can start moving console_setup() character device parsing to the driver subsystem specific code. We use a separate array from the console_cmdline array as the character device name and index may be unknown at the console_setup() time. And we do not want to call __add_preferred_console() until the character device name and index are known. Adding the console name in addition to the character device name, and a flag for an added console, could be added to the struct console_cmdline. And the console_cmdline array handling modified accordingly. But that complicates things compared saving the console options, and then adding the consoles when the subsystems handling the consoles are ready. Signed-off-by: Tony Lindgren --- include/linux/printk.h | 3 + kernel/printk/Makefile | 2 +- kernel/printk/conopt.c | 115 ++++++++++++++++++++++++++++++++ kernel/printk/console_cmdline.h | 4 ++ kernel/printk/printk.c | 11 ++- 5 files changed, 131 insertions(+), 4 deletions(-) create mode 100644 kernel/printk/conopt.c diff --git a/include/linux/printk.h b/include/linux/printk.h --- a/include/linux/printk.h +++ b/include/linux/printk.h @@ -60,6 +60,9 @@ static inline const char *printk_skip_headers(const char = *buffer) #define CONSOLE_LOGLEVEL_DEFAULT CONFIG_CONSOLE_LOGLEVEL_DEFAULT #define CONSOLE_LOGLEVEL_QUIET CONFIG_CONSOLE_LOGLEVEL_QUIET =20 +int add_preferred_console_match(const char *match, const char *name, + const short idx); + extern int console_printk[]; =20 #define console_loglevel (console_printk[0]) diff --git a/kernel/printk/Makefile b/kernel/printk/Makefile --- a/kernel/printk/Makefile +++ b/kernel/printk/Makefile @@ -1,5 +1,5 @@ # SPDX-License-Identifier: GPL-2.0-only -obj-y =3D printk.o +obj-y =3D printk.o conopt.o obj-$(CONFIG_PRINTK) +=3D printk_safe.o nbcon.o obj-$(CONFIG_A11Y_BRAILLE_CONSOLE) +=3D braille.o obj-$(CONFIG_PRINTK_INDEX) +=3D index.o diff --git a/kernel/printk/conopt.c b/kernel/printk/conopt.c new file mode 100644 --- /dev/null +++ b/kernel/printk/conopt.c @@ -0,0 +1,115 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Kernel command line console options for hardware based addressing + * + * Copyright (C) 2023 Texas Instruments Incorporated - https://www.ti.com/ + * Author: Tony Lindgren + */ + +#include +#include + +#include "console_cmdline.h" + +/* + * Allow longer DEVNAME:0.0 style console naming such as abcd0000.serial:0= .0 + * in addition to the legacy ttyS0 style naming. + */ +#define CONSOLE_NAME_MAX 32 + +#define CONSOLE_OPT_MAX 16 + +struct console_option { + char name[CONSOLE_NAME_MAX]; + char opt[CONSOLE_OPT_MAX]; +}; + +/* Updated only at console_setup() time, no locking needed */ +static struct console_option conopt[MAX_CMDLINECONSOLES]; + +/** + * console_opt_save - Saves kernel command line console option for driver = use + * @str: Kernel command line console name and option + * + * Saves a kernel command line console option for driver subsystems to use= for + * adding a preferred console during init. Called from console_setup() onl= y. + */ +int __init console_opt_save(char *str) +{ + struct console_option *con; + const char *opt =3D NULL; + size_t namelen, optlen; + int i; + + namelen =3D strcspn(str, ","); + if (!namelen) + return -EINVAL; + + optlen =3D strlen(str) - namelen; + if (optlen > 1) + opt =3D str + namelen + 1; + + if (namelen >=3D CONSOLE_NAME_MAX || optlen >=3D CONSOLE_OPT_MAX) + return -EINVAL; + + for (i =3D 0; i < MAX_CMDLINECONSOLES; i++) { + con =3D &conopt[i]; + + if (con->name[0]) { + if (!strncmp(str, con->name, namelen)) + return 0; + continue; + } + + strscpy(con->name, str, namelen + 1); + if (opt) + strscpy(con->opt, opt, optlen + 1); + + return 0; + } + + return -ENOMEM; +} + +static struct console_option *console_opt_find(const char *name) +{ + struct console_option *con; + int i; + + for (i =3D 0; i < MAX_CMDLINECONSOLES; i++) { + con =3D &conopt[i]; + if (!strcmp(name, con->name)) + return con; + } + + return NULL; +} + +/** + * add_preferred_console_match - Adds a preferred console if a match is fo= und + * @match: Expected console on kernel command line, such as console=3DDEVN= AME:0.0 + * @name: Name of the console character device to add such as ttyS + * @idx: Index for the console + * + * Allows driver subsystems to add a console after translating the command + * line name to the character device name used for the console. Options are + * added automatically based on the kernel command line. Duplicate preferr= ed + * consoles are ignored by __add_preferred_console(). + */ +int add_preferred_console_match(const char *match, const char *name, + const short idx) +{ + struct console_option *con; + + if (!match || !strlen(match) || !name || !strlen(name) || + idx < 0) + return -EINVAL; + + con =3D console_opt_find(match); + if (!con) + return -ENOENT; + + add_preferred_console(name, idx, con->opt); + + return 0; +} diff --git a/kernel/printk/console_cmdline.h b/kernel/printk/console_cmdlin= e.h --- a/kernel/printk/console_cmdline.h +++ b/kernel/printk/console_cmdline.h @@ -2,6 +2,10 @@ #ifndef _CONSOLE_CMDLINE_H #define _CONSOLE_CMDLINE_H =20 +#define MAX_CMDLINECONSOLES 8 + +int console_opt_save(char *str); + struct console_cmdline { char name[16]; /* Name of the driver */ diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c --- a/kernel/printk/printk.c +++ b/kernel/printk/printk.c @@ -360,9 +360,6 @@ static int console_locked; /* * Array of consoles built from command line options (console=3D) */ - -#define MAX_CMDLINECONSOLES 8 - static struct console_cmdline console_cmdline[MAX_CMDLINECONSOLES]; =20 static int preferred_console =3D -1; @@ -2445,6 +2442,14 @@ static int __init console_setup(char *str) char *s, *options, *brl_options =3D NULL; int idx; =20 + /* + * Save the console for possible driver subsystem use. Bail out early + * for DEVICE:0.0 style console names as the character device name is + * be unknown at this point. + */ + if (!console_opt_save(str) && strchr(str, ':')) + return 1; + /* * console=3D"" or console=3Dnull have been suggested as a way to * disable console output. Use ttynull that has been created --=20 2.42.1 From nobody Thu Dec 18 00:32:49 2025 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 55B14C54FB9 for ; Tue, 21 Nov 2023 11:33:16 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234363AbjKULdP (ORCPT ); Tue, 21 Nov 2023 06:33:15 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:59572 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234335AbjKULdC (ORCPT ); Tue, 21 Nov 2023 06:33:02 -0500 Received: from muru.com (muru.com [72.249.23.125]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id C2DA9CA; Tue, 21 Nov 2023 03:32:57 -0800 (PST) Received: from hillo.muru.com (localhost [127.0.0.1]) by muru.com (Postfix) with ESMTP id B942D80CC; Tue, 21 Nov 2023 11:32:54 +0000 (UTC) From: Tony Lindgren To: Greg Kroah-Hartman , Jiri Slaby Cc: "David S . Miller" , Petr Mladek , Sergey Senozhatsky , Steven Rostedt , Andy Shevchenko , Dhruva Gole , =?UTF-8?q?Ilpo=20J=C3=A4rvinen?= , John Ogness , Johan Hovold , Sebastian Andrzej Siewior , Vignesh Raghavendra , linux-kernel@vger.kernel.org, linux-serial@vger.kernel.org Subject: [PATCH v3 2/3] serial: core: Add support for DEVNAME:0.0 style naming for kernel console Date: Tue, 21 Nov 2023 13:31:56 +0200 Message-ID: <20231121113203.61341-3-tony@atomide.com> X-Mailer: git-send-email 2.42.1 In-Reply-To: <20231121113203.61341-1-tony@atomide.com> References: <20231121113203.61341-1-tony@atomide.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" We can now add hardware based addressing for serial ports. Starting with commit 84a9582fd203 ("serial: core: Start managing serial controllers to enable runtime PM"), and all the related fixes to this commit, the serial core now knows to which serial port controller the ports are connected. The serial ports can be addressed with DEVNAME:0.0 style naming. The names are something like 00:04:0.0 for a serial port on qemu, and something like 2800000.serial:0.0 on platform device using systems like ARM64 for example. The DEVNAME is the unique serial port hardware controller device name, AKA the name for port->dev. The 0.0 are the serial core controller id and port id. Typically 0.0 are used for each controller and port instance unless the serial port hardware controller has multiple controllers or ports. Using DEVNAME:0.0 style naming actually solves two long term issues for addressing the serial ports: 1. According to Andy Shevchenko, using DEVNAME:0.0 style naming fixes an issue where depending on the BIOS settings, the kernel serial port ttyS instance number may change if HSUART is enabled 2. Device tree using architectures no longer necessarily need to specify aliases to find a specific serial port, and we can just allocate the ttyS instance numbers dynamically in whatever probe order To do this, let's match the hardware addressing style console name to the character device name used, and add a preferred console using the character device device name. Signed-off-by: Tony Lindgren --- drivers/tty/serial/serial_base.h | 14 ++++++++++ drivers/tty/serial/serial_base_bus.c | 38 ++++++++++++++++++++++++++++ drivers/tty/serial/serial_core.c | 4 +++ 3 files changed, 56 insertions(+) diff --git a/drivers/tty/serial/serial_base.h b/drivers/tty/serial/serial_b= ase.h --- a/drivers/tty/serial/serial_base.h +++ b/drivers/tty/serial/serial_base.h @@ -45,3 +45,17 @@ void serial_ctrl_unregister_port(struct uart_driver *drv= , struct uart_port *port =20 int serial_core_register_port(struct uart_driver *drv, struct uart_port *p= ort); void serial_core_unregister_port(struct uart_driver *drv, struct uart_port= *port); + +#ifdef CONFIG_SERIAL_CORE_CONSOLE + +int serial_base_add_preferred_console(struct uart_driver *drv, + struct uart_port *port); +#else +static inline +int serial_base_add_preferred_console(struct uart_driver *drv, + struct uart_port *port) +{ + return 0; +} + +#endif diff --git a/drivers/tty/serial/serial_base_bus.c b/drivers/tty/serial/seri= al_base_bus.c --- a/drivers/tty/serial/serial_base_bus.c +++ b/drivers/tty/serial/serial_base_bus.c @@ -204,6 +204,44 @@ void serial_base_port_device_remove(struct serial_port= _device *port_dev) put_device(&port_dev->dev); } =20 +#ifdef CONFIG_SERIAL_CORE_CONSOLE + +/* + * serial_base_add_preferred_console - Adds a preferred console + * @drv: Serial port device driver + * @port: Serial port instance + * + * Tries to add a preferred console for a serial port if specified in the + * kernel command line. Supports both the traditional character device such + * as console=3DttyS0, and a hardware addressing based console=3DDEVNAME:0= .0 + * style name. + * + * Translates the kernel command line option using a hardware based addres= sing + * console=3DDEVNAME:0.0 to the serial port character device such as ttyS0. + * + * Note that duplicates are ignored by add_preferred_console(). + */ +int serial_base_add_preferred_console(struct uart_driver *drv, + struct uart_port *port) +{ + const char *port_match __free(kfree); + int ret; + + port_match =3D kasprintf(GFP_KERNEL, "%s:%i.%i", dev_name(port->dev), + port->ctrl_id, port->port_id); + if (!port_match) + return -ENOMEM; + + /* Translate a hardware addressing style console=3DDEVNAME:0.0 */ + ret =3D add_preferred_console_match(port_match, drv->dev_name, port->line= ); + if (ret && ret !=3D -ENOENT) + return ret; + + return 0; +} + +#endif + static int serial_base_init(void) { int ret; diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_c= ore.c --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c @@ -3359,6 +3359,10 @@ int serial_core_register_port(struct uart_driver *dr= v, struct uart_port *port) if (ret) goto err_unregister_ctrl_dev; =20 + ret =3D serial_base_add_preferred_console(drv, port); + if (ret) + goto err_unregister_port_dev; + ret =3D serial_core_add_one_port(drv, port); if (ret) goto err_unregister_port_dev; --=20 2.42.1 From nobody Thu Dec 18 00:32:49 2025 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 815BAC61D92 for ; Tue, 21 Nov 2023 11:33:24 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234335AbjKULdY (ORCPT ); Tue, 21 Nov 2023 06:33:24 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:59630 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233753AbjKULdM (ORCPT ); Tue, 21 Nov 2023 06:33:12 -0500 Received: from muru.com (muru.com [72.249.23.125]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 5187511A; Tue, 21 Nov 2023 03:33:04 -0800 (PST) Received: from hillo.muru.com (localhost [127.0.0.1]) by muru.com (Postfix) with ESMTP id 6933880CC; Tue, 21 Nov 2023 11:33:01 +0000 (UTC) From: Tony Lindgren To: Greg Kroah-Hartman , Jiri Slaby , Petr Mladek , Steven Rostedt , John Ogness , Sergey Senozhatsky Cc: "David S . Miller" , Andy Shevchenko , Dhruva Gole , =?UTF-8?q?Ilpo=20J=C3=A4rvinen?= , Johan Hovold , Sebastian Andrzej Siewior , Vignesh Raghavendra , linux-kernel@vger.kernel.org, linux-serial@vger.kernel.org Subject: [PATCH v3 3/3] serial: core: Move console character device handling from printk Date: Tue, 21 Nov 2023 13:31:57 +0200 Message-ID: <20231121113203.61341-4-tony@atomide.com> X-Mailer: git-send-email 2.42.1 In-Reply-To: <20231121113203.61341-1-tony@atomide.com> References: <20231121113203.61341-1-tony@atomide.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" There's no need for console_setup() to try to figure out the console character device name for serial ports early on before uart_add_one_port() has been called. And for early debug console we have earlycon. Let's handle the serial port specific commandline options in the serial core subsystem and drop the handling from printk. The serial core subsystem can just call add_preferred_console() when the serial port is getting initialized. Note that eventually we may want to set up driver specific console quirk handling for the serial port device drivers to use. But we need to figure out which driver(s) need to call the quirk. So for now, we just move the sparc quirk and handle it directly. Signed-off-by: Tony Lindgren --- drivers/tty/serial/serial_base_bus.c | 66 ++++++++++++++++++++++++++++ kernel/printk/printk.c | 30 +------------ 2 files changed, 67 insertions(+), 29 deletions(-) diff --git a/drivers/tty/serial/serial_base_bus.c b/drivers/tty/serial/seri= al_base_bus.c --- a/drivers/tty/serial/serial_base_bus.c +++ b/drivers/tty/serial/serial_base_bus.c @@ -206,6 +206,43 @@ void serial_base_port_device_remove(struct serial_port= _device *port_dev) =20 #ifdef CONFIG_SERIAL_CORE_CONSOLE =20 +#ifdef __sparc__ + +/* Handle Sparc ttya and ttyb options as done in console_setup() */ +static int serial_base_add_sparc_console(struct uart_driver *drv, + struct uart_port *port) +{ + const char *name =3D NULL; + int ret; + + switch (port->line) { + case 0: + name =3D "ttya"; + break; + case 1: + name =3D "ttyb"; + break; + default: + return 0; + } + + ret =3D add_preferred_console_match(name, drv->dev_name, port->line); + if (ret && ret !=3D -ENOENT) + return ret; + + return 0; +} + +#else + +static inline int serial_base_add_sparc_console(struct uart_driver *drv, + struct uart_port *port) +{ + return 0; +} + +#endif + /* * serial_base_add_preferred_console - Adds a preferred console * @drv: Serial port device driver @@ -225,6 +262,8 @@ int serial_base_add_preferred_console(struct uart_drive= r *drv, struct uart_port *port) { const char *port_match __free(kfree); + const char *char_match __free(kfree); + const char *nmbr_match __free(kfree); int ret; =20 port_match =3D kasprintf(GFP_KERNEL, "%s:%i.%i", dev_name(port->dev), @@ -232,6 +271,33 @@ int serial_base_add_preferred_console(struct uart_driv= er *drv, if (!port_match) return -ENOMEM; =20 + char_match =3D kasprintf(GFP_KERNEL, "%s%i", drv->dev_name, port->line); + if (!char_match) + return -ENOMEM; + + /* Handle ttyS specific options */ + if (!strncmp(drv->dev_name, "ttyS", 4)) { + /* No name, just a number */ + nmbr_match =3D kasprintf(GFP_KERNEL, "%i", port->line); + if (!nmbr_match) + return -ENODEV; + + ret =3D add_preferred_console_match(nmbr_match, drv->dev_name, + port->line); + if (ret && ret !=3D -ENOENT) + return ret; + + /* Sparc ttya and ttyb */ + ret =3D serial_base_add_sparc_console(drv, port); + if (ret) + return ret; + } + + /* Handle the traditional character device name style console=3DttyS0 */ + ret =3D add_preferred_console_match(char_match, drv->dev_name, port->line= ); + if (ret && ret !=3D -ENOENT) + return ret; + /* Translate a hardware addressing style console=3DDEVNAME:0.0 */ ret =3D add_preferred_console_match(port_match, drv->dev_name, port->line= ); if (ret && ret !=3D -ENOENT) diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c --- a/kernel/printk/printk.c +++ b/kernel/printk/printk.c @@ -2438,9 +2438,7 @@ __setup("console_msg_format=3D", console_msg_format_s= etup); */ static int __init console_setup(char *str) { - char buf[sizeof(console_cmdline[0].name) + 4]; /* 4 for "ttyS" */ - char *s, *options, *brl_options =3D NULL; - int idx; + char *brl_options =3D NULL; =20 /* * Save the console for possible driver subsystem use. Bail out early @@ -2463,32 +2461,6 @@ static int __init console_setup(char *str) if (_braille_console_setup(&str, &brl_options)) return 1; =20 - /* - * Decode str into name, index, options. - */ - if (str[0] >=3D '0' && str[0] <=3D '9') { - strcpy(buf, "ttyS"); - strncpy(buf + 4, str, sizeof(buf) - 5); - } else { - strncpy(buf, str, sizeof(buf) - 1); - } - buf[sizeof(buf) - 1] =3D 0; - options =3D strchr(str, ','); - if (options) - *(options++) =3D 0; -#ifdef __sparc__ - if (!strcmp(str, "ttya")) - strcpy(buf, "ttyS0"); - if (!strcmp(str, "ttyb")) - strcpy(buf, "ttyS1"); -#endif - for (s =3D buf; *s; s++) - if (isdigit(*s) || *s =3D=3D ',') - break; - idx =3D simple_strtoul(s, NULL, 10); - *s =3D 0; - - __add_preferred_console(buf, idx, options, brl_options, true); return 1; } __setup("console=3D", console_setup); --=20 2.42.1