1. 10 Jan, 2022 1 commit
  2. 06 Jan, 2022 2 commits
  3. 16 Dec, 2021 1 commit
  4. 06 Dec, 2021 6 commits
    • Petr Mladek's avatar
      printk/console: Clean up boot console handling in register_console() · 5e8ba485
      Petr Mladek authored
      The variable @bcon has two meanings. It is used several times for iterating
      the list of registered consoles. In the meantime, it holds the information
      whether a boot console is first in @console_drivers list.
      
      The information about the 1st console driver used to be important for
      the decision whether to install the new console by default or not.
      It allowed to re-evaluate the variable @need_default_console when
      a real console with tty binding has been unregistered in the meantime.
      
      The decision about the default console is not longer affected by @bcon
      variable. The current code checks whether the first driver is real
      and has tty binding directly.
      
      The information about the first console is still used for two more
      decisions:
      
        1. It prevents duplicate output on non-boot consoles with
           CON_CONSDEV flag set.
      
        2. Early/boot consoles are unregistered when a real console with
           CON_CONSDEV is registered and @keep_bootcon is not set.
      
      The behavior in the real life is far from obvious. @bcon is set according
      to the first console @console_drivers list. But the first position in
      the list is special:
      
        1. Consoles with CON_CONSDEV flag are put at the beginning of
           the list. It is either the preferred console or any console
           with tty binding registered by default.
      
        2. Another console might become the first in the list when
           the first console in the list is unregistered. It might
           happen either explicitly or automatically when boot
           consoles are unregistered.
      
      There is one more important rule:
      
        + Boot consoles can't be registered when any real console
          is already registered.
      
      It is a puzzle. The main complication is the dependency on the first
      position is the list and the complicated rules around it.
      
      Let's try to make it easier:
      
      1. Add variable @bootcon_enabled and set it by iterating all registered
         consoles. The variable has obvious meaning and more predictable
         behavior. Any speed optimization and other tricks are not worth it.
      
      2. Use a generic name for the variable that is used to iterate
         the list on registered console drivers.
      
      Behavior change:
      
      No, maybe surprisingly, there is _no_ behavior change!
      
      Let's provide the proof by contradiction. Both operations, duplicate
      output prevention and boot consoles removal, are done only when
      the newly added console has CON_CONSDEV flag set. The behavior
      would change when the new @bootcon_enabled has different value
      than the original @bcon.
      
      By other words, the behavior would change when the following conditions
      are true:
      
         + a console with CON_CONSDEV flag is added
         + a real (non-boot) console is the first in the list
         + a boot console is later in the list
      
      Now, a real console might be first in the list only when:
      
         + It was the first registered console. In this case, there can't be
           any boot console because any later ones were rejected.
      
         + It was put at the first position because it had CON_CONSDEV flag
           set. It was either the preferred console or it was a console with
           tty binding registered by default. We are interested only in
           a real consoles here. And real console with tty binding fulfills
           conditions of the default console.
      
           Now, there is always only one console that is either preferred
           or fulfills conditions of the default console. It can't be already
           in the list and being registered at the same time.
      
      As a result, the above three conditions could newer be "true" at
      the same time. Therefore the behavior can't change.
      
      Final dilemma:
      
      OK, the new code has the same behavior. But is the change in the right
      direction? What if the handling of @console_drivers is updated in
      the future?
      
      OK, let's look at it from another angle:
      
      1. The ordering of @console_drivers list is important only in
         console_device() function. The first console driver with tty
         binding gets associated with /dev/console.
      
      2. CON_CONSDEV flag is shown in /proc/consoles. And it should be set
         for the driver that is returned by console_device().
      
      3. A boot console is removed and the duplicated output is prevented
         when the real console with CON_CONSDEV flag is registered.
      
      Now, in the ideal world:
      
      + The driver associated with /dev/console should be either a console
        preferred via the command line, device tree, or SPCR. Or it should
        be the first real console with tty binding registered by default.
      
      + The code should match the related boot and real console drivers.
        It should unregister only the obsolete boot driver. And the duplicated
        output should be prevented only on the related real driver.
      
      It is clear that it is not guaranteed by the current code. Instead,
      the current code looks like a maze of heuristics that try to achieve
      the above.
      
      It is result of adding several features over last few decades. For example,
      a possibility to register more consoles, unregister consoles, boot
      consoles, consoles without tty binding, device tree, SPCR, braille
      consoles.
      
      Anyway, there is no reason why the decision, about removing boot consoles
      and preventing duplicated output, should depend on the first console
      in the list. The current code does the decisions primary by CON_CONSDEV
      flag that is used for the preferred console. It looks like a
      good compromise. And the change seems to be in the right direction.
      Signed-off-by: default avatarPetr Mladek <pmladek@suse.com>
      Link: https://lore.kernel.org/r/20211122132649.12737-6-pmladek@suse.com
      5e8ba485
    • Petr Mladek's avatar
      printk/console: Remove need_default_console variable · 4f546939
      Petr Mladek authored
      The variable @need_default_console is used to decide whether a newly
      registered console should get enabled by default.
      
      The logic is complicated. It can be modified in a register_console()
      call. But it is always re-evaluated in the next call by the following
      condition:
      
      	if (need_default_console || bcon || !console_drivers)
      		need_default_console = preferred_console < 0;
      
      In short, the value is updated when either of the condition is valid:
      
        + the value is still, or again, "true"
        + boot/early console is still the first in @console_driver list
        + @console_driver list is empty
      
      The value is updated according to @preferred_console. In particular,
      it is set to "false" when a @preferred_console was set by
      __add_preferred_console(). This happens when a non-braille console
      was added via the command line, device tree, or SPCR.
      
      It far from clear what this all means together. Let's look at
      @need_default_console from another angle:
      
      1. The value is "true" by default. It means that it is always set
         according to @preferred_console during the first register_console()
         call.
      
         By other words, the first register_console() call will register
         the console by default only when none non-braille console was defined
         via the command line, device tree, or SPCR.
      
      2. The value will always stay "false" when @preferred_console is set.
      
         By other words, try_enable_default_console() will never get called
         when a non-braille console is explicitly required.
      
      4. The value might be set to "false" in try_enable_default_console()
         when a console with tty binding (driver) gets enabled.
      
         In this case CON_CONSDEV is set as well. It causes that the console
         will be inserted as first into the list @console_driver. It might
         be either real or boot/early console.
      
      5. The value will be set _back_ to "true" in the next register_console()
         call when:
      
            + The console added by the previous register_console() had been
      	a boot/early one.
      
            + The last console has been unregistered in the meantime and
      	a boot/early console became first in @console_drivers list
      	again. Or the list became empty.
      
         By other words, the value will stay "false" only when the last
         registered console was real, had tty binding, and was not removed
         in the mean time.
      
      The main logic looks clear:
      
        + Consoles are enabled by default only when no one is preferred
          via the command line, device tree, or SPCR.
      
        + By default, any console is enabled until a real console
          with tty binding gets registered.
      
      The behavior when the real console with tty binding is later removed
      is a bit unclear:
      
        + By default, any new console is registered again only when there
          is no console or the first console in the list is a boot one.
      
      The question is why the code is suddenly happy when a real console
      without tty binding is the first in the list. It looks like an overlook
      and bug.
      
      Conclusion:
      
      The state of @preferred_console and the first console in @console_driver
      list should be enough to decide whether we need to enable the given console
      by default.
      
      The rules are simple. New consoles are _not_ enabled by default
      when either of the following conditions is true:
      
        + @preferred_console is set. It means that a non-braille console
          is explicitly configured via the command line, device tree, or SPCR.
      
        + A real console with tty binding is registered. Such a console will
          have CON_CONSDEV flag set and will always be the first in
          @console_drivers list.
      
      Note:
      
      The new code does not use @bcon variable. The meaning of the variable
      is far from clear. The direct check of the first console in the list
      makes it more clear that only real console fulfills requirements
      of the default console.
      
      Behavior change:
      
      As already discussed above. There was one situation where the original
      code worked a strange way. Let's have:
      
      	+ console A: real console without tty binding
      	+ console B: real console with tty binding
      
      and do:
      
      	register_console(A);	/* 1st step */
      	register_console(B);	/* 2nd step */
      	unregister_console(B);	/* 3rd step */
      	register_console(B);	/* 4th step */
      
      The original code will not register the console B in the 4th step.
      @need_default_console is set to "false" in 2nd step. The real console
      with tty binding (driver) is then removed in the 3rd step.
      But @need_default_console will stay "false" in the 4th step because
      there is no boot/early console and @registered_consoles list is not
      empty.
      
      The new code will register the console B in the 4th step because
      it checks whether the first console has tty binding (->driver)
      
      This behavior change should acceptable:
      
        1. The scenario requires manual intervention (console removal).
           The system should boot with the same consoles as before.
      
        2. Console B is registered again probably because the user wants
           to use it. The most likely scenario is that the related
           module is reloaded.
      
        3. It makes the behavior more consistent and predictable.
      Signed-off-by: default avatarPetr Mladek <pmladek@suse.com>
      Link: https://lore.kernel.org/r/20211122132649.12737-5-pmladek@suse.com
      4f546939
    • Petr Mladek's avatar
      printk/console: Remove unnecessary need_default_console manipulation · f873efe8
      Petr Mladek authored
      There is no need to clear @need_default_console when a console
      preferred by the command line, device tree, or SPCR, gets enabled.
      
      The code is called only when some non-braille console matched a console
      in @console_cmdline array. It means that a non-braille console was added
      in __add_preferred_console() and the variable preferred_console is set
      to a number >= 0. As a result, @need_default_console is always set to
      "false" in the magic condition:
      
      	if (need_default_console || bcon || !console_drivers)
      		need_default_console = preferred_console < 0;
      
      This is one small step in removing the above magic condition
      that is hard to follow.
      
      The patch removes one superfluous assignment and should not change
      the functionality.
      Signed-off-by: default avatarPetr Mladek <pmladek@suse.com>
      Link: https://lore.kernel.org/r/20211122132649.12737-4-pmladek@suse.com
      f873efe8
    • Petr Mladek's avatar
      printk/console: Rename has_preferred_console to need_default_console · a6953370
      Petr Mladek authored
      The logic around the variable @has_preferred_console made my head
      spin many times. Part of the problem is the ambiguous name.
      
      There is the variable @preferred_console. It points to the last
      non-braille console in @console_cmdline array. This array contains
      consoles preferred via the command line, device tree, or SPCR.
      
      Then there is the variable @has_preferred_console. It is set to
      "true" when @preferred_console is enabled or when a console with
      tty binding gets enabled by default.
      
      It might get reset back by the magic condition:
      
      	if (!has_preferred_console || bcon || !console_drivers)
      		has_preferred_console = preferred_console >= 0;
      
      It is a puzzle. Dumb explanation is that it gets re-evaluated
      when:
      
      	+ it was not set before (see above when it gets set)
      	+ there is still an early console enabled (bcon)
      	+ there is no console enabled (!console_drivers)
      
      This is still a puzzle.
      
      It gets more clear when we see where the value is checked. The only
      meaning of the variable is to decide whether we should try to enable
      the new console by default.
      
      Rename the variable according to the single situation where
      the value is checked.
      
      The rename requires an inverted logic. Otherwise, it is a simple
      search & replace. It does not change the functionality.
      Signed-off-by: default avatarPetr Mladek <pmladek@suse.com>
      Reviewed-by: default avatarSergey Senozhatsky <senozhatsky@chromium.org>
      Link: https://lore.kernel.org/r/20211122132649.12737-3-pmladek@suse.com
      a6953370
    • Petr Mladek's avatar
      printk/console: Split out code that enables default console · ed758b30
      Petr Mladek authored
      Put the code enabling a console by default into a separate function
      called try_enable_default_console().
      
      Rename try_enable_new_console() to try_enable_preferred_console() to
      make the purpose of the different variants more clear.
      
      It is a code refactoring without any functional change.
      Signed-off-by: default avatarPetr Mladek <pmladek@suse.com>
      Reviewed-by: default avatarSergey Senozhatsky <senozhatsky@chromium.org>
      Link: https://lore.kernel.org/r/20211122132649.12737-2-pmladek@suse.com
      ed758b30
    • Christophe JAILLET's avatar
      vsprintf: Use non-atomic bitmap API when applicable · 52e68cd6
      Christophe JAILLET authored
      The 'set' bitmap is local to this function. No concurrent access to it is
      possible.
      So prefer the non-atomic '__[set|clear]_bit()' function to save a few
      cycles.
      Signed-off-by: default avatarChristophe JAILLET <christophe.jaillet@wanadoo.fr>
      Reviewed-by: default avatarPetr Mladek <pmladek@suse.com>
      Signed-off-by: default avatarPetr Mladek <pmladek@suse.com>
      Link: https://lore.kernel.org/r/1abf81a5e509d372393bd22041eed4ebc07ef9f7.1638023178.git.christophe.jaillet@wanadoo.fr
      52e68cd6
  5. 18 Nov, 2021 2 commits
  6. 17 Nov, 2021 4 commits
  7. 16 Nov, 2021 4 commits
  8. 15 Nov, 2021 8 commits
  9. 14 Nov, 2021 12 commits