Skip to content

Commit 7640f1a

Browse files
tony-lindgrengregkh
authored andcommitted
printk: Add match_devname_and_update_preferred_console()
Let's add match_devname_and_update_preferred_console() for driver subsystems to call during init when the console is ready, and it's character device name is known. For now, we use it only for the serial layer to allow console=DEVNAME:0.0 style hardware based addressing for consoles. The earlier attempt on doing this caused a regression with the kernel command line console order as it added calling __add_preferred_console() again later on during init. A better approach was suggested by Petr where we add the deferred console to the console_cmdline[] and update it later on when the console is ready. Suggested-by: Petr Mladek <[email protected]> Co-developed-by: Petr Mladek <[email protected]> Signed-off-by: Tony Lindgren <[email protected]> Reviewed-by: Petr Mladek <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 33827dc commit 7640f1a

File tree

3 files changed

+93
-15
lines changed

3 files changed

+93
-15
lines changed

include/linux/printk.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,10 @@ static inline const char *printk_skip_headers(const char *buffer)
6060
#define CONSOLE_LOGLEVEL_DEFAULT CONFIG_CONSOLE_LOGLEVEL_DEFAULT
6161
#define CONSOLE_LOGLEVEL_QUIET CONFIG_CONSOLE_LOGLEVEL_QUIET
6262

63+
int match_devname_and_update_preferred_console(const char *match,
64+
const char *name,
65+
const short idx);
66+
6367
extern int console_printk[];
6468

6569
#define console_loglevel (console_printk[0])

kernel/printk/console_cmdline.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ struct console_cmdline
66
{
77
char name[16]; /* Name of the driver */
88
int index; /* Minor dev. to use */
9+
char devname[32]; /* DEVNAME:0.0 style device name */
910
bool user_specified; /* Specified by command line vs. platform */
1011
char *options; /* Options for the driver */
1112
#ifdef CONFIG_A11Y_BRAILLE_CONSOLE

kernel/printk/printk.c

Lines changed: 88 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2429,28 +2429,34 @@ static void set_user_specified(struct console_cmdline *c, bool user_specified)
24292429
console_set_on_cmdline = 1;
24302430
}
24312431

2432-
static int __add_preferred_console(const char *name, const short idx, char *options,
2432+
static int __add_preferred_console(const char *name, const short idx,
2433+
const char *devname, char *options,
24332434
char *brl_options, bool user_specified)
24342435
{
24352436
struct console_cmdline *c;
24362437
int i;
24372438

2439+
if (!name && !devname)
2440+
return -EINVAL;
2441+
24382442
/*
24392443
* We use a signed short index for struct console for device drivers to
24402444
* indicate a not yet assigned index or port. However, a negative index
2441-
* value is not valid for preferred console.
2445+
* value is not valid when the console name and index are defined on
2446+
* the command line.
24422447
*/
2443-
if (idx < 0)
2448+
if (name && idx < 0)
24442449
return -EINVAL;
24452450

24462451
/*
24472452
* See if this tty is not yet registered, and
24482453
* if we have a slot free.
24492454
*/
24502455
for (i = 0, c = console_cmdline;
2451-
i < MAX_CMDLINECONSOLES && c->name[0];
2456+
i < MAX_CMDLINECONSOLES && (c->name[0] || c->devname[0]);
24522457
i++, c++) {
2453-
if (strcmp(c->name, name) == 0 && c->index == idx) {
2458+
if ((name && strcmp(c->name, name) == 0 && c->index == idx) ||
2459+
(devname && strcmp(c->devname, devname) == 0)) {
24542460
if (!brl_options)
24552461
preferred_console = i;
24562462
set_user_specified(c, user_specified);
@@ -2461,7 +2467,10 @@ static int __add_preferred_console(const char *name, const short idx, char *opti
24612467
return -E2BIG;
24622468
if (!brl_options)
24632469
preferred_console = i;
2464-
strscpy(c->name, name, sizeof(c->name));
2470+
if (name)
2471+
strscpy(c->name, name);
2472+
if (devname)
2473+
strscpy(c->devname, devname);
24652474
c->options = options;
24662475
set_user_specified(c, user_specified);
24672476
braille_set_options(c, brl_options);
@@ -2486,8 +2495,13 @@ __setup("console_msg_format=", console_msg_format_setup);
24862495
*/
24872496
static int __init console_setup(char *str)
24882497
{
2489-
char buf[sizeof(console_cmdline[0].name) + 4]; /* 4 for "ttyS" */
2490-
char *s, *options, *brl_options = NULL;
2498+
static_assert(sizeof(console_cmdline[0].devname) >= sizeof(console_cmdline[0].name) + 4);
2499+
char buf[sizeof(console_cmdline[0].devname)];
2500+
char *brl_options = NULL;
2501+
char *ttyname = NULL;
2502+
char *devname = NULL;
2503+
char *options;
2504+
char *s;
24912505
int idx;
24922506

24932507
/*
@@ -2496,17 +2510,23 @@ static int __init console_setup(char *str)
24962510
* for exactly this purpose.
24972511
*/
24982512
if (str[0] == 0 || strcmp(str, "null") == 0) {
2499-
__add_preferred_console("ttynull", 0, NULL, NULL, true);
2513+
__add_preferred_console("ttynull", 0, NULL, NULL, NULL, true);
25002514
return 1;
25012515
}
25022516

25032517
if (_braille_console_setup(&str, &brl_options))
25042518
return 1;
25052519

2520+
/* For a DEVNAME:0.0 style console the character device is unknown early */
2521+
if (strchr(str, ':'))
2522+
devname = buf;
2523+
else
2524+
ttyname = buf;
2525+
25062526
/*
25072527
* Decode str into name, index, options.
25082528
*/
2509-
if (isdigit(str[0]))
2529+
if (ttyname && isdigit(str[0]))
25102530
scnprintf(buf, sizeof(buf), "ttyS%s", str);
25112531
else
25122532
strscpy(buf, str);
@@ -2523,12 +2543,18 @@ static int __init console_setup(char *str)
25232543
#endif
25242544

25252545
for (s = buf; *s; s++)
2526-
if (isdigit(*s) || *s == ',')
2546+
if ((ttyname && isdigit(*s)) || *s == ',')
25272547
break;
2528-
idx = simple_strtoul(s, NULL, 10);
2548+
2549+
/* @idx will get defined when devname matches. */
2550+
if (devname)
2551+
idx = -1;
2552+
else
2553+
idx = simple_strtoul(s, NULL, 10);
2554+
25292555
*s = 0;
25302556

2531-
__add_preferred_console(buf, idx, options, brl_options, true);
2557+
__add_preferred_console(ttyname, idx, devname, options, brl_options, true);
25322558
return 1;
25332559
}
25342560
__setup("console=", console_setup);
@@ -2548,7 +2574,51 @@ __setup("console=", console_setup);
25482574
*/
25492575
int add_preferred_console(const char *name, const short idx, char *options)
25502576
{
2551-
return __add_preferred_console(name, idx, options, NULL, false);
2577+
return __add_preferred_console(name, idx, NULL, options, NULL, false);
2578+
}
2579+
2580+
/**
2581+
* match_devname_and_update_preferred_console - Update a preferred console
2582+
* when matching devname is found.
2583+
* @devname: DEVNAME:0.0 style device name
2584+
* @name: Name of the corresponding console driver, e.g. "ttyS"
2585+
* @idx: Console index, e.g. port number.
2586+
*
2587+
* The function checks whether a device with the given @devname is
2588+
* preferred via the console=DEVNAME:0.0 command line option.
2589+
* It fills the missing console driver name and console index
2590+
* so that a later register_console() call could find (match)
2591+
* and enable this device.
2592+
*
2593+
* It might be used when a driver subsystem initializes particular
2594+
* devices with already known DEVNAME:0.0 style names. And it
2595+
* could predict which console driver name and index this device
2596+
* would later get associated with.
2597+
*
2598+
* Return: 0 on success, negative error code on failure.
2599+
*/
2600+
int match_devname_and_update_preferred_console(const char *devname,
2601+
const char *name,
2602+
const short idx)
2603+
{
2604+
struct console_cmdline *c = console_cmdline;
2605+
int i;
2606+
2607+
if (!devname || !strlen(devname) || !name || !strlen(name) || idx < 0)
2608+
return -EINVAL;
2609+
2610+
for (i = 0; i < MAX_CMDLINECONSOLES && (c->name[0] || c->devname[0]);
2611+
i++, c++) {
2612+
if (!strcmp(devname, c->devname)) {
2613+
pr_info("associate the preferred console \"%s\" with \"%s%d\"\n",
2614+
devname, name, idx);
2615+
strscpy(c->name, name);
2616+
c->index = idx;
2617+
return 0;
2618+
}
2619+
}
2620+
2621+
return -ENOENT;
25522622
}
25532623

25542624
bool console_suspend_enabled = true;
@@ -3318,8 +3388,11 @@ static int try_enable_preferred_console(struct console *newcon,
33183388
int i, err;
33193389

33203390
for (i = 0, c = console_cmdline;
3321-
i < MAX_CMDLINECONSOLES && c->name[0];
3391+
i < MAX_CMDLINECONSOLES && (c->name[0] || c->devname[0]);
33223392
i++, c++) {
3393+
/* Console not yet initialized? */
3394+
if (!c->name[0])
3395+
continue;
33233396
if (c->user_specified != user_specified)
33243397
continue;
33253398
if (!newcon->match ||

0 commit comments

Comments
 (0)