• 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
printk.c 94.2 KB