lkml.org 
[lkml]   [2020]   [Sep]   [21]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 5.8 101/118] serial: core: fix console port-lock regression
    Date
    From: Johan Hovold <johan@kernel.org>

    commit e0830dbf71f191851ed3772d2760f007b7c5bc3a upstream.

    Fix the port-lock initialisation regression introduced by commit
    a3cb39d258ef ("serial: core: Allow detach and attach serial device for
    console") by making sure that the lock is again initialised during
    console setup.

    The console may be registered before the serial controller has been
    probed in which case the port lock needs to be initialised during
    console setup by a call to uart_set_options(). The console-detach
    changes introduced a regression in several drivers by effectively
    removing that initialisation by not initialising the lock when the port
    is used as a console (which is always the case during console setup).

    Add back the early lock initialisation and instead use a new
    console-reinit flag to handle the case where a console is being
    re-attached through sysfs.

    The question whether the console-detach interface should have been added
    in the first place is left for another discussion.

    Note that the console-enabled check in uart_set_options() is not
    redundant because of kgdboc, which can end up reinitialising an already
    enabled console (see commit 42b6a1baa3ec ("serial_core: Don't
    re-initialize a previously initialized spinlock.")).

    Fixes: a3cb39d258ef ("serial: core: Allow detach and attach serial device for console")
    Cc: stable <stable@vger.kernel.org> # 5.7
    Signed-off-by: Johan Hovold <johan@kernel.org>
    Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
    Link: https://lore.kernel.org/r/20200909143101.15389-3-johan@kernel.org
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

    ---
    drivers/tty/serial/serial_core.c | 32 +++++++++++++++-----------------
    include/linux/serial_core.h | 1 +
    2 files changed, 16 insertions(+), 17 deletions(-)

    --- a/drivers/tty/serial/serial_core.c
    +++ b/drivers/tty/serial/serial_core.c
    @@ -1914,24 +1914,12 @@ static inline bool uart_console_enabled(
    return uart_console(port) && (port->cons->flags & CON_ENABLED);
    }

    -static void __uart_port_spin_lock_init(struct uart_port *port)
    +static void uart_port_spin_lock_init(struct uart_port *port)
    {
    spin_lock_init(&port->lock);
    lockdep_set_class(&port->lock, &port_lock_key);
    }

    -/*
    - * Ensure that the serial console lock is initialised early.
    - * If this port is a console, then the spinlock is already initialised.
    - */
    -static inline void uart_port_spin_lock_init(struct uart_port *port)
    -{
    - if (uart_console(port))
    - return;
    -
    - __uart_port_spin_lock_init(port);
    -}
    -
    #if defined(CONFIG_SERIAL_CORE_CONSOLE) || defined(CONFIG_CONSOLE_POLL)
    /**
    * uart_console_write - write a console message to a serial port
    @@ -2084,7 +2072,15 @@ uart_set_options(struct uart_port *port,
    struct ktermios termios;
    static struct ktermios dummy;

    - uart_port_spin_lock_init(port);
    + /*
    + * Ensure that the serial-console lock is initialised early.
    + *
    + * Note that the console-enabled check is needed because of kgdboc,
    + * which can end up calling uart_set_options() for an already enabled
    + * console via tty_find_polling_driver() and uart_poll_init().
    + */
    + if (!uart_console_enabled(port) && !port->console_reinit)
    + uart_port_spin_lock_init(port);

    memset(&termios, 0, sizeof(struct ktermios));

    @@ -2791,10 +2787,12 @@ static ssize_t console_store(struct devi
    if (oldconsole && !newconsole) {
    ret = unregister_console(uport->cons);
    } else if (!oldconsole && newconsole) {
    - if (uart_console(uport))
    + if (uart_console(uport)) {
    + uport->console_reinit = 1;
    register_console(uport->cons);
    - else
    + } else {
    ret = -ENOENT;
    + }
    }
    } else {
    ret = -ENXIO;
    @@ -2895,7 +2893,7 @@ int uart_add_one_port(struct uart_driver
    * initialised.
    */
    if (!uart_console_enabled(uport))
    - __uart_port_spin_lock_init(uport);
    + uart_port_spin_lock_init(uport);

    if (uport->cons && uport->dev)
    of_console_check(uport->dev->of_node, uport->cons->name, uport->line);
    --- a/include/linux/serial_core.h
    +++ b/include/linux/serial_core.h
    @@ -248,6 +248,7 @@ struct uart_port {

    unsigned char hub6; /* this should be in the 8250 driver */
    unsigned char suspended;
    + unsigned char console_reinit;
    const char *name; /* port name */
    struct attribute_group *attr_group; /* port specific attributes */
    const struct attribute_group **tty_groups; /* all attributes (serial core use only) */

    \
     
     \ /
      Last update: 2020-09-21 18:55    [W:4.082 / U:0.212 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site