diff options
Diffstat (limited to 'debian/patches-rt/0113-printk-Avoid-console_lock-dance-if-no-legacy-or-boot.patch')
-rw-r--r-- | debian/patches-rt/0113-printk-Avoid-console_lock-dance-if-no-legacy-or-boot.patch | 211 |
1 files changed, 211 insertions, 0 deletions
diff --git a/debian/patches-rt/0113-printk-Avoid-console_lock-dance-if-no-legacy-or-boot.patch b/debian/patches-rt/0113-printk-Avoid-console_lock-dance-if-no-legacy-or-boot.patch new file mode 100644 index 0000000000..a733638677 --- /dev/null +++ b/debian/patches-rt/0113-printk-Avoid-console_lock-dance-if-no-legacy-or-boot.patch @@ -0,0 +1,211 @@ +From: John Ogness <john.ogness@linutronix.de> +Date: Tue, 26 Sep 2023 12:44:07 +0000 +Subject: [PATCH 113/134] printk: Avoid console_lock dance if no legacy or boot + consoles +Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz + +Currently the console lock is used to attempt legacy-type +printing even if there are no legacy or boot consoles registered. +If no such consoles are registered, the console lock does not +need to be taken. + +Also, if boot consoles are registered, nbcon consoles must +perform their atomic printing under the console lock in order +to be synchronized with boot consoles. + +Add tracking of legacy console registration and use it with +boot console tracking to avoid unnecessary code paths, i.e. +do not use the console lock if there are no boot consoles +and no legacy consoles. + +Signed-off-by: John Ogness <john.ogness@linutronix.de> +Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> +--- + kernel/printk/internal.h | 12 +++++++++ + kernel/printk/printk.c | 59 +++++++++++++++++++++++++++++++++++------------ + 2 files changed, 56 insertions(+), 15 deletions(-) + +--- a/kernel/printk/internal.h ++++ b/kernel/printk/internal.h +@@ -44,6 +44,16 @@ enum printk_info_flags { + }; + + extern struct printk_ringbuffer *prb; ++extern bool have_legacy_console; ++extern bool have_boot_console; ++ ++/* ++ * Specifies if the console lock/unlock dance is needed for console ++ * printing. If @have_boot_console is true, the nbcon consoles will ++ * be printed serially along with the legacy consoles because nbcon ++ * consoles cannot print simultaneously with boot consoles. ++ */ ++#define printing_via_unlock (have_legacy_console || have_boot_console) + + __printf(4, 0) + int vprintk_store(int facility, int level, +@@ -122,6 +132,8 @@ static inline bool console_is_usable(str + #define PRINTK_MESSAGE_MAX 0 + #define PRINTKRB_RECORD_MAX 0 + ++#define printing_via_unlock (false) ++ + /* + * In !PRINTK builds we still export console_sem + * semaphore and some of console functions (console_unlock()/etc.), so +--- a/kernel/printk/printk.c ++++ b/kernel/printk/printk.c +@@ -464,6 +464,13 @@ static int console_msg_format = MSG_FORM + static DEFINE_MUTEX(syslog_lock); + + /* ++ * Specifies if a legacy console is registered. If legacy consoles are ++ * present, it is necessary to perform the console_lock/console_unlock dance ++ * whenever console flushing should occur. ++ */ ++bool have_legacy_console; ++ ++/* + * Specifies if a boot console is registered. If boot consoles are present, + * nbcon consoles cannot print simultaneously and must be synchronized by + * the console lock. This is because boot consoles and nbcon consoles may +@@ -2345,7 +2352,7 @@ asmlinkage int vprintk_emit(int facility + printed_len = vprintk_store(facility, level, dev_info, fmt, args); + + /* If called from the scheduler, we can not call up(). */ +- if (!in_sched) { ++ if (!in_sched && printing_via_unlock) { + /* + * The caller may be holding system-critical or + * timing-sensitive locks. Disable preemption during +@@ -2646,7 +2653,7 @@ void resume_console(void) + */ + static int console_cpu_notify(unsigned int cpu) + { +- if (!cpuhp_tasks_frozen) { ++ if (!cpuhp_tasks_frozen && printing_via_unlock) { + /* If trylock fails, someone else is doing the printing */ + if (console_trylock()) + console_unlock(); +@@ -3189,7 +3196,8 @@ void console_flush_on_panic(enum con_flu + + nbcon_atomic_flush_all(); + +- console_flush_all(false, &next_seq, &handover); ++ if (printing_via_unlock) ++ console_flush_all(false, &next_seq, &handover); + } + + /* +@@ -3514,8 +3522,11 @@ void register_console(struct console *ne + newcon->dropped = 0; + console_init_seq(newcon, bootcon_registered); + +- if (newcon->flags & CON_NBCON) ++ if (newcon->flags & CON_NBCON) { + nbcon_init(newcon); ++ } else { ++ have_legacy_console = true; ++ } + + if (newcon->flags & CON_BOOT) + have_boot_console = true; +@@ -3572,6 +3583,7 @@ EXPORT_SYMBOL(register_console); + /* Must be called under console_list_lock(). */ + static int unregister_console_locked(struct console *console) + { ++ bool found_legacy_con = false; + bool found_boot_con = false; + struct console *c; + int res; +@@ -3628,9 +3640,13 @@ static int unregister_console_locked(str + for_each_console(c) { + if (c->flags & CON_BOOT) + found_boot_con = true; ++ if (!(c->flags & CON_NBCON)) ++ found_legacy_con = true; + } + if (!found_boot_con) + have_boot_console = false; ++ if (!found_legacy_con) ++ have_legacy_console = false; + + return res; + } +@@ -3782,6 +3798,7 @@ static bool __pr_flush(struct console *c + u64 last_diff = 0; + u64 printk_seq; + short flags; ++ bool locked; + int cookie; + u64 diff; + u64 seq; +@@ -3791,22 +3808,28 @@ static bool __pr_flush(struct console *c + seq = prb_next_reserve_seq(prb); + + /* Flush the consoles so that records up to @seq are printed. */ +- console_lock(); +- console_unlock(); ++ if (printing_via_unlock) { ++ console_lock(); ++ console_unlock(); ++ } + + for (;;) { + unsigned long begin_jiffies; + unsigned long slept_jiffies; + ++ locked = false; + diff = 0; + +- /* +- * Hold the console_lock to guarantee safe access to +- * console->seq. Releasing console_lock flushes more +- * records in case @seq is still not printed on all +- * usable consoles. +- */ +- console_lock(); ++ if (printing_via_unlock) { ++ /* ++ * Hold the console_lock to guarantee safe access to ++ * console->seq. Releasing console_lock flushes more ++ * records in case @seq is still not printed on all ++ * usable consoles. ++ */ ++ console_lock(); ++ locked = true; ++ } + + cookie = console_srcu_read_lock(); + for_each_console_srcu(c) { +@@ -3826,6 +3849,7 @@ static bool __pr_flush(struct console *c + if (flags & CON_NBCON) { + printk_seq = nbcon_seq_read(c); + } else { ++ WARN_ON_ONCE(!locked); + printk_seq = c->seq; + } + +@@ -3837,7 +3861,8 @@ static bool __pr_flush(struct console *c + if (diff != last_diff && reset_on_progress) + remaining_jiffies = timeout_jiffies; + +- console_unlock(); ++ if (locked) ++ console_unlock(); + + /* Note: @diff is 0 if there are no usable consoles. */ + if (diff == 0 || remaining_jiffies == 0) +@@ -3959,7 +3984,11 @@ void defer_console_output(void) + * New messages may have been added directly to the ringbuffer + * using vprintk_store(), so wake any waiters as well. + */ +- __wake_up_klogd(PRINTK_PENDING_WAKEUP | PRINTK_PENDING_OUTPUT); ++ int val = PRINTK_PENDING_WAKEUP; ++ ++ if (printing_via_unlock) ++ val |= PRINTK_PENDING_OUTPUT; ++ __wake_up_klogd(val); + } + + void printk_trigger_flush(void) |