Merge tag 'printk-for-6.2-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/print...
authorLinus Torvalds <torvalds@linux-foundation.org>
Thu, 19 Jan 2023 20:32:07 +0000 (12:32 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Thu, 19 Jan 2023 20:32:07 +0000 (12:32 -0800)
Pull printk fixes from Petr Mladek:

 - Prevent a potential deadlock when configuring kgdb console

 - Fix a kernel doc warning

* tag 'printk-for-6.2-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/printk/linux:
  kernel/printk/printk.c: Fix W=1 kernel-doc warning
  tty: serial: kgdboc: fix mutex locking order for configure_kgdboc()

drivers/tty/serial/kgdboc.c
drivers/tty/serial/serial_core.c
kernel/printk/printk.c

index a3ed9b34e2abb557374f91c64e23a1bad4cb16b2..7ce7bb1640054dd309e2feb45eea9083eb89705e 100644 (file)
@@ -171,6 +171,7 @@ static int configure_kgdboc(void)
        int err = -ENODEV;
        char *cptr = config;
        struct console *cons;
+       int cookie;
 
        if (!strlen(config) || isspace(config[0])) {
                err = 0;
@@ -189,20 +190,9 @@ static int configure_kgdboc(void)
        if (kgdboc_register_kbd(&cptr))
                goto do_register;
 
-       /*
-        * tty_find_polling_driver() can call uart_set_options()
-        * (via poll_init) to configure the uart. Take the console_list_lock
-        * in order to synchronize against register_console(), which can also
-        * configure the uart via uart_set_options(). This also allows safe
-        * traversal of the console list.
-        */
-       console_list_lock();
-
        p = tty_find_polling_driver(cptr, &tty_line);
-       if (!p) {
-               console_list_unlock();
+       if (!p)
                goto noconfig;
-       }
 
        /*
         * Take console_lock to serialize device() callback with
@@ -211,7 +201,8 @@ static int configure_kgdboc(void)
         */
        console_lock();
 
-       for_each_console(cons) {
+       cookie = console_srcu_read_lock();
+       for_each_console_srcu(cons) {
                int idx;
                if (cons->device && cons->device(cons, &idx) == p &&
                    idx == tty_line) {
@@ -219,11 +210,10 @@ static int configure_kgdboc(void)
                        break;
                }
        }
+       console_srcu_read_unlock(cookie);
 
        console_unlock();
 
-       console_list_unlock();
-
        kgdb_tty_driver = p;
        kgdb_tty_line = tty_line;
 
index b9fbbee598b815e8cd41527dc0acec65c8958710..ec874f3a567ca79bea6fd1d3503f5b78dfba4f8b 100644 (file)
@@ -2212,6 +2212,9 @@ EXPORT_SYMBOL_GPL(uart_parse_options);
  * @parity: parity character - 'n' (none), 'o' (odd), 'e' (even)
  * @bits: number of data bits
  * @flow: flow control character - 'r' (rts)
+ *
+ * Locking: Caller must hold console_list_lock in order to serialize
+ * early initialization of the serial-console lock.
  */
 int
 uart_set_options(struct uart_port *port, struct console *co,
@@ -2619,7 +2622,9 @@ static int uart_poll_init(struct tty_driver *driver, int line, char *options)
 
        if (!ret && options) {
                uart_parse_options(options, &baud, &parity, &bits, &flow);
+               console_list_lock();
                ret = uart_set_options(port, NULL, baud, parity, bits, flow);
+               console_list_unlock();
        }
 out:
        mutex_unlock(&tport->mutex);
index 7decf1e9c48635c3b151661208108a70c5d63e22..a5ed2e53547c94fdcd016427111f2bc26ee8cc74 100644 (file)
@@ -123,6 +123,7 @@ bool console_srcu_read_lock_is_held(void)
 {
        return srcu_read_lock_held(&console_srcu);
 }
+EXPORT_SYMBOL(console_srcu_read_lock_is_held);
 #endif
 
 enum devkmsg_log_bits {
@@ -1891,6 +1892,7 @@ static void console_lock_spinning_enable(void)
 /**
  * console_lock_spinning_disable_and_check - mark end of code where another
  *     thread was able to busy wait and check if there is a waiter
+ * @cookie: cookie returned from console_srcu_read_lock()
  *
  * This is called at the end of the section where spinning is allowed.
  * It has two functions. First, it is a signal that it is no longer