@@ -86,7 +86,7 @@ EXPORT_SYMBOL(oops_in_progress);
86
86
static DEFINE_MUTEX (console_mutex );
87
87
88
88
/*
89
- * console_sem protects updates to console->seq and console_suspended,
89
+ * console_sem protects updates to console->seq
90
90
* and also provides serialization for console printing.
91
91
*/
92
92
static DEFINE_SEMAPHORE (console_sem );
@@ -359,7 +359,7 @@ static bool panic_in_progress(void)
359
359
* paths in the console code where we end up in places I want
360
360
* locked without the console semaphore held).
361
361
*/
362
- static int console_locked , console_suspended ;
362
+ static int console_locked ;
363
363
364
364
/*
365
365
* 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
2549
2549
*/
2550
2550
void suspend_console (void )
2551
2551
{
2552
+ struct console * con ;
2553
+
2552
2554
if (!console_suspend_enabled )
2553
2555
return ;
2554
2556
pr_info ("Suspending console(s) (use no_console_suspend to debug)\n" );
2555
2557
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 );
2559
2571
}
2560
2572
2561
2573
void resume_console (void )
2562
2574
{
2575
+ struct console * con ;
2576
+
2563
2577
if (!console_suspend_enabled )
2564
2578
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
+
2568
2592
pr_flush (1000 , true);
2569
2593
}
2570
2594
@@ -2623,8 +2647,6 @@ void console_lock(void)
2623
2647
msleep (1000 );
2624
2648
2625
2649
down_console_sem ();
2626
- if (console_suspended )
2627
- return ;
2628
2650
console_locked = 1 ;
2629
2651
console_may_schedule = 1 ;
2630
2652
}
@@ -2645,10 +2667,6 @@ int console_trylock(void)
2645
2667
return 0 ;
2646
2668
if (down_trylock_console_sem ())
2647
2669
return 0 ;
2648
- if (console_suspended ) {
2649
- up_console_sem ();
2650
- return 0 ;
2651
- }
2652
2670
console_locked = 1 ;
2653
2671
console_may_schedule = 0 ;
2654
2672
return 1 ;
@@ -2674,6 +2692,9 @@ static inline bool console_is_usable(struct console *con)
2674
2692
if (!(flags & CON_ENABLED ))
2675
2693
return false;
2676
2694
2695
+ if ((flags & CON_SUSPENDED ))
2696
+ return false;
2697
+
2677
2698
if (!con -> write )
2678
2699
return false;
2679
2700
@@ -2992,11 +3013,6 @@ void console_unlock(void)
2992
3013
bool flushed ;
2993
3014
u64 next_seq ;
2994
3015
2995
- if (console_suspended ) {
2996
- up_console_sem ();
2997
- return ;
2998
- }
2999
-
3000
3016
/*
3001
3017
* Console drivers are called with interrupts disabled, so
3002
3018
* @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
3726
3742
3727
3743
/*
3728
3744
* 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.
3731
3746
*/
3732
3747
console_lock ();
3733
3748
3734
3749
cookie = console_srcu_read_lock ();
3735
3750
for_each_console_srcu (c ) {
3736
3751
if (con && con != c )
3737
3752
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
+ */
3738
3758
if (!console_is_usable (c ))
3739
3759
continue ;
3740
3760
printk_seq = c -> seq ;
@@ -3743,18 +3763,12 @@ static bool __pr_flush(struct console *con, int timeout_ms, bool reset_on_progre
3743
3763
}
3744
3764
console_srcu_read_unlock (cookie );
3745
3765
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 )
3754
3767
remaining = timeout_ms ;
3755
3768
3756
3769
console_unlock ();
3757
3770
3771
+ /* Note: @diff is 0 if there are no usable consoles. */
3758
3772
if (diff == 0 || remaining == 0 )
3759
3773
break ;
3760
3774
@@ -3788,7 +3802,7 @@ static bool __pr_flush(struct console *con, int timeout_ms, bool reset_on_progre
3788
3802
* printer has been seen to make some forward progress.
3789
3803
*
3790
3804
* 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.
3792
3806
*/
3793
3807
static bool pr_flush (int timeout_ms , bool reset_on_progress )
3794
3808
{
0 commit comments