diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-18 17:39:59 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-18 17:39:59 +0000 |
commit | 27d3313807296c3943a96ceef8c2b7279cb56962 (patch) | |
tree | 7d08e78c36ab6437b403fc7cd8c23e41f135c7a3 /debian/patches-rt/0029-printk-Avoid-console_lock-dance-if-no-legacy-or-boot.patch | |
parent | Merging upstream version 6.7.7. (diff) | |
download | linux-debian/6.7.7-1.tar.xz linux-debian/6.7.7-1.zip |
Adding debian version 6.7.7-1.debian/6.7.7-1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'debian/patches-rt/0029-printk-Avoid-console_lock-dance-if-no-legacy-or-boot.patch')
-rw-r--r-- | debian/patches-rt/0029-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/0029-printk-Avoid-console_lock-dance-if-no-legacy-or-boot.patch b/debian/patches-rt/0029-printk-Avoid-console_lock-dance-if-no-legacy-or-boot.patch new file mode 100644 index 0000000000..a0be40fe7b --- /dev/null +++ b/debian/patches-rt/0029-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 29/50] printk: Avoid console_lock dance if no legacy or boot + consoles +Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.7/older/patches-6.7-rt6.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 +@@ -2344,7 +2351,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 +@@ -2653,7 +2660,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(); +@@ -3196,7 +3203,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); + } + + /* +@@ -3521,8 +3529,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; +@@ -3579,6 +3590,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; +@@ -3635,9 +3647,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; + } +@@ -3789,6 +3805,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; +@@ -3798,22 +3815,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) { +@@ -3833,6 +3856,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; + } + +@@ -3844,7 +3868,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) +@@ -3966,7 +3991,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) |