From c81ea7203b224cb85c5daf360556304e7212bab6 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 3 Feb 2020 15:31:24 +0200 Subject: [PATCH 1/7] console: Don't perform test for CON_BRL flag We don't call braille_register_console() without CON_BRL flag set. And the _braille_unregister_console() already tests for console to have CON_BRL flag. No need to repeat this in braille_unregister_console(). Drop the repetitive checks from Braille console driver. Link: http://lkml.kernel.org/r/20200203133130.11591-1-andriy.shevchenko@linux.intel.com To: linux-kernel@vger.kernel.org To: Steven Rostedt Signed-off-by: Andy Shevchenko Reviewed-by: Petr Mladek Reviewed-by: Sergey Senozhatsky Signed-off-by: Petr Mladek --- drivers/accessibility/braille/braille_console.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/accessibility/braille/braille_console.c b/drivers/accessibility/braille/braille_console.c index 1339c586bf645..a8f7c278b6918 100644 --- a/drivers/accessibility/braille/braille_console.c +++ b/drivers/accessibility/braille/braille_console.c @@ -347,8 +347,6 @@ int braille_register_console(struct console *console, int index, { int ret; - if (!(console->flags & CON_BRL)) - return 0; if (!console_options) /* Only support VisioBraille for now */ console_options = "57600o8"; @@ -371,8 +369,6 @@ int braille_unregister_console(struct console *console) { if (braille_co != console) return -EINVAL; - if (!(console->flags & CON_BRL)) - return 0; unregister_keyboard_notifier(&keyboard_notifier_block); unregister_vt_notifier(&vt_notifier_block); braille_co = NULL; From caa72c3bc584bc28b557bcf1a47532a7a6f37e6f Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 3 Feb 2020 15:31:25 +0200 Subject: [PATCH 2/7] console: Drop double check for console_drivers being non-NULL There is no need to explicitly check for console_drivers to be non-NULL since for_each_console() does this. Link: http://lkml.kernel.org/r/20200203133130.11591-2-andriy.shevchenko@linux.intel.com To: linux-kernel@vger.kernel.org To: Steven Rostedt Signed-off-by: Andy Shevchenko Reviewed-by: Petr Mladek Reviewed-by: Sergey Senozhatsky Signed-off-by: Petr Mladek --- kernel/printk/printk.c | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c index fada22dc4ab6c..51337ed426e09 100644 --- a/kernel/printk/printk.c +++ b/kernel/printk/printk.c @@ -1772,9 +1772,6 @@ static void call_console_drivers(const char *ext_text, size_t ext_len, trace_console_rcuidle(text, len); - if (!console_drivers) - return; - for_each_console(con) { if (exclusive_console && con != exclusive_console) continue; @@ -2653,18 +2650,17 @@ void register_console(struct console *newcon) struct console_cmdline *c; static bool has_preferred; - if (console_drivers) - for_each_console(bcon) - if (WARN(bcon == newcon, - "console '%s%d' already registered\n", - bcon->name, bcon->index)) - return; + for_each_console(bcon) { + if (WARN(bcon == newcon, "console '%s%d' already registered\n", + bcon->name, bcon->index)) + return; + } /* * before we register a new CON_BOOT console, make sure we don't * already have a valid console */ - if (console_drivers && newcon->flags & CON_BOOT) { + if (newcon->flags & CON_BOOT) { /* find the last or real console */ for_each_console(bcon) { if (!(bcon->flags & CON_BOOT)) { From 12825e6ba8ea8efbb6d81363b0cf6b5bf84c051a Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 3 Feb 2020 15:31:26 +0200 Subject: [PATCH 3/7] console: Use for_each_console() helper in unregister_console() We have rather open coded single linked list manipulations where we may simple use for_each_console() helper with properly set exit conditions. Replace open coded single-linked list handling with for_each_console() helper in use. Link: http://lkml.kernel.org/r/20200203133130.11591-3-andriy.shevchenko@linux.intel.com To: linux-kernel@vger.kernel.org To: Steven Rostedt Signed-off-by: Andy Shevchenko Reviewed-by: Petr Mladek Reviewed-by: Sergey Senozhatsky Signed-off-by: Petr Mladek --- kernel/printk/printk.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c index 51337ed426e09..d40a316908dad 100644 --- a/kernel/printk/printk.c +++ b/kernel/printk/printk.c @@ -2809,7 +2809,7 @@ EXPORT_SYMBOL(register_console); int unregister_console(struct console *console) { - struct console *a, *b; + struct console *con; int res; pr_info("%sconsole [%s%d] disabled\n", @@ -2825,11 +2825,10 @@ int unregister_console(struct console *console) if (console_drivers == console) { console_drivers=console->next; res = 0; - } else if (console_drivers) { - for (a=console_drivers->next, b=console_drivers ; - a; b=a, a=b->next) { - if (a == console) { - b->next = a->next; + } else { + for_each_console(con) { + if (con->next == console) { + con->next = console->next; res = 0; break; } From d58ad10122e6f8f84b1ef60227233b7c5de2bc02 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 3 Feb 2020 15:31:27 +0200 Subject: [PATCH 4/7] console: Drop misleading comment /* find the last or real console */ This comment is misleading. The purpose of the loop is to check if we are trying to register boot console after a real one has already been registered. This is already mentioned in a comment above. Link: http://lkml.kernel.org/r/20200203133130.11591-4-andriy.shevchenko@linux.intel.com To: linux-kernel@vger.kernel.org To: Steven Rostedt Suggested-by: Petr Mladek Signed-off-by: Andy Shevchenko [pmladek@suse.com: Updated commit message.] Reviewed-by: Sergey Senozhatsky Signed-off-by: Petr Mladek --- kernel/printk/printk.c | 1 - 1 file changed, 1 deletion(-) diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c index d40a316908dad..b0c12c08cac43 100644 --- a/kernel/printk/printk.c +++ b/kernel/printk/printk.c @@ -2661,7 +2661,6 @@ void register_console(struct console *newcon) * already have a valid console */ if (newcon->flags & CON_BOOT) { - /* find the last or real console */ for_each_console(bcon) { if (!(bcon->flags & CON_BOOT)) { pr_info("Too late to register bootconsole %s%d\n", From bb72e3981d8e7bb80db7cebc57a4e10769a509c9 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 3 Feb 2020 15:31:28 +0200 Subject: [PATCH 5/7] console: Avoid positive return code from unregister_console() There are only two callers that use the returned code from unregister_console(): - unregister_early_console() in arch/m68k/kernel/early_printk.c - kgdb_unregister_nmi_console() in drivers/tty/serial/kgdb_nmi.c They both expect to get "0" on success and a non-zero value on error. But the current behavior is confusing and buggy: - _braille_unregister_console() returns "1" on success - unregister_console() returns "1" on error Fix and clean up the behavior: - Return success when _braille_unregister_console() succeeded - Return a meaningful error code when the console was not registered before Link: http://lkml.kernel.org/r/20200203133130.11591-5-andriy.shevchenko@linux.intel.com To: linux-kernel@vger.kernel.org To: Steven Rostedt Signed-off-by: Andy Shevchenko Reviewed-by: Sergey Senozhatsky Signed-off-by: Petr Mladek --- kernel/printk/printk.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c index b0c12c08cac43..61d188f4c672d 100644 --- a/kernel/printk/printk.c +++ b/kernel/printk/printk.c @@ -2816,10 +2816,12 @@ int unregister_console(struct console *console) console->name, console->index); res = _braille_unregister_console(console); - if (res) + if (res < 0) return res; + if (res > 0) + return 0; - res = 1; + res = -ENODEV; console_lock(); if (console_drivers == console) { console_drivers=console->next; From e78bedbd42b7caa65551f3d56cbff451ccbd0aee Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 3 Feb 2020 15:31:29 +0200 Subject: [PATCH 6/7] console: Don't notify user space when unregister non-listed console If console is not on the list then there is nothing for us to do and sysfs notify is pointless. Note, that nr_ext_console_drivers is being changed only for listed consoles. Suggested-by: Sergey Senozhatsky Link: http://lkml.kernel.org/r/20200203133130.11591-6-andriy.shevchenko@linux.intel.com To: linux-kernel@vger.kernel.org To: Steven Rostedt Signed-off-by: Andy Shevchenko Reviewed-by: Sergey Senozhatsky Reviewed-by: Petr Mladek Signed-off-by: Petr Mladek --- kernel/printk/printk.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c index 61d188f4c672d..f435a17ef9882 100644 --- a/kernel/printk/printk.c +++ b/kernel/printk/printk.c @@ -2836,7 +2836,10 @@ int unregister_console(struct console *console) } } - if (!res && (console->flags & CON_EXTENDED)) + if (res) + goto out_disable_unlock; + + if (console->flags & CON_EXTENDED) nr_ext_console_drivers--; /* @@ -2849,6 +2852,13 @@ int unregister_console(struct console *console) console->flags &= ~CON_ENABLED; console_unlock(); console_sysfs_notify(); + + return res; + +out_disable_unlock: + console->flags &= ~CON_ENABLED; + console_unlock(); + return res; } EXPORT_SYMBOL(unregister_console); From ed31685c96e18f773ca11dd1a637974d62130673 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 3 Feb 2020 15:31:30 +0200 Subject: [PATCH 7/7] console: Introduce ->exit() callback Some consoles might require special operations on unregistering. For instance, serial console, when registered in the kernel, keeps power on for entire time, until it gets unregistered. Example of use: ->setup(console): pm_runtime_get(...); ->exit(console): pm_runtime_put(...); For such cases to have a balance we would provide ->exit() callback. Link: http://lkml.kernel.org/r/20200203133130.11591-7-andriy.shevchenko@linux.intel.com To: linux-kernel@vger.kernel.org To: Steven Rostedt Signed-off-by: Andy Shevchenko Reviewed-by: Sergey Senozhatsky Reviewed-by: Petr Mladek Signed-off-by: Petr Mladek --- include/linux/console.h | 1 + kernel/printk/printk.c | 3 +++ 2 files changed, 4 insertions(+) diff --git a/include/linux/console.h b/include/linux/console.h index d09951d5a94e4..0cbd2a36aa002 100644 --- a/include/linux/console.h +++ b/include/linux/console.h @@ -149,6 +149,7 @@ struct console { struct tty_driver *(*device)(struct console *, int *); void (*unblank)(void); int (*setup)(struct console *, char *); + int (*exit)(struct console *); int (*match)(struct console *, char *name, int idx, char *options); short flags; short index; diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c index f435a17ef9882..633f41a11d759 100644 --- a/kernel/printk/printk.c +++ b/kernel/printk/printk.c @@ -2853,6 +2853,9 @@ int unregister_console(struct console *console) console_unlock(); console_sysfs_notify(); + if (console->exit) + res = console->exit(console); + return res; out_disable_unlock: