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.
Introduce update_preferred_console() to centralize the initialization
and updating of struct preferred_console entries. This refactoring
explicitly defines and enforces the following rules:
1. Console names and/or indexes are not set when a console is preferred
via devname; these are resolved later during device matching.
2. Console names are only added alongside a valid index.
3. Only matching entries are updated.
4. Console and Braille options are never cleared. They are updated
only via the command line.
5. The global 'preferred_dev_console' index and 'console_set_on_cmdline'
flag are updated consistently.
Additionally, rename braille_set_options() to braille_update_options()
to better reflect its conditional behavior.
While this is primarily a refactoring, it fixes two minor behavioral
consistencies: console options can now be overridden via the command
line, and Braille options are preserved even if a non-Braille console
with the same name was previously defined.
Signed-off-by: Petr Mladek <pmladek@suse.com>
---
kernel/printk/braille.h | 7 +--
kernel/printk/printk.c | 110 +++++++++++++++++++++++++++-------------
2 files changed, 80 insertions(+), 37 deletions(-)
diff --git a/kernel/printk/braille.h b/kernel/printk/braille.h
index 55cd3178a17a..0bdac303f8b1 100644
--- a/kernel/printk/braille.h
+++ b/kernel/printk/braille.h
@@ -5,9 +5,10 @@
#ifdef CONFIG_A11Y_BRAILLE_CONSOLE
static inline void
-braille_set_options(struct preferred_console *pc, char *brl_options)
+braille_update_options(struct preferred_console *pc, char *brl_options)
{
- pc->brl_options = brl_options;
+ if (brl_options)
+ pc->brl_options = brl_options;
}
/*
@@ -29,7 +30,7 @@ _braille_unregister_console(struct console *console);
#else
static inline void
-braille_set_options(struct preferred_console *pc, char *brl_options)
+braille_update_options(struct preferred_console *pc, char *brl_options)
{
}
diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c
index 3f856a438e74..ee57c7ac9d02 100644
--- a/kernel/printk/printk.c
+++ b/kernel/printk/printk.c
@@ -2491,18 +2491,82 @@ asmlinkage __visible void early_printk(const char *fmt, ...)
}
#endif
-static void set_user_specified(struct preferred_console *pc, bool user_specified)
+static int update_preferred_console(int i, const char *name, const short idx,
+ const char *devname, char *options,
+ char *brl_options, bool user_specified)
{
- if (!user_specified)
- return;
+ struct preferred_console *pc;
+
+ if (i >= MAX_PREFERRED_CONSOLES)
+ return -E2BIG;
+
+ pc = &preferred_consoles[i];
+
+ if (!name && !devname)
+ return -EINVAL;
+
+ if (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;
+ }
+ if (idx != -1) {
+ pr_err("Adding a preferred console devname with a hard-coded index: %s, %d\n",
+ devname, idx);
+ return -EINVAL;
+ }
+
+ if (!pc->devname[0]) {
+ 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 (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;
+ }
+
+ if (!pc->name[0]) {
+ 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;
+ }
+ }
+
+ if (!pc->options || (user_specified && options))
+ pc->options = options;
+
+ braille_update_options(pc, brl_options);
+
+ if (!brl_options)
+ preferred_dev_console = i;
/*
* @c 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;
+ 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,
@@ -2515,14 +2579,6 @@ static int __add_preferred_console(const char *name, const short idx,
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;
/*
* See if this tty is not yet registered, and
@@ -2531,28 +2587,14 @@ static int __add_preferred_console(const char *name, const short idx,
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 update_preferred_console(i, name, idx, devname, options,
+ brl_options, user_specified);
}
static int __init console_msg_format_setup(char *str)
--
2.52.0