OSDN Git Service

printk: do not wait for consoles when suspended
authorJohn Ogness <john.ogness@linutronix.de>
Fri, 15 Jul 2022 06:10:42 +0000 (08:16 +0206)
committerPetr Mladek <pmladek@suse.com>
Fri, 15 Jul 2022 08:52:11 +0000 (10:52 +0200)
The console_stop() and console_start() functions call pr_flush().
When suspending, these functions are called by the serial subsystem
while the serial port is suspended. In this scenario, if there are
any pending messages, a call to pr_flush() will always result in a
timeout because the serial port cannot make forward progress. This
causes longer suspend and resume times.

Add a check in pr_flush() so that it will immediately timeout if
the consoles are suspended.

Fixes: 3b604ca81202 ("printk: add pr_flush()")
Reported-by: Todd Brandt <todd.e.brandt@linux.intel.com>
Signed-off-by: John Ogness <john.ogness@linutronix.de>
Tested-by: Todd Brandt <todd.e.brandt@linux.intel.com>
Signed-off-by: Petr Mladek <pmladek@suse.com>
Link: https://lore.kernel.org/r/20220715061042.373640-2-john.ogness@linutronix.de
kernel/printk/printk.c

index b49c6ff..a1a81fd 100644 (file)
@@ -3380,6 +3380,7 @@ static bool __pr_flush(struct console *con, int timeout_ms, bool reset_on_progre
                diff = 0;
 
                console_lock();
+
                for_each_console(c) {
                        if (con && con != c)
                                continue;
@@ -3389,11 +3390,19 @@ static bool __pr_flush(struct console *con, int timeout_ms, bool reset_on_progre
                        if (printk_seq < seq)
                                diff += seq - printk_seq;
                }
-               console_unlock();
 
-               if (diff != last_diff && reset_on_progress)
+               /*
+                * If consoles are suspended, it cannot be expected that they
+                * make forward progress, so timeout immediately. @diff is
+                * still used to return a valid flush status.
+                */
+               if (console_suspended)
+                       remaining = 0;
+               else if (diff != last_diff && reset_on_progress)
                        remaining = timeout_ms;
 
+               console_unlock();
+
                if (diff == 0 || remaining == 0)
                        break;