@@ -2296,6 +2296,8 @@ asmlinkage __visible int _printk(const char *fmt, ...)
22962296}
22972297EXPORT_SYMBOL (_printk );
22982298
2299+ static bool __pr_flush (struct console * con , int timeout_ms , bool reset_on_progress );
2300+
22992301#else /* CONFIG_PRINTK */
23002302
23012303#define CONSOLE_LOG_MAX 0
@@ -2328,6 +2330,7 @@ static void call_console_driver(struct console *con, const char *text, size_t le
23282330{
23292331}
23302332static bool suppress_message_printing (int level ) { return false; }
2333+ static bool __pr_flush (struct console * con , int timeout_ms , bool reset_on_progress ) { return true; }
23312334
23322335#endif /* CONFIG_PRINTK */
23332336
@@ -2515,6 +2518,7 @@ void suspend_console(void)
25152518 if (!console_suspend_enabled )
25162519 return ;
25172520 pr_info ("Suspending console(s) (use no_console_suspend to debug)\n" );
2521+ pr_flush (1000 , true);
25182522 console_lock ();
25192523 console_suspended = 1 ;
25202524 up_console_sem ();
@@ -2527,6 +2531,7 @@ void resume_console(void)
25272531 down_console_sem ();
25282532 console_suspended = 0 ;
25292533 console_unlock ();
2534+ pr_flush (1000 , true);
25302535}
25312536
25322537/**
@@ -2912,6 +2917,9 @@ void console_unblank(void)
29122917 if ((c -> flags & CON_ENABLED ) && c -> unblank )
29132918 c -> unblank ();
29142919 console_unlock ();
2920+
2921+ if (!oops_in_progress )
2922+ pr_flush (1000 , true);
29152923}
29162924
29172925/**
@@ -2970,6 +2978,7 @@ struct tty_driver *console_device(int *index)
29702978 */
29712979void console_stop (struct console * console )
29722980{
2981+ __pr_flush (console , 1000 , true);
29732982 console_lock ();
29742983 console -> flags &= ~CON_ENABLED ;
29752984 console_unlock ();
@@ -2981,6 +2990,7 @@ void console_start(struct console *console)
29812990 console_lock ();
29822991 console -> flags |= CON_ENABLED ;
29832992 console_unlock ();
2993+ __pr_flush (console , 1000 , true);
29842994}
29852995EXPORT_SYMBOL (console_start );
29862996
@@ -3352,6 +3362,79 @@ static int __init printk_late_init(void)
33523362late_initcall (printk_late_init );
33533363
33543364#if defined CONFIG_PRINTK
3365+ /* If @con is specified, only wait for that console. Otherwise wait for all. */
3366+ static bool __pr_flush (struct console * con , int timeout_ms , bool reset_on_progress )
3367+ {
3368+ int remaining = timeout_ms ;
3369+ struct console * c ;
3370+ u64 last_diff = 0 ;
3371+ u64 printk_seq ;
3372+ u64 diff ;
3373+ u64 seq ;
3374+
3375+ might_sleep ();
3376+
3377+ seq = prb_next_seq (prb );
3378+
3379+ for (;;) {
3380+ diff = 0 ;
3381+
3382+ console_lock ();
3383+ for_each_console (c ) {
3384+ if (con && con != c )
3385+ continue ;
3386+ if (!console_is_usable (c ))
3387+ continue ;
3388+ printk_seq = c -> seq ;
3389+ if (printk_seq < seq )
3390+ diff += seq - printk_seq ;
3391+ }
3392+ console_unlock ();
3393+
3394+ if (diff != last_diff && reset_on_progress )
3395+ remaining = timeout_ms ;
3396+
3397+ if (diff == 0 || remaining == 0 )
3398+ break ;
3399+
3400+ if (remaining < 0 ) {
3401+ /* no timeout limit */
3402+ msleep (100 );
3403+ } else if (remaining < 100 ) {
3404+ msleep (remaining );
3405+ remaining = 0 ;
3406+ } else {
3407+ msleep (100 );
3408+ remaining -= 100 ;
3409+ }
3410+
3411+ last_diff = diff ;
3412+ }
3413+
3414+ return (diff == 0 );
3415+ }
3416+
3417+ /**
3418+ * pr_flush() - Wait for printing threads to catch up.
3419+ *
3420+ * @timeout_ms: The maximum time (in ms) to wait.
3421+ * @reset_on_progress: Reset the timeout if forward progress is seen.
3422+ *
3423+ * A value of 0 for @timeout_ms means no waiting will occur. A value of -1
3424+ * represents infinite waiting.
3425+ *
3426+ * If @reset_on_progress is true, the timeout will be reset whenever any
3427+ * printer has been seen to make some forward progress.
3428+ *
3429+ * Context: Process context. May sleep while acquiring console lock.
3430+ * Return: true if all enabled printers are caught up.
3431+ */
3432+ bool pr_flush (int timeout_ms , bool reset_on_progress )
3433+ {
3434+ return __pr_flush (NULL , timeout_ms , reset_on_progress );
3435+ }
3436+ EXPORT_SYMBOL (pr_flush );
3437+
33553438/*
33563439 * Delayed printk version, for scheduler-internal messages:
33573440 */
0 commit comments