@@ -86,7 +86,7 @@ EXPORT_SYMBOL(oops_in_progress);
8686static DEFINE_MUTEX (console_mutex );
8787
8888/*
89- * console_sem protects updates to console->seq and console_suspended,
89+ * console_sem protects updates to console->seq
9090 * and also provides serialization for console printing.
9191 */
9292static DEFINE_SEMAPHORE (console_sem );
@@ -359,7 +359,7 @@ static bool panic_in_progress(void)
359359 * paths in the console code where we end up in places I want
360360 * locked without the console semaphore held).
361361 */
362- static int console_locked , console_suspended ;
362+ static int console_locked ;
363363
364364/*
365365 * Array of consoles built from command line options (console=)
@@ -2549,22 +2549,46 @@ MODULE_PARM_DESC(console_no_auto_verbose, "Disable console loglevel raise to hig
25492549 */
25502550void suspend_console (void )
25512551{
2552+ struct console * con ;
2553+
25522554 if (!console_suspend_enabled )
25532555 return ;
25542556 pr_info ("Suspending console(s) (use no_console_suspend to debug)\n" );
25552557 pr_flush (1000 , true);
2556- console_lock ();
2557- console_suspended = 1 ;
2558- up_console_sem ();
2558+
2559+ console_list_lock ();
2560+ for_each_console (con )
2561+ console_srcu_write_flags (con , con -> flags | CON_SUSPENDED );
2562+ console_list_unlock ();
2563+
2564+ /*
2565+ * Ensure that all SRCU list walks have completed. All printing
2566+ * contexts must be able to see that they are suspended so that it
2567+ * is guaranteed that all printing has stopped when this function
2568+ * completes.
2569+ */
2570+ synchronize_srcu (& console_srcu );
25592571}
25602572
25612573void resume_console (void )
25622574{
2575+ struct console * con ;
2576+
25632577 if (!console_suspend_enabled )
25642578 return ;
2565- down_console_sem ();
2566- console_suspended = 0 ;
2567- console_unlock ();
2579+
2580+ console_list_lock ();
2581+ for_each_console (con )
2582+ console_srcu_write_flags (con , con -> flags & ~CON_SUSPENDED );
2583+ console_list_unlock ();
2584+
2585+ /*
2586+ * Ensure that all SRCU list walks have completed. All printing
2587+ * contexts must be able to see they are no longer suspended so
2588+ * that they are guaranteed to wake up and resume printing.
2589+ */
2590+ synchronize_srcu (& console_srcu );
2591+
25682592 pr_flush (1000 , true);
25692593}
25702594
@@ -2623,8 +2647,6 @@ void console_lock(void)
26232647 msleep (1000 );
26242648
26252649 down_console_sem ();
2626- if (console_suspended )
2627- return ;
26282650 console_locked = 1 ;
26292651 console_may_schedule = 1 ;
26302652}
@@ -2645,10 +2667,6 @@ int console_trylock(void)
26452667 return 0 ;
26462668 if (down_trylock_console_sem ())
26472669 return 0 ;
2648- if (console_suspended ) {
2649- up_console_sem ();
2650- return 0 ;
2651- }
26522670 console_locked = 1 ;
26532671 console_may_schedule = 0 ;
26542672 return 1 ;
@@ -2674,6 +2692,9 @@ static inline bool console_is_usable(struct console *con)
26742692 if (!(flags & CON_ENABLED ))
26752693 return false;
26762694
2695+ if ((flags & CON_SUSPENDED ))
2696+ return false;
2697+
26772698 if (!con -> write )
26782699 return false;
26792700
@@ -2992,11 +3013,6 @@ void console_unlock(void)
29923013 bool flushed ;
29933014 u64 next_seq ;
29943015
2995- if (console_suspended ) {
2996- up_console_sem ();
2997- return ;
2998- }
2999-
30003016 /*
30013017 * Console drivers are called with interrupts disabled, so
30023018 * @console_may_schedule should be cleared before; however, we may
@@ -3726,15 +3742,19 @@ static bool __pr_flush(struct console *con, int timeout_ms, bool reset_on_progre
37263742
37273743 /*
37283744 * Hold the console_lock to guarantee safe access to
3729- * console->seq and to prevent changes to @console_suspended
3730- * until all consoles have been processed.
3745+ * console->seq.
37313746 */
37323747 console_lock ();
37333748
37343749 cookie = console_srcu_read_lock ();
37353750 for_each_console_srcu (c ) {
37363751 if (con && con != c )
37373752 continue ;
3753+ /*
3754+ * If consoles are not usable, it cannot be expected
3755+ * that they make forward progress, so only increment
3756+ * @diff for usable consoles.
3757+ */
37383758 if (!console_is_usable (c ))
37393759 continue ;
37403760 printk_seq = c -> seq ;
@@ -3743,18 +3763,12 @@ static bool __pr_flush(struct console *con, int timeout_ms, bool reset_on_progre
37433763 }
37443764 console_srcu_read_unlock (cookie );
37453765
3746- /*
3747- * If consoles are suspended, it cannot be expected that they
3748- * make forward progress, so timeout immediately. @diff is
3749- * still used to return a valid flush status.
3750- */
3751- if (console_suspended )
3752- remaining = 0 ;
3753- else if (diff != last_diff && reset_on_progress )
3766+ if (diff != last_diff && reset_on_progress )
37543767 remaining = timeout_ms ;
37553768
37563769 console_unlock ();
37573770
3771+ /* Note: @diff is 0 if there are no usable consoles. */
37583772 if (diff == 0 || remaining == 0 )
37593773 break ;
37603774
@@ -3788,7 +3802,7 @@ static bool __pr_flush(struct console *con, int timeout_ms, bool reset_on_progre
37883802 * printer has been seen to make some forward progress.
37893803 *
37903804 * Context: Process context. May sleep while acquiring console lock.
3791- * Return: true if all enabled printers are caught up.
3805+ * Return: true if all usable printers are caught up.
37923806 */
37933807static bool pr_flush (int timeout_ms , bool reset_on_progress )
37943808{
0 commit comments