mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH v5 00/16] printk: Clean up preferred console handling
@ 2026-09-29 12:05 Petr Mladek
  2026-09-29 12:05 ` [PATCH v5 01/16] printk: Rename struct console_cmdline to preferred_console Petr Mladek
                   ` (15 more replies)
  0 siblings, 16 replies; 17+ messages in thread
From: Petr Mladek @ 2026-09-29 12:05 UTC (permalink / raw)
  To: John Ogness
  Cc: Sergey Senozhatsky, Steven Rostedt, Marcos Paulo de Souza,
	Chris Down, Naveen Kumar Chaudhary, linux-kernel, Petr Mladek

Hi,

this patchset does some clean up of the code for handling preferred
consoles in the console registration code.

It is a prerequisite for Marcos' clean up of CON_ENABLE
flag handling. It should prevent regressions caused by the
hidden effects of try_enable_preferred_console(), for example,
see https://lore.kernel.org/r/89409a0f48e6998ff6dd2245691b9954f0e1e435.camel@suse.com

Also I am working on a feature which would allow to explicitly
enable/prefer consoles proposed by SPCR, device tree, or
platform-specific code using a generic "console=platform".
This clean up is a prerequisite, see
https://github.com/pmladek/linux/tree/console-platform-poc1-iter9

Note: I split the 4th patch => should be easier for review than v4 ;-) /o\

Important: An extra fix is needed to get the Braille console
	working on a serial port using NBCON API, see
	https://lore.kernel.org/r/20260922072558.98854-1-pmladek@suse.com
	https://lore.kernel.org/r/20260925141729.173943-1-pmladek@suse.com


Changes against [v4]:

  + Removed 1st patch from v4. Already in upstream.

  +  Cleanup _braille_(un)register_console() wrappers already in 3rd
     patch. is_braille_console_preferred() will be needed sooner.

  + Split 4th patch. Start with reshufling the add_preferred_console()
    code without any functional changes. Add the various checks
    and behavior changes one by one is a followup patches.

  + Rework the code to make it clear when it is a new entry or an update.

  + Put back braille_set_options() which just updates the optional
    entry. The logic when the value should get updated is the same
    as for pc->options.

  + Make sure that options can be overridden by the command line.

  + Add preferred_dev_node to remember the ordering of preferred consoles.
    Use it when the last one becomes Braille. The previous version tried to
    remembered just the last preferred console. But the logic because
    pretty complicated when I tried to make it error proof. AI was
    able to find many scenarios where it broke. The list is
    the ultimate solution and is easier in the end.

  + Use console_call_setup() in braille_register_console() instead
    of duplicating the code [John]


Changes against [v3]:

  + Move the handling of pre-enabled consoles into register_console()
    as 1st patch. It prevents a possible invalid access. [Petr]

  + Move the code for handling pre-enabled to console to
    try_enable_console() in 7th patch. The resulting code
    is the same as in v3.

    This 2nd move was not needed in v3 because the code
    was moved to this final location later. [Petr]

  + Switch order of the 10th and 11th patch. Aka make
    try_enable_default_console() return an err before
    refactoring try_enable_console() call
    try_enable_preferred_console() only when there is any.
    [Petr]

  + Initialize err value in try_enable_console() in 11th patch.
    It prevents using a non-initialized variable. [AI:gemini-3]

  + Make sure that pre-enabled consoles won't get registered
    when something went wrong in try_enable_console()
    in 11th patch [Petr]


Changes against [v2]:

  + Move static_assert() after declaration (1st patch) [Steven]

  + Rename update_preferred_console() to add_or_update_preferred_console() [John]
  + WARN_ON() when called without "name" and "devname" [John]
  + print error when reached MAX_PREFERRED_CONSOLES
  + Add comment above code adding new entries [John]
    (all in 4th patch)

  + Call console->setup() under console_lock() in braille_register_console()
    (new patch) [Sashiko]

  + Use "No functional changes." phrase in commit messages. [Steven]

  + Call try_enable_preferred_console() only when there is no
    preferred console (reworked and split 9th patch) [Petr]

  + Added taken Reviewed-by and Acked-by tags [John, Macros]


Changes against [v1]:

  + Fix stale comment (1st patch, Chris)

  + Add comment descibing update_preferred_console() behavior (3rd patch, John)

  + Better describe behavior changes caused by update_preferred_console()
    in the commit message (3rd patch, Chris)

  + Use unsigned int for iterating/indexing preferred_consoles[]
    table (3rd patch, John)

  + Add a check preventing an update via "devname" is already assigned
    to a real "name". (3rd patch, Petr)

  + Use only Braille entries when trying to enable Braille console (Chris)

  + Split all try_enable_*console() calls into new try_enable_console()
    and return early when try_enable_braille_console() succeeded.
    Note that we do not longer need to initialize "err" variable
    in this case. (new 5th patch, Chris, Petr)

  + Put back the explicit check of CON_BRL flag in register_console()
    so that it returns prelimitary only when the driver is used in Braille
    mode. (6th patch, Chris, Petr)

  + Add comments explaining that try_enable_braille_console() might succeeded
    also when newcon->match() succeeded. In this case, the Braille mode can't
    be used because the console device was already used as an early console.[*]
    (6th patch, Chris, Petr)

  + Reset preferred_dev_console_prev when used to revert the value.
    (7th patch, John)

  + Add Acked-by and Reviewed-by tags (1st, 2nd, 4th patch, Chris, Marcos)


[v1] https://lore.kernel.org/r/20260206165002.496724-1-pmladek@suse.com
[v2] https://lore.kernel.org/r/20260423130015.85175-1-pmladek@suse.com
[v3] https://lore.kernel.org/r/20260602085312.228251-1-pmladek@suse.com
[v4] https://lore.kernel.org/r/20260604101459.393162-1-pmladek@suse.com

Petr Mladek (16):
  printk: Rename struct console_cmdline to preferred_console
  printk: Rename preferred_console to preferred_dev_console
  printk: Cleanup _braille_(un)register_console() wrappers
  printk: Separate code for adding/updating preferred console metadata
  printk: Prefer the console either via name or devname exclusively
  printk: Check that index is not defined when a console is preferred
    via devname
  printk: Ensure consistent name and devname when updating preferred
    console
  printk: Do not quietly ignore adding entry for a preferred console
    when there is no space
  printk: Allow to override options via the command line
  printk: Allow to debug misuse of add_or_update_preferred_console()
  console/braille: Lock console->setup() call during the registration
  printk: Separate code for enabling console
  printk: Try to register each console as Braille first
  printk: Do not set Braille console as preferred_console
  printk: Modify try_enable_default_console() to return error/success
  printk: Try enable preferred consoles only when there are any

 .../accessibility/braille/braille_console.c   |  17 +-
 include/linux/console.h                       |   1 +
 kernel/printk/braille.c                       |  20 +-
 kernel/printk/braille.h                       |  22 +-
 .../{console_cmdline.h => console_register.h} |   9 +-
 kernel/printk/printk.c                        | 414 ++++++++++++------
 6 files changed, 326 insertions(+), 157 deletions(-)
 rename kernel/printk/{console_cmdline.h => console_register.h} (74%)

-- 
2.55.0


^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH v5 01/16] printk: Rename struct console_cmdline to preferred_console
  2026-09-29 12:05 [PATCH v5 00/16] printk: Clean up preferred console handling Petr Mladek
@ 2026-09-29 12:05 ` Petr Mladek
  2026-09-29 12:05 ` [PATCH v5 02/16] printk: Rename preferred_console to preferred_dev_console Petr Mladek
                   ` (14 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Petr Mladek @ 2026-09-29 12:05 UTC (permalink / raw)
  To: John Ogness
  Cc: Sergey Senozhatsky, Steven Rostedt, Marcos Paulo de Souza,
	Chris Down, Naveen Kumar Chaudhary, linux-kernel, Petr Mladek

The structure 'console_cmdline' was originally intended to store details
about consoles defined on the kernel command line. However, its usage
has since expanded; it now stores information for consoles preferred
via SPCR, device tree, or by particular platforms, e.g. XEN.

The current naming is misleading as it implies the configuration only
originates from the command line.

Rename the structure and associated artifacts to better reflect their
current purpose, for example:

  - struct console_cmdline c -> struct preferred_console pc
  - console_cmdline[]        -> preferred_consoles[]
  - console_cmdline.h        -> console_register.h
  - c			     -> pc

Additionally, renaming the header file to console_register.h would
eventually allow to decouple console registration logic from
the monolithic printk.c.

Finally, renaming the local variable from "c" to "pc" helps to distinguish
it from struct console variables. Note that "c" is used for struct console
in some code, for example see vt_console_device() function definition.

No functional changes.

Signed-off-by: Petr Mladek <pmladek@suse.com>
Acked-by: Chris Down <chris@chrisdown.name>
Acked-by: Marcos Paulo de Souza <mpdesouza@suse.com>
Reviewed-by: John Ogness <john.ogness@linutronix.de>
---
 kernel/printk/braille.c                       | 10 +--
 kernel/printk/braille.h                       | 10 +--
 .../{console_cmdline.h => console_register.h} |  6 +-
 kernel/printk/printk.c                        | 85 ++++++++++---------
 4 files changed, 57 insertions(+), 54 deletions(-)
 rename kernel/printk/{console_cmdline.h => console_register.h} (83%)

diff --git a/kernel/printk/braille.c b/kernel/printk/braille.c
index 17a9591e54ff..9d21a2bb1d38 100644
--- a/kernel/printk/braille.c
+++ b/kernel/printk/braille.c
@@ -6,7 +6,7 @@
 #include <linux/errno.h>
 #include <linux/string.h>
 
-#include "console_cmdline.h"
+#include "console_register.h"
 #include "braille.h"
 
 int _braille_console_setup(char **str, char **brl_options)
@@ -35,14 +35,14 @@ int _braille_console_setup(char **str, char **brl_options)
 }
 
 int
-_braille_register_console(struct console *console, struct console_cmdline *c)
+_braille_register_console(struct console *console, struct preferred_console *pc)
 {
 	int rtn = 0;
 
-	if (c->brl_options) {
+	if (pc->brl_options) {
 		console->flags |= CON_BRL;
-		rtn = braille_register_console(console, c->index, c->options,
-					       c->brl_options);
+		rtn = braille_register_console(console, pc->index, pc->options,
+					       pc->brl_options);
 	}
 
 	return rtn;
diff --git a/kernel/printk/braille.h b/kernel/printk/braille.h
index 123154f86304..55cd3178a17a 100644
--- a/kernel/printk/braille.h
+++ b/kernel/printk/braille.h
@@ -5,9 +5,9 @@
 #ifdef CONFIG_A11Y_BRAILLE_CONSOLE
 
 static inline void
-braille_set_options(struct console_cmdline *c, char *brl_options)
+braille_set_options(struct preferred_console *pc, char *brl_options)
 {
-	c->brl_options = brl_options;
+	pc->brl_options = brl_options;
 }
 
 /*
@@ -21,7 +21,7 @@ int
 _braille_console_setup(char **str, char **brl_options);
 
 int
-_braille_register_console(struct console *console, struct console_cmdline *c);
+_braille_register_console(struct console *console, struct preferred_console *pc);
 
 int
 _braille_unregister_console(struct console *console);
@@ -29,7 +29,7 @@ _braille_unregister_console(struct console *console);
 #else
 
 static inline void
-braille_set_options(struct console_cmdline *c, char *brl_options)
+braille_set_options(struct preferred_console *pc, char *brl_options)
 {
 }
 
@@ -40,7 +40,7 @@ _braille_console_setup(char **str, char **brl_options)
 }
 
 static inline int
-_braille_register_console(struct console *console, struct console_cmdline *c)
+_braille_register_console(struct console *console, struct preferred_console *pc)
 {
 	return 0;
 }
diff --git a/kernel/printk/console_cmdline.h b/kernel/printk/console_register.h
similarity index 83%
rename from kernel/printk/console_cmdline.h
rename to kernel/printk/console_register.h
index 0ab573b6d4dc..9ab3e1cc749b 100644
--- a/kernel/printk/console_cmdline.h
+++ b/kernel/printk/console_register.h
@@ -1,8 +1,8 @@
 /* SPDX-License-Identifier: GPL-2.0 */
-#ifndef _CONSOLE_CMDLINE_H
-#define _CONSOLE_CMDLINE_H
+#ifndef _CONSOLE_REGISTER_H
+#define _CONSOLE_REGISTER_H
 
-struct console_cmdline
+struct preferred_console
 {
 	char	name[16];			/* Name of the driver	    */
 	int	index;				/* Minor dev. to use	    */
diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c
index 6d3d18a50da7..2cff224cf1e2 100644
--- a/kernel/printk/printk.c
+++ b/kernel/printk/printk.c
@@ -58,7 +58,7 @@
 #include <trace/events/printk.h>
 
 #include "printk_ringbuffer.h"
-#include "console_cmdline.h"
+#include "console_register.h"
 #include "braille.h"
 #include "internal.h"
 
@@ -362,9 +362,9 @@ static int console_locked;
  *	Array of consoles built from command line options (console=)
  */
 
-#define MAX_CMDLINECONSOLES 8
+#define MAX_PREFERRED_CONSOLES 8
 
-static struct console_cmdline console_cmdline[MAX_CMDLINECONSOLES];
+static struct preferred_console preferred_consoles[MAX_PREFERRED_CONSOLES];
 
 static int preferred_console = -1;
 int console_set_on_cmdline;
@@ -2544,16 +2544,16 @@ asmlinkage __visible void early_printk(const char *fmt, ...)
 }
 #endif
 
-static void set_user_specified(struct console_cmdline *c, bool user_specified)
+static void set_user_specified(struct preferred_console *pc, bool user_specified)
 {
 	if (!user_specified)
 		return;
 
 	/*
-	 * @c console was defined by the user on the command line.
+	 * @pc console was defined by the user on the command line.
 	 * Do not clear when added twice also by SPCR or the device tree.
 	 */
-	c->user_specified = true;
+	pc->user_specified = true;
 	/* At least one console defined by the user on the command line. */
 	console_set_on_cmdline = 1;
 }
@@ -2562,7 +2562,7 @@ static int __add_preferred_console(const char *name, const short idx,
 				   const char *devname, char *options,
 				   char *brl_options, bool user_specified)
 {
-	struct console_cmdline *c;
+	struct preferred_console *pc;
 	int i;
 
 	if (!name && !devname)
@@ -2581,30 +2581,30 @@ static int __add_preferred_console(const char *name, const short idx,
 	 *	See if this tty is not yet registered, and
 	 *	if we have a slot free.
 	 */
-	for (i = 0, c = console_cmdline;
-	     i < MAX_CMDLINECONSOLES && (c->name[0] || c->devname[0]);
-	     i++, c++) {
-		if ((name && strcmp(c->name, name) == 0 && c->index == idx) ||
-		    (devname && strcmp(c->devname, devname) == 0)) {
+	for (i = 0, pc = preferred_consoles;
+	     i < MAX_PREFERRED_CONSOLES && (pc->name[0] || pc->devname[0]);
+	     i++, pc++) {
+		if ((name && strcmp(pc->name, name) == 0 && pc->index == idx) ||
+		    (devname && strcmp(pc->devname, devname) == 0)) {
 			if (!brl_options)
 				preferred_console = i;
-			set_user_specified(c, user_specified);
+			set_user_specified(pc, user_specified);
 			return 0;
 		}
 	}
-	if (i == MAX_CMDLINECONSOLES)
+	if (i == MAX_PREFERRED_CONSOLES)
 		return -E2BIG;
 	if (!brl_options)
 		preferred_console = i;
 	if (name)
-		strscpy(c->name, name);
+		strscpy(pc->name, name);
 	if (devname)
-		strscpy(c->devname, devname);
-	c->options = options;
-	set_user_specified(c, user_specified);
-	braille_set_options(c, brl_options);
+		strscpy(pc->devname, devname);
+	pc->options = options;
+	set_user_specified(pc, user_specified);
+	braille_set_options(pc, brl_options);
 
-	c->index = idx;
+	pc->index = idx;
 	return 0;
 }
 
@@ -2624,8 +2624,7 @@ __setup("console_msg_format=", console_msg_format_setup);
  */
 static int __init console_setup(char *str)
 {
-	static_assert(sizeof(console_cmdline[0].devname) >= sizeof(console_cmdline[0].name) + 4);
-	char buf[sizeof(console_cmdline[0].devname)];
+	char buf[sizeof(preferred_consoles[0].devname)];
 	char *brl_options = NULL;
 	char *ttyname = NULL;
 	char *devname = NULL;
@@ -2633,6 +2632,10 @@ static int __init console_setup(char *str)
 	char *s;
 	int idx;
 
+	static_assert(sizeof(preferred_consoles[0].devname) >=
+		      sizeof(preferred_consoles[0].name) + 4);
+
+
 	/*
 	 * console="" or console=null have been suggested as a way to
 	 * disable console output. Use ttynull that has been created
@@ -2730,19 +2733,19 @@ int match_devname_and_update_preferred_console(const char *devname,
 					       const char *name,
 					       const short idx)
 {
-	struct console_cmdline *c = console_cmdline;
+	struct preferred_console *pc = preferred_consoles;
 	int i;
 
 	if (!devname || !strlen(devname) || !name || !strlen(name) || idx < 0)
 		return -EINVAL;
 
-	for (i = 0; i < MAX_CMDLINECONSOLES && (c->name[0] || c->devname[0]);
-	     i++, c++) {
-		if (!strcmp(devname, c->devname)) {
+	for (i = 0; i < MAX_PREFERRED_CONSOLES && (pc->name[0] || pc->devname[0]);
+	     i++, pc++) {
+		if (!strcmp(devname, pc->devname)) {
 			pr_info("associate the preferred console \"%s\" with \"%s%d\"\n",
 				devname, name, idx);
-			strscpy(c->name, name);
-			c->index = idx;
+			strscpy(pc->name, name);
+			pc->index = idx;
 			return 0;
 		}
 	}
@@ -3901,33 +3904,33 @@ static int console_call_setup(struct console *newcon, char *options)
 static int try_enable_preferred_console(struct console *newcon,
 					bool user_specified)
 {
-	struct console_cmdline *c;
+	struct preferred_console *pc;
 	int i, err;
 
-	for (i = 0, c = console_cmdline;
-	     i < MAX_CMDLINECONSOLES && (c->name[0] || c->devname[0]);
-	     i++, c++) {
+	for (i = 0, pc = preferred_consoles;
+	     i < MAX_PREFERRED_CONSOLES && (pc->name[0] || pc->devname[0]);
+	     i++, pc++) {
 		/* Console not yet initialized? */
-		if (!c->name[0])
+		if (!pc->name[0])
 			continue;
-		if (c->user_specified != user_specified)
+		if (pc->user_specified != user_specified)
 			continue;
 		if (!newcon->match ||
-		    newcon->match(newcon, c->name, c->index, c->options) != 0) {
+		    newcon->match(newcon, pc->name, pc->index, pc->options) != 0) {
 			/* default matching */
-			BUILD_BUG_ON(sizeof(c->name) != sizeof(newcon->name));
-			if (strcmp(c->name, newcon->name) != 0)
+			BUILD_BUG_ON(sizeof(pc->name) != sizeof(newcon->name));
+			if (strcmp(pc->name, newcon->name) != 0)
 				continue;
 			if (newcon->index >= 0 &&
-			    newcon->index != c->index)
+			    newcon->index != pc->index)
 				continue;
 			if (newcon->index < 0)
-				newcon->index = c->index;
+				newcon->index = pc->index;
 
-			if (_braille_register_console(newcon, c))
+			if (_braille_register_console(newcon, pc))
 				return 0;
 
-			err = console_call_setup(newcon, c->options);
+			err = console_call_setup(newcon, pc->options);
 			if (err)
 				return err;
 		}
-- 
2.55.0


^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH v5 02/16] printk: Rename preferred_console to preferred_dev_console
  2026-09-29 12:05 [PATCH v5 00/16] printk: Clean up preferred console handling Petr Mladek
  2026-09-29 12:05 ` [PATCH v5 01/16] printk: Rename struct console_cmdline to preferred_console Petr Mladek
@ 2026-09-29 12:05 ` Petr Mladek
  2026-09-29 12:05 ` [PATCH v5 03/16] printk: Cleanup _braille_(un)register_console() wrappers Petr Mladek
                   ` (13 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Petr Mladek @ 2026-09-29 12:05 UTC (permalink / raw)
  To: John Ogness
  Cc: Sergey Senozhatsky, Steven Rostedt, Marcos Paulo de Souza,
	Chris Down, Naveen Kumar Chaudhary, linux-kernel, Petr Mladek

The preferred_consoles[] array stores information about consoles requested
via the command line, SPCR, Device Tree, or platform-specific code.
Within this array, the 'preferred_console' variable tracks the specific
index that should be associated with /dev/console (typically the last
non-braille console defined).

The current name "preferred_console" is ambiguous and leads to confusion.
It does not clearly communicate why one console is "more preferred" than
others in the array. Furthermore, entries for Braille consoles can exist
within the preferred_consoles[] array, yet they are never associated with
/dev/console and do not receive standard printk() output. Consequently,
the 'preferred_console' index must skip these entries, which is not
immediately obvious from the name.

Rename the variable to 'preferred_dev_console' to explicitly clarify its
role in identifying which entry is linked to /dev/console.

No behavior change.

Signed-off-by: Petr Mladek <pmladek@suse.com>
Acked-by: Chris Down <chris@chrisdown.name>
Acked-by: Marcos Paulo de Souza <mpdesouza@suse.com>
Reviewed-by: John Ogness <john.ogness@linutronix.de>
---
 kernel/printk/printk.c | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c
index 2cff224cf1e2..8166828a9801 100644
--- a/kernel/printk/printk.c
+++ b/kernel/printk/printk.c
@@ -366,7 +366,7 @@ static int console_locked;
 
 static struct preferred_console preferred_consoles[MAX_PREFERRED_CONSOLES];
 
-static int preferred_console = -1;
+static int preferred_dev_console = -1;
 int console_set_on_cmdline;
 EXPORT_SYMBOL(console_set_on_cmdline);
 
@@ -2587,7 +2587,7 @@ static int __add_preferred_console(const char *name, const short idx,
 		if ((name && strcmp(pc->name, name) == 0 && pc->index == idx) ||
 		    (devname && strcmp(pc->devname, devname) == 0)) {
 			if (!brl_options)
-				preferred_console = i;
+				preferred_dev_console = i;
 			set_user_specified(pc, user_specified);
 			return 0;
 		}
@@ -2595,7 +2595,7 @@ static int __add_preferred_console(const char *name, const short idx,
 	if (i == MAX_PREFERRED_CONSOLES)
 		return -E2BIG;
 	if (!brl_options)
-		preferred_console = i;
+		preferred_dev_console = i;
 	if (name)
 		strscpy(pc->name, name);
 	if (devname)
@@ -3935,7 +3935,7 @@ static int try_enable_preferred_console(struct console *newcon,
 				return err;
 		}
 		newcon->flags |= CON_ENABLED;
-		if (i == preferred_console)
+		if (i == preferred_dev_console)
 			newcon->flags |= CON_CONSDEV;
 		return 0;
 	}
@@ -4108,7 +4108,7 @@ void register_console(struct console *newcon)
 	 * Note that a console with tty binding will have CON_CONSDEV
 	 * flag set and will be first in the list.
 	 */
-	if (preferred_console < 0) {
+	if (preferred_dev_console < 0) {
 		if (hlist_empty(&console_list) || !console_first()->device ||
 		    console_first()->flags & CON_BOOT) {
 			try_enable_default_console(newcon);
-- 
2.55.0


^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH v5 03/16] printk: Cleanup _braille_(un)register_console() wrappers
  2026-09-29 12:05 [PATCH v5 00/16] printk: Clean up preferred console handling Petr Mladek
  2026-09-29 12:05 ` [PATCH v5 01/16] printk: Rename struct console_cmdline to preferred_console Petr Mladek
  2026-09-29 12:05 ` [PATCH v5 02/16] printk: Rename preferred_console to preferred_dev_console Petr Mladek
@ 2026-09-29 12:05 ` Petr Mladek
  2026-09-29 12:05 ` [PATCH v5 04/16] printk: Separate code for adding/updating preferred console metadata Petr Mladek
                   ` (12 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Petr Mladek @ 2026-09-29 12:05 UTC (permalink / raw)
  To: John Ogness
  Cc: Sergey Senozhatsky, Steven Rostedt, Marcos Paulo de Souza,
	Chris Down, Naveen Kumar Chaudhary, linux-kernel, Petr Mladek

The _braille_(un)register_console() wrappers currently attempt to hide
implementation details like the CON_BRL flag and pc->brl_options. This
forces callers to handle an unconventional tri-state return value (0 for
NOP, >0 for success, <0 for error), which makes the control flow harder
to follow and non-standard.

Refactor the wrappers to use standard kernel return codes (0 for success,
-ERRCODE on failure). Move the responsibility of checking brl_options
to the caller to make the logic more explicit.

Additionally, move the assignment of the CON_BRL flag from the internal
wrapper to braille_register_console(). This aligns it with how
CON_ENABLED is handled. To maintain symmetry and fix a potential bug
where flags might persist after removal, explicitly clear both
CON_ENABLED and CON_BRL in braille_unregister_console().

No behavior change.

Signed-off-by: Petr Mladek <pmladek@suse.com>
Acked-by: Chris Down <chris@chrisdown.name>
Reviewed-by: Marcos Paulo de Souza <mpdesouza@suse.com>
Reviewed-by: John Ogness <john.ogness@linutronix.de>
---
 drivers/accessibility/braille/braille_console.c |  7 ++++---
 kernel/printk/braille.c                         | 16 +++-------------
 kernel/printk/braille.h                         | 12 ++++++++++++
 kernel/printk/printk.c                          | 13 +++++--------
 4 files changed, 24 insertions(+), 24 deletions(-)

diff --git a/drivers/accessibility/braille/braille_console.c b/drivers/accessibility/braille/braille_console.c
index 4205c894df17..7e6011f9d823 100644
--- a/drivers/accessibility/braille/braille_console.c
+++ b/drivers/accessibility/braille/braille_console.c
@@ -394,12 +394,12 @@ int braille_register_console(struct console *console, int index,
 		if (ret != 0)
 			return ret;
 	}
-	console->flags |= CON_ENABLED;
+	console->flags |= CON_ENABLED | CON_BRL;
 	console->index = index;
 	braille_co = console;
 	register_keyboard_notifier(&keyboard_notifier_block);
 	register_vt_notifier(&vt_notifier_block);
-	return 1;
+	return 0;
 }
 
 int braille_unregister_console(struct console *console)
@@ -409,5 +409,6 @@ int braille_unregister_console(struct console *console)
 	unregister_keyboard_notifier(&keyboard_notifier_block);
 	unregister_vt_notifier(&vt_notifier_block);
 	braille_co = NULL;
-	return 1;
+	console->flags &= ~(CON_ENABLED | CON_BRL);
+	return 0;
 }
diff --git a/kernel/printk/braille.c b/kernel/printk/braille.c
index 9d21a2bb1d38..593f83eb0487 100644
--- a/kernel/printk/braille.c
+++ b/kernel/printk/braille.c
@@ -37,22 +37,12 @@ int _braille_console_setup(char **str, char **brl_options)
 int
 _braille_register_console(struct console *console, struct preferred_console *pc)
 {
-	int rtn = 0;
-
-	if (pc->brl_options) {
-		console->flags |= CON_BRL;
-		rtn = braille_register_console(console, pc->index, pc->options,
-					       pc->brl_options);
-	}
-
-	return rtn;
+	return braille_register_console(console, pc->index, pc->options,
+					pc->brl_options);
 }
 
 int
 _braille_unregister_console(struct console *console)
 {
-	if (console->flags & CON_BRL)
-		return braille_unregister_console(console);
-
-	return 0;
+	return braille_unregister_console(console);
 }
diff --git a/kernel/printk/braille.h b/kernel/printk/braille.h
index 55cd3178a17a..e9790c28027d 100644
--- a/kernel/printk/braille.h
+++ b/kernel/printk/braille.h
@@ -10,6 +10,12 @@ braille_set_options(struct preferred_console *pc, char *brl_options)
 	pc->brl_options = brl_options;
 }
 
+static inline bool
+is_braille_console_preferred(struct preferred_console *pc)
+{
+	return (!!pc->brl_options);
+}
+
 /*
  * Setup console according to braille options.
  * Return -EINVAL on syntax error, 0 on success (or no braille option was
@@ -33,6 +39,12 @@ braille_set_options(struct preferred_console *pc, char *brl_options)
 {
 }
 
+static inline bool
+is_braille_console_preferred(struct preferred_console *pc)
+{
+	return false;
+}
+
 static inline int
 _braille_console_setup(char **str, char **brl_options)
 {
diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c
index 8166828a9801..c3e50f19a32b 100644
--- a/kernel/printk/printk.c
+++ b/kernel/printk/printk.c
@@ -3927,8 +3927,8 @@ static int try_enable_preferred_console(struct console *newcon,
 			if (newcon->index < 0)
 				newcon->index = pc->index;
 
-			if (_braille_register_console(newcon, pc))
-				return 0;
+			if (is_braille_console_preferred(pc))
+				return _braille_register_console(newcon, pc);
 
 			err = console_call_setup(newcon, pc->options);
 			if (err)
@@ -4240,17 +4240,14 @@ static int unregister_console_locked(struct console *console)
 	bool found_boot_con = false;
 	unsigned long flags;
 	struct console *c;
-	int res;
+	int res = 0;
 
 	lockdep_assert_console_list_lock_held();
 
 	con_printk(KERN_INFO, console, "disabled\n");
 
-	res = _braille_unregister_console(console);
-	if (res < 0)
-		return res;
-	if (res > 0)
-		return 0;
+	if (console->flags & CON_BRL)
+		return _braille_unregister_console(console);
 
 	if (!console_is_registered_locked(console))
 		res = -ENODEV;
-- 
2.55.0


^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH v5 04/16] printk: Separate code for adding/updating preferred console metadata
  2026-09-29 12:05 [PATCH v5 00/16] printk: Clean up preferred console handling Petr Mladek
                   ` (2 preceding siblings ...)
  2026-09-29 12:05 ` [PATCH v5 03/16] printk: Cleanup _braille_(un)register_console() wrappers Petr Mladek
@ 2026-09-29 12:05 ` Petr Mladek
  2026-09-29 12:05 ` [PATCH v5 05/16] printk: Prefer the console either via name or devname exclusively Petr Mladek
                   ` (11 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Petr Mladek @ 2026-09-29 12:05 UTC (permalink / raw)
  To: John Ogness
  Cc: Sergey Senozhatsky, Steven Rostedt, Marcos Paulo de Souza,
	Chris Down, Naveen Kumar Chaudhary, linux-kernel, Petr Mladek

The logic for adding or updating a preferred console is currently
duplicated within __add_preferred_console(), making the code difficult
to follow and prone to consistency issues.

Split the code for adding or updating entries to avoid code duplication.
Make it clear what operations are done only for new entries.

Use this opportunity and replace an int with an unsigned int for
iterating over the preferred_consoles array.

It is a preparation step before adding more consistency checks.
No intended functional changes.

Signed-off-by: Petr Mladek <pmladek@suse.com>
---
 kernel/printk/printk.c | 108 ++++++++++++++++++++++++++---------------
 1 file changed, 68 insertions(+), 40 deletions(-)

diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c
index c3e50f19a32b..174aee533a53 100644
--- a/kernel/printk/printk.c
+++ b/kernel/printk/printk.c
@@ -2544,26 +2544,33 @@ asmlinkage __visible void early_printk(const char *fmt, ...)
 }
 #endif
 
-static void set_user_specified(struct preferred_console *pc, bool user_specified)
-{
-	if (!user_specified)
-		return;
-
-	/*
-	 * @pc console was defined by the user on the command line.
-	 * Do not clear when added twice also by SPCR or the device tree.
-	 */
-	pc->user_specified = true;
-	/* At least one console defined by the user on the command line. */
-	console_set_on_cmdline = 1;
-}
-
-static int __add_preferred_console(const char *name, const short idx,
-				   const char *devname, char *options,
-				   char *brl_options, bool user_specified)
+/** add_or_update_preferred_console - Add or update a given entry in
+ *	the preferred_consoles[] array.
+ * @i: index of the entry in @preferred_consoles table which should get updated.
+ * @name: The name of the preferred console driver.
+ * @idx: Preferred console index, e.g. port number.
+ * @devname: The name of the preferred physical device.
+ * @options: Options used when setting up the console driver.
+ * @brl_options: Options used when setting up the console driver
+ *	as a braille console.
+ * @user_specified: True if preferred via the kernel command line.
+ *
+ * The function adds or updates an entry in preferred_consoles[] array. Also
+ * it updates some global variables which are used to make the right decisions
+ * in register_console().
+ */
+static int add_or_update_preferred_console(unsigned int i,
+					   const char *name, const short idx,
+					   const char *devname, char *options,
+					   char *brl_options, bool user_specified)
 {
 	struct preferred_console *pc;
-	int i;
+	bool is_new_entry = false;
+
+	if (i >= MAX_PREFERRED_CONSOLES)
+		return -E2BIG;
+
+	pc = &preferred_consoles[i];
 
 	if (!name && !devname)
 		return -EINVAL;
@@ -2577,35 +2584,56 @@ static int __add_preferred_console(const char *name, const short idx,
 	if (name && idx < 0)
 		return -EINVAL;
 
+	if (!pc->name[0] && !pc->devname[0])
+		is_new_entry = true;
+
+	if (is_new_entry) {
+		if (devname)
+			strscpy(pc->devname, devname);
+		if (name)
+			strscpy(pc->name, name);
+		pc->index = idx;
+	}
+
 	/*
-	 *	See if this tty is not yet registered, and
-	 *	if we have a slot free.
+	 * Historically, the preferred options are stored only by the first
+	 * caller who prefers the particular console.
 	 */
+	if (is_new_entry) {
+		pc->options = options;
+		braille_set_options(pc, brl_options);
+	}
+
+	if (!brl_options)
+		preferred_dev_console = i;
+
+	if (user_specified) {
+		pc->user_specified = true;
+		console_set_on_cmdline = 1;
+	}
+
+	return 0;
+}
+
+static int __add_preferred_console(const char *name, const short idx,
+				   const char *devname, char *options,
+				   char *brl_options, bool user_specified)
+{
+	struct preferred_console *pc;
+	unsigned int i;
+
+	/* See if this console is already preferred. */
 	for (i = 0, pc = preferred_consoles;
 	     i < MAX_PREFERRED_CONSOLES && (pc->name[0] || pc->devname[0]);
 	     i++, pc++) {
-		if ((name && strcmp(pc->name, name) == 0 && pc->index == idx) ||
-		    (devname && strcmp(pc->devname, devname) == 0)) {
-			if (!brl_options)
-				preferred_dev_console = i;
-			set_user_specified(pc, user_specified);
-			return 0;
-		}
+		if (name && strcmp(pc->name, name) == 0 && pc->index == idx)
+			break;
+		if (devname && strcmp(pc->devname, devname) == 0)
+			break;
 	}
-	if (i == MAX_PREFERRED_CONSOLES)
-		return -E2BIG;
-	if (!brl_options)
-		preferred_dev_console = i;
-	if (name)
-		strscpy(pc->name, name);
-	if (devname)
-		strscpy(pc->devname, devname);
-	pc->options = options;
-	set_user_specified(pc, user_specified);
-	braille_set_options(pc, brl_options);
 
-	pc->index = idx;
-	return 0;
+	return add_or_update_preferred_console(i, name, idx, devname, options,
+					       brl_options, user_specified);
 }
 
 static int __init console_msg_format_setup(char *str)
-- 
2.55.0


^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH v5 05/16] printk: Prefer the console either via name or devname exclusively
  2026-09-29 12:05 [PATCH v5 00/16] printk: Clean up preferred console handling Petr Mladek
                   ` (3 preceding siblings ...)
  2026-09-29 12:05 ` [PATCH v5 04/16] printk: Separate code for adding/updating preferred console metadata Petr Mladek
@ 2026-09-29 12:05 ` Petr Mladek
  2026-09-29 12:05 ` [PATCH v5 06/16] printk: Check that index is not defined when a console is preferred via devname Petr Mladek
                   ` (10 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Petr Mladek @ 2026-09-29 12:05 UTC (permalink / raw)
  To: John Ogness
  Cc: Sergey Senozhatsky, Steven Rostedt, Marcos Paulo de Souza,
	Chris Down, Naveen Kumar Chaudhary, linux-kernel, Petr Mladek

The commit 7640f1a44eba0cc1a4 ("printk:
Add match_devname_and_update_preferred_console()") added the possibility
to prefer a console driver via device name. The name of the console driver
gets assigned when the device gets initialized and it triers whether
it is eligible for a console.

The above mentioned commit ensures that __add_preferred_console() is called
at least with name or devname value. But it does not check whether
both are defined which is a non-sense.

Add the check and do not fail quietly. Also shuffle the code a bit
to make it ready for adding more checks.

Signed-off-by: Petr Mladek <pmladek@suse.com>
---
 kernel/printk/printk.c | 30 ++++++++++++++++++++++++------
 1 file changed, 24 insertions(+), 6 deletions(-)

diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c
index 174aee533a53..0199c918ef03 100644
--- a/kernel/printk/printk.c
+++ b/kernel/printk/printk.c
@@ -2557,7 +2557,13 @@ asmlinkage __visible void early_printk(const char *fmt, ...)
  *
  * The function adds or updates an entry in preferred_consoles[] array. Also
  * it updates some global variables which are used to make the right decisions
- * in register_console().
+ * in register_console(). Finally, it enforces some rules:
+ *
+ *   1. Either @name OR @devname are allowed. [*]
+ *
+ *  [*] A valid @name and @idx will get assigned for a devname later when
+ *	@devname matches during the device initialization, see
+ *	match_devname_and_update_preferred_console().
  */
 static int add_or_update_preferred_console(unsigned int i,
 					   const char *name, const short idx,
@@ -2587,11 +2593,23 @@ static int add_or_update_preferred_console(unsigned int i,
 	if (!pc->name[0] && !pc->devname[0])
 		is_new_entry = true;
 
-	if (is_new_entry) {
-		if (devname)
-			strscpy(pc->devname, devname);
-		if (name)
-			strscpy(pc->name, name);
+	if (is_new_entry && devname) {
+		/*
+		 * A valid console name and index will get assigned when
+		 * a matching device gets registered.
+		 */
+		if (name) {
+			pr_err("Adding a preferred console devname with a hard-coded console name: %s, %s\n",
+			       devname, name);
+			return -EINVAL;
+		}
+
+		strscpy(pc->devname, devname);
+		pc->index = idx;
+	}
+
+	if (is_new_entry && name) {
+		strscpy(pc->name, name);
 		pc->index = idx;
 	}
 
-- 
2.55.0


^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH v5 06/16] printk: Check that index is not defined when a console is preferred via devname
  2026-09-29 12:05 [PATCH v5 00/16] printk: Clean up preferred console handling Petr Mladek
                   ` (4 preceding siblings ...)
  2026-09-29 12:05 ` [PATCH v5 05/16] printk: Prefer the console either via name or devname exclusively Petr Mladek
@ 2026-09-29 12:05 ` Petr Mladek
  2026-09-29 12:05 ` [PATCH v5 07/16] printk: Ensure consistent name and devname when updating preferred console Petr Mladek
                   ` (9 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Petr Mladek @ 2026-09-29 12:05 UTC (permalink / raw)
  To: John Ogness
  Cc: Sergey Senozhatsky, Steven Rostedt, Marcos Paulo de Souza,
	Chris Down, Naveen Kumar Chaudhary, linux-kernel, Petr Mladek

The current code makes sure that a valid index is defined when a console
is preferred via a name.

On the contrary, the index must not be defined when the console is
defined via a devname. The index will be defined later when the device
matches and gets registered.

Enforce the 2nd rule. Make the checks symmetric in the code.
Do not ignore the errors quietly.

Signed-off-by: Petr Mladek <pmladek@suse.com>
---
 kernel/printk/printk.c | 23 +++++++++++++----------
 1 file changed, 13 insertions(+), 10 deletions(-)

diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c
index 0199c918ef03..b8c348e305eb 100644
--- a/kernel/printk/printk.c
+++ b/kernel/printk/printk.c
@@ -2559,7 +2559,7 @@ asmlinkage __visible void early_printk(const char *fmt, ...)
  * it updates some global variables which are used to make the right decisions
  * in register_console(). Finally, it enforces some rules:
  *
- *   1. Either @name OR @devname are allowed. [*]
+ *   1. Either @name and valid @idx OR @devname and @idx=-1 are allowed.
  *
  *  [*] A valid @name and @idx will get assigned for a devname later when
  *	@devname matches during the device initialization, see
@@ -2581,15 +2581,6 @@ static int add_or_update_preferred_console(unsigned int i,
 	if (!name && !devname)
 		return -EINVAL;
 
-	/*
-	 * We use a signed short index for struct console for device drivers to
-	 * indicate a not yet assigned index or port. However, a negative index
-	 * value is not valid when the console name and index are defined on
-	 * the command line.
-	 */
-	if (name && idx < 0)
-		return -EINVAL;
-
 	if (!pc->name[0] && !pc->devname[0])
 		is_new_entry = true;
 
@@ -2603,12 +2594,24 @@ static int add_or_update_preferred_console(unsigned int i,
 			       devname, name);
 			return -EINVAL;
 		}
+		if (idx != -1) {
+			pr_err("Adding a preferred console devname with a hard-coded index: %s, %d\n",
+			       devname, idx);
+			return -EINVAL;
+		}
 
 		strscpy(pc->devname, devname);
 		pc->index = idx;
 	}
 
 	if (is_new_entry && name) {
+		/* A console name must be defined with a valid index. */
+		if (idx < 0) {
+			pr_err("Adding a preferred console with an invalid index: %s, %d\n",
+			       name, idx);
+			return -EINVAL;
+		}
+
 		strscpy(pc->name, name);
 		pc->index = idx;
 	}
-- 
2.55.0


^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH v5 07/16] printk: Ensure consistent name and devname when updating preferred console
  2026-09-29 12:05 [PATCH v5 00/16] printk: Clean up preferred console handling Petr Mladek
                   ` (5 preceding siblings ...)
  2026-09-29 12:05 ` [PATCH v5 06/16] printk: Check that index is not defined when a console is preferred via devname Petr Mladek
@ 2026-09-29 12:05 ` Petr Mladek
  2026-09-29 12:05 ` [PATCH v5 08/16] printk: Do not quietly ignore adding entry for a preferred console when there is no space Petr Mladek
                   ` (8 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Petr Mladek @ 2026-09-29 12:05 UTC (permalink / raw)
  To: John Ogness
  Cc: Sergey Senozhatsky, Steven Rostedt, Marcos Paulo de Souza,
	Chris Down, Naveen Kumar Chaudhary, linux-kernel, Petr Mladek

Make sure that add_or_update_preferred_console() updates the right entry.
It is a paranoid check which prevents a potential misuse of the API in
the future.

Signed-off-by: Petr Mladek <pmladek@suse.com>
---
 kernel/printk/printk.c | 31 ++++++++++++++++++++++---------
 1 file changed, 22 insertions(+), 9 deletions(-)

diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c
index b8c348e305eb..0fafc579bdd3 100644
--- a/kernel/printk/printk.c
+++ b/kernel/printk/printk.c
@@ -2561,6 +2561,8 @@ asmlinkage __visible void early_printk(const char *fmt, ...)
  *
  *   1. Either @name and valid @idx OR @devname and @idx=-1 are allowed.
  *
+ *   2. Only matching entries can be updated.
+ *
  *  [*] A valid @name and @idx will get assigned for a devname later when
  *	@devname matches during the device initialization, see
  *	match_devname_and_update_preferred_console().
@@ -2581,10 +2583,7 @@ static int add_or_update_preferred_console(unsigned int i,
 	if (!name && !devname)
 		return -EINVAL;
 
-	if (!pc->name[0] && !pc->devname[0])
-		is_new_entry = true;
-
-	if (is_new_entry && devname) {
+	if (devname) {
 		/*
 		 * A valid console name and index will get assigned when
 		 * a matching device gets registered.
@@ -2600,11 +2599,18 @@ static int add_or_update_preferred_console(unsigned int i,
 			return -EINVAL;
 		}
 
-		strscpy(pc->devname, devname);
-		pc->index = idx;
+		if (!pc->devname[0]) {
+			is_new_entry = true;
+			strscpy(pc->devname, devname);
+			pc->index = idx;
+		} else if (strcmp(pc->devname, devname) != 0) {
+			pr_err("Updating a preferred console with an invalid devname: %s vs. %s\n",
+			       pc->devname, devname);
+			return -EINVAL;
+		}
 	}
 
-	if (is_new_entry && name) {
+	if (name) {
 		/* A console name must be defined with a valid index. */
 		if (idx < 0) {
 			pr_err("Adding a preferred console with an invalid index: %s, %d\n",
@@ -2612,8 +2618,15 @@ static int add_or_update_preferred_console(unsigned int i,
 			return -EINVAL;
 		}
 
-		strscpy(pc->name, name);
-		pc->index = idx;
+		if (!pc->name[0]) {
+			is_new_entry = true;
+			strscpy(pc->name, name);
+			pc->index = idx;
+		} else if (strcmp(pc->name, name) != 0 || pc->index != idx) {
+			pr_err("Updating a preferred console with an invalid name or index: %s%d vs. %s%d\n",
+			       pc->name, pc->index, name, idx);
+			return -EINVAL;
+		}
 	}
 
 	/*
-- 
2.55.0


^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH v5 08/16] printk: Do not quietly ignore adding entry for a preferred console when there is no space
  2026-09-29 12:05 [PATCH v5 00/16] printk: Clean up preferred console handling Petr Mladek
                   ` (6 preceding siblings ...)
  2026-09-29 12:05 ` [PATCH v5 07/16] printk: Ensure consistent name and devname when updating preferred console Petr Mladek
@ 2026-09-29 12:05 ` Petr Mladek
  2026-09-29 12:05 ` [PATCH v5 09/16] printk: Allow to override options via the command line Petr Mladek
                   ` (7 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Petr Mladek @ 2026-09-29 12:05 UTC (permalink / raw)
  To: John Ogness
  Cc: Sergey Senozhatsky, Steven Rostedt, Marcos Paulo de Souza,
	Chris Down, Naveen Kumar Chaudhary, linux-kernel, Petr Mladek

It is hard to imagine that anyone would want to add more than 8 preferred
consoles. But never say never. And do not ignore new entries quietly.

Signed-off-by: Petr Mladek <pmladek@suse.com>
---
 kernel/printk/printk.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c
index 0fafc579bdd3..4670787195d1 100644
--- a/kernel/printk/printk.c
+++ b/kernel/printk/printk.c
@@ -2575,8 +2575,10 @@ static int add_or_update_preferred_console(unsigned int i,
 	struct preferred_console *pc;
 	bool is_new_entry = false;
 
-	if (i >= MAX_PREFERRED_CONSOLES)
+	if (i >= MAX_PREFERRED_CONSOLES) {
+		pr_err_once("Reached maximal number of preferred consoles.\n");
 		return -E2BIG;
+	}
 
 	pc = &preferred_consoles[i];
 
-- 
2.55.0


^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH v5 09/16] printk: Allow to override options via the command line
  2026-09-29 12:05 [PATCH v5 00/16] printk: Clean up preferred console handling Petr Mladek
                   ` (7 preceding siblings ...)
  2026-09-29 12:05 ` [PATCH v5 08/16] printk: Do not quietly ignore adding entry for a preferred console when there is no space Petr Mladek
@ 2026-09-29 12:05 ` Petr Mladek
  2026-09-29 12:05 ` [PATCH v5 10/16] printk: Allow to debug misuse of add_or_update_preferred_console() Petr Mladek
                   ` (6 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Petr Mladek @ 2026-09-29 12:05 UTC (permalink / raw)
  To: John Ogness
  Cc: Sergey Senozhatsky, Steven Rostedt, Marcos Paulo de Souza,
	Chris Down, Naveen Kumar Chaudhary, linux-kernel, Petr Mladek

Consoles can be preferred either via the console= command line parameter
or by some platform specific code, e.g. SPCR, device tree.

Historically, the preferred console options are stored only by the first
caller who prefers the particular console. The ordering is:

  1. acpi_parse_spcr() is called via setup_arch(). Also some platforms,
     for example, s390, powerpc, x86 Xen, explicitly call
     add_preferred_console() before or in setup_arch().

  2. console= command line parameter adds the preferred consoles via
     console_setup().

  3. The device tree is read in setup_arch(), see unflatten_device_tree().
     But the preferred console entries are added later when probing
     particular devices in do_initcalls(), see of_console_check().

It means that users could override console options via the command line
only for entries defined via the device tree but not for entries added
via SPCR or another platform-specific code.

I looks like a bug. It should always be possible to override any
platform-specific defaults via the command line. Also it is usual
that the last variant wins.

Be conservative when Braille console is wanted and prefer the Braille
variant.

The change might theoretically break setups where users passed wrong
console options and they used to be ignored. But the fix seems to
be worth the risk.

Signed-off-by: Petr Mladek <pmladek@suse.com>
---
 kernel/printk/printk.c | 10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)

diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c
index 4670787195d1..b458a920ce5a 100644
--- a/kernel/printk/printk.c
+++ b/kernel/printk/printk.c
@@ -2563,6 +2563,9 @@ asmlinkage __visible void early_printk(const char *fmt, ...)
  *
  *   2. Only matching entries can be updated.
  *
+ *   3. Allow to override @options via the command line. Last one wins
+ *	except that the Braille variant is preferred.
+ *
  *  [*] A valid @name and @idx will get assigned for a devname later when
  *	@devname matches during the device initialization, see
  *	match_devname_and_update_preferred_console().
@@ -2632,10 +2635,11 @@ static int add_or_update_preferred_console(unsigned int i,
 	}
 
 	/*
-	 * Historically, the preferred options are stored only by the first
-	 * caller who prefers the particular console.
+	 * Allow to override options via the command line but always
+	 * prefer the Braille variant.
 	 */
-	if (is_new_entry) {
+	if (is_new_entry || brl_options ||
+	    (user_specified && !is_braille_console_preferred(pc))) {
 		pc->options = options;
 		braille_set_options(pc, brl_options);
 	}
-- 
2.55.0


^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH v5 10/16] printk: Allow to debug misuse of add_or_update_preferred_console()
  2026-09-29 12:05 [PATCH v5 00/16] printk: Clean up preferred console handling Petr Mladek
                   ` (8 preceding siblings ...)
  2026-09-29 12:05 ` [PATCH v5 09/16] printk: Allow to override options via the command line Petr Mladek
@ 2026-09-29 12:05 ` Petr Mladek
  2026-09-29 12:05 ` [PATCH v5 11/16] console/braille: Lock console->setup() call during the registration Petr Mladek
                   ` (5 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Petr Mladek @ 2026-09-29 12:05 UTC (permalink / raw)
  To: John Ogness
  Cc: Sergey Senozhatsky, Steven Rostedt, Marcos Paulo de Souza,
	Chris Down, Naveen Kumar Chaudhary, linux-kernel, Petr Mladek

__add_preferred_console() should always be called only when either @name
or @devname is defined. Allow to debug the case when they are misused.

Use WARN_ON() because it is rather an implementation problem, it should
never happen. Also the consoles are typically added during boot so this
should not panic a running system even when panic_on_warn is enabled.

Signed-off-by: Petr Mladek <pmladek@suse.com>
---
 kernel/printk/printk.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c
index b458a920ce5a..683083405230 100644
--- a/kernel/printk/printk.c
+++ b/kernel/printk/printk.c
@@ -2585,7 +2585,7 @@ static int add_or_update_preferred_console(unsigned int i,
 
 	pc = &preferred_consoles[i];
 
-	if (!name && !devname)
+	if (WARN_ON(!name && !devname))
 		return -EINVAL;
 
 	if (devname) {
-- 
2.55.0


^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH v5 11/16] console/braille: Lock console->setup() call during the registration
  2026-09-29 12:05 [PATCH v5 00/16] printk: Clean up preferred console handling Petr Mladek
                   ` (9 preceding siblings ...)
  2026-09-29 12:05 ` [PATCH v5 10/16] printk: Allow to debug misuse of add_or_update_preferred_console() Petr Mladek
@ 2026-09-29 12:05 ` Petr Mladek
  2026-09-29 12:05 ` [PATCH v5 12/16] printk: Separate code for enabling console Petr Mladek
                   ` (4 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Petr Mladek @ 2026-09-29 12:05 UTC (permalink / raw)
  To: John Ogness
  Cc: Sergey Senozhatsky, Steven Rostedt, Marcos Paulo de Souza,
	Chris Down, Naveen Kumar Chaudhary, linux-kernel, Petr Mladek,
	Sashiko

In braille_register_console(), the console->setup() callback must be
called while holding the console_lock. This prevents a race condition
with a possible active boot console that might be using the same hardware
registers.

See also the commit 801410b26a0e ("serial: Lock console when calling into
driver before registration").

Reported-by: Sashiko <sashiko-bot@kernel.org>
Closes: https://sashiko.dev/#/patchset/20260423130015.85175-1-pmladek%40suse.com
Suggested-by: John Ogness <john.ogness@linutronix.de>
Signed-off-by: Petr Mladek <pmladek@suse.com>
---
 drivers/accessibility/braille/braille_console.c | 10 +++++-----
 include/linux/console.h                         |  1 +
 kernel/printk/printk.c                          |  2 +-
 3 files changed, 7 insertions(+), 6 deletions(-)

diff --git a/drivers/accessibility/braille/braille_console.c b/drivers/accessibility/braille/braille_console.c
index 7e6011f9d823..200ca305c6af 100644
--- a/drivers/accessibility/braille/braille_console.c
+++ b/drivers/accessibility/braille/braille_console.c
@@ -389,11 +389,11 @@ int braille_register_console(struct console *console, int index,
 		console_options = "57600o8";
 	if (braille_co)
 		return -ENODEV;
-	if (console->setup) {
-		ret = console->setup(console, console_options);
-		if (ret != 0)
-			return ret;
-	}
+
+	ret = console_call_setup(console, console_options);
+	if (ret != 0)
+		return ret;
+
 	console->flags |= CON_ENABLED | CON_BRL;
 	console->index = index;
 	braille_co = console;
diff --git a/include/linux/console.h b/include/linux/console.h
index d780f6de303a..11d6b854ee63 100644
--- a/include/linux/console.h
+++ b/include/linux/console.h
@@ -699,6 +699,7 @@ enum con_flush_mode {
 };
 
 extern int add_preferred_console(const char *name, const short idx, char *options);
+extern int console_call_setup(struct console *newcon, char *options);
 extern void console_force_preferred_locked(struct console *con);
 extern void register_console(struct console *);
 extern int unregister_console(struct console *);
diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c
index 683083405230..f2a602a05614 100644
--- a/kernel/printk/printk.c
+++ b/kernel/printk/printk.c
@@ -3948,7 +3948,7 @@ static int __init keep_bootcon_setup(char *str)
 
 early_param("keep_bootcon", keep_bootcon_setup);
 
-static int console_call_setup(struct console *newcon, char *options)
+int console_call_setup(struct console *newcon, char *options)
 {
 	int err;
 
-- 
2.55.0


^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH v5 12/16] printk: Separate code for enabling console
  2026-09-29 12:05 [PATCH v5 00/16] printk: Clean up preferred console handling Petr Mladek
                   ` (10 preceding siblings ...)
  2026-09-29 12:05 ` [PATCH v5 11/16] console/braille: Lock console->setup() call during the registration Petr Mladek
@ 2026-09-29 12:05 ` Petr Mladek
  2026-09-29 12:05 ` [PATCH v5 13/16] printk: Try to register each console as Braille first Petr Mladek
                   ` (3 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Petr Mladek @ 2026-09-29 12:05 UTC (permalink / raw)
  To: John Ogness
  Cc: Sergey Senozhatsky, Steven Rostedt, Marcos Paulo de Souza,
	Chris Down, Naveen Kumar Chaudhary, linux-kernel, Petr Mladek

There are several code paths which try to enable a newly registered
console. Move the logic into a separate try_enable_console() function.

It simplifies a bit the long register_console() function definition.

Also followup patches are going to add even more code paths. And it will
be easier to use "return" when it does not make sense to try other
variants.

No behavior change.

Signed-off-by: Petr Mladek <pmladek@suse.com>
---
 kernel/printk/printk.c | 84 ++++++++++++++++++++++++------------------
 1 file changed, 48 insertions(+), 36 deletions(-)

diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c
index f2a602a05614..8a51c4b690b7 100644
--- a/kernel/printk/printk.c
+++ b/kernel/printk/printk.c
@@ -4026,6 +4026,53 @@ static void try_enable_default_console(struct console *newcon)
 		newcon->flags |= CON_CONSDEV;
 }
 
+#define console_first()				\
+	hlist_entry(console_list.first, struct console, node)
+
+static int try_enable_console(struct console *newcon)
+{
+	int err;
+
+	/*
+	 * See if we want to enable this console driver by default.
+	 *
+	 * Nope when a console is preferred by the command line, device
+	 * tree, or SPCR.
+	 *
+	 * The first real console with tty binding (driver) wins. More
+	 * consoles might get enabled before the right one is found.
+	 *
+	 * Note that a console with tty binding will have CON_CONSDEV
+	 * flag set and will be first in the list.
+	 */
+	if (preferred_dev_console < 0) {
+		if (hlist_empty(&console_list) || !console_first()->device ||
+		    console_first()->flags & CON_BOOT) {
+			try_enable_default_console(newcon);
+		}
+	}
+
+	/* See if this console matches one we selected on the command line */
+	err = try_enable_preferred_console(newcon, true);
+	if (err != -ENOENT)
+		return err;
+
+	/* If not, try to match against the platform default(s) */
+	err = try_enable_preferred_console(newcon, false);
+	if (err != -ENOENT)
+		return err;
+
+	/*
+	 * Some consoles, such as pstore and netconsole, can be enabled even
+	 * without matching. Accept them at this stage when they had a chance
+	 * to match() and call setup().
+	 */
+	if (newcon->flags & CON_ENABLED)
+		err = 0;
+
+	return err;
+}
+
 /* Return the starting sequence number for a newly registered console. */
 static u64 get_init_console_seq(struct console *newcon, bool bootcon_registered)
 {
@@ -4100,9 +4147,6 @@ static u64 get_init_console_seq(struct console *newcon, bool bootcon_registered)
 	return init_seq;
 }
 
-#define console_first()				\
-	hlist_entry(console_list.first, struct console, node)
-
 static int unregister_console_locked(struct console *console);
 
 /*
@@ -4164,39 +4208,7 @@ void register_console(struct console *newcon)
 			goto unlock;
 	}
 
-	/*
-	 * See if we want to enable this console driver by default.
-	 *
-	 * Nope when a console is preferred by the command line, device
-	 * tree, or SPCR.
-	 *
-	 * The first real console with tty binding (driver) wins. More
-	 * consoles might get enabled before the right one is found.
-	 *
-	 * Note that a console with tty binding will have CON_CONSDEV
-	 * flag set and will be first in the list.
-	 */
-	if (preferred_dev_console < 0) {
-		if (hlist_empty(&console_list) || !console_first()->device ||
-		    console_first()->flags & CON_BOOT) {
-			try_enable_default_console(newcon);
-		}
-	}
-
-	/* See if this console matches one we selected on the command line */
-	err = try_enable_preferred_console(newcon, true);
-
-	/* If not, try to match against the platform default(s) */
-	if (err == -ENOENT)
-		err = try_enable_preferred_console(newcon, false);
-
-	/*
-	 * Some consoles, such as pstore and netconsole, can be enabled even
-	 * without matching. Accept them at this stage when they had a chance
-	 * to match() and call setup().
-	 */
-	if (err == -ENOENT && (newcon->flags & CON_ENABLED))
-		err = 0;
+	err = try_enable_console(newcon);
 
 	/* printk() messages are not printed to the Braille console. */
 	if (err || newcon->flags & CON_BRL) {
-- 
2.55.0


^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH v5 13/16] printk: Try to register each console as Braille first
  2026-09-29 12:05 [PATCH v5 00/16] printk: Clean up preferred console handling Petr Mladek
                   ` (11 preceding siblings ...)
  2026-09-29 12:05 ` [PATCH v5 12/16] printk: Separate code for enabling console Petr Mladek
@ 2026-09-29 12:05 ` Petr Mladek
  2026-09-29 12:05 ` [PATCH v5 14/16] printk: Do not set Braille console as preferred_console Petr Mladek
                   ` (2 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Petr Mladek @ 2026-09-29 12:05 UTC (permalink / raw)
  To: John Ogness
  Cc: Sergey Senozhatsky, Steven Rostedt, Marcos Paulo de Souza,
	Chris Down, Naveen Kumar Chaudhary, linux-kernel, Petr Mladek

Braille consoles are unique: they can only be enabled via the command
line and use the preferred console framework for initialization, yet
they are never added to the console_list or associated with
/dev/console. Because of this, the preferred_console variable remains
unset when only a Braille console is requested.

Currently, try_enable_preferred_console() must be called even when
"preferred_dev_console" variable is not set, just to catch these "hidden"
Braille requests.

Refactor the logic by adding a parameter to try_enable_preferred_console()
to explicitly handle Braille vs. non-Braille cases. It will eventually
allow to skip try_enable_preferred_console() when there are no preferred
consoles. This improves code robustness by ensuring the console
setup is explicit and only performed once.

Note that _braille_register_console() is skipped when the given console
driver has a match() callback and it succeeded. It means that it took
over an early console and can't be used as a Braille console.

As a result try_enable_braille_console() might return success even
when it did not enabled the console in the Braille mode. It is
the reason why register_console() has to explicitly check whether
CON_BRL flag was really set and could skip the further steps.

The refactoring even fixes two subtle bugs:

1. When only the Braille console is defined on the command line,
   the original code might attempt to enable the same console twice—once
   as a default and once as a Braille console. This results in calling
   the setup() callback twice and incorrectly setting the CON_CONSDEV flag.

2. When the same console is defined on the command line using devname
   and then as Braille console, for example:

      console=00:00:0.0,115200 console=brl,ttyS0,115200

   It would have two separate entries in preferred_consoles[] array.

   The 2nd (Braille) entry would be used when univ8250_console_init()
   tries to register the generic "ttyS" console driver. Note that
   the 1st entry still does not have defined the "name" entry at
   this stage.

   The 1st non-Braille entry would be used later when serial8250_init()
   registers all found devices, assigns "tty0" for the given "00:00:0.0"
   devname and tries to register the same struct console once again.

   The original code would call newcon->setup() twice in this scenario.
   It won't add the console into console_list only because the later
   check in register_console() would detect CON_BRL flag set from
   the 1st registration and return early.

Signed-off-by: Petr Mladek <pmladek@suse.com>
---
 kernel/printk/printk.c | 58 +++++++++++++++++++++++++++++++++++++-----
 1 file changed, 52 insertions(+), 6 deletions(-)

diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c
index 8a51c4b690b7..75d2a1085926 100644
--- a/kernel/printk/printk.c
+++ b/kernel/printk/printk.c
@@ -367,6 +367,7 @@ static int console_locked;
 static struct preferred_console preferred_consoles[MAX_PREFERRED_CONSOLES];
 
 static int preferred_dev_console = -1;
+static bool want_braille_console;
 int console_set_on_cmdline;
 EXPORT_SYMBOL(console_set_on_cmdline);
 
@@ -2644,7 +2645,9 @@ static int add_or_update_preferred_console(unsigned int i,
 		braille_set_options(pc, brl_options);
 	}
 
-	if (!brl_options)
+	if (brl_options)
+		want_braille_console = true;
+	else
 		preferred_dev_console = i;
 
 	if (user_specified) {
@@ -3969,8 +3972,9 @@ int console_call_setup(struct console *newcon, char *options)
  * by either the command line or add_preferred_console() and
  * setup/enable it.
  */
-static int try_enable_preferred_console(struct console *newcon,
-					bool user_specified)
+static int __try_enable_preferred_console(struct console *newcon,
+					  bool user_specified,
+					  bool try_only_braille)
 {
 	struct preferred_console *pc;
 	int i, err;
@@ -3981,8 +3985,21 @@ static int try_enable_preferred_console(struct console *newcon,
 		/* Console not yet initialized? */
 		if (!pc->name[0])
 			continue;
-		if (pc->user_specified != user_specified)
-			continue;
+
+		/*
+		 * @try_only_braille and @user_specifified define which
+		 * preferred console entries are handled in this round.
+		 */
+		if (try_only_braille) {
+			if (!is_braille_console_preferred(pc))
+				continue;
+		} else {
+			if (is_braille_console_preferred(pc))
+				continue;
+			if (pc->user_specified != user_specified)
+				continue;
+		}
+
 		if (!newcon->match ||
 		    newcon->match(newcon, pc->name, pc->index, pc->options) != 0) {
 			/* default matching */
@@ -3995,7 +4012,7 @@ static int try_enable_preferred_console(struct console *newcon,
 			if (newcon->index < 0)
 				newcon->index = pc->index;
 
-			if (is_braille_console_preferred(pc))
+			if (try_only_braille)
 				return _braille_register_console(newcon, pc);
 
 			err = console_call_setup(newcon, pc->options);
@@ -4011,6 +4028,17 @@ static int try_enable_preferred_console(struct console *newcon,
 	return -ENOENT;
 }
 
+static int try_enable_preferred_console(struct console *newcon,
+					bool user_specified)
+{
+	return __try_enable_preferred_console(newcon, user_specified, false);
+}
+
+static int try_enable_braille_console(struct console *newcon)
+{
+	return __try_enable_preferred_console(newcon, true, true);
+}
+
 /* Try to enable the console unconditionally */
 static void try_enable_default_console(struct console *newcon)
 {
@@ -4033,6 +4061,24 @@ static int try_enable_console(struct console *newcon)
 {
 	int err;
 
+	/*
+	 * First, try to enable the console driver as a Braille console.
+	 * It would have metadata in the preferred_consoles[] array.
+	 * But it won't be counted as @preferred_console because
+	 * it does not get printk() messages and is not associated
+	 * with /dev/console.
+	 *
+	 * Note that it might succeed also when the driver has a match()
+	 * callback and it took over a boot console. In this case,
+	 * the driver will continue working as a classic non-Braille
+	 * console.
+	 */
+	if (want_braille_console) {
+		err = try_enable_braille_console(newcon);
+		if (err != -ENOENT)
+			return err;
+	}
+
 	/*
 	 * See if we want to enable this console driver by default.
 	 *
-- 
2.55.0


^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH v5 14/16] printk: Do not set Braille console as preferred_console
  2026-09-29 12:05 [PATCH v5 00/16] printk: Clean up preferred console handling Petr Mladek
                   ` (12 preceding siblings ...)
  2026-09-29 12:05 ` [PATCH v5 13/16] printk: Try to register each console as Braille first Petr Mladek
@ 2026-09-29 12:05 ` Petr Mladek
  2026-09-29 12:05 ` [PATCH v5 15/16] printk: Modify try_enable_default_console() to return error/success Petr Mladek
  2026-09-29 12:05 ` [PATCH v5 16/16] printk: Try enable preferred consoles only when there are any Petr Mladek
  15 siblings, 0 replies; 17+ messages in thread
From: Petr Mladek @ 2026-09-29 12:05 UTC (permalink / raw)
  To: John Ogness
  Cc: Sergey Senozhatsky, Steven Rostedt, Marcos Paulo de Souza,
	Chris Down, Naveen Kumar Chaudhary, linux-kernel, Petr Mladek

The Braille console reuses the framework for handling consoles preferred
via the command line. However, it is a special-purpose interface that
neither receives standard printk messages nor associates with
/dev/console.

Currently, the "preferred_dev_console" variable can point to a Braille
console entry in the "preferred_consoles[]" array. This occurs if an
entry was first created for a non-Braille console, but a later 'console='
parameter redefined it as a Braille console.

Since a Braille console will only ever be enabled as such, it should not
be tracked as the primary system console. Adjust the logic to ensure
"preferred_dev_console" continues to point to the previously designated
normal console instead.

Signed-off-by: Petr Mladek <pmladek@suse.com>
Assisted-by: gemini-1.5-pro
---
 kernel/printk/console_register.h |  3 +++
 kernel/printk/printk.c           | 33 ++++++++++++++++++++++++++------
 2 files changed, 30 insertions(+), 6 deletions(-)

diff --git a/kernel/printk/console_register.h b/kernel/printk/console_register.h
index 9ab3e1cc749b..64cf12fd6ea5 100644
--- a/kernel/printk/console_register.h
+++ b/kernel/printk/console_register.h
@@ -2,6 +2,8 @@
 #ifndef _CONSOLE_REGISTER_H
 #define _CONSOLE_REGISTER_H
 
+#include <linux/list.h>
+
 struct preferred_console
 {
 	char	name[16];			/* Name of the driver	    */
@@ -12,6 +14,7 @@ struct preferred_console
 #ifdef CONFIG_A11Y_BRAILLE_CONSOLE
 	char	*brl_options;			/* Options for braille driver */
 #endif
+	struct list_head preferred_dev_node;
 };
 
 #endif
diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c
index 75d2a1085926..a2cc7bf3a62e 100644
--- a/kernel/printk/printk.c
+++ b/kernel/printk/printk.c
@@ -366,7 +366,7 @@ static int console_locked;
 
 static struct preferred_console preferred_consoles[MAX_PREFERRED_CONSOLES];
 
-static int preferred_dev_console = -1;
+static LIST_HEAD(preferred_dev_console);
 static bool want_braille_console;
 int console_set_on_cmdline;
 EXPORT_SYMBOL(console_set_on_cmdline);
@@ -2567,9 +2567,16 @@ asmlinkage __visible void early_printk(const char *fmt, ...)
  *   3. Allow to override @options via the command line. Last one wins
  *	except that the Braille variant is preferred.
  *
+ *   4. Braille console is never associated with /dev/console.[**]
+ *
  *  [*] A valid @name and @idx will get assigned for a devname later when
  *	@devname matches during the device initialization, see
  *	match_devname_and_update_preferred_console().
+ *
+ * [**] Braille console is using the mechanism for registering consoles
+ *	but it is very special. It is primarily used for user interaction
+ *	with the system. It neither gets printk() messages nor is
+ *	associated with /dev/console.
  */
 static int add_or_update_preferred_console(unsigned int i,
 					   const char *name, const short idx,
@@ -2645,10 +2652,24 @@ static int add_or_update_preferred_console(unsigned int i,
 		braille_set_options(pc, brl_options);
 	}
 
-	if (brl_options)
+	if (is_new_entry)
+		INIT_LIST_HEAD(&pc->preferred_dev_node);
+
+	/*
+	 * The last preferred console should get associated with /dev/console.
+	 * Except for the Braille console which can't get associated with
+	 * /dev/console.
+	 */
+	if (brl_options) {
 		want_braille_console = true;
-	else
-		preferred_dev_console = i;
+		if (!list_empty(&pc->preferred_dev_node))
+			list_del_init(&pc->preferred_dev_node);
+	} else if (!is_braille_console_preferred(pc)) {
+		if (list_empty(&pc->preferred_dev_node))
+			list_add(&pc->preferred_dev_node, &preferred_dev_console);
+		else
+			list_move(&pc->preferred_dev_node, &preferred_dev_console);
+	}
 
 	if (user_specified) {
 		pc->user_specified = true;
@@ -4020,7 +4041,7 @@ static int __try_enable_preferred_console(struct console *newcon,
 				return err;
 		}
 		newcon->flags |= CON_ENABLED;
-		if (i == preferred_dev_console)
+		if (list_is_first(&pc->preferred_dev_node, &preferred_dev_console))
 			newcon->flags |= CON_CONSDEV;
 		return 0;
 	}
@@ -4091,7 +4112,7 @@ static int try_enable_console(struct console *newcon)
 	 * Note that a console with tty binding will have CON_CONSDEV
 	 * flag set and will be first in the list.
 	 */
-	if (preferred_dev_console < 0) {
+	if (list_empty(&preferred_dev_console)) {
 		if (hlist_empty(&console_list) || !console_first()->device ||
 		    console_first()->flags & CON_BOOT) {
 			try_enable_default_console(newcon);
-- 
2.55.0


^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH v5 15/16] printk: Modify try_enable_default_console() to return error/success
  2026-09-29 12:05 [PATCH v5 00/16] printk: Clean up preferred console handling Petr Mladek
                   ` (13 preceding siblings ...)
  2026-09-29 12:05 ` [PATCH v5 14/16] printk: Do not set Braille console as preferred_console Petr Mladek
@ 2026-09-29 12:05 ` Petr Mladek
  2026-09-29 12:05 ` [PATCH v5 16/16] printk: Try enable preferred consoles only when there are any Petr Mladek
  15 siblings, 0 replies; 17+ messages in thread
From: Petr Mladek @ 2026-09-29 12:05 UTC (permalink / raw)
  To: John Ogness
  Cc: Sergey Senozhatsky, Steven Rostedt, Marcos Paulo de Souza,
	Chris Down, Naveen Kumar Chaudhary, linux-kernel, Petr Mladek

Currently, try_enable_default_console() has a void return type, and
its potential failures (specifically when console_call_setup() fails)
are ignored by its caller, try_enable_console().

Modify try_enable_default_console() to return error/success, and update
try_enable_console() to capture and propagate this error.

With this change, try_enable_console() will no longer return success
for a pre-enabled console if try_enable_default_console() failed (such
as when newcon->setup() fails). While this might change existing behavior,
it is the correct approach to ensure setup errors are not silently ignored
or treated as successful registrations simply because the console was
marked pre-enabled.

Assisted-by: Gemini:gemini-3 # commit message
Signed-off-by: Petr Mladek <pmladek@suse.com>
---
 kernel/printk/printk.c | 15 +++++++++++----
 1 file changed, 11 insertions(+), 4 deletions(-)

diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c
index a2cc7bf3a62e..1eb749da9e24 100644
--- a/kernel/printk/printk.c
+++ b/kernel/printk/printk.c
@@ -4061,18 +4061,23 @@ static int try_enable_braille_console(struct console *newcon)
 }
 
 /* Try to enable the console unconditionally */
-static void try_enable_default_console(struct console *newcon)
+static int try_enable_default_console(struct console *newcon)
 {
+	int err;
+
 	if (newcon->index < 0)
 		newcon->index = 0;
 
-	if (console_call_setup(newcon, NULL) != 0)
-		return;
+	err = console_call_setup(newcon, NULL);
+	if (err)
+		return err;
 
 	newcon->flags |= CON_ENABLED;
 
 	if (newcon->device)
 		newcon->flags |= CON_CONSDEV;
+
+	return 0;
 }
 
 #define console_first()				\
@@ -4115,7 +4120,9 @@ static int try_enable_console(struct console *newcon)
 	if (list_empty(&preferred_dev_console)) {
 		if (hlist_empty(&console_list) || !console_first()->device ||
 		    console_first()->flags & CON_BOOT) {
-			try_enable_default_console(newcon);
+			err = try_enable_default_console(newcon);
+			if (err != -ENOENT)
+				return err;
 		}
 	}
 
-- 
2.55.0


^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH v5 16/16] printk: Try enable preferred consoles only when there are any
  2026-09-29 12:05 [PATCH v5 00/16] printk: Clean up preferred console handling Petr Mladek
                   ` (14 preceding siblings ...)
  2026-09-29 12:05 ` [PATCH v5 15/16] printk: Modify try_enable_default_console() to return error/success Petr Mladek
@ 2026-09-29 12:05 ` Petr Mladek
  15 siblings, 0 replies; 17+ messages in thread
From: Petr Mladek @ 2026-09-29 12:05 UTC (permalink / raw)
  To: John Ogness
  Cc: Sergey Senozhatsky, Steven Rostedt, Marcos Paulo de Souza,
	Chris Down, Naveen Kumar Chaudhary, linux-kernel, Petr Mladek

try_enable_preferred_console() used to be always called because it
had several hidden effects, namely:

- returned success when a console was pre-enabled using CON_ENABLED
  flag.

- enabled Braille consoles which were ignored by "preferred_dev_console"
  because they were not associated with /dev/console.

- returned success when a console was enabled by default because
  try_enable_default_console() did not return success.

The first two hidden effects were removed in previous patches. The already
fixed handling of pre-enabled consoles actually helps even the 3rd case.
try_enable_default_console() sets CON_ENABLED flag on success and
is later handled as pre-enabled.

Prevent any future hidden effects and call try_enable_preferred_console()
only when some console is preferred.

No behavior change.

Signed-off-by: Petr Mladek <pmladek@suse.com>
---
 kernel/printk/printk.c | 26 +++++++++++++++++---------
 1 file changed, 17 insertions(+), 9 deletions(-)

diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c
index 1eb749da9e24..06c49042dd8f 100644
--- a/kernel/printk/printk.c
+++ b/kernel/printk/printk.c
@@ -4085,7 +4085,7 @@ static int try_enable_default_console(struct console *newcon)
 
 static int try_enable_console(struct console *newcon)
 {
-	int err;
+	int err = -ENOENT;
 
 	/*
 	 * First, try to enable the console driver as a Braille console.
@@ -4124,16 +4124,24 @@ static int try_enable_console(struct console *newcon)
 			if (err != -ENOENT)
 				return err;
 		}
+	} else {
+		/* See if this console matches one we selected on the command line */
+		err = try_enable_preferred_console(newcon, true);
+		if (err != -ENOENT)
+			return err;
+
+		/* If not, try to match against the platform default(s) */
+		err = try_enable_preferred_console(newcon, false);
+		if (err != -ENOENT)
+			return err;
 	}
 
-	/* See if this console matches one we selected on the command line */
-	err = try_enable_preferred_console(newcon, true);
-	if (err != -ENOENT)
-		return err;
-
-	/* If not, try to match against the platform default(s) */
-	err = try_enable_preferred_console(newcon, false);
-	if (err != -ENOENT)
+	/*
+	 * Make sure that pre-enabled consoles won't get registered when
+	 * something went wrong. This is just a paranoid check that all
+	 * branches above returned on error.
+	 */
+	if (WARN_ON(err != -ENOENT))
 		return err;
 
 	/*
-- 
2.55.0


^ permalink raw reply	[flat|nested] 17+ messages in thread

end of thread, other threads:[~2026-09-29 12:09 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-09-29 12:05 [PATCH v5 00/16] printk: Clean up preferred console handling Petr Mladek
2026-09-29 12:05 ` [PATCH v5 01/16] printk: Rename struct console_cmdline to preferred_console Petr Mladek
2026-09-29 12:05 ` [PATCH v5 02/16] printk: Rename preferred_console to preferred_dev_console Petr Mladek
2026-09-29 12:05 ` [PATCH v5 03/16] printk: Cleanup _braille_(un)register_console() wrappers Petr Mladek
2026-09-29 12:05 ` [PATCH v5 04/16] printk: Separate code for adding/updating preferred console metadata Petr Mladek
2026-09-29 12:05 ` [PATCH v5 05/16] printk: Prefer the console either via name or devname exclusively Petr Mladek
2026-09-29 12:05 ` [PATCH v5 06/16] printk: Check that index is not defined when a console is preferred via devname Petr Mladek
2026-09-29 12:05 ` [PATCH v5 07/16] printk: Ensure consistent name and devname when updating preferred console Petr Mladek
2026-09-29 12:05 ` [PATCH v5 08/16] printk: Do not quietly ignore adding entry for a preferred console when there is no space Petr Mladek
2026-09-29 12:05 ` [PATCH v5 09/16] printk: Allow to override options via the command line Petr Mladek
2026-09-29 12:05 ` [PATCH v5 10/16] printk: Allow to debug misuse of add_or_update_preferred_console() Petr Mladek
2026-09-29 12:05 ` [PATCH v5 11/16] console/braille: Lock console->setup() call during the registration Petr Mladek
2026-09-29 12:05 ` [PATCH v5 12/16] printk: Separate code for enabling console Petr Mladek
2026-09-29 12:05 ` [PATCH v5 13/16] printk: Try to register each console as Braille first Petr Mladek
2026-09-29 12:05 ` [PATCH v5 14/16] printk: Do not set Braille console as preferred_console Petr Mladek
2026-09-29 12:05 ` [PATCH v5 15/16] printk: Modify try_enable_default_console() to return error/success Petr Mladek
2026-09-29 12:05 ` [PATCH v5 16/16] printk: Try enable preferred consoles only when there are any Petr Mladek

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®