Merge branch 'for-5.8' into for-linus
authorPetr Mladek <pmladek@suse.com>
Mon, 1 Jun 2020 08:15:16 +0000 (10:15 +0200)
committerPetr Mladek <pmladek@suse.com>
Mon, 1 Jun 2020 08:15:16 +0000 (10:15 +0200)
include/linux/console.h
kernel/printk/console_cmdline.h
kernel/printk/printk.c
lib/vsprintf.c

index 7a140f4..75dd206 100644 (file)
@@ -134,7 +134,7 @@ static inline int con_debug_leave(void)
  */
 
 #define CON_PRINTBUFFER        (1)
-#define CON_CONSDEV    (2) /* Last on the command line */
+#define CON_CONSDEV    (2) /* Preferred console, /dev/console */
 #define CON_ENABLED    (4)
 #define CON_BOOT       (8)
 #define CON_ANYTIME    (16) /* Safe to call when cpu is offline */
index 11f19c4..3ca74ad 100644 (file)
@@ -6,6 +6,7 @@ struct console_cmdline
 {
        char    name[16];                       /* Name of the driver       */
        int     index;                          /* Minor dev. to use        */
+       bool    user_specified;                 /* Specified by command line vs. platform */
        char    *options;                       /* Options for the driver   */
 #ifdef CONFIG_A11Y_BRAILLE_CONSOLE
        char    *brl_options;                   /* Options for braille driver */
index a399050..2bafd5c 100644 (file)
@@ -280,6 +280,7 @@ static struct console *exclusive_console;
 static struct console_cmdline console_cmdline[MAX_CMDLINECONSOLES];
 
 static int preferred_console = -1;
+static bool has_preferred_console;
 int console_set_on_cmdline;
 EXPORT_SYMBOL(console_set_on_cmdline);
 
@@ -2150,7 +2151,7 @@ asmlinkage __visible void early_printk(const char *fmt, ...)
 #endif
 
 static int __add_preferred_console(char *name, int idx, char *options,
-                                  char *brl_options)
+                                  char *brl_options, bool user_specified)
 {
        struct console_cmdline *c;
        int i;
@@ -2165,6 +2166,8 @@ static int __add_preferred_console(char *name, int idx, char *options,
                if (strcmp(c->name, name) == 0 && c->index == idx) {
                        if (!brl_options)
                                preferred_console = i;
+                       if (user_specified)
+                               c->user_specified = true;
                        return 0;
                }
        }
@@ -2174,6 +2177,7 @@ static int __add_preferred_console(char *name, int idx, char *options,
                preferred_console = i;
        strlcpy(c->name, name, sizeof(c->name));
        c->options = options;
+       c->user_specified = user_specified;
        braille_set_options(c, brl_options);
 
        c->index = idx;
@@ -2231,7 +2235,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, brl_options, true);
        console_set_on_cmdline = 1;
        return 1;
 }
@@ -2252,7 +2256,7 @@ __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, NULL, false);
 }
 
 bool console_suspend_enabled = true;
@@ -2451,9 +2455,9 @@ again:
                printk_safe_enter_irqsave(flags);
                raw_spin_lock(&logbuf_lock);
                if (console_seq < log_first_seq) {
-                       len = sprintf(text,
-                                     "** %llu printk messages dropped **\n",
-                                     log_first_seq - console_seq);
+                       len = snprintf(text, sizeof(text),
+                                      "** %llu printk messages dropped **\n",
+                                      log_first_seq - console_seq);
 
                        /* messages are gone, move to first one */
                        console_seq = log_first_seq;
@@ -2664,6 +2668,63 @@ static int __init keep_bootcon_setup(char *str)
 
 early_param("keep_bootcon", keep_bootcon_setup);
 
+/*
+ * This is called by register_console() to try to match
+ * the newly registered console with any of the ones selected
+ * by either the command line or add_preferred_console() and
+ * setup/enable it.
+ *
+ * Care need to be taken with consoles that are statically
+ * enabled such as netconsole
+ */
+static int try_enable_new_console(struct console *newcon, bool user_specified)
+{
+       struct console_cmdline *c;
+       int i;
+
+       for (i = 0, c = console_cmdline;
+            i < MAX_CMDLINECONSOLES && c->name[0];
+            i++, c++) {
+               if (c->user_specified != user_specified)
+                       continue;
+               if (!newcon->match ||
+                   newcon->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)
+                               continue;
+                       if (newcon->index >= 0 &&
+                           newcon->index != c->index)
+                               continue;
+                       if (newcon->index < 0)
+                               newcon->index = c->index;
+
+                       if (_braille_register_console(newcon, c))
+                               return 0;
+
+                       if (newcon->setup &&
+                           newcon->setup(newcon, c->options) != 0)
+                               return -EIO;
+               }
+               newcon->flags |= CON_ENABLED;
+               if (i == preferred_console) {
+                       newcon->flags |= CON_CONSDEV;
+                       has_preferred_console = true;
+               }
+               return 0;
+       }
+
+       /*
+        * Some consoles, such as pstore and netconsole, can be enabled even
+        * without matching. Accept the pre-enabled consoles only when match()
+        * and setup() had a change to be called.
+        */
+       if (newcon->flags & CON_ENABLED && c->user_specified == user_specified)
+               return 0;
+
+       return -ENOENT;
+}
+
 /*
  * The console driver calls this routine during kernel initialization
  * to register the console printing procedure with printk() and to
@@ -2685,11 +2746,9 @@ early_param("keep_bootcon", keep_bootcon_setup);
  */
 void register_console(struct console *newcon)
 {
-       int i;
        unsigned long flags;
        struct console *bcon = NULL;
-       struct console_cmdline *c;
-       static bool has_preferred;
+       int err;
 
        for_each_console(bcon) {
                if (WARN(bcon == newcon, "console '%s%d' already registered\n",
@@ -2714,15 +2773,15 @@ void register_console(struct console *newcon)
        if (console_drivers && console_drivers->flags & CON_BOOT)
                bcon = console_drivers;
 
-       if (!has_preferred || bcon || !console_drivers)
-               has_preferred = preferred_console >= 0;
+       if (!has_preferred_console || bcon || !console_drivers)
+               has_preferred_console = preferred_console >= 0;
 
        /*
         *      See if we want to use this console driver. If we
         *      didn't select a console we take the first one
         *      that registers here.
         */
-       if (!has_preferred) {
+       if (!has_preferred_console) {
                if (newcon->index < 0)
                        newcon->index = 0;
                if (newcon->setup == NULL ||
@@ -2730,47 +2789,20 @@ void register_console(struct console *newcon)
                        newcon->flags |= CON_ENABLED;
                        if (newcon->device) {
                                newcon->flags |= CON_CONSDEV;
-                               has_preferred = true;
+                               has_preferred_console = true;
                        }
                }
        }
 
-       /*
-        *      See if this console matches one we selected on
-        *      the command line.
-        */
-       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) {
-                       /* default matching */
-                       BUILD_BUG_ON(sizeof(c->name) != sizeof(newcon->name));
-                       if (strcmp(c->name, newcon->name) != 0)
-                               continue;
-                       if (newcon->index >= 0 &&
-                           newcon->index != c->index)
-                               continue;
-                       if (newcon->index < 0)
-                               newcon->index = c->index;
-
-                       if (_braille_register_console(newcon, c))
-                               return;
-
-                       if (newcon->setup &&
-                           newcon->setup(newcon, c->options) != 0)
-                               break;
-               }
+       /* See if this console matches one we selected on the command line */
+       err = try_enable_new_console(newcon, true);
 
-               newcon->flags |= CON_ENABLED;
-               if (i == preferred_console) {
-                       newcon->flags |= CON_CONSDEV;
-                       has_preferred = true;
-               }
-               break;
-       }
+       /* If not, try to match against the platform default(s) */
+       if (err == -ENOENT)
+               err = try_enable_new_console(newcon, false);
 
-       if (!(newcon->flags & CON_ENABLED))
+       /* printk() messages are not printed to the Braille console. */
+       if (err || newcon->flags & CON_BRL)
                return;
 
        /*
@@ -2792,6 +2824,8 @@ void register_console(struct console *newcon)
                console_drivers = newcon;
                if (newcon->next)
                        newcon->next->flags &= ~CON_CONSDEV;
+               /* Ensure this flag is always set for the head of the list */
+               newcon->flags |= CON_CONSDEV;
        } else {
                newcon->next = console_drivers->next;
                console_drivers->next = newcon;
index 7c488a1..d5641a2 100644 (file)
@@ -58,7 +58,7 @@
  * @endp: A pointer to the end of the parsed string will be placed here
  * @base: The number base to use
  *
- * This function is obsolete. Please use kstrtoull instead.
+ * This function has caveats. Please use kstrtoull instead.
  */
 unsigned long long simple_strtoull(const char *cp, char **endp, unsigned int base)
 {
@@ -83,7 +83,7 @@ EXPORT_SYMBOL(simple_strtoull);
  * @endp: A pointer to the end of the parsed string will be placed here
  * @base: The number base to use
  *
- * This function is obsolete. Please use kstrtoul instead.
+ * This function has caveats. Please use kstrtoul instead.
  */
 unsigned long simple_strtoul(const char *cp, char **endp, unsigned int base)
 {
@@ -97,7 +97,7 @@ EXPORT_SYMBOL(simple_strtoul);
  * @endp: A pointer to the end of the parsed string will be placed here
  * @base: The number base to use
  *
- * This function is obsolete. Please use kstrtol instead.
+ * This function has caveats. Please use kstrtol instead.
  */
 long simple_strtol(const char *cp, char **endp, unsigned int base)
 {
@@ -114,7 +114,7 @@ EXPORT_SYMBOL(simple_strtol);
  * @endp: A pointer to the end of the parsed string will be placed here
  * @base: The number base to use
  *
- * This function is obsolete. Please use kstrtoll instead.
+ * This function has caveats. Please use kstrtoll instead.
  */
 long long simple_strtoll(const char *cp, char **endp, unsigned int base)
 {