mirror of https://github.com/torvalds/linux.git
Merge branch 'rework/suspend-fixes' into for-linus
This commit is contained in:
commit
3a9a3f5fb2
|
|
@ -185,6 +185,8 @@ struct console_flush_type {
|
||||||
bool legacy_offload;
|
bool legacy_offload;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
extern bool console_irqwork_blocked;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Identify which console flushing methods should be used in the context of
|
* Identify which console flushing methods should be used in the context of
|
||||||
* the caller.
|
* the caller.
|
||||||
|
|
@ -196,7 +198,7 @@ static inline void printk_get_console_flush_type(struct console_flush_type *ft)
|
||||||
switch (nbcon_get_default_prio()) {
|
switch (nbcon_get_default_prio()) {
|
||||||
case NBCON_PRIO_NORMAL:
|
case NBCON_PRIO_NORMAL:
|
||||||
if (have_nbcon_console && !have_boot_console) {
|
if (have_nbcon_console && !have_boot_console) {
|
||||||
if (printk_kthreads_running)
|
if (printk_kthreads_running && !console_irqwork_blocked)
|
||||||
ft->nbcon_offload = true;
|
ft->nbcon_offload = true;
|
||||||
else
|
else
|
||||||
ft->nbcon_atomic = true;
|
ft->nbcon_atomic = true;
|
||||||
|
|
@ -206,7 +208,7 @@ static inline void printk_get_console_flush_type(struct console_flush_type *ft)
|
||||||
if (have_legacy_console || have_boot_console) {
|
if (have_legacy_console || have_boot_console) {
|
||||||
if (!is_printk_legacy_deferred())
|
if (!is_printk_legacy_deferred())
|
||||||
ft->legacy_direct = true;
|
ft->legacy_direct = true;
|
||||||
else
|
else if (!console_irqwork_blocked)
|
||||||
ft->legacy_offload = true;
|
ft->legacy_offload = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
@ -219,7 +221,7 @@ static inline void printk_get_console_flush_type(struct console_flush_type *ft)
|
||||||
if (have_legacy_console || have_boot_console) {
|
if (have_legacy_console || have_boot_console) {
|
||||||
if (!is_printk_legacy_deferred())
|
if (!is_printk_legacy_deferred())
|
||||||
ft->legacy_direct = true;
|
ft->legacy_direct = true;
|
||||||
else
|
else if (!console_irqwork_blocked)
|
||||||
ft->legacy_offload = true;
|
ft->legacy_offload = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
|
|
@ -1302,6 +1302,13 @@ void nbcon_kthreads_wake(void)
|
||||||
if (!printk_kthreads_running)
|
if (!printk_kthreads_running)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* It is not allowed to call this function when console irq_work
|
||||||
|
* is blocked.
|
||||||
|
*/
|
||||||
|
if (WARN_ON_ONCE(console_irqwork_blocked))
|
||||||
|
return;
|
||||||
|
|
||||||
cookie = console_srcu_read_lock();
|
cookie = console_srcu_read_lock();
|
||||||
for_each_console_srcu(con) {
|
for_each_console_srcu(con) {
|
||||||
if (!(console_srcu_read_flags(con) & CON_NBCON))
|
if (!(console_srcu_read_flags(con) & CON_NBCON))
|
||||||
|
|
@ -1892,7 +1899,7 @@ void nbcon_device_release(struct console *con)
|
||||||
if (console_trylock())
|
if (console_trylock())
|
||||||
console_unlock();
|
console_unlock();
|
||||||
} else if (ft.legacy_offload) {
|
} else if (ft.legacy_offload) {
|
||||||
printk_trigger_flush();
|
defer_console_output();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
console_srcu_read_unlock(cookie);
|
console_srcu_read_unlock(cookie);
|
||||||
|
|
|
||||||
|
|
@ -462,6 +462,9 @@ bool have_boot_console;
|
||||||
/* See printk_legacy_allow_panic_sync() for details. */
|
/* See printk_legacy_allow_panic_sync() for details. */
|
||||||
bool legacy_allow_panic_sync;
|
bool legacy_allow_panic_sync;
|
||||||
|
|
||||||
|
/* Avoid using irq_work when suspending. */
|
||||||
|
bool console_irqwork_blocked;
|
||||||
|
|
||||||
#ifdef CONFIG_PRINTK
|
#ifdef CONFIG_PRINTK
|
||||||
DECLARE_WAIT_QUEUE_HEAD(log_wait);
|
DECLARE_WAIT_QUEUE_HEAD(log_wait);
|
||||||
static DECLARE_WAIT_QUEUE_HEAD(legacy_wait);
|
static DECLARE_WAIT_QUEUE_HEAD(legacy_wait);
|
||||||
|
|
@ -2390,7 +2393,7 @@ asmlinkage int vprintk_emit(int facility, int level,
|
||||||
/* If called from the scheduler, we can not call up(). */
|
/* If called from the scheduler, we can not call up(). */
|
||||||
if (level == LOGLEVEL_SCHED) {
|
if (level == LOGLEVEL_SCHED) {
|
||||||
level = LOGLEVEL_DEFAULT;
|
level = LOGLEVEL_DEFAULT;
|
||||||
ft.legacy_offload |= ft.legacy_direct;
|
ft.legacy_offload |= ft.legacy_direct && !console_irqwork_blocked;
|
||||||
ft.legacy_direct = false;
|
ft.legacy_direct = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2426,7 +2429,7 @@ asmlinkage int vprintk_emit(int facility, int level,
|
||||||
|
|
||||||
if (ft.legacy_offload)
|
if (ft.legacy_offload)
|
||||||
defer_console_output();
|
defer_console_output();
|
||||||
else
|
else if (!console_irqwork_blocked)
|
||||||
wake_up_klogd();
|
wake_up_klogd();
|
||||||
|
|
||||||
return printed_len;
|
return printed_len;
|
||||||
|
|
@ -2730,10 +2733,20 @@ void console_suspend_all(void)
|
||||||
{
|
{
|
||||||
struct console *con;
|
struct console *con;
|
||||||
|
|
||||||
|
if (console_suspend_enabled)
|
||||||
|
pr_info("Suspending console(s) (use no_console_suspend to debug)\n");
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Flush any console backlog and then avoid queueing irq_work until
|
||||||
|
* console_resume_all(). Until then deferred printing is no longer
|
||||||
|
* triggered, NBCON consoles transition to atomic flushing, and
|
||||||
|
* any klogd waiters are not triggered.
|
||||||
|
*/
|
||||||
|
pr_flush(1000, true);
|
||||||
|
console_irqwork_blocked = true;
|
||||||
|
|
||||||
if (!console_suspend_enabled)
|
if (!console_suspend_enabled)
|
||||||
return;
|
return;
|
||||||
pr_info("Suspending console(s) (use no_console_suspend to debug)\n");
|
|
||||||
pr_flush(1000, true);
|
|
||||||
|
|
||||||
console_list_lock();
|
console_list_lock();
|
||||||
for_each_console(con)
|
for_each_console(con)
|
||||||
|
|
@ -2754,9 +2767,14 @@ void console_resume_all(void)
|
||||||
struct console_flush_type ft;
|
struct console_flush_type ft;
|
||||||
struct console *con;
|
struct console *con;
|
||||||
|
|
||||||
if (!console_suspend_enabled)
|
/*
|
||||||
return;
|
* Allow queueing irq_work. After restoring console state, deferred
|
||||||
|
* printing and any klogd waiters need to be triggered in case there
|
||||||
|
* is now a console backlog.
|
||||||
|
*/
|
||||||
|
console_irqwork_blocked = false;
|
||||||
|
|
||||||
|
if (console_suspend_enabled) {
|
||||||
console_list_lock();
|
console_list_lock();
|
||||||
for_each_console(con)
|
for_each_console(con)
|
||||||
console_srcu_write_flags(con, con->flags & ~CON_SUSPENDED);
|
console_srcu_write_flags(con, con->flags & ~CON_SUSPENDED);
|
||||||
|
|
@ -2768,12 +2786,15 @@ void console_resume_all(void)
|
||||||
* that they are guaranteed to wake up and resume printing.
|
* that they are guaranteed to wake up and resume printing.
|
||||||
*/
|
*/
|
||||||
synchronize_srcu(&console_srcu);
|
synchronize_srcu(&console_srcu);
|
||||||
|
}
|
||||||
|
|
||||||
printk_get_console_flush_type(&ft);
|
printk_get_console_flush_type(&ft);
|
||||||
if (ft.nbcon_offload)
|
if (ft.nbcon_offload)
|
||||||
nbcon_kthreads_wake();
|
nbcon_kthreads_wake();
|
||||||
if (ft.legacy_offload)
|
if (ft.legacy_offload)
|
||||||
defer_console_output();
|
defer_console_output();
|
||||||
|
else
|
||||||
|
wake_up_klogd();
|
||||||
|
|
||||||
pr_flush(1000, true);
|
pr_flush(1000, true);
|
||||||
}
|
}
|
||||||
|
|
@ -4559,6 +4580,13 @@ static void __wake_up_klogd(int val)
|
||||||
if (!printk_percpu_data_ready())
|
if (!printk_percpu_data_ready())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* It is not allowed to call this function when console irq_work
|
||||||
|
* is blocked.
|
||||||
|
*/
|
||||||
|
if (WARN_ON_ONCE(console_irqwork_blocked))
|
||||||
|
return;
|
||||||
|
|
||||||
preempt_disable();
|
preempt_disable();
|
||||||
/*
|
/*
|
||||||
* Guarantee any new records can be seen by tasks preparing to wait
|
* Guarantee any new records can be seen by tasks preparing to wait
|
||||||
|
|
@ -4615,8 +4643,29 @@ void defer_console_output(void)
|
||||||
__wake_up_klogd(PRINTK_PENDING_WAKEUP | PRINTK_PENDING_OUTPUT);
|
__wake_up_klogd(PRINTK_PENDING_WAKEUP | PRINTK_PENDING_OUTPUT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* printk_trigger_flush - Attempt to flush printk buffer to consoles.
|
||||||
|
*
|
||||||
|
* If possible, flush the printk buffer to all consoles in the caller's
|
||||||
|
* context. If offloading is available, trigger deferred printing.
|
||||||
|
*
|
||||||
|
* This is best effort. Depending on the system state, console states,
|
||||||
|
* and caller context, no actual flushing may result from this call.
|
||||||
|
*/
|
||||||
void printk_trigger_flush(void)
|
void printk_trigger_flush(void)
|
||||||
{
|
{
|
||||||
|
struct console_flush_type ft;
|
||||||
|
|
||||||
|
printk_get_console_flush_type(&ft);
|
||||||
|
if (ft.nbcon_atomic)
|
||||||
|
nbcon_atomic_flush_pending();
|
||||||
|
if (ft.nbcon_offload)
|
||||||
|
nbcon_kthreads_wake();
|
||||||
|
if (ft.legacy_direct) {
|
||||||
|
if (console_trylock())
|
||||||
|
console_unlock();
|
||||||
|
}
|
||||||
|
if (ft.legacy_offload)
|
||||||
defer_console_output();
|
defer_console_output();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue