Skip to content

Commit e0830db

Browse files
jhovoldgregkh
authored andcommitted
serial: core: fix console port-lock regression
Fix the port-lock initialisation regression introduced by commit a3cb39d ("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 42b6a1b ("serial_core: Don't re-initialize a previously initialized spinlock.")). Fixes: a3cb39d ("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>
1 parent fe88c64 commit e0830db

2 files changed

Lines changed: 16 additions & 17 deletions

File tree

drivers/tty/serial/serial_core.c

Lines changed: 15 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1916,24 +1916,12 @@ static inline bool uart_console_enabled(struct uart_port *port)
19161916
return uart_console(port) && (port->cons->flags & CON_ENABLED);
19171917
}
19181918

1919-
static void __uart_port_spin_lock_init(struct uart_port *port)
1919+
static void uart_port_spin_lock_init(struct uart_port *port)
19201920
{
19211921
spin_lock_init(&port->lock);
19221922
lockdep_set_class(&port->lock, &port_lock_key);
19231923
}
19241924

1925-
/*
1926-
* Ensure that the serial console lock is initialised early.
1927-
* If this port is a console, then the spinlock is already initialised.
1928-
*/
1929-
static inline void uart_port_spin_lock_init(struct uart_port *port)
1930-
{
1931-
if (uart_console(port))
1932-
return;
1933-
1934-
__uart_port_spin_lock_init(port);
1935-
}
1936-
19371925
#if defined(CONFIG_SERIAL_CORE_CONSOLE) || defined(CONFIG_CONSOLE_POLL)
19381926
/**
19391927
* uart_console_write - write a console message to a serial port
@@ -2086,7 +2074,15 @@ uart_set_options(struct uart_port *port, struct console *co,
20862074
struct ktermios termios;
20872075
static struct ktermios dummy;
20882076

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

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

@@ -2794,10 +2790,12 @@ static ssize_t console_store(struct device *dev,
27942790
if (oldconsole && !newconsole) {
27952791
ret = unregister_console(uport->cons);
27962792
} else if (!oldconsole && newconsole) {
2797-
if (uart_console(uport))
2793+
if (uart_console(uport)) {
2794+
uport->console_reinit = 1;
27982795
register_console(uport->cons);
2799-
else
2796+
} else {
28002797
ret = -ENOENT;
2798+
}
28012799
}
28022800
} else {
28032801
ret = -ENXIO;
@@ -2898,7 +2896,7 @@ int uart_add_one_port(struct uart_driver *drv, struct uart_port *uport)
28982896
* initialised.
28992897
*/
29002898
if (!uart_console_enabled(uport))
2901-
__uart_port_spin_lock_init(uport);
2899+
uart_port_spin_lock_init(uport);
29022900

29032901
if (uport->cons && uport->dev)
29042902
of_console_check(uport->dev->of_node, uport->cons->name, uport->line);

include/linux/serial_core.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,7 @@ struct uart_port {
248248

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

0 commit comments

Comments
 (0)