* [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