Per-console loglevel support, console device bus
Subsystems (57)
cover Per-console loglevel support, console device bus
Hello all,
This is an extremely overdue refresh of this series:
https://lkml.org/lkml/2017/9/28/770
The big change here is the 3rd patch, which actually wires up the console drivers to support embedding a device structure, so we can place them on a "console" bus and expose attributes in sysfs.
I left the very long list of driver maintainers off this first submission, once there's agreement on the core idea here I'll add them.
Thanks,
Calvin
Calvin Owens (4):
printk: Introduce per-console loglevel setting
printk: Add ability to set loglevel via "console=" cmdline
printk: Add consoles to a virtual "console" bus
printk: Add a device attribute for the per-console loglevel
131 files changed, 1859 insertions(+), 1061 deletions(-)
Signature · 1 line
2.17.1
PATCH 1/4 printk: Introduce per-console loglevel setting
Not all consoles are created equal: depending on the actual hardware, the latency of a printk() call can vary dramatically. The worst examples are serial consoles, where it can spin for tens of milliseconds banging the UART to emit a message, which can cause application-level problems when the kernel spews onto the console.
At Facebook we use netconsole to monitor our fleet, but we still have serial consoles attached on each host for live debugging, and the latter has caused problems. An obvious solution is to disable the kernel console output to ttyS0, but this makes live debugging frustrating, since crashes become silent and opaque to the ttyS0 user. Enabling it on the fly when needed isn't feasible, since boxes you need to debug via serial are likely to be borked in ways that make this impossible.
That puts us between a rock and a hard place: we'd love to set kernel.printk to KERN_INFO and get all the logs. But while netconsole is fast enough to permit that without perturbing userspace, ttyS0 is not, and we're forced to limit console logging to KERN_WARNING and higher.
This patch introduces a new per-console loglevel setting, and changes console_unlock() to use max(global_level, per_console_level) when deciding whether or not to emit a given log message.
This lets us have our cake and eat it too: instead of being forced to limit all consoles verbosity based on the speed of the slowest one, we can "promote" the faster console while still using a conservative system loglevel setting to avoid disturbing applications.
--- include/linux/console.h | 1 + kernel/printk/printk.c | 36 +++++++++++++++++++----------------- 2 files changed, 20 insertions(+), 17 deletions(-)
include/linux/console.h +1 -0
@@ -155,6 +155,7 @@ struct console {int cflag;void *data;struct console *next; +int level; };/*
kernel/printk/printk.c +19 -17
@@ -1164,9 +1164,14 @@ module_param(ignore_loglevel, bool, S_IRUGO | S_IWUSR);MODULE_PARM_DESC (ignore_loglevel,"ignore loglevel setting (prints all kernel messages to the console)" ); -static bool suppress_message_printing (int level) +static int effective_loglevel (struct console *con) { -return (level >= console_loglevel && !ignore_loglevel); +return max (console_loglevel, con ? con->level :LOGLEVEL_EMERG ); +} + +static bool suppress_message_printing (int level,struct console *con) +{ +return (level >=effective_loglevel (con) && !ignore_loglevel); }#ifdef CONFIG_BOOT_PRINTK_DELAY
@@ -1198,7 +1203,7 @@ static void boot_delay_msec(int level)unsigned long timeout;if ((boot_delay ==0 || system_state >=SYSTEM_RUNNING ) - ||suppress_message_printing (level)) { + ||suppress_message_printing (level,NULL )) {return ; }
@@ -1712,7 +1717,7 @@ static int console_trylock_spinning(void)* The console_lock must be held. */ static void call_console_drivers (const char *ext_text,size_t ext_len, -const char *text,size_t len) +const char *text,size_t len,int level) {struct console *con;
@@ -1731,6 +1736,8 @@ static void call_console_drivers(const char *ext_text, size_t ext_len,if (!cpu_online (smp_processor_id ()) && !(con->flags &CON_ANYTIME ))continue ; +if (suppress_message_printing (level, con)) +continue ;if (con->flags &CON_EXTENDED ) con->write (con, ext_text, ext_len);else
@@ -2022,7 +2029,7 @@ static ssize_t msg_print_ext_body(char *buf, size_t size,static void console_lock_spinning_enable (void ) { }static int console_lock_spinning_disable_and_check (void ) {return 0 ; }static void call_console_drivers (const char *ext_text,size_t ext_len, -const char *text,size_t len) {} +const char *text,size_t len,int level) {}static size_t msg_print_text (const struct printk_log *msg,bool syslog,bool time,char *buf,size_t size) {return 0 ; }static bool suppress_message_printing (int level) {return false; }
@@ -2358,21 +2365,11 @@ void console_unlock(void) }else { len =0 ; } -skip: +if (console_seq == log_next_seq)break ; msg =log_from_idx (console_idx); -if (suppress_message_printing (msg->level)) { -/* -* Skip record we have buffered and already printed -* directly to the console when we received it, and -* record that has level above the console loglevel. -*/ - console_idx =log_next (console_idx); - console_seq++; - goto skip; - }/* Output to all consoles once old messages replayed. */ if (unlikely(exclusive_console &&
@@ -2405,7 +2402,7 @@ void console_unlock(void)console_lock_spinning_enable ();stop_critical_timings ();/* don't trace print latency */ -call_console_drivers (ext_text, ext_len, text, len); +call_console_drivers (ext_text, ext_len, text, len, msg->level);start_critical_timings ();if (console_lock_spinning_disable_and_check ()) {
@@ -2671,6 +2668,11 @@ void register_console(struct console *newcon)if (bcon && ((newcon->flags & (CON_CONSDEV |CON_BOOT )) ==CON_CONSDEV )) newcon->flags &= ~CON_PRINTBUFFER ; +/* +* By default, the per-console minimum forces no messages through. +*/ + newcon->level =LOGLEVEL_EMERG ; +/* * Put this console in the list - keep the * preferred driver at the head of the list.
Signature · 1 line
2.17.1
Re: [PATCH 1/4] printk: Introduce per-console loglevel setting
On (03/01/19 16:48), Calvin Owens wrote:
[..]
Quoted 15 lines
kernel/printk/printk.c +0
-10msg =log_from_idx (console_idx); -if (suppress_message_printing (msg->level)) { -/* -* Skip record we have buffered and already printed -* directly to the console when we received it, and -* record that has level above the console loglevel. -*/ - console_idx =log_next (console_idx); - console_seq++; - goto skip; - }/* Output to all consoles once old messages replayed. */ if (unlikely(exclusive_console &&
kernel/printk/printk.c void console_unlock(void) · line 2406
Quoted 6 lines
kernel/printk/printk.c +1
-1@@ -2405,7 +2402,7 @@ void console_unlock(void)console_lock_spinning_enable ();stop_critical_timings ();/* don't trace print latency */ -call_console_drivers (ext_text, ext_len, text, len); +call_console_drivers (ext_text, ext_len, text, len, msg->level);start_critical_timings ();
So it seems that now we always format the text and ext message (if needed) and only then check if there is at least one console we can print that message on.
Can we iterate the consoles first and check if msg is worth the effort (per console suppress_message_printing()) and only if it is do all the formatting and call console drivers?
-ss
Re: [PATCH 1/4] printk: Introduce per-console loglevel setting
Quoted 28 lines · Sergey Senozhatsky
On (03/01/19 16:48), Calvin Owens wrote:
[..]Quoted 15 lines
kernel/printk/printk.c +0
-10msg =log_from_idx (console_idx); -if (suppress_message_printing (msg->level)) { -/* -* Skip record we have buffered and already printed -* directly to the console when we received it, and -* record that has level above the console loglevel. -*/ - console_idx =log_next (console_idx); - console_seq++; - goto skip; - }/* Output to all consoles once old messages replayed. */ if (unlikely(exclusive_console &&kernel/printk/printk.c void console_unlock(void) · line 2406
Quoted 6 lines
kernel/printk/printk.c +1
-1@@ -2405,7 +2402,7 @@ void console_unlock(void)console_lock_spinning_enable ();stop_critical_timings ();/* don't trace print latency */ -call_console_drivers (ext_text, ext_len, text, len); +call_console_drivers (ext_text, ext_len, text, len, msg->level);start_critical_timings ();So it seems that now we always format the text and ext message (if needed) and only then check if there is at least one console we can print that message on.
Quoted 3 lines
Can we iterate the consoles first and check if msg is worth the effort (per console
suppress_message_printing()) and only if it is do all the formatting and call console drivers?
Makes sense, will do.
Thanks,
Calvin
Quoted 1 line
-ss
Petr Mladek
maintainerRe: [PATCH 1/4] printk: Introduce per-console loglevel setting
In reply to Calvin OwensQuoted 6 lines · Calvin Owens
Not all consoles are created equal: depending on the actual hardware, the latency of a
printk()call can vary dramatically. The worst examples are serial consoles, where it can spin for tens of milliseconds banging the UART to emit a message, which can cause application-level problems when the kernel spews onto the console.
Quoted 7 lines
At Facebook we use netconsole to monitor our fleet, but we still have serial consoles attached on each host for live debugging, and the latter has caused problems. An obvious solution is to disable the kernel console output to ttyS0, but this makes live debugging frustrating, since crashes become silent and opaque to the ttyS0 user. Enabling it on the fly when needed isn't feasible, since boxes you need to debug via serial are likely to be borked in ways that make this impossible.
I guess that many other people have similar problem.
Quoted 8 lines
kernel/printk/printk.c +0
-0@@ -1164,9 +1164,14 @@ module_param(ignore_loglevel, bool, S_IRUGO | S_IWUSR);MODULE_PARM_DESC (ignore_loglevel,"ignore loglevel setting (prints all kernel messages to the console)" );
kernel/printk/printk.c module_param(ignore_loglevel, bool, S_IRUGO | S_IWUSR); · line 1174
Quoted 10 lines
kernel/printk/printk.c +7
-2-static bool suppress_message_printing (int level) +static int effective_loglevel (struct console *con) { -return (level >= console_loglevel && !ignore_loglevel); +return max (console_loglevel, con ? con->level :LOGLEVEL_EMERG ); +} + +static bool suppress_message_printing (int level,struct console *con) +{ +return (level >=effective_loglevel (con) && !ignore_loglevel);
Hmm, the semantic is cleaner when the per-console level defines the minimal loglevel. But it is still complicated. Also it is very confusing that the per-console value is called "level" or "loglevel" but it is actually minimal loglevel.
It might be even more straightforward when the per-console value defines the effective console level. I mean the following semantic:
+ "console_loglevel" would define the default loglevel used by consoles at runtime.
+ the per-console loglevel could override the default console_loglevel.
+ We would need a custom handler for the sysctl "console_loglevel". It would write the given value to the global console_loglevel variable and for all already registered consoles (con->loglevel).
The value will be used also for all newly registered consoles when they do not have any custom one.
+ The handler for "loglevel" early param should behave the same as the sysctl handler.
IMHO, there is no perfect solution. The advantage of the above proposal is that you "see" and "use" exactly what you "set".
kernel/printk/printk.c static void boot_delay_msec(int level) · line 1206
Quoted 9 lines
kernel/printk/printk.c +1
-1}#ifdef CONFIG_BOOT_PRINTK_DELAY @@ -1198,7 +1203,7 @@ static void boot_delay_msec(int level)unsigned long timeout;if ((boot_delay ==0 || system_state >=SYSTEM_RUNNING ) - ||suppress_message_printing (level)) { + ||suppress_message_printing (level,NULL )) {
We should delay the message only when it will really reach the console. The same check might be used also for formatting the text as pointed out by Sergey in the other mail.
If the above proposal was accepted, we would have custom handlers for sysctl. Then we could easily maintain a global variable with maximal effective console loglevel.
Best Regards,
Petr
Re: [PATCH 1/4] printk: Introduce per-console loglevel setting
Quoted 6 lines · Petr Mladek
It might be even more straightforward when the per-console value defines the effective console level. I mean the following semantic:
+ "
console_loglevel" would define the default loglevel used by consoles at runtime.
Quoted 6 lines
+ the per-console loglevel could override the default
console_loglevel.+ We would need a custom handler for the sysctl "
console_loglevel". It would write the given value to the globalconsole_loglevelvariable and for all already registered consoles (con->loglevel).
But some functions change console_loglevel without sysctl (e.g. console_verbose() when reporting hung tasks and panic()). Should con->loglevel be changed (which might result in too much messages to slow consoles) when console_loglevel changes?
Quoted 11 lines
The value will be used also for all newly registered consoles when they do not have any custom one.
+ The handler for "loglevel" early param should behave the same as the sysctl handler.
IMHO, there is no perfect solution. The advantage of the above proposal is that you "see" and "use" exactly what you "set".
Petr Mladek
maintainerRe: [PATCH 1/4] printk: Introduce per-console loglevel setting
Quoted 10 lines · Tetsuo Handa
Quoted 9 lines · Petr Mladek
It might be even more straightforward when the per-console value defines the effective console level. I mean the following semantic:
+ "
console_loglevel" would define the default loglevel used by consoles at runtime.+ the per-console loglevel could override the default
console_loglevel.
Quoted 8 lines
Quoted 3 lines
+ We would need a custom handler for the sysctl "
console_loglevel". It would write the given value to the globalconsole_loglevelvariable and for all already registered consoles (con->loglevel).But some functions change
console_loglevelwithout sysctl (e.g.console_verbose()when reporting hung tasks andpanic()). Shouldcon->loglevelbe changed (which might result in too much messages to slow consoles) whenconsole_loglevelchanges?
It is about the semantic. We either want to set a hard limit for each console or we want to set per-console loglevel that will get used in normal situations.
I prefer the 2nd semantic. IMHO, console_verbose() should be used only in situations when people really want to see all lines, for example, panic, sysrq output when the machine looks deadlocked, ignore_loglevel is set. I believe that they want to see them even on the slow consoles that are there exactly for debugging these critical situations.
Best Regards,
Petr
PATCH 2/4 printk: Add ability to set loglevel via "console=" cmdline
In reply to Calvin OwensThis extends the "console=" interface to allow setting the per-console loglevel by adding "/N" to the string, where N is the desired loglevel expressed as a base 10 integer. Invalid values are silently ignored.
--- .../admin-guide/kernel-parameters.txt | 6 ++-- kernel/printk/console_cmdline.h | 1 + kernel/printk/printk.c | 30 +++++++++++++++---- 3 files changed, 28 insertions(+), 9 deletions(-)
Documentation/admin-guide/kernel-parameters.txt +3 -3
@@ -612,10 +612,10 @@ ttyS<n>[,options] ttyUSB0[,options] Use the specified serial port. The options are of - the form "bbbbpnf", where "bbbb" is the baud rate, + the form "bbbbpnf/l", where "bbbb" is the baud rate, "p" is parity ("n", "o", or "e"), "n" is number of - bits, and "f" is flow control ("r" for RTS or - omit it). Default is "9600n8". + bits, "f" is flow control ("r" for RTS or omit it), + and "l" is the loglevel on [0,7]. Default is "9600n8". See Documentation/admin-guide/serial-console.rst for more information. See
kernel/printk/console_cmdline.h +1 -0
@@ -6,6 +6,7 @@ struct console_cmdline {char name[16 ];/* Name of the driver */ int index;/* Minor dev. to use */ +int loglevel;/* Loglevel to use */ char *options;/* Options for the driver */ #ifdef CONFIG_A11Y_BRAILLE_CONSOLE char *brl_options;/* Options for braille driver */
kernel/printk/printk.c +24 -6
@@ -2057,7 +2057,7 @@ asmlinkage __visible void early_printk(const char *fmt, ...)#endif static int __add_preferred_console (char *name,int idx,char *options, -char *brl_options) +int loglevel,char *brl_options) {struct console_cmdline *c;int i;
@@ -2083,6 +2083,7 @@ static int __add_preferred_console(char *name, int idx, char *options, c->options = options;braille_set_options (c, brl_options); + c->loglevel = loglevel; c->index = idx;return 0 ; }
@@ -2104,8 +2105,8 @@ __setup("console_msg_format=", console_msg_format_setup);static int __init console_setup (char *str) {char buf[sizeof (console_cmdline[0 ].name) +4 ];/* 4 for "ttyS" */ -char *s, *options, *brl_options =NULL ; -int idx; +char *s, *options, *llevel, *brl_options =NULL ; +int idx, loglevel =LOGLEVEL_EMERG ;if (_braille_console_setup (&str, &brl_options))return 1 ;
@@ -2123,6 +2124,14 @@ static int __init console_setup(char *str) options =strchr (str,',' );if (options) *(options++) =0 ; + + llevel =strchr (str,'/' ); +if (llevel) { + *(llevel++) =0 ; +if (kstrtoint (llevel,10 , &loglevel)) + loglevel =LOGLEVEL_EMERG ; + } +#ifdef __sparc__if (!strcmp (str,"ttya" ))strcpy (buf,"ttyS0" );
@@ -2135,7 +2144,7 @@ static int __init console_setup(char *str) idx =simple_strtoul (s,NULL ,10 ); *s =0 ; -__add_preferred_console (buf, idx, options, brl_options); +__add_preferred_console (buf, idx, options, loglevel, brl_options); console_set_on_cmdline =1 ;return 1 ; }
@@ -2156,7 +2165,8 @@ __setup("console=", console_setup);*/ int add_preferred_console (char *name,int idx,char *options) { -return __add_preferred_console (name, idx, options,NULL ); +return __add_preferred_console (name, idx, options,LOGLEVEL_EMERG , +NULL ); }bool console_suspend_enabled = true;
@@ -2574,6 +2584,7 @@ void register_console(struct console *newcon)struct console *bcon =NULL ;struct console_cmdline *c;static bool has_preferred; +bool cmdline_exists = false;if (console_drivers)for_each_console (bcon)
@@ -2640,6 +2651,12 @@ void register_console(struct console *newcon)if (newcon->index <0 ) newcon->index = c->index; +/* +* Carry over the loglevel from the cmdline +*/ + newcon->level = c->loglevel; + cmdline_exists = true; +if (_braille_register_console (newcon, c))return ;
@@ -2671,7 +2688,8 @@ void register_console(struct console *newcon)/* * By default, the per-console minimum forces no messages through. */ - newcon->level =LOGLEVEL_EMERG ; +if (!cmdline_exists) + newcon->level =LOGLEVEL_EMERG ;/* * Put this console in the list - keep the
Signature · 1 line
2.17.1
Petr Mladek
maintainerRe: [PATCH 2/4] printk: Add ability to set loglevel via "console=" cmdline
Quoted 16 lines · Calvin Owens
This extends the "console=" interface to allow setting the per-console loglevel by adding "/N" to the string, where N is the desired loglevel expressed as a base 10 integer. Invalid values are silently ignored.
Signed-off-by Calvin Owens <[email protected]>--- .../admin-guide/kernel-parameters.txt | 6 ++-- kernel/printk/console_cmdline.h | 1 + kernel/printk/printk.c | 30 +++++++++++++++---- 3 files changed, 28 insertions(+), 9 deletions(-)Documentation/admin-guide/kernel-parameters.txt +0
-0
Documentation/admin-guide/kernel-parameters.txt line 618
Quoted 10 lines
Documentation/admin-guide/kernel-parameters.txt +3
-3@@ -612,10 +612,10 @@ ttyS<n>[,options] ttyUSB0[,options] Use the specified serial port. The options are of - the form "bbbbpnf", where "bbbb" is the baud rate, + the form "bbbbpnf/l", where "bbbb" is the baud rate, "p" is parity ("n", "o", or "e"), "n" is number of - bits, and "f" is flow control ("r" for RTS or - omit it). Default is "9600n8". + bits, "f" is flow control ("r" for RTS or omit it), + and "l" is the loglevel on [0,7]. Default is "9600n8".
We should a more detailed explanation about the loglevel semantic. It is either minimal loglevel. Or that it overrides the global console_loglevel if you accept my proposal.
kernel/printk/console_cmdline.h struct console_cmdline · line 9
Quoted 12 lines
Documentation/admin-guide/kernel-parameters.txt +0
-0See Documentation/admin-guide/serial-console.rst for more information. Seekernel/printk/console_cmdline.h +1
-0@@ -6,6 +6,7 @@ struct console_cmdline {char name[16 ];/* Name of the driver */ int index;/* Minor dev. to use */ +int loglevel;/* Loglevel to use */
The comment will be true only with the new proposal.
Quoted 19 lines
kernel/printk/console_cmdline.h +0
-0char *options;/* Options for the driver */ #ifdef CONFIG_A11Y_BRAILLE_CONSOLE char *brl_options;/* Options for braille driver */ kernel/printk/printk.c +2
-2@@ -2104,8 +2105,8 @@ __setup("console_msg_format=", console_msg_format_setup);static int __init console_setup (char *str) {char buf[sizeof (console_cmdline[0 ].name) +4 ];/* 4 for "ttyS" */ -char *s, *options, *brl_options =NULL ; -int idx; +char *s, *options, *llevel, *brl_options =NULL ; +int idx, loglevel =LOGLEVEL_EMERG ;if (_braille_console_setup (&str, &brl_options))return 1 ;
kernel/printk/printk.c static int __init console_setup(char *str) · line 2128
Quoted 5 lines
kernel/printk/printk.c +2
-0@@ -2123,6 +2124,14 @@ static int __init console_setup(char *str) options =strchr (str,',' );if (options) *(options++) =0 ; + + llevel =strchr (str,'/' );
This should be:
if (options) llevel = strchr(options, '/');
kernel/printk/printk.c static int __init console_setup(char *str) · line 2137
Quoted 9 lines
kernel/printk/printk.c +6
-0+if (llevel) { + *(llevel++) =0 ; +if (kstrtoint (llevel,10 , &loglevel)) + loglevel =LOGLEVEL_EMERG ; + } +#ifdef __sparc__if (!strcmp (str,"ttya" ))strcpy (buf,"ttyS0" );
Best Regards,
Petr
PATCH 3/4 printk: Add consoles to a virtual "console" bus
In reply to Calvin OwensThis patch embeds a device struct in the console struct, and registers them on a "console" bus so we can expose attributes in sysfs.
Currently, most drivers declare static console structs, and that is incompatible with the dev refcount model. So we end up needing to patch all of the console drivers to:
1. Dynamically allocate the console struct using a new helper
2. Handle the allocation in (1) possibly failing
3. Dispose of (1) with put_device()
Early console structures must still be static, since they're required before we're able to allocate memory. The least ugly way I can come up with to handle this is an "is_static" flag in the structure which makes the gets and puts NOPs, and is checked in ->release() to catch mistakes.
--- arch/alpha/kernel/srmcons.c | 10 +- arch/arm/kernel/early_printk.c | 7 +- arch/ia64/hp/sim/hpsim_console.c | 9 +- arch/m68k/amiga/config.c | 17 ++- arch/m68k/atari/debug.c | 29 ++++- arch/m68k/emu/nfcon.c | 60 ++++++--- arch/m68k/kernel/early_printk.c | 9 +- arch/m68k/q40/config.c | 7 +- arch/m68k/sun3x/prom.c | 7 +- arch/mips/dec/prom/console.c | 7 +- arch/mips/fw/arc/arc_con.c | 12 +- arch/mips/kernel/early_printk.c | 9 +- arch/mips/sibyte/common/cfe_console.c | 12 +- arch/parisc/kernel/pdc_cons.c | 9 +- arch/powerpc/kernel/udbg.c | 7 +- arch/s390/kernel/early_printk.c | 7 +- arch/sh/kernel/sh_bios.c | 9 +- arch/sparc/kernel/btext.c | 7 +- arch/sparc/kernel/setup_32.c | 7 +- arch/sparc/kernel/setup_64.c | 7 +- arch/um/drivers/mconsole_kern.c | 15 ++- arch/um/drivers/ssl.c | 22 +++- arch/um/drivers/stderr_console.c | 7 +- arch/um/drivers/stdio_console.c | 22 +++- arch/um/kernel/early_printk.c | 7 +- arch/unicore32/kernel/early_printk.c | 7 +- arch/x86/include/asm/efi.h | 1 + arch/x86/kernel/early_printk.c | 14 ++- arch/x86/platform/efi/early_printk.c | 9 +- arch/xtensa/platforms/iss/console.c | 10 +- .../accessibility/braille/braille_console.c | 6 +- drivers/char/lp.c | 19 ++- drivers/hwtracing/stm/console.c | 19 +-- drivers/misc/pti.c | 26 ++-- drivers/net/netconsole.c | 99 +++++++-------- drivers/s390/char/con3215.c | 11 +- drivers/s390/char/con3270.c | 12 +- drivers/s390/char/sclp_con.c | 17 ++- drivers/s390/char/sclp_vt220.c | 18 ++- drivers/tty/amiserial.c | 13 +- drivers/tty/ehv_bytechan.c | 19 ++- drivers/tty/goldfish.c | 34 ++++-- drivers/tty/hvc/hvc_console.c | 8 +- drivers/tty/hvc/hvc_xen.c | 15 ++- drivers/tty/hvc/hvsi.c | 14 ++- drivers/tty/mips_ejtag_fdc.c | 44 ++++--- drivers/tty/serial/21285.c | 25 ++-- drivers/tty/serial/8250/8250_core.c | 22 ++-- drivers/tty/serial/8250/8250_early.c | 18 ++- drivers/tty/serial/8250/8250_ingenic.c | 6 +- drivers/tty/serial/altera_jtaguart.c | 33 +++-- drivers/tty/serial/altera_uart.c | 25 ++-- drivers/tty/serial/amba-pl010.c | 35 ++++-- drivers/tty/serial/amba-pl011.c | 47 +++++--- drivers/tty/serial/apbuart.c | 24 ++-- drivers/tty/serial/ar933x_uart.c | 13 +- drivers/tty/serial/arc_uart.c | 27 +++-- drivers/tty/serial/atmel_serial.c | 31 +++-- drivers/tty/serial/bcm63xx_uart.c | 25 ++-- drivers/tty/serial/clps711x.c | 17 +-- drivers/tty/serial/cpm_uart/cpm_uart_core.c | 21 ++-- drivers/tty/serial/digicolor-usart.c | 24 ++-- drivers/tty/serial/dz.c | 18 +-- drivers/tty/serial/earlycon-arm-semihost.c | 6 +- drivers/tty/serial/earlycon.c | 5 +- drivers/tty/serial/efm32-uart.c | 22 ++-- drivers/tty/serial/fsl_lpuart.c | 57 ++++----- drivers/tty/serial/imx.c | 35 ++++-- drivers/tty/serial/ip22zilog.c | 18 +-- drivers/tty/serial/kgdb_nmi.c | 21 +++- drivers/tty/serial/kgdboc.c | 2 +- drivers/tty/serial/lantiq.c | 23 ++-- drivers/tty/serial/lpc32xx_hs.c | 21 ++-- drivers/tty/serial/mcf.c | 18 +-- drivers/tty/serial/meson_uart.c | 26 ++-- drivers/tty/serial/mpc52xx_uart.c | 18 +-- drivers/tty/serial/mps2-uart.c | 34 ++++-- drivers/tty/serial/mpsc.c | 23 ++-- drivers/tty/serial/msm_serial.c | 36 ++++-- drivers/tty/serial/mux.c | 44 ++++--- drivers/tty/serial/mvebu-uart.c | 30 +++-- drivers/tty/serial/mxs-auart.c | 18 +-- drivers/tty/serial/netx-serial.c | 20 +-- drivers/tty/serial/omap-serial.c | 40 +++--- drivers/tty/serial/owl-uart.c | 29 +++-- drivers/tty/serial/pch_uart.c | 26 ++-- drivers/tty/serial/pic32_uart.c | 30 +++-- drivers/tty/serial/pmac_zilog.c | 19 +-- drivers/tty/serial/pnx8xxx_uart.c | 20 +-- drivers/tty/serial/pxa.c | 25 ++-- drivers/tty/serial/qcom_geni_serial.c | 57 ++++----- drivers/tty/serial/rda-uart.c | 26 ++-- drivers/tty/serial/sa1100.c | 20 +-- drivers/tty/serial/samsung.c | 41 +++++-- drivers/tty/serial/sb1250-duart.c | 20 +-- drivers/tty/serial/sccnxp.c | 26 ++-- drivers/tty/serial/serial_core.c | 16 ++- drivers/tty/serial/serial_ks8695.c | 25 ++-- drivers/tty/serial/serial_txx9.c | 21 ++-- drivers/tty/serial/sh-sci.c | 55 ++++++--- drivers/tty/serial/sirfsoc_uart.c | 26 ++-- drivers/tty/serial/sn_console.c | 25 ++-- drivers/tty/serial/sprd_serial.c | 25 ++-- drivers/tty/serial/st-asc.c | 27 +++-- drivers/tty/serial/stm32-usart.c | 17 ++- drivers/tty/serial/sunhv.c | 29 +++-- drivers/tty/serial/sunsab.c | 29 ++--- drivers/tty/serial/sunsu.c | 26 ++-- drivers/tty/serial/sunzilog.c | 26 ++-- drivers/tty/serial/uartlite.c | 23 ++-- drivers/tty/serial/vr41xx_siu.c | 31 +++-- drivers/tty/serial/vt8500_serial.c | 25 ++-- drivers/tty/serial/xilinx_uartps.c | 42 +++---- drivers/tty/serial/zs.c | 25 ++-- drivers/tty/tty_io.c | 6 +- drivers/tty/vt/vt.c | 14 ++- drivers/usb/early/ehci-dbgp.c | 7 +- drivers/usb/early/xhci-dbc.c | 7 +- drivers/usb/gadget/function/u_serial.c | 22 ++-- drivers/usb/serial/console.c | 24 ++-- drivers/usb/serial/usb-serial.c | 13 +- fs/proc/consoles.c | 10 +- fs/pstore/platform.c | 25 ++-- include/linux/console.h | 36 +++++- include/linux/serial_core.h | 19 +++ include/linux/usb/serial.h | 4 +- kernel/debug/debug_core.c | 7 +- kernel/debug/kdb/kdb_io.c | 4 +- kernel/printk/printk.c | 114 +++++++++++++++--- 129 files changed, 1772 insertions(+), 1036 deletions(-)
arch/alpha/kernel/srmcons.c +8 -2
@@ -266,15 +266,21 @@ srm_console_setup(struct console *co, char *options)return 0 ; } -static struct console srmcons = { - .name ="srm" , +static const struct console_operations srmcons_cons_ops = { .write = srm_console_write, .device = srm_console_device, .setup = srm_console_setup, +}; + +static struct console srmcons = { + .name ="srm" , + .ops = &srmcons_cons_ops, .flags =CON_PRINTBUFFER |CON_BOOT , .index =-1 , + .is_static =1 , }; +void __init register_srm_console (void ) {
arch/arm/kernel/early_printk.c +6 -1
@@ -33,11 +33,16 @@ static void early_console_write(struct console *con, const char *s, unsigned n)early_write (s, n); } +static const struct console_operations early_console_ops = { + .write = early_console_write, +}; +static struct console early_console_dev = { .name ="earlycon" , - .write = early_console_write, .flags =CON_PRINTBUFFER |CON_BOOT , .index =-1 , + .ops = &early_console_ops, + .is_static =1 , };static int __init setup_early_printk (char *buf)
arch/ia64/hp/sim/hpsim_console.c +7 -2
@@ -30,13 +30,18 @@ static int simcons_init (struct console *, char *);static void simcons_write (struct console *,const char *,unsigned );static struct tty_driver *simcons_console_device (struct console *,int *); -static struct console hpsim_cons = { - .name ="simcons" , +static const struct console_operations hpsim_cons_ops = { .write = simcons_write, .device = simcons_console_device, .setup = simcons_init, +}; + +static struct console hpsim_cons = { + .name ="simcons" , .flags =CON_PRINTBUFFER , + .ops = &hpsim_cons_ops, .index =-1 , + .is_static =1 , }; static int
arch/m68k/amiga/config.c +13 -4
@@ -110,6 +110,7 @@ static struct console amiga_console_driver = { .name = "debug", .flags = CON_PRINTBUFFER, .index = -1, + .is_static = 1, };
@@ -617,6 +618,10 @@ static void amiga_mem_console_write(struct console *co, const char *s, } } +static const struct console_operations amiga_mem_ops = { + .write = amiga_mem_console_write, +}; +static int __init amiga_savekmsg_setup (char *arg) {bool registered;
@@ -637,8 +642,8 @@ static int __init amiga_savekmsg_setup(char *arg) savekmsg->magicptr =ZTWO_PADDR (savekmsg); savekmsg->size =0 ; - registered = !!amiga_console_driver.write; - amiga_console_driver.write = amiga_mem_console_write; + registered = !!amiga_console_driver.ops; + amiga_console_driver.ops = &amiga_mem_ops;if (!registered)register_console (&amiga_console_driver);return 0 ;
@@ -663,6 +668,10 @@ static void amiga_serial_console_write(struct console *co, const char *s, } } +static const struct console_operations amiga_serial_ops = { + .write = amiga_serial_console_write, +}; +#if 0 void amiga_serial_puts (const char *s) {
@@ -728,8 +737,8 @@ static int __init amiga_debug_setup(char *arg)return 0 ;/* no initialization required (?) */ - registered = !!amiga_console_driver.write; - amiga_console_driver.write = amiga_serial_console_write; + registered = !!amiga_console_driver.ops; + amiga_console_driver.ops = &amiga_serial_ops;if (!registered)register_console (&amiga_console_driver);return 0 ;
arch/m68k/atari/debug.c +23 -6
@@ -29,6 +29,7 @@ static struct console atari_console_driver = { .name = "debug", .flags = CON_PRINTBUFFER, .index = -1, + .is_static = 1, };
@@ -49,6 +50,10 @@ static void atari_mfp_console_write(struct console *co, const char *str, } } +static const struct console_operations mfp_ops = { + .write = atari_mfp_console_write, +}; +static inline void ata_scc_out (char c) { do {
@@ -68,6 +73,10 @@ static void atari_scc_console_write(struct console *co, const char *str, } } +static const struct console_operations scc_ops = { + .write = atari_scc_console_write, +}; +static inline void ata_midi_out (char c) {while (!(acia.mid_ctrl &ACIA_TDRE ))/* wait for tx buf empty */
@@ -85,6 +94,10 @@ static void atari_midi_console_write(struct console *co, const char *str, } } +static const struct console_operations midi_ops = { + .write = atari_midi_console_write, +}; +static int ata_par_out (char c) {unsigned char tmp;
@@ -128,6 +141,10 @@ static void atari_par_console_write(struct console *co, const char *str, } } +static const struct console_operations par_ops = { + .write = atari_par_console_write, +}; +#if 0 int atari_mfp_console_wait_key (struct console *co) {
@@ -296,19 +313,19 @@ static int __init atari_debug_setup(char *arg)/* defaults to ser2 for a Falcon and ser1 otherwise */ arg =MACH_IS_FALCON ?"ser2" :"ser1" ; - registered = !!atari_console_driver.write; + registered = !!atari_console_driver.ops;if (!strcmp (arg,"ser1" )) {/* ST-MFP Modem1 serial port */ atari_init_mfp_port (B9600 |CS8 ); - atari_console_driver.write = atari_mfp_console_write; + atari_console_driver.ops = &mfp_ops; }else if (!strcmp (arg,"ser2" )) {/* SCC Modem2 serial port */ atari_init_scc_port (B9600 |CS8 ); - atari_console_driver.write = atari_scc_console_write; + atari_console_driver.ops = &scc_ops; }else if (!strcmp (arg,"midi" )) {/* MIDI port */ atari_init_midi_port (B9600 |CS8 ); - atari_console_driver.write = atari_midi_console_write; + atari_console_driver.ops = &midi_ops; }else if (!strcmp (arg,"par" )) {/* parallel printer */ atari_turnoff_irq (IRQ_MFP_BUSY );/* avoid ints */
@@ -318,9 +335,9 @@ static int __init atari_debug_setup(char *arg) sound_ym.wd_data =0 ;/* no char */ sound_ym.rd_data_reg_sel =14 ;/* select port A */ sound_ym.wd_data = sound_ym.rd_data_reg_sel |0x20 ;/* strobe H */ - atari_console_driver.write = atari_par_console_write; + atari_console_driver.ops = &par_ops; } -if (atari_console_driver.write && !registered) +if (atari_console_driver.ops && !registered)register_console (&atari_console_driver);return 0 ;
arch/m68k/emu/nfcon.c +41 -19
94 lines not on this page · raw message
arch/m68k/kernel/early_printk.c +7 -2
@@ -29,11 +29,16 @@ static void __ref debug_cons_write(struct console *c,#endif } +static const struct console_operations early_ops = { + .write = debug_cons_write, +}; +static struct console early_console_instance = { .name ="debug" , - .write = debug_cons_write, .flags =CON_PRINTBUFFER |CON_BOOT , - .index =-1 + .ops = &early_ops, + .index =-1 , + .is_static =1 , };static int __init setup_early_printk (char *buf)
arch/m68k/q40/config.c +6 -1
@@ -53,11 +53,16 @@ static void q40_mem_console_write(struct console *co, const char *b,extern int ql_ticks; +static const struct console_operations q40_mem_ops = { + .write = q40_mem_console_write, +}; +static struct console q40_console_driver = { .name ="debug" , - .write = q40_mem_console_write, .flags =CON_PRINTBUFFER , + .ops = &q40_mem_ops, .index =-1 , + .is_static =1 , };
arch/m68k/sun3x/prom.c +6 -1
@@ -85,11 +85,16 @@ static void sun3x_prom_write(struct console *co, const char *s,/* debug console - write-only */ +static const struct console_operations sun3x_prom = { + .write = sun3x_prom_write, +}; +static struct console sun3x_debug = { .name ="debug" , - .write = sun3x_prom_write, .flags =CON_PRINTBUFFER , + .ops = &sun3x_prom, .index =-1 , + .is_static =1 , };void __init sun3x_prom_init (void )
arch/mips/dec/prom/console.c +6 -1
@@ -32,11 +32,16 @@ static void __init prom_console_write(struct console *con, const char *s, } } +static struct console_operations early_ops__initdata = { + .write = prom_console_write, +}; +static struct console promcons__initdata = { .name ="prom" , - .write = prom_console_write, .flags =CON_BOOT |CON_PRINTBUFFER , + .ops = &early_ops, .index =-1 , + .is_static =1 , };void __init register_prom_console (void )
arch/mips/fw/arc/arc_con.c +7 -5
@@ -31,12 +31,9 @@ static int prom_console_setup(struct console *co, char *options)return !(prom_flags &PROM_FLAG_USE_AS_CONSOLE ); } -static struct console arc_cons = { - .name ="arc" , +static const struct console_operations arc_ops = { .write = prom_console_write, .setup = prom_console_setup, - .flags =CON_PRINTBUFFER , - .index =-1 , };/*
@@ -45,8 +42,13 @@ static struct console arc_cons = {static int __init arc_console_init (void ) { -register_console (&arc_cons); +struct console *arc_cons; + arc_cons =allocate_console_dfl (&arc_ops,"arc" ,NULL ); +if (!arc_cons) +return -ENOMEM ; + +register_console (arc_cons);return 0 ; }console_initcall (arc_console_init);
arch/mips/kernel/early_printk.c +7 -2
@@ -24,11 +24,16 @@ static void early_console_write(struct console *con, const char *s, unsigned n) } } +static const struct console_operations early_ops = { + .write = early_console_write, +}; +static struct console early_console_prom = { .name ="early" , - .write = early_console_write, .flags =CON_PRINTBUFFER |CON_BOOT , - .index =-1 + .ops = &early_ops, + .index =-1 , + .is_static =1 , };void __init setup_early_printk (void )
arch/mips/sibyte/common/cfe_console.c +7 -5
@@ -64,17 +64,19 @@ static int cfe_console_setup(struct console *cons, char *str)return 0 ; } -static struct console sb1250_cfe_cons = { - .name ="cfe" , +static const struct console_operations cfe_ops = { .write = cfe_console_write, .setup = cfe_console_setup, - .flags =CON_PRINTBUFFER , - .index =-1 , };static int __init sb1250_cfe_console_init (void ) { -register_console (&sb1250_cfe_cons); +struct console *sb1250_cfe =allocate_console_dfl (&cfe_ops,"cfe" , +NULL ); +if (!sb1250_cfe) +return -ENOMEM ; + +register_console (sb1250_cfe);return 0 ; }
arch/parisc/kernel/pdc_cons.c +7 -2
@@ -218,13 +218,18 @@ static struct tty_driver * pdc_console_device (struct console *c, int *index)#define pdc_console_device NULL#endif -static struct console pdc_cons = { - .name ="ttyB" , +static const struct console_operations pdc_ops = { .write = pdc_console_write, .device = pdc_console_device, .setup = pdc_console_setup, +}; + +static struct console pdc_cons = { + .name ="ttyB" , .flags =CON_BOOT |CON_PRINTBUFFER , + .ops = &pdc_ops, .index =-1 , + .is_static =1 , };static int pdc_console_initialized;
arch/powerpc/kernel/udbg.c +6 -1
@@ -148,11 +148,16 @@ static void udbg_console_write(struct console *con, const char *s,udbg_write (s, n); } +static const struct console_operations udbg_ops = { + .write = udbg_console_write, +}; +static struct console udbg_console = { .name ="udbg" , - .write = udbg_console_write, .flags =CON_PRINTBUFFER |CON_ENABLED |CON_BOOT |CON_ANYTIME , + .ops = &udbg_ops, .index =0 , + .is_static =1 , };/*
arch/s390/kernel/early_printk.c +6 -1
@@ -13,11 +13,16 @@ static void sclp_early_write(struct console *con, const char *s, unsigned int le__sclp_early_printk (s, len,0 ); } +static const struct console_operations sclp_ops = { + .write = sclp_early_write, +}; +static struct console sclp_early_console = { .name ="earlysclp" , - .write = sclp_early_write, .flags =CON_PRINTBUFFER |CON_BOOT , + .ops = &sclp_ops, .index =-1 , + .is_static =1 , };static int __init setup_early_printk (char *buf)
arch/sh/kernel/sh_bios.c +7 -2
@@ -134,12 +134,17 @@ static int __init sh_console_setup(struct console *co, char *options)return 0 ; } -static struct console bios_console = { - .name ="bios" , +static const struct console_operations bios_ops = { .write = sh_console_write, .setup = sh_console_setup, +}; + +static struct console bios_console = { + .name ="bios" , .flags =CON_PRINTBUFFER , + .ops = &bios_ops, .index =-1 , + .is_static =1 , };static int __init setup_early_printk (char *buf)
arch/sparc/kernel/btext.c +6 -1
@@ -300,11 +300,16 @@ static void btext_console_write(struct console *con, const char *s,btext_drawtext (s, n); } +static const struct console_operations btext_ops = { + .write = btext_console_write, +}; +static struct console btext_console = { .name ="btext" , - .write = btext_console_write, .flags =CON_PRINTBUFFER |CON_ENABLED |CON_BOOT |CON_ANYTIME , + .ops = &btext_ops, .index =0 , + .is_static =1 , };int __init btext_find_display (void )
arch/sparc/kernel/setup_32.c +6 -1
@@ -114,11 +114,16 @@ prom_console_write(struct console *con, const char *s, unsigned int n)prom_write (s, n); } +static const struct console_operations prom_ops = { + .write = prom_console_write, +}; +static struct console prom_early_console = { .name ="earlyprom" , - .write = prom_console_write, .flags =CON_PRINTBUFFER |CON_BOOT , + .ops = &prom_ops, .index =-1 , + .is_static =1 , };/*
arch/sparc/kernel/setup_64.c +6 -1
@@ -90,11 +90,16 @@ prom_console_write(struct console *con, const char *s, unsigned int n)/* Exported for mm/init.c:paging_init. */ unsigned long cmdline_memory_size =0 ; +static const struct console_operations prom_ops = { + .write = prom_console_write, +}; +static struct console prom_early_console = { .name ="earlyprom" , - .write = prom_console_write, .flags =CON_PRINTBUFFER |CON_BOOT |CON_ANYTIME , + .ops = &prom_ops, .index =-1 , + .is_static =1 , };/*
arch/um/drivers/mconsole_kern.c +10 -5
@@ -572,14 +572,19 @@ static void console_write(struct console *console, const char *string, } } -static struct console mc_console = { .name ="mc" , - .write = console_write, - .flags =CON_ENABLED , - .index =-1 }; +static const struct console_operations mc_cons_ops = { + .write = console_write, +};static int mc_add_console (void ) { -register_console (&mc_console); +struct console *mc_console =allocate_console_dfl (&mc_cons_ops,"mc" , +NULL ); +if (!mc_console) +return -ENOMEM ; + + mc_console->flags =CON_ENABLED ; +register_console (mc_console);return 0 ; }
arch/um/drivers/ssl.c +17 -5
@@ -138,15 +138,15 @@ static int ssl_console_setup(struct console *co, char *options) }/* No locking for register_console call - relies on single-threaded initcalls */ -static struct console ssl_cons = { - .name ="ttyS" , + +static const struct console_operations ssl_cons_ops = { .write = ssl_console_write, .device = ssl_console_device, .setup = ssl_console_setup, - .flags =CON_PRINTBUFFER |CON_ANYTIME , - .index =-1 , }; +static struct console *ssl_cons; +static int ssl_init (void ) {char *new_title;
@@ -156,10 +156,16 @@ static int ssl_init(void)printk (KERN_INFO "Initializing software serial port version %d\n" , ssl_version); + ssl_cons =allocate_console_dfl (&ssl_cons_ops,"ttyS" ,NULL ); +if (!ssl_cons) +return -ENOMEM ; + + ssl_cons->flags |=CON_ANYTIME ; + err =register_lines (&driver, &ssl_ops, serial_lines,ARRAY_SIZE (serial_lines));if (err) -return err; + goto out; new_title =add_xterm_umid (opts.xterm_title);if (new_title !=NULL )
@@ -178,6 +184,9 @@ static int ssl_init(void) ssl_init_done =1 ;register_console (&ssl_cons);return 0 ; +out: +kfree (ssl_cons); +return err; }late_initcall (ssl_init);
@@ -185,7 +194,10 @@ static void ssl_exit(void) {if (!ssl_init_done)return ; + +unregister_console (&ssl_cons);close_lines (serial_lines,ARRAY_SIZE (serial_lines)); +put_device (&ssl_cons->dev); }__uml_exitcall (ssl_exit);
arch/um/drivers/stderr_console.c +6 -1
@@ -22,10 +22,15 @@ static void stderr_console_write(struct console *console, const char *string,generic_write (2 /* stderr */ , string, len,NULL ); } +static const struct console_operations stderr_ops = { + .write = stderr_console_write, +}; +static struct console stderr_console = { .name ="stderr" , - .write = stderr_console_write, .flags =CON_PRINTBUFFER , + .ops = &stderr_ops, + .is_static =1 , };static int __init stderr_console_init (void )
arch/um/drivers/stdio_console.c +16 -6
@@ -138,25 +138,31 @@ static int uml_console_setup(struct console *co, char *options) }/* No locking for register_console call - relies on single-threaded initcalls */ -static struct console stdiocons = { - .name ="tty" , + +static const struct console_operations uml_cons_ops = { .write = uml_console_write, .device = uml_console_device, .setup = uml_console_setup, - .flags =CON_PRINTBUFFER |CON_ANYTIME , - .index =-1 , }; +static struct console *stdiocons; +static int stdio_init (void ) {char *new_title;int err;int i; + stdiocons =allocate_console_dfl (¨_cons_ops,"tty" ,NULL ); +if (!stdiocons) +return -ENOMEM ; + + stdiocons->flags |=CON_ANYTIME ; + err =register_lines (&driver, &console_ops, vts,ARRAY_SIZE (vts));if (err) -return err; + goto out;printk (KERN_INFO "Initialized stdio console driver\n" );
@@ -177,8 +183,11 @@ static int stdio_init(void) } con_init_done =1 ; -register_console (&stdiocons); +register_console (stdiocons);return 0 ; +out: +put_console (stdiocons); +return err; }late_initcall (stdio_init);
@@ -187,6 +196,7 @@ static void console_exit(void)if (!con_init_done)return ;close_lines (vts,ARRAY_SIZE (vts)); +put_console (stdiocons); }__uml_exitcall (console_exit);
arch/um/kernel/early_printk.c +6 -1
@@ -16,11 +16,16 @@ static void early_console_write(struct console *con, const char *s, unsigned intum_early_printk (s, n); } +static const struct console_operations early_ops = { + .write = early_console_write, +}; +static struct console early_console_dev = { .name ="earlycon" , - .write = early_console_write, .flags =CON_BOOT , + .ops = &early_ops, .index =-1 , + .is_static =1 , };static int __init setup_early_printk (char *buf)
arch/unicore32/kernel/early_printk.c +6 -1
@@ -26,11 +26,16 @@ static void early_ocd_write(struct console *con, const char *s, unsigned n) } } +static const struct console_operations ocd_ops = { + .write = early_ocd_write, +}; +static struct console early_ocd_console = { .name ="earlyocd" , - .write = early_ocd_write, .flags =CON_PRINTBUFFER , + .ops = &ocd_ops, .index =-1 , + .is_static =1 , };static int __init setup_early_printk (char *buf)
arch/x86/include/asm/efi.h +1 -0
@@ -171,6 +171,7 @@ static inline bool efi_runtime_supported(void) }extern struct console early_efi_console; +extern const struct console_operations early_efi_ops;extern void parse_efi_setup (u64 phys_addr,u32 data_len);extern void efifb_setup_from_dmi (struct screen_info *si,const char *opt);
arch/x86/kernel/early_printk.c +12 -2
@@ -70,11 +70,16 @@ static void early_vga_write(struct console *con, const char *str, unsigned n) } } +static const struct console_operations early_vga_ops = { + .write = early_vga_write, +}; +static struct console early_vga_console = { .name ="earlyvga" , - .write = early_vga_write, .flags =CON_PRINTBUFFER , .index =-1 , + .ops = &early_vga_ops, + .is_static =1 , };/* Serial functions loosely based on a similar package from Klaus P. Gerlicher */
@@ -320,11 +325,16 @@ static __init void early_pci_serial_init(char *s) }#endif +static const struct console_operations early_serial_ops = { + .write = early_serial_write, +}; +static struct console early_serial_console = { .name ="earlyser" , - .write = early_serial_write, .flags =CON_PRINTBUFFER , .index =-1 , + .ops = &early_serial_ops, + .is_static =1 , };static void early_console_register (struct console *con,int keep_early)
arch/x86/platform/efi/early_printk.c +7 -2
@@ -231,10 +231,15 @@ static __init int early_efi_setup(struct console *con, char *options)return 0 ; } -struct console early_efi_console = { - .name ="earlyefi" , +static const struct console_operations early_efi_ops = { .write = early_efi_write, .setup = early_efi_setup, +}; + +struct console early_efi_console = { + .name ="earlyefi" , .flags =CON_PRINTBUFFER , + .ops = &early_efi_ops, .index =-1 , + .is_static =1 , };
arch/xtensa/platforms/iss/console.c +7 -3
@@ -236,13 +236,17 @@ static struct tty_driver* iss_console_device(struct console *c, int *index)return serial_driver; } +static const struct console_operations iss_ops = { + .write = iss_console_write, + .device = iss_console_device, +};static struct console sercons = { .name ="ttyS" , - .write = iss_console_write, - .device = iss_console_device, .flags =CON_PRINTBUFFER , - .index =-1 + .ops = &iss_ops, + .index =-1 , + .is_static =1 , };static int __init iss_console_init (void )
drivers/accessibility/braille/braille_console.c +3 -3
@@ -116,7 +116,7 @@ static void braille_write(u16 *buf) *c++ = csum; *c++ =ETX ; - braille_co->write (braille_co, data, c - data); + braille_co->ops->write (braille_co, data, c - data); }/* Follow the VC cursor*/
@@ -367,8 +367,8 @@ 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 (console->ops->setup) { + ret = console->ops->setup (console, console_options);if (ret !=0 )return ret; }
drivers/char/lp.c +13 -6
@@ -857,12 +857,12 @@ static void lp_console_write(struct console *co, const char *s, parport_release(dev); } -static struct console lpcons = { - .name ="lp" , +static const struct console_operations lp_cons_ops = { .write = lp_console_write, - .flags =CON_PRINTBUFFER , }; +static struct console *lpcons; +#endif /* console on line printer */ /* --- initialisation code ------------------------------------- */
@@ -921,6 +921,11 @@ static int lp_register(int nr, struct parport *port) &ppdev_cb, nr);if (lp_table[nr].dev ==NULL )return 1 ; + + lpcons =allocate_console_dfl (&lp_cons_ops,"lp" ,NULL ); +if (!lpcons) +return -ENOMEM ; + lp_table[nr].flags |=LP_EXIST ;if (reset)
@@ -935,7 +940,7 @@ static int lp_register(int nr, struct parport *port)#ifdef CONFIG_LP_CONSOLE if (!nr) {if (port->modes &PARPORT_MODE_SAFEININT ) { -register_console (&lpcons); +register_console (lpcons); console_registered = port;printk (KERN_INFO "lp%d: console ready\n" ,CONSOLE_LP ); }else
@@ -989,8 +994,9 @@ static void lp_detach(struct parport *port)/* Write this some day. */ #ifdef CONFIG_LP_CONSOLE if (console_registered == port) { -unregister_console (&lpcons); +unregister_console (lpcons); console_registered =NULL ; +put_device (&lpcons->dev); }#endif /* CONFIG_LP_CONSOLE */
@@ -1105,7 +1111,8 @@ static void lp_cleanup_module(void)parport_unregister_driver (&lp_driver);#ifdef CONFIG_LP_CONSOLE -unregister_console (&lpcons); +unregister_console (lpcons); +put_device (&lpcons->dev);#endif unregister_chrdev (LP_MAJOR ,"lp" );
drivers/hwtracing/stm/console.c +12 -7
@@ -17,7 +17,7 @@ static void stm_console_unlink(struct stm_source_data *data);static struct stm_console {struct stm_source_data data; -struct console console; +struct console *console; } stm_console = { .data = { .name ="console" ,
@@ -30,20 +30,25 @@ static struct stm_console {static void stm_console_write (struct console *con,const char *buf,unsigned len) { - struct stm_console *sc = container_of(con, struct stm_console, console); +struct stm_console *sc = con->data;stm_source_write (&sc->data,0 , buf, len); } +static const struct console_operations stm_cons_ops = { + .write = stm_console_write, +}; +static int stm_console_link (struct stm_source_data *data) { struct stm_console *sc = container_of(data, struct stm_console, data); -strcpy (sc->console.name,"stm_console" ); - sc->console.write = stm_console_write; - sc->console.flags =CON_ENABLED |CON_PRINTBUFFER ; -register_console (&sc->console); + sc->console =allocate_console_dfl (&stm_cons_ops,"stm_console" , data); +if (!sc->console) +return -ENOMEM ; + sc->console->flags |=CON_ENABLED ; +register_console (sc->console);return 0 ; }
@@ -51,7 +56,7 @@ static void stm_console_unlink(struct stm_source_data *data) { struct stm_console *sc = container_of(data, struct stm_console, data); -unregister_console (&sc->console); +unregister_console (sc->console); }static int stm_console_init (void )
drivers/misc/pti.c +16 -10
@@ -729,15 +729,14 @@ static int pti_console_setup(struct console *c, char *opts)* the tty port is to hook up syslog to it, the tty port * will be open for a really long time. */ -static struct console pti_console = { - .name =TTYNAME , +static const struct console_operations pti_cons_ops = { .write = pti_console_write, .device = pti_console_device, .setup = pti_console_setup, - .flags =CON_PRINTBUFFER , - .index =0 , }; +static struct console *pti_console; +/** * pti_port_activate()- Used to start/initialize any items upon * first opening of tty_port().
@@ -755,7 +754,7 @@ static struct console pti_console = {static int pti_port_activate (struct tty_port *port,struct tty_struct *tty) {if (port->tty->index ==PTITTY_MINOR_START ) -console_start (&pti_console); +console_start (pti_console);return 0 ; }
@@ -772,7 +771,7 @@ static int pti_port_activate(struct tty_port *port, struct tty_struct *tty)static void pti_port_shutdown (struct tty_port *port) {if (port->tty->index ==PTITTY_MINOR_START ) -console_stop (&pti_console); +console_stop (pti_console); }static const struct tty_port_operations tty_port_ops = {
@@ -800,19 +799,23 @@ static int pti_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) {unsigned int a; -int retval = -EINVAL ; +int retval = -ENOMEM ;int pci_bar =1 ;dev_dbg (&pdev->dev,"%s %s(%d): PTI PCI ID %04x:%04x\n" , __FILE__, __func__, __LINE__, pdev->vendor, pdev->device); + pti_console =allocate_console_dfl (&pti_cons_ops,TTYNAME ,NULL ); +if (!pti_console) + goto err; + retval =misc_register (&pti_char_driver);if (retval) {pr_err ("%s(%d): CHAR registration failed of pti driver\n" , __func__, __LINE__);pr_err ("%s(%d): Error value returned: %d\n" , __func__, __LINE__, retval); - goto err; + goto err_put_con; } retval =pci_enable_device (pdev);
@@ -859,7 +862,7 @@ static int pti_pci_probe(struct pci_dev *pdev,tty_port_register_device (port, pti_tty_driver, a, &pdev->dev); } -register_console (&pti_console); +register_console (pti_console);return 0 ; err_rel_reg:
@@ -870,6 +873,8 @@ static int pti_pci_probe(struct pci_dev *pdev,pci_disable_device (pdev); err_unreg_misc:misc_deregister (&pti_char_driver); +err_put_con: +put_device (&pti_console->dev); err:return retval; }
@@ -884,7 +889,8 @@ static void pti_pci_remove(struct pci_dev *pdev)struct pti_dev *drv_data =pci_get_drvdata (pdev);unsigned int a; -unregister_console (&pti_console); +unregister_console (pti_console); +put_device (&pti_console->dev);for (a =0 ; a <PTITTY_MINOR_NUM ; a++) {tty_unregister_device (pti_tty_driver, a);
drivers/net/netconsole.c +41 -58
176 lines not on this page · raw message
drivers/s390/char/con3215.c +7 -4
@@ -887,11 +887,9 @@ static struct notifier_block on_reboot_nb = {/* * The console structure for the 3215 console */ -static struct console con3215 = { - .name ="ttyS" , +static const struct console_operations con3215_cons_ops = { .write = con3215_write, .device = con3215_device, - .flags =CON_PRINTBUFFER , };/*
@@ -902,6 +900,7 @@ static int __init con3215_init(void)struct ccw_device *cdev;struct raw3215_info *raw;struct raw3215_req *req; +struct console *con3215;int i;/* Check if 3215 is to be the console */
@@ -925,6 +924,10 @@ static int __init con3215_init(void) raw3215_freelist = req; } + con3215 =allocate_console_dfl (&con3215_cons_ops,"ttyS" ,NULL ); +if (!con3215) +return -ENOMEM ; + cdev =ccw_device_create_console (&raw3215_ccw_driver);if (IS_ERR (cdev))return -ENODEV ;
@@ -950,7 +953,7 @@ static int __init con3215_init(void) }atomic_notifier_chain_register (&panic_notifier_list, &on_panic_nb);register_reboot_notifier (&on_reboot_nb); -register_console (&con3215); +register_console (con3215);return 0 ; }console_initcall (con3215_init);
drivers/s390/char/con3270.c +8 -4
@@ -580,11 +580,10 @@ static struct notifier_block on_reboot_nb = {/* * The console structure for the 3270 console */ -static struct console con3270 = { - .name ="tty3270" , + +static const struct console_operations con3270_cons_ops = { .write = con3270_write, .device = con3270_device, - .flags =CON_PRINTBUFFER , };/*
@@ -593,6 +592,7 @@ static struct console con3270 = {static int __init con3270_init (void ) { +struct console *con3270;struct raw3270 *rp;void *cbuf;int i;
@@ -607,6 +607,10 @@ con3270_init(void)cpcmd ("TERM AUTOCR OFF" ,NULL ,0 ,NULL ); } + con3270 =allocate_console_dfl (&con3270_cons_ops,"tty3270" ,NULL ); +if (!con3270) +return -ENOMEM ; + rp =raw3270_setup_console ();if (IS_ERR (rp))return PTR_ERR (rp);
@@ -642,7 +646,7 @@ con3270_init(void) condev->input =alloc_string (&condev->freemem,80 );atomic_notifier_chain_register (&panic_notifier_list, &on_panic_nb);register_reboot_notifier (&on_reboot_nb); -register_console (&con3270); +register_console (con3270);return 0 ; }
drivers/s390/char/sclp_con.c +11 -6
@@ -281,15 +281,12 @@ static struct notifier_block on_reboot_nb = {* used to register the SCLP console to the kernel and to * give printk necessary information */ -static struct console sclp_console = -{ - .name = sclp_console_name, +static const struct console_operations sclp_cons_ops = { .write = sclp_console_write, .device = sclp_console_device, - .flags =CON_PRINTBUFFER , - .index =0 /* ttyS0 */ }; +/* * This function is called for SCLP suspend and resume events. */
@@ -312,6 +309,7 @@ void sclp_console_pm_event(enum sclp_pm_event sclp_pm_event)static int __init sclp_console_init (void ) { +struct console *sclp_console;void *page;int i;int rc;
@@ -319,9 +317,16 @@ sclp_console_init(void)/* SCLP consoles are handled together */ if (!(CONSOLE_IS_SCLP ||CONSOLE_IS_VT220 ))return 0 ; + rc =sclp_rw_init ();if (rc)return rc; + + sclp_console =allocate_console_dfl (&sclp_cons_ops, sclp_console_name, +NULL ); +if (!sclp_console) +return -ENOMEM ; +/* Allocate pages for output buffering */ INIT_LIST_HEAD (&sclp_con_pages);for (i =0 ; i < sclp_console_pages; i++) {
@@ -347,7 +352,7 @@ sclp_console_init(void)/* enable printk-access to this driver */ atomic_notifier_chain_register (&panic_notifier_list, &on_panic_nb);register_reboot_notifier (&on_reboot_nb); -register_console (&sclp_console); +register_console (sclp_console);return 0 ; }
drivers/s390/char/sclp_vt220.c +12 -6
@@ -869,27 +869,33 @@ static struct notifier_block on_reboot_nb = { };/* Structure needed to register with printk */ -static struct console sclp_vt220_console = -{ - .name =SCLP_VT220_CONSOLE_NAME , +static const struct console_operations sclp_vt220_cons_ops = { .write = sclp_vt220_con_write, .device = sclp_vt220_con_device, - .flags =CON_PRINTBUFFER , - .index =SCLP_VT220_CONSOLE_INDEX };static int __init sclp_vt220_con_init (void ) { +struct console *sclp_vt220_console;int rc; + sclp_vt220_console =allocate_console_dfl (&sclp_vt220_cons_ops, +SCLP_VT220_CONSOLE_NAME , +NULL ); +if (!sclp_vt220_console) +return -ENOMEM ; + + sclp_vt220_console->index =SCLP_VT220_CONSOLE_INDEX ; + rc =__sclp_vt220_init (sclp_console_pages);if (rc)return rc; +/* Attach linux console */ atomic_notifier_chain_register (&panic_notifier_list, &on_panic_nb);register_reboot_notifier (&on_reboot_nb); -register_console (&sclp_vt220_console); +register_console (sclp_vt220_console);return 0 ; }
drivers/tty/amiserial.c +8 -5
@@ -1779,12 +1779,9 @@ static struct tty_driver *serial_console_device(struct console *c, int *index)return serial_driver; } -static struct console sercons = { - .name ="ttyS" , +static const struct console_operations ami_cons_ops = { .write = serial_console_write, .device = serial_console_device, - .flags =CON_PRINTBUFFER , - .index =-1 , };/*
@@ -1792,10 +1789,16 @@ static struct console sercons = {*/ static int __init amiserial_console_init (void ) { +struct console *sercons; +if (!MACH_IS_AMIGA )return -ENODEV ; -register_console (&sercons); + sercons =allocate_console_dfl (&ami_cons_ops,"ttyS" ,NULL ); +if (!sercons) +return -ENOMEM ; + +register_console (sercons);return 0 ; }console_initcall (amiserial_console_init);
drivers/tty/ehv_bytechan.c +13 -6
@@ -277,13 +277,13 @@ static struct tty_driver *ehv_bc_console_device(struct console *co, int *index)return ehv_bc_driver; } -static struct console ehv_bc_console = { - .name ="ttyEHV" , +static const struct console_operations ehv_bc_cons_ops = { .write = ehv_bc_console_write, .device = ehv_bc_console_device, - .flags =CON_PRINTBUFFER |CON_ENABLED , }; +static struct console *ehv_bc_console; +/* * Console initialization *
@@ -308,12 +308,19 @@ static int __init ehv_bc_console_init(void) CONFIG_PPC_EARLY_DEBUG_EHV_BC_HANDLE);#endif + ehv_bc_console =allocate_console_dfl (&ehv_bc_cons_ops,"ttyEHV" ,NULL ); +if (!ehv_bc_console) +return -ENOMEM ; + + ehv_bc_console->flags |=CON_ENABLED ; +/* add_preferred_console() must be called before register_console(), otherwise it won't work. However, we don't want to enumerate all the byte channels here, either, since we only care about one. */ -add_preferred_console (ehv_bc_console.name, ehv_bc_console.index,NULL ); -register_console (&ehv_bc_console); +add_preferred_console (ehv_bc_console->name, ehv_bc_console->index, +NULL ); +register_console (ehv_bc_console);pr_info ("ehv-bc: registered console driver for byte channel %u\n" , stdout_bc);
@@ -765,7 +772,7 @@ static int __init ehv_bc_init(void) } ehv_bc_driver->driver_name ="ehv-bc" ; - ehv_bc_driver->name = ehv_bc_console.name; + ehv_bc_driver->name = ehv_bc_console->name; ehv_bc_driver->type =TTY_DRIVER_TYPE_CONSOLE ; ehv_bc_driver->subtype =SYSTEM_TYPE_CONSOLE ; ehv_bc_driver->init_termios = tty_std_termios;
drivers/tty/goldfish.c +23 -11
@@ -39,7 +39,7 @@ struct goldfish_tty {void __iomem *base;u32 irq;int opencount; -struct console console; +struct console *console;u32 version;struct device *dev; };
@@ -241,6 +241,12 @@ static const struct tty_operations goldfish_tty_ops = { .chars_in_buffer = goldfish_tty_chars_in_buffer, }; +static const struct console_operations goldfish_cons_ops = { + .write = goldfish_tty_console_write, + .device = goldfish_tty_console_device, + .setup = goldfish_tty_console_setup, +}; +static int goldfish_tty_create_driver (void ) {int ret;
@@ -392,18 +398,19 @@ static int goldfish_tty_probe(struct platform_device *pdev) goto err_tty_register_device_failed; } -strcpy (qtty->console.name,"ttyGF" ); - qtty->console.write = goldfish_tty_console_write; - qtty->console.device = goldfish_tty_console_device; - qtty->console.setup = goldfish_tty_console_setup; - qtty->console.flags =CON_PRINTBUFFER ; - qtty->console.index = line; -register_console (&qtty->console); + qtty->console =allocate_console_dfl (&goldfish_cons_ops,"ttyGF" ,NULL ); +if (!qtty->console) + goto err_alloc_console_failed; + + qtty->console->index = line; +register_console (qtty->console);platform_set_drvdata (pdev, qtty);mutex_unlock (&goldfish_tty_lock);return 0 ; +err_alloc_console_failed: +tty_unregister_device (goldfish_tty_driver, line); err_tty_register_device_failed:free_irq (irq, qtty); err_dec_line_count:
@@ -423,8 +430,9 @@ static int goldfish_tty_remove(struct platform_device *pdev)mutex_lock (&goldfish_tty_lock); -unregister_console (&qtty->console); -tty_unregister_device (goldfish_tty_driver, qtty->console.index); +unregister_console (qtty->console); +put_device (&qtty->console->dev); +tty_unregister_device (goldfish_tty_driver, qtty->console->index);iounmap (qtty->base); qtty->base =NULL ;free_irq (qtty->irq, pdev);
@@ -448,13 +456,17 @@ static void gf_early_write(struct console *con, const char *s, unsigned int n)uart_console_write (&dev->port, s, n, gf_early_console_putchar); } +static const struct console_operations goldfish_early_cons_ops = { + .write = gf_early_write, +}; +static int __init gf_earlycon_setup (struct earlycon_device *device,const char *opt) {if (!device->port.membase)return -ENODEV ; - device->con->write = gf_early_write; + device->con->ops = &goldfish_early_cons_ops;return 0 ; }
drivers/tty/hvc/hvc_console.c +6 -2
@@ -214,13 +214,17 @@ static int hvc_console_setup(struct console *co, char *options)return 0 ; } -static struct console hvc_console = { - .name ="hvc" , +static const struct console_operations hvc_console_ops = { .write = hvc_console_print, .device = hvc_console_device, .setup = hvc_console_setup, +}; + +static struct console hvc_console = { .flags =CON_PRINTBUFFER , .index =-1 , + .ops = &hvc_console_ops, + .is_static =1 , };/*
drivers/tty/hvc/hvc_xen.c +12 -3
@@ -644,12 +644,17 @@ static void xenboot_write_console(struct console *console, const char *string, domU_write_console(0, string+off, len-off); } -struct console xenboot_console = { - .name ="xenboot" , +static const struct console_operations xenboot_cons_ops = { .write = xenboot_write_console, .setup = xenboot_setup_console, +}; + +struct console xenboot_console = { + .name ="xenboot" , + .ops = &xenboot_cons_ops, .flags =CON_PRINTBUFFER |CON_BOOT |CON_ANYTIME , .index =-1 , + .is_static =1 , };#endif /* CONFIG_EARLY_PRINTK */
@@ -685,10 +690,14 @@ static void xenboot_earlycon_write(struct console *console,dom0_write_console (0 , string, len); } +static const struct console_operations xenboot_early_cons_ops = { + .write = xenboot_earlycon_write, +}; +static int __init xenboot_earlycon_setup (struct earlycon_device *device,const char *opt) { - device->con->write = xenboot_earlycon_write; + device->con->ops = &xenboot_early_cons_ops;return 0 ; }EARLYCON_DECLARE (xenboot, xenboot_earlycon_setup);
drivers/tty/hvc/hvsi.c +9 -5
@@ -1151,21 +1151,23 @@ static int __init hvsi_console_setup(struct console *console, char *options)return 0 ; } -static struct console hvsi_console = { - .name ="hvsi" , +static const struct console_operations hvsi_cons_ops = { .write = hvsi_console_print, .device = hvsi_console_device, .setup = hvsi_console_setup, - .flags =CON_PRINTBUFFER , - .index =-1 , };static int __init hvsi_console_init (void ) { +struct console *hvsi_console;struct device_node *vty; hvsi_wait = poll_for_state;/* no irqs yet; must poll */ + hvsi_console =allocate_console_dfl (&hvsi_cons_ops,"hvsi" ,NULL ); +if (!hvsi_console) +return -ENOMEM ; +/* search device tree for vty nodes */ for_each_compatible_node (vty,"serial" ,"hvterm-protocol" ) {struct hvsi_struct *hp;
@@ -1204,7 +1206,9 @@ static int __init hvsi_console_init(void) }if (hvsi_count) -register_console (&hvsi_console); +register_console (hvsi_console); + +put_console (hvsi_console);return 0 ; }console_initcall (hvsi_console_init);
drivers/tty/mips_ejtag_fdc.c +24 -20
97 lines not on this page · raw message
drivers/tty/serial/21285.c +13 -12
@@ -444,28 +444,28 @@ static int __init serial21285_console_setup(struct console *co, char *options)static struct uart_driver serial21285_reg; -static struct console serial21285_console = -{ - .name =SERIAL_21285_NAME , +static const struct console_operations serial2125_cons_ops = { .write = serial21285_console_write, .device = uart_console_device, .setup = serial21285_console_setup, - .flags =CON_PRINTBUFFER , - .index =-1 , - .data = &serial21285_reg, }; +static struct console __initdata *serial21285_console; +static int __init rs285_console_init (void ) { + serial21285_console =allocate_console_dfl (&serial2125_cons_ops, +SERIAL_21285_NAME , + &serial21285_reg); +if (!serial21285_console) +return -ENOMEM ; +serial21285_setup_ports (); -register_console (&serial21285_console); +register_console (serial21285_console);return 0 ; }console_initcall (rs285_console_init); -#define SERIAL_21285_CONSOLE &serial21285_console -#else -#define SERIAL_21285_CONSOLE NULL#endif static struct uart_driver serial21285_reg = {
@@ -475,7 +475,6 @@ static struct uart_driver serial21285_reg = { .major = SERIAL_21285_MAJOR, .minor = SERIAL_21285_MINOR, .nr = 1, - .cons = SERIAL_21285_CONSOLE, };static int __init serial21285_init (void )
@@ -487,8 +486,10 @@ static int __init serial21285_init(void)serial21285_setup_ports (); ret =uart_register_driver (&serial21285_reg); -if (ret ==0 ) +if (ret ==0 ) {uart_add_one_port (&serial21285_reg, &serial21285_port); + serial21285_reg.cons = serial21285_console; + }return ret; }
drivers/tty/serial/8250/8250_core.c +14 -8
@@ -661,29 +661,33 @@ static int univ8250_console_match(struct console *co, char *name, int idx, return -ENODEV; } -static struct console univ8250_console = { - .name ="ttyS" , +static const struct console_operations univ8250_console_ops = { .write = univ8250_console_write, .device = uart_console_device, .setup = univ8250_console_setup, .match = univ8250_console_match, - .flags =CON_PRINTBUFFER |CON_ANYTIME , - .index =-1 , - .data = &serial8250_reg, }; +static struct console __initdata *univ8250_console; +static int __init univ8250_console_init (void ) {if (nr_uarts ==0 )return -ENODEV ; + univ8250_console =allocate_console_dfl (&univ8250_console_ops,"ttyS" , + &serial8250_reg); +if (!univ8250_console) +return -ENOMEM ; + + univ8250_console->flags |=CON_ANYTIME ;serial8250_isa_init_ports (); -register_console (&univ8250_console); +register_console (univ8250_console);return 0 ; }console_initcall (univ8250_console_init); -#define SERIAL8250_CONSOLE (&univ8250_console) +#define SERIAL8250_CONSOLE (univ8250_console)#else #define SERIAL8250_CONSOLE NULL#endif
@@ -694,7 +698,6 @@ static struct uart_driver serial8250_reg = { .dev_name = "ttyS", .major = TTY_MAJOR, .minor = 64, - .cons = SERIAL8250_CONSOLE, };/*
@@ -1136,6 +1139,8 @@ static int __init serial8250_init(void)pr_info ("Serial: 8250/16550 driver, %d ports, IRQ sharing %sabled\n" , nr_uarts, share_irqs ?"en" :"dis" ); + serial8250_reg.cons =SERIAL8250_CONSOLE ; +#ifdef CONFIG_SPARC ret =sunserial_register_minors (&serial8250_reg,UART_NR );#else
@@ -1178,6 +1183,7 @@ static int __init serial8250_init(void)uart_unregister_driver (&serial8250_reg);#endif out: +put_console (SERIAL8250_CONSOLE );return ret; }
drivers/tty/serial/8250/8250_early.c +15 -3
@@ -132,6 +132,10 @@ static void __init init_port(struct earlycon_device *device) } } +static struct console_operations early_serial8250_ops = { + .write = early_serial8250_write, +}; +int __init early_serial8250_setup (struct earlycon_device *device,const char *options) {
@@ -148,7 +152,7 @@ int __init early_serial8250_setup(struct earlycon_device *device, }else init_port (device); - device->con->write = early_serial8250_write; + device->con->ops = &early_serial8250_ops;return 0 ; }EARLYCON_DECLARE (uart8250, early_serial8250_setup);
@@ -160,6 +164,10 @@ OF_EARLYCON_DECLARE(uart, "snps,dw-apb-uart", early_serial8250_setup);#ifdef CONFIG_SERIAL_8250_OMAP +static const struct console_operations early_omap8250_cons_ops = { + .write = early_serial8250_write, +}; +static int __init early_omap8250_setup (struct earlycon_device *device,const char *options) {
@@ -169,7 +177,7 @@ static int __init early_omap8250_setup(struct earlycon_device *device,return -ENODEV ; port->regshift =2 ; - device->con->write = early_serial8250_write; + device->con->ops = &early_omap8250_cons_ops;return 0 ; }
@@ -184,12 +192,16 @@ OF_EARLYCON_DECLARE(omap8250, "ti,omap4-uart", early_omap8250_setup);unsigned int au_serial_in (struct uart_port *p,int offset);void au_serial_out (struct uart_port *p,int offset,int value); +static const struct console_operations early_serial8250_cons_ops = { + .write = early_serial8250_write, +}; +static int __init early_au_setup (struct earlycon_device *dev,const char *opt) { dev->port.serial_in = au_serial_in; dev->port.serial_out = au_serial_out; dev->port.iotype =UPIO_AU ; - dev->con->write = early_serial8250_write; + dev->con->ops = &early_serial8250_cons_ops;return 0 ; }OF_EARLYCON_DECLARE (palmchip,"ralink,rt2880-uart" , early_au_setup);
drivers/tty/serial/8250/8250_ingenic.c +5 -1
@@ -87,6 +87,10 @@ static void __init ingenic_early_console_setup_clock(struct earlycon_device *dev dev->port.uartclk =be32_to_cpup (prop); } +static struct console_operations ingenic_early_cons_ops = { + .write = ingenic_early_console_write, +}; +static int __init ingenic_early_console_setup (struct earlycon_device *dev,const char *opt) {
@@ -124,7 +128,7 @@ static int __init ingenic_early_console_setup(struct earlycon_device *dev,early_out (port,UART_LCR ,UART_LCR_WLEN8 ); early_device = dev; - dev->con->write = ingenic_early_console_write; + dev->con->ops = &ingenic_early_cons_ops;return 0 ; }
drivers/tty/serial/altera_jtaguart.c +20 -13
@@ -359,26 +359,28 @@ static int __init altera_jtaguart_console_setup(struct console *co,static struct uart_driver altera_jtaguart_driver; -static struct console altera_jtaguart_console = { - .name ="ttyJ" , +static const struct console_operations jtaguart_cons_ops = { .write = altera_jtaguart_console_write, .device = uart_console_device, .setup = altera_jtaguart_console_setup, - .flags =CON_PRINTBUFFER , - .index =-1 , - .data = &altera_jtaguart_driver, }; +static struct console __initdata *altera_jtaguart_console; +static int __init altera_jtaguart_console_init (void ) { -register_console (&altera_jtaguart_console); + altera_jtaguart_console =allocate_console_dfl (&jtaguart_cons_ops, +"ttyJ" , + &altera_jtaguart_driver); +if (!altera_jtaguart_console) +return -ENOMEM ; + +register_console (altera_jtaguart_console);return 0 ; }console_initcall (altera_jtaguart_console_init); -#define ALTERA_JTAGUART_CONSOLE (&altera_jtaguart_console) -static void altera_jtaguart_earlycon_write (struct console *co,const char *s,unsigned int count) {
@@ -387,22 +389,25 @@ static void altera_jtaguart_earlycon_write(struct console *co, const char *s,uart_console_write (&dev->port, s, count, altera_jtaguart_console_putc); } +static const struct console_operations jtaguart_earlycon_con_ops = { + .write = altera_jtaguart_earlycon_write, +}; +static int __init altera_jtaguart_earlycon_setup (struct earlycon_device *dev,const char *options) {if (!dev->port.membase)return -ENODEV ; - dev->con->write = altera_jtaguart_earlycon_write; + dev->con->ops = &jtaguart_earlycon_con_ops;return 0 ; }OF_EARLYCON_DECLARE (juart,"altr,juart-1.0" , altera_jtaguart_earlycon_setup); +#define ALTERA_JTAGUART_CONSOLE (altera_jtaguart_console)#else - -#define ALTERA_JTAGUART_CONSOLE NULL - +#define ALTERA_JTAGUART_CONSOLE NULL#endif /* CONFIG_SERIAL_ALTERA_JTAGUART_CONSOLE */ static struct uart_driver altera_jtaguart_driver = {
@@ -412,7 +417,6 @@ static struct uart_driver altera_jtaguart_driver = { .major = ALTERA_JTAGUART_MAJOR, .minor = ALTERA_JTAGUART_MINOR, .nr = ALTERA_JTAGUART_MAXPORTS, - .cons = ALTERA_JTAGUART_CONSOLE, };static int altera_jtaguart_probe (struct platform_device *pdev)
@@ -501,12 +505,15 @@ static int __init altera_jtaguart_init(void) {int rc; + altera_jtaguart_driver.cons =ALTERA_JTAGUART_CONSOLE ; rc =uart_register_driver (&altera_jtaguart_driver);if (rc)return rc; + rc =platform_driver_register (&altera_jtaguart_platform_driver);if (rc)uart_unregister_driver (&altera_jtaguart_driver); +return rc; }
drivers/tty/serial/altera_uart.c +16 -9
@@ -479,25 +479,28 @@ static int __init altera_uart_console_setup(struct console *co, char *options)static struct uart_driver altera_uart_driver; -static struct console altera_uart_console = { - .name ="ttyAL" , +static const struct console_operations altera_cons_ops = { .write = altera_uart_console_write, .device = uart_console_device, .setup = altera_uart_console_setup, - .flags =CON_PRINTBUFFER , - .index =-1 , - .data = &altera_uart_driver, }; +static struct console __initdata *altera_uart_console; +static int __init altera_uart_console_init (void ) { -register_console (&altera_uart_console); + altera_uart_console =allocate_console_dfl (&altera_cons_ops,"ttyAL" , + &altera_uart_driver); +if (!altera_uart_console) +return -ENOMEM ; + +register_console (altera_uart_console);return 0 ; }console_initcall (altera_uart_console_init); -#define ALTERA_UART_CONSOLE (&altera_uart_console) +#define ALTERA_UART_CONSOLE (altera_uart_console)static void altera_uart_earlycon_write (struct console *co,const char *s,unsigned int count)
@@ -507,6 +510,10 @@ static void altera_uart_earlycon_write(struct console *co, const char *s,uart_console_write (&dev->port, s, count, altera_uart_console_putc); } +static const struct console_operations altera_early_cons_ops = { + .write = altera_uart_earlycon_write, +}; +static int __init altera_uart_earlycon_setup (struct earlycon_device *dev,const char *options) {
@@ -525,7 +532,7 @@ static int __init altera_uart_earlycon_setup(struct earlycon_device *dev,altera_uart_writel (port, baudclk,ALTERA_UART_DIVISOR_REG ); } - dev->con->write = altera_uart_earlycon_write; + dev->con->ops = &altera_early_cons_ops;return 0 ; }
@@ -547,7 +554,6 @@ static struct uart_driver altera_uart_driver = { .major = SERIAL_ALTERA_MAJOR, .minor = SERIAL_ALTERA_MINOR, .nr = CONFIG_SERIAL_ALTERA_UART_MAXPORTS, - .cons = ALTERA_UART_CONSOLE, };static int altera_uart_probe (struct platform_device *pdev)
@@ -653,6 +659,7 @@ static int __init altera_uart_init(void) {int rc; + altera_uart_driver.cons =ALTERA_UART_CONSOLE ; rc =uart_register_driver (&altera_uart_driver);if (rc)return rc;
drivers/tty/serial/amba-pl010.c +22 -13
@@ -668,20 +668,14 @@ static int __init pl010_console_setup(struct console *co, char *options) return uart_set_options(&uap->port, co, baud, parity, bits, flow); } -static struct uart_driver amba_reg; -static struct console amba_console = { - .name ="ttyAM" , +static const struct console_operations amba_cons_ops = { .write = pl010_console_write, .device = uart_console_device, .setup = pl010_console_setup, - .flags =CON_PRINTBUFFER , - .index =-1 , - .data = &amba_reg, }; -#define AMBA_CONSOLE &amba_console#else -#define AMBA_CONSOLE NULL +static const struct console_operations amba_cons_ops;#endif static DEFINE_MUTEX (amba_reg_lock);
@@ -692,7 +686,6 @@ static struct uart_driver amba_reg = { .major = SERIAL_AMBA_MAJOR, .minor = SERIAL_AMBA_MINOR, .nr = UART_NR, - .cons = AMBA_CONSOLE, };static int pl010_probe (struct amba_device *dev,const struct amba_id *id)
@@ -740,20 +733,36 @@ static int pl010_probe(struct amba_device *dev, const struct amba_id *id)mutex_lock (&amba_reg_lock);if (!amba_reg.state) { + ret =uart_allocate_console_dfl (&amba_reg, &amba_cons_ops, +"ttyAM" , +SERIAL_AMBA_PL010_CONSOLE ); +if (ret <0 ) { +mutex_unlock (&amba_reg_lock); + goto out; + } + ret =uart_register_driver (&amba_reg);if (ret <0 ) {mutex_unlock (&amba_reg_lock); -dev_err (uap->port.dev, -"Failed to register AMBA-PL010 driver\n" ); -return ret; + goto out; } }mutex_unlock (&amba_reg_lock); ret =uart_add_one_port (&amba_reg, &uap->port);if (ret) - amba_ports[i] =NULL ; + goto out_unregister; + +return 0 ; + +out_unregister: +uart_unregister_driver (&amba_reg); +out: + amba_ports[i] =NULL ; +uart_put_console (&amba_reg); +kfree (uap); +pr_err ("Failed to register AMBA-PL010 driver\n" );return ret; }
drivers/tty/serial/amba-pl011.c +29 -18
106 lines not on this page · raw message
drivers/tty/serial/apbuart.c +15 -9
@@ -507,30 +507,36 @@ static int __init apbuart_console_setup(struct console *co, char *options)static struct uart_driver grlib_apbuart_driver; -static struct console grlib_apbuart_console = { - .name ="ttyS" , +static const struct console_operations grlib_cons_ops = { .write = apbuart_console_write, .device = uart_console_device, .setup = apbuart_console_setup, - .flags =CON_PRINTBUFFER , - .index =-1 , - .data = &grlib_apbuart_driver, }; +static struct console __initdata *grlib_apbuart_console;static int grlib_apbuart_configure (void );static int __init apbuart_console_init (void ) { + grlib_apbuart_console =allocate_console_dfl (&grlib_cons_ops,"ttyS" , + &grlib_apbuart_driver); +if (!grlib_apbuart_console) +return -ENOMEM ; +if (grlib_apbuart_configure ()) -return -ENODEV ; -register_console (&grlib_apbuart_console); + goto err; + +register_console (grlib_apbuart_console);return 0 ; +err: +put_console (grlib_apbuart_console); +return -ENODEV ; }console_initcall (apbuart_console_init); -#define APBUART_CONSOLE (&grlib_apbuart_console) +#define APBUART_CONSOLE (grlib_apbuart_console)#else #define APBUART_CONSOLE NULL#endif
@@ -542,7 +548,6 @@ static struct uart_driver grlib_apbuart_driver = { .major = SERIAL_APBUART_MAJOR, .minor = SERIAL_APBUART_MINOR, .nr = UART_NR, - .cons = APBUART_CONSOLE, };
@@ -652,6 +657,7 @@ static int __init grlib_apbuart_init(void)printk (KERN_INFO "Serial: GRLIB APBUART driver\n" ); + grlib_apbuart_driver.cons =APBUART_CONSOLE ; ret =uart_register_driver (&grlib_apbuart_driver);if (ret) {
drivers/tty/serial/ar933x_uart.c +6 -7
@@ -595,14 +595,10 @@ static int ar933x_uart_console_setup(struct console *co, char *options)return uart_set_options (&up->port, co, baud, parity, bits, flow); } -static struct console ar933x_uart_console = { - .name ="ttyATH" , +static const struct console_operations ar933x_cons_ops = { .write = ar933x_uart_console_write, .device = uart_console_device, .setup = ar933x_uart_console_setup, - .flags =CON_PRINTBUFFER , - .index =-1 , - .data = &ar933x_uart_driver, };static void ar933x_uart_add_console_port (struct ar933x_uart_port *up)
@@ -749,8 +745,10 @@ static int __init ar933x_uart_init(void) {int ret; -if (ar933x_uart_console_enabled ()) - ar933x_uart_driver.cons = &ar933x_uart_console; + ret =uart_allocate_console_dfl (&ar933x_uart_driver, &ar933x_cons_ops, +"ttyATH" ,SERIAL_AR933X_CONSOLE ); +if (ret) +return ret; ret =uart_register_driver (&ar933x_uart_driver);if (ret)
@@ -765,6 +763,7 @@ static int __init ar933x_uart_init(void) err_unregister_uart_driver:uart_unregister_driver (&ar933x_uart_driver); err_out: +uart_put_console (&ar933x_uart_driver);return ret; }
drivers/tty/serial/arc_uart.c +14 -13
@@ -105,10 +105,6 @@ struct arc_uart_port {static struct arc_uart_port arc_uart_ports[CONFIG_SERIAL_ARC_NR_PORTS ]; -#ifdef CONFIG_SERIAL_ARC_CONSOLE -static struct console arc_console; -#endif -#define DRIVER_NAME "arc-uart"static struct uart_driver arc_uart_driver = {
@@ -118,9 +114,6 @@ static struct uart_driver arc_uart_driver = { .major = 0, .minor = 0, .nr = CONFIG_SERIAL_ARC_NR_PORTS, -#ifdef CONFIG_SERIAL_ARC_CONSOLE - .cons = &arc_console, -#endif };static void arc_serial_stop_rx (struct uart_port *port)
@@ -536,14 +529,10 @@ static void arc_serial_console_write(struct console *co, const char *s,spin_unlock_irqrestore (&port->lock, flags); } -static struct console arc_console = { - .name =ARC_SERIAL_DEV_NAME , +static const struct console_operations arc_cons_ops = { .write = arc_serial_console_write, .device = uart_console_device, .setup = arc_serial_console_setup, - .flags =CON_PRINTBUFFER , - .index =-1 , - .data = &arc_uart_driver }; static void arc_early_serial_write(struct console *con, const char *s,
@@ -554,6 +543,10 @@ static void arc_early_serial_write(struct console *con, const char *s,uart_console_write (&dev->port, s, n, arc_serial_console_putchar); } +static const struct console_operations arc_early_cons_ops = { + .write = arc_early_serial_write, +}; +static int __init arc_early_console_setup (struct earlycon_device *dev,const char *opt) {
@@ -570,11 +563,13 @@ static int __init arc_early_console_setup(struct earlycon_device *dev,UART_SET_BAUDL (port, l);UART_SET_BAUDH (port, h); - dev->con->write = arc_early_serial_write; + dev->con->ops = &arc_early_cons_ops; return 0; }OF_EARLYCON_DECLARE (arc_uart,"snps,arc-uart" , arc_early_console_setup); +#else +static const struct console_operations arc_cons_ops;#endif /* CONFIG_SERIAL_ARC_CONSOLE */ static int arc_serial_probe (struct platform_device *pdev)
@@ -662,6 +657,12 @@ static int __init arc_serial_init(void) {int ret; + ret =uart_allocate_console_dfl (&arc_uart_driver, &arc_cons_ops, +ARC_SERIAL_DEV_NAME , +SERIAL_ARC_CONSOLE ); +if (ret) +return ret; + ret =uart_register_driver (&arc_uart_driver);if (ret)return ret;
drivers/tty/serial/atmel_serial.c +15 -16
@@ -194,10 +194,6 @@ struct atmel_uart_port {static struct atmel_uart_port atmel_ports[ATMEL_MAX_UART ]; static DECLARE_BITMAP(atmel_ports_in_use, ATMEL_MAX_UART); -#ifdef SUPPORT_SYSRQ -static struct console atmel_console; -#endif -#if defined(CONFIG_OF )static const struct of_device_id atmel_serial_dt_ids[] = { { .compatible = "atmel,at91rm9200-usart-serial" },
@@ -2684,25 +2680,19 @@ static int __init atmel_console_setup(struct console *co, char *options)static struct uart_driver atmel_uart; -static struct console atmel_console = { - .name =ATMEL_DEVICENAME , +static const struct console_operations atmel_cons_ops = { .write = atmel_console_write, .device = uart_console_device, .setup = atmel_console_setup, - .flags =CON_PRINTBUFFER , - .index =-1 , - .data = &atmel_uart, }; -#define ATMEL_CONSOLE_DEVICE (&atmel_console) -static inline bool atmel_is_console_port (struct uart_port *port) {return port->cons && port->cons->index == port->line; }#else -#define ATMEL_CONSOLE_DEVICE NULL +static const struct console_operations atmel_cons_ops;static inline bool atmel_is_console_port (struct uart_port *port) {
@@ -2717,7 +2707,6 @@ static struct uart_driver atmel_uart = { .major = SERIAL_ATMEL_MAJOR, .minor = MINOR_START, .nr = ATMEL_MAX_UART, - .cons = ATMEL_CONSOLE_DEVICE, };#ifdef CONFIG_PM
@@ -2933,7 +2922,7 @@ static int atmel_serial_probe(struct platform_device *pdev)#ifdef CONFIG_SERIAL_ATMEL_CONSOLE if (atmel_is_console_port (&atmel_port->uart) - &&ATMEL_CONSOLE_DEVICE ->flags &CON_ENABLED ) { + && atmel_uart.cons->flags &CON_ENABLED ) {/* * The serial core enabled the clock for us, so undo * the clk_prepare_enable() in atmel_console_setup()
@@ -3035,14 +3024,24 @@ static int __init atmel_serial_init(void) {int ret; - ret =uart_register_driver (&atmel_uart); + ret =uart_allocate_console_dfl (&atmel_uart, &atmel_cons_ops, +ATMEL_DEVICENAME , +SERIAL_ATMEL_CONSOLE );if (ret)return ret; + ret =uart_register_driver (&atmel_uart); +if (ret) + goto out; + ret =platform_driver_register (&atmel_serial_driver);if (ret) -uart_unregister_driver (&atmel_uart); + goto out_unregister; +out_unregister: +uart_unregister_driver (&atmel_uart); +out: +uart_put_console (&atmel_uart);return ret; }device_initcall (atmel_serial_init);
drivers/tty/serial/bcm63xx_uart.c +16 -9
@@ -752,19 +752,22 @@ static int bcm_console_setup(struct console *co, char *options)static struct uart_driver bcm_uart_driver; -static struct console bcm63xx_console = { - .name ="ttyS" , +static const struct console_operations bcm63xx_cons_ops = { .write = bcm_console_write, .device = uart_console_device, .setup = bcm_console_setup, - .flags =CON_PRINTBUFFER , - .index =-1 , - .data = &bcm_uart_driver, }; +static struct console __initdata *bcm63xx_console; +static int __init bcm63xx_console_init (void ) { -register_console (&bcm63xx_console); + bcm63xx_console =allocate_console_dfl (&bcm63xx_cons_ops,"ttyS" , + &bcm_uart_driver); +if (!bcm63xx_console) +return -ENOMEM ; + +register_console (bcm63xx_console);return 0 ; }
@@ -778,19 +781,23 @@ static void bcm_early_write(struct console *con, const char *s, unsigned n) wait_for_xmitr(&dev->port); } +static const struct console_operations bcm63xx_early_ops = { + .write = bcm_early_write, +}; +static int __init bcm_early_console_setup (struct earlycon_device *device,const char *opt) {if (!device->port.membase)return -ENODEV ; - device->con->write = bcm_early_write; + device->con->ops = &bcm63xx_early_ops;return 0 ; }OF_EARLYCON_DECLARE (bcm63xx_uart,"brcm,bcm6345-uart" , bcm_early_console_setup); -#define BCM63XX_CONSOLE (&bcm63xx_console) +#define BCM63XX_CONSOLE (bcm63xx_console)#else #define BCM63XX_CONSOLE NULL#endif /* CONFIG_SERIAL_BCM63XX_CONSOLE */
@@ -802,7 +809,6 @@ static struct uart_driver bcm_uart_driver = { .major = TTY_MAJOR, .minor = 64, .nr = BCM63XX_NR_UARTS, - .cons = BCM63XX_CONSOLE, };/*
@@ -902,6 +908,7 @@ static int __init bcm_uart_init(void) {int ret; + bcm_uart_driver.cons =BCM63XX_CONSOLE ; ret =uart_register_driver (&bcm_uart_driver);if (ret)return ret;
drivers/tty/serial/clps711x.c +9 -8
@@ -429,14 +429,14 @@ static int uart_clps711x_console_setup(struct console *co, char *options) SYSCON_UARTEN, SYSCON_UARTEN); } -static struct console clps711x_console = { - .name =UART_CLPS711X_DEVNAME , +static const struct console_operations clps711x_cons_ops = { .device = uart_console_device, .write = uart_clps711x_console_write, .setup = uart_clps711x_console_setup, - .flags =CON_PRINTBUFFER , - .index =-1 , }; + +#else +static const struct console_operations clps711x_cons_ops;#endif static int uart_clps711x_probe (struct platform_device *pdev)
@@ -553,10 +553,11 @@ static int __init uart_clps711x_init(void) {int ret; -#ifdef CONFIG_SERIAL_CLPS711X_CONSOLE - clps711x_uart.cons = &clps711x_console; - clps711x_console.data = &clps711x_uart; -#endif + ret =uart_allocate_console_dfl (&clps711x_uart, &clps711x_cons_ops, +UART_CLPS711X_DEVNAME , +SERIAL_CLPS711X_CONSOLE ); +if (ret) +return ret; ret =uart_register_driver (&clps711x_uart);if (ret)
drivers/tty/serial/cpm_uart/cpm_uart_core.c +11 -10
@@ -1363,27 +1363,29 @@ static int __init cpm_uart_console_setup(struct console *co, char *options) }static struct uart_driver cpm_reg; -static struct console cpm_scc_uart_console = { - .name ="ttyCPM" , + +static const struct console_operations cpm_scc_cons_ops = { .write = cpm_uart_console_write, .device = uart_console_device, .setup = cpm_uart_console_setup, - .flags =CON_PRINTBUFFER , - .index =-1 , - .data = &cpm_reg, };static int __init cpm_uart_console_init (void ) { -register_console (&cpm_scc_uart_console); +struct console *cpm_scc_uart_console; + + cpm_scc_uart_console =allocate_console_dfl (&cpm_scc_cons_ops,"ttyCPM" , + &cpm_reg); +if (!cpm_scc_uart_console) +return -ENOMEM ; + + cpm_reg->cons = cpm_scc_uart_console; +register_console (cpm_scc_uart_console);return 0 ; }console_initcall (cpm_uart_console_init); -#define CPM_UART_CONSOLE &cpm_scc_uart_console -#else -#define CPM_UART_CONSOLE NULL#endif static struct uart_driver cpm_reg = {
@@ -1392,7 +1394,6 @@ static struct uart_driver cpm_reg = { .dev_name = "ttyCPM", .major = SERIAL_CPM_MAJOR, .minor = SERIAL_CPM_MINOR, - .cons = CPM_UART_CONSOLE, .nr = UART_NR, };
drivers/tty/serial/digicolor-usart.c +11 -13
@@ -431,21 +431,18 @@ static int digicolor_uart_console_setup(struct console *co, char *options)return uart_set_options (port, co, baud, parity, bits, flow); } -static struct console digicolor_console = { - .name ="ttyS" , - .device = uart_console_device, - .write = digicolor_uart_console_write, - .setup = digicolor_uart_console_setup, - .flags =CON_PRINTBUFFER , - .index =-1 , -}; -static struct uart_driver digicolor_uart = { .driver_name ="digicolor-usart" , .dev_name ="ttyS" , .nr =DIGICOLOR_USART_NR , }; +static const struct console_operations digicolor_cons_ops = { + .device = uart_console_device, + .write = digicolor_uart_console_write, + .setup = digicolor_uart_console_setup, +}; +static int digicolor_uart_probe (struct platform_device *pdev) {struct device_node *np = pdev->dev.of_node;
@@ -532,10 +529,11 @@ static int __init digicolor_uart_init(void) {int ret; -if (IS_ENABLED (CONFIG_SERIAL_CONEXANT_DIGICOLOR_CONSOLE )) { - digicolor_uart.cons = &digicolor_console; - digicolor_console.data = &digicolor_uart; - } + ret =uart_allocate_console_dfl (&digicolor_uart, &digicolor_cons_ops, +"ttyS" , +SERIAL_CONEXANT_DIGICOLOR_CONSOLE ); +if (ret) +return ret; ret =uart_register_driver (&digicolor_uart);if (ret)
drivers/tty/serial/dz.c +11 -7
@@ -887,19 +887,23 @@ static int __init dz_console_setup(struct console *co, char *options) }static struct uart_driver dz_reg; -static struct console dz_console = { - .name ="ttyS" , + +static const struct console_operations dz_cons_ops = { .write = dz_console_print, .device = uart_console_device, .setup = dz_console_setup, - .flags =CON_PRINTBUFFER , - .index =-1 , - .data = &dz_reg, }; +static struct console __initdata *dz_console; +static int __init dz_serial_console_init (void ) {if (!IOASIC ) { + dz_console =allocate_console_dfl (&dz_cons_ops,"ttyS" , + &dz_reg); +if (!dz_console) +return -ENOMEM ; +dz_init_ports ();register_console (&dz_console);return 0 ;
@@ -909,7 +913,7 @@ static int __init dz_serial_console_init(void)console_initcall (dz_serial_console_init); -#define SERIAL_DZ_CONSOLE &dz_console +#define SERIAL_DZ_CONSOLE (dz_console)#else #define SERIAL_DZ_CONSOLE NULL#endif /* CONFIG_SERIAL_DZ_CONSOLE */
@@ -921,7 +925,6 @@ static struct uart_driver dz_reg = { .major = TTY_MAJOR, .minor = 64, .nr = DZ_NB_PORT, - .cons = SERIAL_DZ_CONSOLE, };static int __init dz_init (void )
@@ -935,6 +938,7 @@ static int __init dz_init(void)dz_init_ports (); + dz_reg.cons =SERIAL_DZ_CONSOLE ; ret =uart_register_driver (&dz_reg);if (ret)return ret;
drivers/tty/serial/earlycon-arm-semihost.c +5 -1
@@ -42,10 +42,14 @@ static void smh_write(struct console *con, const char *s, unsigned n)uart_console_write (&dev->port, s, n, smh_putc); } +static const struct console_operations smh_early_cons_ops = { + .write = smh_write, +}; +static int __init early_smh_setup (struct earlycon_device *device,const char *opt) { - device->con->write = smh_write; + device->con->ops = &smh_early_cons_ops;return 0 ; }EARLYCON_DECLARE (smh, early_smh_setup);
drivers/tty/serial/earlycon.c +3 -2
@@ -30,6 +30,7 @@ static struct console early_con = { .name = "uart", /* fixed up at earlycon registration */ .flags = CON_PRINTBUFFER | CON_BOOT, .index = 0, + .is_static = 1, };static struct earlycon_device early_console_dev = {
@@ -142,7 +143,7 @@ static int __init register_earlycon(char *buf, const struct earlycon_id *match) err = match->setup (&early_console_dev, buf);if (err <0 )return err; -if (!early_console_dev.con->write) +if (!early_console_dev.con->ops || !early_console_dev.con->ops->write)return -ENODEV ;register_console (early_console_dev.con);
@@ -293,7 +294,7 @@ int __init of_setup_earlycon(const struct earlycon_id *match, err = match->setup (&early_console_dev, options);if (err <0 )return err; -if (!early_console_dev.con->write) +if (!early_console_dev.con->ops || !early_console_dev.con->ops->write)return -ENODEV ;
drivers/tty/serial/efm32-uart.c +14 -8
@@ -639,18 +639,14 @@ static int efm32_uart_console_setup(struct console *co, char *options)static struct uart_driver efm32_uart_reg; -static struct console efm32_uart_console = { - .name =DEV_NAME , +static const struct console_operations efm32_cons_ops = { .write = efm32_uart_console_write, .device = uart_console_device, .setup = efm32_uart_console_setup, - .flags =CON_PRINTBUFFER , - .index =-1 , - .data = &efm32_uart_reg, };#else -#define efm32_uart_console (*(struct console *)NULL) +static const struct console_operations efm32_cons_ops;#endif /* ifdef CONFIG_SERIAL_EFM32_UART_CONSOLE / else */ static struct uart_driver efm32_uart_reg = {
@@ -828,16 +824,26 @@ static int __init efm32_uart_init(void) {int ret; - ret =uart_register_driver (&efm32_uart_reg); + ret =uart_allocate_console_dfl (&efm32_uart_reg, &efm32_cons_ops, +DEV_NAME ,SERIAL_EFM32_UART_CONSOLE );if (ret)return ret; + ret =uart_register_driver (&efm32_uart_reg); +if (ret) + goto out; + ret =platform_driver_register (&efm32_uart_driver);if (ret) -uart_unregister_driver (&efm32_uart_reg); + goto out_unregister;pr_info ("EFM32 UART/USART driver\n" ); +return 0 ; +out_unregister: +uart_unregister_driver (&efm32_uart_reg); +out: +uart_put_console (&efm32_uart_reg);return ret; }module_init (efm32_uart_init);
drivers/tty/serial/fsl_lpuart.c +29 -28
141 lines not on this page · raw message
drivers/tty/serial/imx.c +22 -13
@@ -2071,18 +2071,13 @@ imx_uart_console_setup(struct console *co, char *options) }static struct uart_driver imx_uart_uart_driver; -static struct console imx_uart_console = { - .name =DEV_NAME , + +static const struct console_operations imx_cons_ops = { .write = imx_uart_console_write, .device = uart_console_device, .setup = imx_uart_console_setup, - .flags =CON_PRINTBUFFER , - .index =-1 , - .data = &imx_uart_uart_driver, }; -#define IMX_CONSOLE &imx_uart_console -#ifdef CONFIG_OF static void imx_uart_console_early_putchar (struct uart_port *port,int ch) {
@@ -2102,14 +2097,17 @@ static void imx_uart_console_early_write(struct console *con, const char *s,uart_console_write (&dev->port, s, count, imx_uart_console_early_putchar); } +static const struct console_operations imx_early_cons_ops = { + .write = imx_uart_console_early_write, +}; +static int __init imx_console_early_setup (struct earlycon_device *dev,const char *opt) {if (!dev->port.membase)return -ENODEV ; - dev->con->write = imx_uart_console_early_write; - + dev->con->ops = &imx_early_cons_ops;return 0 ; }OF_EARLYCON_DECLARE (ec_imx6q,"fsl,imx6q-uart" , imx_console_early_setup);
@@ -2117,7 +2115,7 @@ OF_EARLYCON_DECLARE(ec_imx21, "fsl,imx21-uart", imx_console_early_setup);#endif #else -#define IMX_CONSOLE NULL +static const struct console_operations imx_cons_ops;#endif static struct uart_driver imx_uart_uart_driver = {
@@ -2127,7 +2125,6 @@ static struct uart_driver imx_uart_uart_driver = { .major = SERIAL_IMX_MAJOR, .minor = MINOR_START, .nr = ARRAY_SIZE(imx_uart_ports), - .cons = IMX_CONSOLE, };#ifdef CONFIG_OF
@@ -2553,15 +2550,27 @@ static struct platform_driver imx_uart_platform_driver = {static int __init imx_uart_init (void ) { -int ret =uart_register_driver (&imx_uart_uart_driver); +int ret; + ret =uart_allocate_console_dfl (&imx_uart_uart_driver, &imx_cons_ops, +DEV_NAME ,SERIAL_IMX_CONSOLE );if (ret)return ret; + ret =uart_register_driver (&imx_uart_uart_driver); +if (ret) + goto out; + ret =platform_driver_register (&imx_uart_platform_driver);if (ret !=0 ) -uart_unregister_driver (&imx_uart_uart_driver); + goto out_unregister; + +return 0 ; +out_unregister: +uart_unregister_driver (&imx_uart_uart_driver); +out: +uart_put_console (&imx_uart_uart_driver);return ret; }
drivers/tty/serial/ip22zilog.c +10 -8
@@ -1055,15 +1055,14 @@ static int __init ip22zilog_console_setup(struct console *con, char *options)static struct uart_driver ip22zilog_reg; -static struct console ip22zilog_console = { - .name ="ttyS" , +static const struct console_operations ip22zilog_cons_ops = { .write = ip22zilog_console_write, .device = uart_console_device, .setup = ip22zilog_console_setup, - .flags =CON_PRINTBUFFER , - .index =-1 , - .data = &ip22zilog_reg, };
Lines of this file are not shown. View the raw message.
drivers/tty/serial/mux.c +30 -14
44 lines not on this page · raw message
drivers/tty/serial/qcom_geni_serial.c +21 -36
57 lines not on this page · raw message
drivers/tty/serial/samsung.c +30 -11
41 lines not on this page · raw message
drivers/tty/serial/sh-sci.c +35 -20
55 lines not on this page · raw message
drivers/tty/serial/xilinx_uartps.c +20 -22
42 lines not on this page · raw message
drivers/usb/gadget/function/u_serial.c +13 -9
Lines of this file are not shown. View the raw message.
kernel/printk/printk.c +95 -19
114 lines not on this page · raw message
The rest of this diff is not shown. View the raw message.
Signature · 1 line
2.17.1
Part of the diff is not shown here. View the raw message.
John Ogness
maintainerRe: [PATCH 3/4] printk: Add consoles to a virtual "console" bus
Quoted 2 lines · Calvin Owens
This patch embeds a device struct in the console struct, and registers them on a "console" bus so we can expose attributes in sysfs.
I expect that "class" would be more appropriate than "bus". These devices really are grouped together based on their function and not the medium by which they are accessed.
John Ogness
Petr Mladek
maintainerRe: [PATCH 3/4] printk: Add consoles to a virtual "console" bus
Quoted 7 lines · John Ogness
Quoted 2 lines · Calvin Owens
This patch embeds a device struct in the console struct, and registers them on a "console" bus so we can expose attributes in sysfs.
I expect that "class" would be more appropriate than "bus". These devices really are grouped together based on their function and not the medium by which they are accessed.
Good point. "class" looks better to me as well.
Greg, any opinion, where to put the entries for struct console ?
Best Regards,
Petr
Greg Kroah-Hartman
maintainerRe: [PATCH 3/4] printk: Add consoles to a virtual "console" bus
Quoted 5 lines · Petr Mladek
Quoted 4 lines · John Ogness
Quoted 2 lines · Calvin Owens
This patch embeds a device struct in the console struct, and registers them on a "console" bus so we can expose attributes in sysfs.
Quoted 7 lines
Quoted 3 lines
I expect that "class" would be more appropriate than "bus". These devices really are grouped together based on their function and not the medium by which they are accessed.
Good point. "class" looks better to me as well.
Greg, any opinion, where to put the entries for struct console ?
Hang them off of the device that the console belongs to?
Classes and busses are almost identical except:
- busses is the binding of a driver to a device (usb, pci, etc.)
- classes are usually userspace interactions to a device (input, tty, etc.)
So this sounds like a class to me.
If you want me to review this, I'll be glad to so do once 5.1-rc1 is out...
thanks,
greg k-h
Re: [PATCH 3/4] printk: Add consoles to a virtual "console" bus
Quoted 14 lines · Greg Kroah-Hartman
Quoted 5 lines · Petr Mladek
Quoted 4 lines · John Ogness
Quoted 2 lines · Calvin Owens
This patch embeds a device struct in the console struct, and registers them on a "console" bus so we can expose attributes in sysfs.
Quoted 7 lines
Quoted 3 lines
I expect that "class" would be more appropriate than "bus". These devices really are grouped together based on their function and not the medium by which they are accessed.
Good point. "class" looks better to me as well.
Greg, any opinion, where to put the entries for struct console ?
Quoted 8 lines
Hang them off of the device that the console belongs to?
Classes and busses are almost identical except:
- busses is the binding of a driver to a device (usb, pci, etc.)
- classes are usually userspace interactions to a device (input, tty, etc.)So this sounds like a class to me.
Sounds good, will make it a class.
Quoted 2 lines
If you want me to review this, I'll be glad to so do once 5.1-rc1 is out...
Yeah, I realized after sending this the timing was pretty terrible, I'll wait for 5.1-rc1 before rebasing/resending.
Thanks,
Calvin
Quoted 3 lines
thanks,
greg k-h
Petr Mladek
maintainerRe: [PATCH 3/4] printk: Add consoles to a virtual "console" bus
In reply to Calvin OwensQuoted 7 lines · Calvin Owens
This patch embeds a device struct in the console struct, and registers them on a "console" bus so we can expose attributes in sysfs.
Early console structures must still be static, since they're required before we're able to allocate memory. The least ugly way I can come up with to handle this is an "
is_static" flag in the structure which makes the gets and puts NOPs, and is checked in ->release() to catch mistakes.
I wonder if it might get detected by is_kernel_inittext().
Best Regards,
Petr
Re: [PATCH 3/4] printk: Add consoles to a virtual "console" bus
Quoted 10 lines · Petr Mladek
Quoted 7 lines · Calvin Owens
This patch embeds a device struct in the console struct, and registers them on a "console" bus so we can expose attributes in sysfs.
Early console structures must still be static, since they're required before we're able to allocate memory. The least ugly way I can come up with to handle this is an "
is_static" flag in the structure which makes the gets and puts NOPs, and is checked in ->release() to catch mistakes.I wonder if it might get detected by
is_kernel_inittext().
I don't think inittext() in particular would work, since these actually need to exist forever if you pass "earlyprintk=[...],keep" so they aren't __init.
But I bet you're right that we could catch the static case without needing the explicit flag, something like is_module_address() (but it would also need to work for the built-in case). I'll see if I can get this to work.
Thanks,
Calvin
Quoted 2 lines
Best Regards,
Petr
Petr Mladek
maintainerRe: [PATCH 3/4] printk: Add consoles to a virtual "console" bus
In reply to Calvin OwensQuoted 22 lines · Calvin Owens
This patch embeds a device struct in the console struct, and registers them on a "console" bus so we can expose attributes in sysfs.
Currently, most drivers declare static console structs, and that is incompatible with the dev refcount model. So we end up needing to patch all of the console drivers to:
1. Dynamically allocate the console struct using a new helper
2. Handle the allocation in (1) possibly failing
3. Dispose of (1) withput_device()Early console structures must still be static, since they're required before we're able to allocate memory. The least ugly way I can come up with to handle this is an "
is_static" flag in the structure which makes the gets and puts NOPs, and is checked in ->release() to catch mistakes.drivers/char/lp.c +0
-0@@ -857,12 +857,12 @@ static void lp_console_write(struct console *co, const char *s,parport_release (dev);
drivers/char/lp.c static void lp_console_write(struct console *co, const char *s, · line 864
Quoted 10 lines
drivers/char/lp.c +2
-3} -static struct console lpcons = { - .name ="lp" , +static const struct console_operations lp_cons_ops = { .write = lp_console_write, - .flags =CON_PRINTBUFFER , }; +static struct console *lpcons;
I have got the following compilation error (see below):
CC drivers/char/lp.odrivers/char/lp.c: In function ‘lp_register’:drivers/char/lp.c:925:2: error: ‘lpcons’ undeclared (first use in this function)
lpcons = allocate_console_dfl(&lp_cons_ops, "lp", NULL);
^drivers/char/lp.c:925:2: note: each undeclared identifier is reported only once for each function it appears in In file included from drivers/char/lp.c:125:0:drivers/char/lp.c:925:33: error: ‘lp_cons_ops’ undeclared (first use in this function)
drivers/char/lp.c static int lp_register(int nr, struct parport *port) · line 927
Quoted 11 lines
drivers/char/lp.c +4
-0#endif /* console on line printer */ /* --- initialisation code ------------------------------------- */ @@ -921,6 +921,11 @@ static int lp_register(int nr, struct parport *port) &ppdev_cb, nr);if (lp_table[nr].dev ==NULL )return 1 ; + + lpcons =allocate_console_dfl (&lp_cons_ops,"lp" ,NULL ); +if (!lpcons) +return -ENOMEM ;
This should be done inside #ifdef CONFIG_LP_CONSOLE to avoid the above compilation error.
Quoted 4 lines
drivers/char/lp.c +1
-0+ lp_table[nr].flags |=LP_EXIST ;if (reset)
[...]
Quoted 71 lines
include/linux/console.h +33
-2@@ -142,20 +143,28 @@ static inline int con_debug_leave(void)#define CON_BRL (32)/* Used for a braille device */ #define CON_EXTENDED (64)/* Use the extended output format a la /dev/kmsg */ -struct console { -char name[16 ]; +struct console ; + +struct console_operations {void (*write)(struct console *,const char *,unsigned );int (*read)(struct console *,char *,unsigned );struct tty_driver *(*device)(struct console *,int *);void (*unblank)(void );int (*setup)(struct console *,char *);int (*match)(struct console *,char *name,int idx,char *options); +}; + +struct console { +char name[16 ];short flags;short index;int cflag;void *data;struct console *next;int level; +const struct console_operations *ops; +struct device dev; +int is_static; };/* @@ -167,6 +176,29 @@ struct console {extern int console_set_on_cmdline;extern struct console *early_console; +extern struct console *allocate_console (const struct console_operations *ops, +const char *name,short flags, +short index,void *data); + +#define allocate_console_dfl (ops, name, data) \ + allocate_console(ops, name, CON_PRINTBUFFER, -1, data) + +/* +* Helpers for get/put that do the right thing for static early consoles. +*/ + +#define get_console (con) \ +do { \ + if (!con->is_static) \ + get_device(&(con)->dev); \ +} while (0) + +#define put_console (con) \ +do { \ + if (con && !con->is_static) \ + put_device(&((struct console *)con)->dev); \ +} while (0) +extern int add_preferred_console (char *name,int idx,char *options);extern void register_console (struct console *);extern int unregister_console (struct console *);include/linux/serial_core.h +0
-0@@ -426,6 +426,25 @@ int uart_add_one_port(struct uart_driver *reg, struct uart_port *port);int uart_remove_one_port (struct uart_driver *reg,struct uart_port *port);
include/linux/serial_core.h int uart_add_one_port(struct uart_driver *reg, struct uart_port *port); · line 436
Quoted 10 lines
include/linux/serial_core.h +8
-0int uart_match_port (struct uart_port *port1,struct uart_port *port2); +/* +* This ugliness removes the need for #ifdef boilerplate in UART drivers which +* allow their console functionality to be disabled via Kconfig. +*/ +#define uart_allocate_console (drv, ops, name, flags, idx, kcfg) \ +({ \ + int __retval = 0; \ + if (IS_ENABLED(CONFIG_##kcfg)) { \
I wonder if it is worth it. I do not see much existing #ifdef's removed by this patch. I would expect that the code is never called when the driver is disabled in Kconfig.
IMHO, such a trick hidden in a macro could cause more confusion than good.
Quoted 122 lines
include/linux/serial_core.h +11
-0+ (drv)->cons =allocate_console (ops, name, flags, idx, drv); \ + __retval = (drv)->cons ?0 : -ENOMEM ; \ + } \ + __retval; \ +}) + +#define uart_allocate_console_dfl (drv, ops, name, kcfg) \ + uart_allocate_console(drv, ops, name, CON_PRINTBUFFER, -1, kcfg) + +#define uart_put_console (drv) put_console((drv)->cons) +/* * Power Management */ kernel/printk/printk.c +48
-8@@ -108,6 +108,8 @@ enum devkmsg_log_masks {static unsigned int __read_mostly devkmsg_log =DEVKMSG_LOG_MASK_DEFAULT ; +static int printk_late_done; +static int __control_devkmsg (char *str) {if (!str)@@ -1731,7 +1733,7 @@ static void call_console_drivers(const char *ext_text, size_t ext_len,continue ;if (!(con->flags &CON_ENABLED ))continue ; -if (!con->write) +if (!con->ops->write)continue ;if (!cpu_online (smp_processor_id ()) && !(con->flags &CON_ANYTIME ))@@ -1739,9 +1741,9 @@ static void call_console_drivers(const char *ext_text, size_t ext_len,if (suppress_message_printing (level, con))continue ;if (con->flags &CON_EXTENDED ) - con->write (con, ext_text, ext_len); + con->ops->write (con, ext_text, ext_len);else - con->write (con, text, len); + con->ops->write (con, text, len); } }@@ -2052,7 +2054,7 @@ asmlinkage __visible void early_printk(const char *fmt, ...) n =vscnprintf (buf,sizeof (buf), fmt, ap);va_end (ap); - early_console->write(early_console, buf, n); + early_console->ops->write(early_console, buf, n); }#endif @@ -2481,8 +2483,8 @@ void console_unblank(void) console_locked =1 ; console_may_schedule =0 ;for_each_console (c) -if ((c->flags &CON_ENABLED ) && c->unblank) - c->unblank (); +if ((c->flags &CON_ENABLED ) && c->ops->unblank) + c->ops->unblank ();console_unlock (); }@@ -2515,9 +2517,9 @@ struct tty_driver *console_device(int *index)console_lock ();for_each_console (c) { -if (!c->device) +if (!c->ops->device)continue ; - driver = c->device (c, index); + driver = c->ops->device (c, index);if (driver)break ; }@@ -2558,6 +2560,68 @@ static int __init keep_bootcon_setup(char *str)early_param ("keep_bootcon" , keep_bootcon_setup); +static struct bus_type console_subsys = { + .name ="console" , +}; + +static void console_release (struct device *dev) +{ + struct console *con = container_of(dev, struct console, dev); + +if (WARN (con->is_static,"Freeing static early console!\n" )) +return ; + +if (WARN (con->flags &CON_ENABLED ,"Freeing running console!\n" )) +return ; + +pr_info ("Freeing console %s\n" , con->name); +kfree (con); +} + +static void console_init_device (struct console *con) +{ +device_initialize (&con->dev); +dev_set_name (&con->dev,"%s" , con->name); + con->dev.release = console_release; +} + +static void console_register_device (struct console *new) +{ +/* +* We might be called very early from register_console(): in that case, +* printk_late_init() will take care of this later. +*/ +if (!printk_late_done) +return ; + +if (new->is_static) +console_init_device (new); + + new->dev.bus = &console_subsys;
kernel/printk/printk.c static int __init keep_bootcon_setup(char *str) · line 2610
Quoted 10 lines
kernel/printk/printk.c +10
-0+WARN_ON (device_add (&new->dev)); +} + +struct console *allocate_console (const struct console_operations *ops, +const char *name,short flags,short index, +void *data) +{ +struct console *new; + + new =kzalloc (sizeof (*new),GFP_KERNEL );
I have just realized that page_alloc_init() is called before parse_early_param(). Therefore we should be able to use memblock_alloc() for early consoles and reduce problems with static structures.
kernel/printk/printk.c static int __init keep_bootcon_setup(char *str) · line 2620
Quoted 10 lines
kernel/printk/printk.c +10
-0+if (!new) +return NULL ; + + new->ops = ops; +strscpy (new->name, name,sizeof (new->name)); + new->flags = flags; + new->index = index; + new->data = data; + +console_init_device (new);
This is a side effect that I would not expect from a function called alloc*(). I would rename:
s/allocate_console/create_console/ or
s/allocate_console/init_console/
Quoted 8 lines
kernel/printk/printk.c +4
-0+return new; +} +EXPORT_SYMBOL_GPL (allocate_console); +/* * The console driver calls this routine during kernel initialization * to register the console printing procedure with printk() and to
kernel/printk/printk.c void register_console(struct console *newcon) · line 2692
Quoted 10 lines
kernel/printk/printk.c +3
-3@@ -2622,10 +2686,10 @@ void register_console(struct console *newcon)if (!has_preferred) {if (newcon->index <0 ) newcon->index =0 ; -if (newcon->setup ==NULL || - newcon->setup (newcon,NULL ) ==0 ) { +if (newcon->ops->setup ==NULL || + newcon->ops->setup (newcon,NULL ) ==0 ) { newcon->flags |=CON_ENABLED ; -if (newcon->device) { +if (newcon->ops->device) {
There might be confusion why we need two devices (con->dev and con->ops->device).
I would rename con->ops->device to con->ops->tty_dev.
Quoted 35 lines
kernel/printk/printk.c +6
-4newcon->flags |=CON_CONSDEV ; has_preferred = true; }@@ -2639,8 +2703,8 @@ void register_console(struct console *newcon)for (i =0 , c = console_cmdline; i <MAX_CMDLINECONSOLES && c->name[0 ]; i++, c++) { -if (!newcon->match || - newcon->match (newcon, c->name, c->index, c->options) !=0 ) { +if (!newcon->ops->match || + newcon->ops->match (newcon, c->name, c->index, c->options) !=0 ) {/* default matching */ BUILD_BUG_ON (sizeof (c->name) !=sizeof (newcon->name));if (strcmp (c->name, newcon->name) !=0 )@@ -2660,8 +2724,8 @@ void register_console(struct console *newcon)if (_braille_register_console (newcon, c))return ; -if (newcon->setup && - newcon->setup (newcon, c->options) !=0 ) +if (newcon->ops->setup && + newcon->ops->setup (newcon, c->options) !=0 )break ; }@@ -2706,6 +2770,8 @@ void register_console(struct console *newcon) console_drivers->next = newcon; } +get_console (newcon); +if (newcon->flags &CON_EXTENDED ) nr_ext_console_drivers++;
kernel/printk/printk.c void register_console(struct console *newcon) · line 2799
Quoted 4 lines
kernel/printk/printk.c +1
-0@@ -2730,6 +2796,7 @@ void register_console(struct console *newcon) exclusive_console_stop_seq = console_seq;logbuf_unlock_irqrestore (flags); } +console_register_device (newcon);
This calls console_init_device() for the statically defined early consoles. I guess that it would invalidate the above get_console().
Also it is not symmetric with unregister_console(). We add it to the console_subsys here and did not remove it when the console is unregistered.
IMHO, this might be done already in allocate_console(). And eventually in printk_late_init() for consoles that are allocated earlier.
I am not familiar with the device-related sysfs API. But I see that device_initialize() and device_add() can be done by device_register(). The separate calls are needed only when a special reference handling is needed. Are we special?
Anyway, please, try to describe the expected workflow in the commit description:
+ where the structure should get allocated
+ when it is added to the sysfs hierarchy
+ what happens when the console gets registered and unregistered
+ when it is removed from the sysfs hierarchy
+ when the structure is released/freed
+ What is needed to get the console registered and unregistered repeatedly on a running system
Finally, we might want to show state of the CON_ENABLED flag in sysfs to distinguish the currently used consoles.
kernel/printk/printk.c void register_console(struct console *newcon) · line 2801
Quoted 2 lines
kernel/printk/printk.c +0
-0console_unlock ();console_sysfs_notify ();
Thanks a lot for working on this. I know that it is not easy. But it is really appreciated.
Best Regards,
Petr
Re: [PATCH 3/4] printk: Add consoles to a virtual "console" bus
Quoted 36 lines · Petr Mladek
Quoted 22 lines · Calvin Owens
This patch embeds a device struct in the console struct, and registers them on a "console" bus so we can expose attributes in sysfs.
Currently, most drivers declare static console structs, and that is incompatible with the dev refcount model. So we end up needing to patch all of the console drivers to:
1. Dynamically allocate the console struct using a new helper
2. Handle the allocation in (1) possibly failing
3. Dispose of (1) withput_device()Early console structures must still be static, since they're required before we're able to allocate memory. The least ugly way I can come up with to handle this is an "
is_static" flag in the structure which makes the gets and puts NOPs, and is checked in ->release() to catch mistakes.drivers/char/lp.c +0
-0@@ -857,12 +857,12 @@ static void lp_console_write(struct console *co, const char *s,parport_release (dev);drivers/char/lp.c static void lp_console_write(struct console *co, const char *s, · line 864
Quoted 10 lines
drivers/char/lp.c +2
-3} -static struct console lpcons = { - .name ="lp" , +static const struct console_operations lp_cons_ops = { .write = lp_console_write, - .flags =CON_PRINTBUFFER , }; +static struct console *lpcons;I have got the following compilation error (see below):
Quoted 8 lines
CC
drivers/char/lp.odrivers/char/lp.c: In function ‘lp_register’:drivers/char/lp.c:925:2: error: ‘lpcons’ undeclared (first use in this function)
lpcons =allocate_console_dfl(&lp_cons_ops, "lp", NULL);
^drivers/char/lp.c:925:2: note: each undeclared identifier is reported only once for each function it appears in In file included fromdrivers/char/lp.c:125:0:drivers/char/lp.c:925:33: error: ‘lp_cons_ops’ undeclared (first use in this function)
D'oh, will fix.
Quoted 108 lines
drivers/char/lp.c static int lp_register(int nr, struct parport *port) · line 927
Quoted 12 lines
drivers/char/lp.c +4
-0#endif /* console on line printer */ /* --- initialisation code ------------------------------------- */ @@ -921,6 +921,11 @@ static int lp_register(int nr, struct parport *port) &ppdev_cb, nr);if (lp_table[nr].dev ==NULL )return 1 ; + + lpcons =allocate_console_dfl (&lp_cons_ops,"lp" ,NULL ); +if (!lpcons) +return -ENOMEM ;This should be done inside #ifdef
CONFIG_LP_CONSOLEto avoid the above compilation error.Quoted 4 lines
drivers/char/lp.c +1
-0+ lp_table[nr].flags |=LP_EXIST ;if (reset)[...]
Quoted 71 lines
include/linux/console.h +33
-2@@ -142,20 +143,28 @@ static inline int con_debug_leave(void)#define CON_BRL (32)/* Used for a braille device */ #define CON_EXTENDED (64)/* Use the extended output format a la /dev/kmsg */ -struct console { -char name[16 ]; +struct console ; + +struct console_operations {void (*write)(struct console *,const char *,unsigned );int (*read)(struct console *,char *,unsigned );struct tty_driver *(*device)(struct console *,int *);void (*unblank)(void );int (*setup)(struct console *,char *);int (*match)(struct console *,char *name,int idx,char *options); +}; + +struct console { +char name[16 ];short flags;short index;int cflag;void *data;struct console *next;int level; +const struct console_operations *ops; +struct device dev; +int is_static; };/* @@ -167,6 +176,29 @@ struct console {extern int console_set_on_cmdline;extern struct console *early_console; +extern struct console *allocate_console (const struct console_operations *ops, +const char *name,short flags, +short index,void *data); + +#define allocate_console_dfl (ops, name, data) \ + allocate_console(ops, name, CON_PRINTBUFFER, -1, data) + +/* +* Helpers for get/put that do the right thing for static early consoles. +*/ + +#define get_console (con) \ +do { \ + if (!con->is_static) \ + get_device(&(con)->dev); \ +} while (0) + +#define put_console (con) \ +do { \ + if (con && !con->is_static) \ + put_device(&((struct console *)con)->dev); \ +} while (0) +extern int add_preferred_console (char *name,int idx,char *options);extern void register_console (struct console *);extern int unregister_console (struct console *);include/linux/serial_core.h +0
-0@@ -426,6 +426,25 @@ int uart_add_one_port(struct uart_driver *reg, struct uart_port *port);int uart_remove_one_port (struct uart_driver *reg,struct uart_port *port);include/linux/serial_core.h int uart_add_one_port(struct uart_driver *reg, struct uart_port *port); · line 436
Quoted 10 lines
include/linux/serial_core.h +8
-0int uart_match_port (struct uart_port *port1,struct uart_port *port2); +/* +* This ugliness removes the need for #ifdef boilerplate in UART drivers which +* allow their console functionality to be disabled via Kconfig. +*/ +#define uart_allocate_console (drv, ops, name, flags, idx, kcfg) \ +({ \ + int __retval = 0; \ + if (IS_ENABLED(CONFIG_##kcfg)) { \I wonder if it is worth it. I do not see much existing #ifdef's removed by this patch. I would expect that the code is never called when the driver is disabled in
Kconfig.
Quoted 2 lines
IMHO, such a trick hidden in a macro could cause more confusion than good.
Yeah... I wasn't really sure about this either, I don't disagree that it's marginally evil.
Quoted 130 lines
Quoted 130 lines
include/linux/serial_core.h +11
-0+ (drv)->cons =allocate_console (ops, name, flags, idx, drv); \ + __retval = (drv)->cons ?0 : -ENOMEM ; \ + } \ + __retval; \ +}) + +#define uart_allocate_console_dfl (drv, ops, name, kcfg) \ + uart_allocate_console(drv, ops, name, CON_PRINTBUFFER, -1, kcfg) + +#define uart_put_console (drv) put_console((drv)->cons) +/* * Power Management */ kernel/printk/printk.c +55
-8@@ -108,6 +108,8 @@ enum devkmsg_log_masks {static unsigned int __read_mostly devkmsg_log =DEVKMSG_LOG_MASK_DEFAULT ; +static int printk_late_done; +static int __control_devkmsg (char *str) {if (!str)@@ -1731,7 +1733,7 @@ static void call_console_drivers(const char *ext_text, size_t ext_len,continue ;if (!(con->flags &CON_ENABLED ))continue ; -if (!con->write) +if (!con->ops->write)continue ;if (!cpu_online (smp_processor_id ()) && !(con->flags &CON_ANYTIME ))@@ -1739,9 +1741,9 @@ static void call_console_drivers(const char *ext_text, size_t ext_len,if (suppress_message_printing (level, con))continue ;if (con->flags &CON_EXTENDED ) - con->write (con, ext_text, ext_len); + con->ops->write (con, ext_text, ext_len);else - con->write (con, text, len); + con->ops->write (con, text, len); } }@@ -2052,7 +2054,7 @@ asmlinkage __visible void early_printk(const char *fmt, ...) n =vscnprintf (buf,sizeof (buf), fmt, ap);va_end (ap); - early_console->write(early_console, buf, n); + early_console->ops->write(early_console, buf, n); }#endif @@ -2481,8 +2483,8 @@ void console_unblank(void) console_locked =1 ; console_may_schedule =0 ;for_each_console (c) -if ((c->flags &CON_ENABLED ) && c->unblank) - c->unblank (); +if ((c->flags &CON_ENABLED ) && c->ops->unblank) + c->ops->unblank ();console_unlock (); }@@ -2515,9 +2517,9 @@ struct tty_driver *console_device(int *index)console_lock ();for_each_console (c) { -if (!c->device) +if (!c->ops->device)continue ; - driver = c->device (c, index); + driver = c->ops->device (c, index);if (driver)break ; }@@ -2558,6 +2560,68 @@ static int __init keep_bootcon_setup(char *str)early_param ("keep_bootcon" , keep_bootcon_setup); +static struct bus_type console_subsys = { + .name ="console" , +}; + +static void console_release (struct device *dev) +{ + struct console *con = container_of(dev, struct console, dev); + +if (WARN (con->is_static,"Freeing static early console!\n" )) +return ; + +if (WARN (con->flags &CON_ENABLED ,"Freeing running console!\n" )) +return ; + +pr_info ("Freeing console %s\n" , con->name); +kfree (con); +} + +static void console_init_device (struct console *con) +{ +device_initialize (&con->dev); +dev_set_name (&con->dev,"%s" , con->name); + con->dev.release = console_release; +} + +static void console_register_device (struct console *new) +{ +/* +* We might be called very early from register_console(): in that case, +* printk_late_init() will take care of this later. +*/ +if (!printk_late_done) +return ; + +if (new->is_static) +console_init_device (new); + + new->dev.bus = &console_subsys; +WARN_ON (device_add (&new->dev)); +} + +struct console *allocate_console (const struct console_operations *ops, +const char *name,short flags,short index, +void *data) +{
Quoted 8 lines
kernel/printk/printk.c static int __init keep_bootcon_setup(char *str) · line 2610
Quoted 3 lines
kernel/printk/printk.c +3
-0+struct console *new; + + new =kzalloc (sizeof (*new),GFP_KERNEL );I have just realized that
page_alloc_init()is called beforeparse_early_param(). Therefore we should be able to usememblock_alloc()for early consoles and reduce problems with static structures.
Ah nice, I'll look into that. This would all be a lot nicer without the special cases.
Quoted 15 lines
kernel/printk/printk.c static int __init keep_bootcon_setup(char *str) · line 2620
Quoted 11 lines
kernel/printk/printk.c +10
-0+if (!new) +return NULL ; + + new->ops = ops; +strscpy (new->name, name,sizeof (new->name)); + new->flags = flags; + new->index = index; + new->data = data; + +console_init_device (new);This is a side effect that I would not expect from a function called alloc*(). I would rename:
Quoted 2 lines
s/allocate_console/create_console/ or
s/allocate_console/init_console/
Makes sense.
Quoted 23 lines
Quoted 9 lines
kernel/printk/printk.c +4
-0+return new; +} +EXPORT_SYMBOL_GPL (allocate_console); +/* * The console driver calls this routine during kernel initialization * to register the console printing procedure with printk() and to kernel/printk/printk.c void register_console(struct console *newcon) · line 2692
Quoted 10 lines
kernel/printk/printk.c +3
-3@@ -2622,10 +2686,10 @@ void register_console(struct console *newcon)if (!has_preferred) {if (newcon->index <0 ) newcon->index =0 ; -if (newcon->setup ==NULL || - newcon->setup (newcon,NULL ) ==0 ) { +if (newcon->ops->setup ==NULL || + newcon->ops->setup (newcon,NULL ) ==0 ) { newcon->flags |=CON_ENABLED ; -if (newcon->device) { +if (newcon->ops->device) {There might be confusion why we need two devices (
con->devandcon->ops->device).
Quoted 1 line
I would rename
con->ops->devicetocon->ops->tty_dev.
Makes sense.
Quoted 35 lines
Quoted 35 lines
kernel/printk/printk.c +6
-4newcon->flags |=CON_CONSDEV ; has_preferred = true; }@@ -2639,8 +2703,8 @@ void register_console(struct console *newcon)for (i =0 , c = console_cmdline; i <MAX_CMDLINECONSOLES && c->name[0 ]; i++, c++) { -if (!newcon->match || - newcon->match (newcon, c->name, c->index, c->options) !=0 ) { +if (!newcon->ops->match || + newcon->ops->match (newcon, c->name, c->index, c->options) !=0 ) {/* default matching */ BUILD_BUG_ON (sizeof (c->name) !=sizeof (newcon->name));if (strcmp (c->name, newcon->name) !=0 )@@ -2660,8 +2724,8 @@ void register_console(struct console *newcon)if (_braille_register_console (newcon, c))return ; -if (newcon->setup && - newcon->setup (newcon, c->options) !=0 ) +if (newcon->ops->setup && + newcon->ops->setup (newcon, c->options) !=0 )break ; }@@ -2706,6 +2770,8 @@ void register_console(struct console *newcon) console_drivers->next = newcon; } +get_console (newcon); +if (newcon->flags &CON_EXTENDED ) nr_ext_console_drivers++;
Quoted 9 lines
kernel/printk/printk.c void register_console(struct console *newcon) · line 2799
Quoted 5 lines
kernel/printk/printk.c +1
-0@@ -2730,6 +2796,7 @@ void register_console(struct console *newcon) exclusive_console_stop_seq = console_seq;logbuf_unlock_irqrestore (flags); } +console_register_device (newcon);This calls
console_init_device()for the statically defined early consoles. I guess that it would invalidate the aboveget_console().
The get_console() macro checks for ->is_static and is a NOP if it's set, which is definitely confusing.
Quoted 3 lines
Also it is not symmetric with
unregister_console(). We add it to theconsole_subsyshere and did not remove it when the console is unregistered.
We do a put() in the unregister path, somebody could hold a reference through sysfs so we can't just remove it. Or am I misunderstanding?
Quoted 9 lines
IMHO, this might be done already in
allocate_console(). And eventually inprintk_late_init()for consoles that are allocated earlier.I am not familiar with the device-related sysfs API. But I see that
device_initialize()anddevice_add()can be done bydevice_register(). The separate calls are needed only when a special reference handling is needed. Are we special?
We're special: the console initcalls run before the device core is initialized, initialize() lets us use the refcount.
That said, I'm hopeful your suggestion about using memblock_alloc() will make some of this confusion unnecessary, it's definitely... confusing.
Quoted 10 lines
Anyway, please, try to describe the expected workflow in the commit description:
+ where the structure should get allocated
+ when it is added to the sysfs hierarchy
+ what happens when the console gets registered and unregistered
+ when it is removed from the sysfs hierarchy
+ when the structure is released/freed
Quoted 5 lines
+ What is needed to get the console registered and unregistered repeatedly on a running system
Finally, we might want to show state of the
CON_ENABLEDflag in sysfs to distinguish the currently used consoles.
Makes sense.
Quoted 6 lines
kernel/printk/printk.c void register_console(struct console *newcon) · line 2801
Quoted 3 lines
kernel/printk/printk.c +0
-0console_unlock ();console_sysfs_notify ();Thanks a lot for working on this. I know that it is not easy. But it is really appreciated.
Thanks :)
--Calvin
Quoted 2 lines
Best Regards,
Petr
Petr Mladek
maintainerRe: [PATCH 3/4] printk: Add consoles to a virtual "console" bus
Quoted 44 lines · Calvin Owens
Quoted 30 lines · Petr Mladek
Quoted 29 lines · Calvin Owens
This patch embeds a device struct in the console struct, and registers them on a "console" bus so we can expose attributes in sysfs.
Currently, most drivers declare static console structs, and that is incompatible with the dev refcount model. So we end up needing to patch all of the console drivers to:
1. Dynamically allocate the console struct using a new helper
2. Handle the allocation in (1) possibly failing
3. Dispose of (1) withput_device()Early console structures must still be static, since they're required before we're able to allocate memory. The least ugly way I can come up with to handle this is an "
is_static" flag in the structure which makes the gets and puts NOPs, and is checked in ->release() to catch mistakes.kernel/printk/printk.c +2
-0@@ -2706,6 +2770,8 @@ void register_console(struct console *newcon) console_drivers->next = newcon; } +get_console (newcon); +if (newcon->flags &CON_EXTENDED ) nr_ext_console_drivers++;Quoted 9 lines
kernel/printk/printk.c void register_console(struct console *newcon) · line 2799
Quoted 5 lines
kernel/printk/printk.c +1
-0@@ -2730,6 +2796,7 @@ void register_console(struct console *newcon) exclusive_console_stop_seq = console_seq;logbuf_unlock_irqrestore (flags); } +console_register_device (newcon);This calls
console_init_device()for the statically defined early consoles. I guess that it would invalidate the aboveget_console().The
get_console()macro checks for ->is_static and is a NOP if it's set, which is definitely confusing.
Quoted 6 lines
Quoted 3 lines
Also it is not symmetric with
unregister_console(). We add it to theconsole_subsyshere and did not remove it when the console is unregistered.We do a
put()in the unregister path, somebody could hold a reference through sysfs so we can't just remove it. Or am I misunderstanding?
To be honest, I am not sure what the effect of get_device() and put_device() is. But they are called also in device_add(). This suggests that the sysfs interface and struct device stay even when we call device_put() in unregister_console().
This is an asymmetry. The sysfs interface is created only for successfully registered console but it stays even after unregistration (if it works as I expect).
Another problem is that register_console()/unregister_console() might get called repeatedly for the same console. But device_add() should get called only once.
I think that we could do better, see below.
Quoted 4 lines
Quoted 4 lines
IMHO, this might be done already in
allocate_console(). And eventually inprintk_late_init()for consoles that are allocated earlier.
Quoted 8 lines
Quoted 5 lines
I am not familiar with the device-related sysfs API. But I see that
device_initialize()anddevice_add()can be done bydevice_register(). The separate calls are needed only when a special reference handling is needed. Are we special?We're special: the console initcalls run before the device core is initialized,
initialize()lets us use the refcount.
But console_init_device() is called later from printk_late_init() for the statically defined structures (early consoles). This would reset the refcount for these consoles.
I think that we should delay calling console_init_device() for all consoles until printk_late_done is set. Then it should be safe to call device_register() there.
Best Regards,
Petr
PATCH 4/4 printk: Add a device attribute for the per-console loglevel
In reply to Calvin Owens--- kernel/printk/printk.c | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+)
kernel/printk/printk.c +40 -0
@@ -2560,8 +2560,48 @@ static int __init keep_bootcon_setup(char *str)early_param ("keep_bootcon" , keep_bootcon_setup); +static ssize_t loglevel_show (struct device *dev,struct device_attribute *attr, +char *buf) +{ + struct console *con = container_of(dev, struct console, dev); +return sprintf (buf,"%d\n" , con->level); +} + +static ssize_t loglevel_store (struct device *dev,struct device_attribute *attr, +const char *buf,size_t count) +{ + struct console *con = container_of(dev, struct console, dev); +ssize_t ret; +int tmp; + + ret =kstrtoint (buf,10 , &tmp); +if (ret <0 ) +return ret; + +if (tmp <LOGLEVEL_EMERG ) +return -ERANGE ; + +/* +* Mimic the behavior of /dev/kmsg with respect to minimum_loglevel. +*/ +if (tmp < minimum_console_loglevel) + tmp = minimum_console_loglevel; + + con->level = tmp; +return ret; +} + +static DEVICE_ATTR_RW (loglevel); + +static struct attribute *console_sysfs_attrs[] = { + &dev_attr_loglevel.attr, +NULL , +}; +ATTRIBUTE_GROUPS (console_sysfs); +static struct bus_type console_subsys = { .name ="console" , + .dev_groups = console_sysfs_groups, };static void console_release (struct device *dev)
Signature · 1 line
2.17.1
Re: [PATCH 4/4] printk: Add a device attribute for the per-console loglevel
Quoted 26 lines · Calvin Owens
kernel/printk/printk.c +26
-0+static ssize_t loglevel_store (struct device *dev,struct device_attribute *attr, +const char *buf,size_t count) +{ + struct console *con = container_of(dev, struct console, dev); +ssize_t ret; +int tmp; + + ret =kstrtoint (buf,10 , &tmp); +if (ret <0 ) +return ret; + +if (tmp <LOGLEVEL_EMERG ) +return -ERANGE ; + +/* +* Mimic the behavior of /dev/kmsg with respect to minimum_loglevel. +*/ +if (tmp < minimum_console_loglevel) + tmp = minimum_console_loglevel; + + con->level = tmp; +return ret; +} + +static DEVICE_ATTR_RW (loglevel); +
kernel/printk/printk.c static int __init keep_bootcon_setup(char *str) · line 2605
Quoted 10 lines
kernel/printk/printk.c +7
-0+static struct attribute *console_sysfs_attrs[] = { + &dev_attr_loglevel.attr, +NULL , +}; +ATTRIBUTE_GROUPS (console_sysfs); +static struct bus_type console_subsys = { .name ="console" , + .dev_groups = console_sysfs_groups, };
Do we really need to change this dynamically? Console options are traditionally static (boot param or DT). Can we also be happy with the static per-console loglevel?
-ss
Re: [PATCH 4/4] printk: Add a device attribute for the per-console loglevel
Quoted 15 lines · Sergey Senozhatsky
kernel/printk/printk.c static int __init keep_bootcon_setup(char *str) · line 2605
Quoted 10 lines · Calvin Owens
kernel/printk/printk.c +7
-0+static struct attribute *console_sysfs_attrs[] = { + &dev_attr_loglevel.attr, +NULL , +}; +ATTRIBUTE_GROUPS (console_sysfs); +static struct bus_type console_subsys = { .name ="console" , + .dev_groups = console_sysfs_groups, };Do we really need to change this dynamically? Console options are traditionally static (boot param or DT). Can we also be happy with the static per-console loglevel?
It really does need to be runtime configurable: there are a lot of usecases that enables, like turning the fast console up to KERN_DEBUG on a pile of machines you want to take a closer look at. The 'kernel.printk' global loglevel is also already changable at runtime, and since that setting interacts with this one it would be strange if only the former were able to be changed.
I also want to add more attribute knobs related to extended consoles, so the plumbing to get things exposed in sysfs is worth it for me.
Thanks,
Calvin
Re: [PATCH 4/4] printk: Add a device attribute for the per-console loglevel
Quoted 17 lines · Calvin Owens
Quoted 15 lines · Sergey Senozhatsky
kernel/printk/printk.c static int __init keep_bootcon_setup(char *str) · line 2605
Quoted 10 lines · Calvin Owens
kernel/printk/printk.c +7
-0+static struct attribute *console_sysfs_attrs[] = { + &dev_attr_loglevel.attr, +NULL , +}; +ATTRIBUTE_GROUPS (console_sysfs); +static struct bus_type console_subsys = { .name ="console" , + .dev_groups = console_sysfs_groups, };Do we really need to change this dynamically? Console options are traditionally static (boot param or DT). Can we also be happy with the static per-console loglevel?
Quoted 6 lines
It really does need to be runtime configurable: there are a lot of usecases that enables, like turning the fast console up to
KERN_DEBUGon a pile of machines you want to take a closer look at. The 'kernel.printk' global loglevel is also already changable at runtime, and since that setting interacts with this one it would be strange if only the former were able to be changed.
Fair enough.
-ss