@@ -2296,6 +2296,8 @@ asmlinkage __visible int _printk(const char *fmt, ...)
2296
2296
}
2297
2297
EXPORT_SYMBOL (_printk );
2298
2298
2299
+ static bool __pr_flush (struct console * con , int timeout_ms , bool reset_on_progress );
2300
+
2299
2301
#else /* CONFIG_PRINTK */
2300
2302
2301
2303
#define CONSOLE_LOG_MAX 0
@@ -2328,6 +2330,7 @@ static void call_console_driver(struct console *con, const char *text, size_t le
2328
2330
{
2329
2331
}
2330
2332
static 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; }
2331
2334
2332
2335
#endif /* CONFIG_PRINTK */
2333
2336
@@ -2515,6 +2518,7 @@ void suspend_console(void)
2515
2518
if (!console_suspend_enabled )
2516
2519
return ;
2517
2520
pr_info ("Suspending console(s) (use no_console_suspend to debug)\n" );
2521
+ pr_flush (1000 , true);
2518
2522
console_lock ();
2519
2523
console_suspended = 1 ;
2520
2524
up_console_sem ();
@@ -2527,6 +2531,7 @@ void resume_console(void)
2527
2531
down_console_sem ();
2528
2532
console_suspended = 0 ;
2529
2533
console_unlock ();
2534
+ pr_flush (1000 , true);
2530
2535
}
2531
2536
2532
2537
/**
@@ -2912,6 +2917,9 @@ void console_unblank(void)
2912
2917
if ((c -> flags & CON_ENABLED ) && c -> unblank )
2913
2918
c -> unblank ();
2914
2919
console_unlock ();
2920
+
2921
+ if (!oops_in_progress )
2922
+ pr_flush (1000 , true);
2915
2923
}
2916
2924
2917
2925
/**
@@ -2970,6 +2978,7 @@ struct tty_driver *console_device(int *index)
2970
2978
*/
2971
2979
void console_stop (struct console * console )
2972
2980
{
2981
+ __pr_flush (console , 1000 , true);
2973
2982
console_lock ();
2974
2983
console -> flags &= ~CON_ENABLED ;
2975
2984
console_unlock ();
@@ -2981,6 +2990,7 @@ void console_start(struct console *console)
2981
2990
console_lock ();
2982
2991
console -> flags |= CON_ENABLED ;
2983
2992
console_unlock ();
2993
+ __pr_flush (console , 1000 , true);
2984
2994
}
2985
2995
EXPORT_SYMBOL (console_start );
2986
2996
@@ -3352,6 +3362,79 @@ static int __init printk_late_init(void)
3352
3362
late_initcall (printk_late_init );
3353
3363
3354
3364
#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
+
3355
3438
/*
3356
3439
* Delayed printk version, for scheduler-internal messages:
3357
3440
*/
0 commit comments