summaryrefslogtreecommitdiffstats
path: root/debian/patches-rt/0002-printk-Properly-deal-with-nbcon-consoles-on-seq-init.patch
diff options
context:
space:
mode:
Diffstat (limited to 'debian/patches-rt/0002-printk-Properly-deal-with-nbcon-consoles-on-seq-init.patch')
-rw-r--r--debian/patches-rt/0002-printk-Properly-deal-with-nbcon-consoles-on-seq-init.patch190
1 files changed, 190 insertions, 0 deletions
diff --git a/debian/patches-rt/0002-printk-Properly-deal-with-nbcon-consoles-on-seq-init.patch b/debian/patches-rt/0002-printk-Properly-deal-with-nbcon-consoles-on-seq-init.patch
new file mode 100644
index 0000000000..e42d83f140
--- /dev/null
+++ b/debian/patches-rt/0002-printk-Properly-deal-with-nbcon-consoles-on-seq-init.patch
@@ -0,0 +1,190 @@
+From: Petr Mladek <pmladek@suse.com>
+Date: Wed, 22 Nov 2023 11:23:43 +0000
+Subject: [PATCH 02/46] printk: Properly deal with nbcon consoles on seq init
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.9/older/patches-6.9-rt5.tar.xz
+
+If a non-boot console is registering and boot consoles exist,
+the consoles are flushed before being unregistered. This allows
+the non-boot console to continue where the boot console left
+off.
+
+If for whatever reason flushing fails, the lowest seq found from
+any of the enabled boot consoles is used. Until now con->seq was
+checked. However, if it is an nbcon boot console, the function
+nbcon_seq_read() must be used to read seq because con->seq is
+not updated for nbcon consoles.
+
+Check if it is an nbcon boot console and if so call
+nbcon_seq_read() to read seq.
+
+Also, avoid usage of con->seq as temporary storage of the
+starting record. Instead, rename console_init_seq() to
+get_init_console_seq() and just return the value. For nbcon
+consoles set the sequence via nbcon_init(), for legacy consoles
+set con->seq.
+
+The cleaned design should make sure that the value stays and is
+set before the printing kthread is created.
+
+Signed-off-by: Petr Mladek <pmladek@suse.com>
+Reviewed-by: John Ogness <john.ogness@linutronix.de>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ kernel/printk/internal.h | 4 ++--
+ kernel/printk/nbcon.c | 10 +++-------
+ kernel/printk/printk.c | 41 +++++++++++++++++++++++++++++------------
+ 3 files changed, 34 insertions(+), 21 deletions(-)
+
+--- a/kernel/printk/internal.h
++++ b/kernel/printk/internal.h
+@@ -75,7 +75,7 @@ u16 printk_parse_prefix(const char *text
+ u64 nbcon_seq_read(struct console *con);
+ void nbcon_seq_force(struct console *con, u64 seq);
+ bool nbcon_alloc(struct console *con);
+-void nbcon_init(struct console *con);
++void nbcon_init(struct console *con, u64 init_seq);
+ void nbcon_free(struct console *con);
+
+ #else
+@@ -96,7 +96,7 @@ static inline bool printk_percpu_data_re
+ static inline u64 nbcon_seq_read(struct console *con) { return 0; }
+ static inline void nbcon_seq_force(struct console *con, u64 seq) { }
+ static inline bool nbcon_alloc(struct console *con) { return false; }
+-static inline void nbcon_init(struct console *con) { }
++static inline void nbcon_init(struct console *con, u64 init_seq) { }
+ static inline void nbcon_free(struct console *con) { }
+
+ #endif /* CONFIG_PRINTK */
+--- a/kernel/printk/nbcon.c
++++ b/kernel/printk/nbcon.c
+@@ -172,9 +172,6 @@ void nbcon_seq_force(struct console *con
+ u64 valid_seq = max_t(u64, seq, prb_first_valid_seq(prb));
+
+ atomic_long_set(&ACCESS_PRIVATE(con, nbcon_seq), __u64seq_to_ulseq(valid_seq));
+-
+- /* Clear con->seq since nbcon consoles use con->nbcon_seq instead. */
+- con->seq = 0;
+ }
+
+ /**
+@@ -961,20 +958,19 @@ bool nbcon_alloc(struct console *con)
+ /**
+ * nbcon_init - Initialize the nbcon console specific data
+ * @con: Console to initialize
++ * @init_seq: Sequence number of the first record to be emitted
+ *
+ * nbcon_alloc() *must* be called and succeed before this function
+ * is called.
+- *
+- * This function expects that the legacy @con->seq has been set.
+ */
+-void nbcon_init(struct console *con)
++void nbcon_init(struct console *con, u64 init_seq)
+ {
+ struct nbcon_state state = { };
+
+ /* nbcon_alloc() must have been called and successful! */
+ BUG_ON(!con->pbufs);
+
+- nbcon_seq_force(con, con->seq);
++ nbcon_seq_force(con, init_seq);
+ nbcon_state_set(con, &state);
+ }
+
+--- a/kernel/printk/printk.c
++++ b/kernel/printk/printk.c
+@@ -3363,19 +3363,21 @@ static void try_enable_default_console(s
+ newcon->flags |= CON_CONSDEV;
+ }
+
+-static void console_init_seq(struct console *newcon, bool bootcon_registered)
++/* Return the starting sequence number for a newly registered console. */
++static u64 get_init_console_seq(struct console *newcon, bool bootcon_registered)
+ {
+ struct console *con;
+ bool handover;
++ u64 init_seq;
+
+ if (newcon->flags & (CON_PRINTBUFFER | CON_BOOT)) {
+ /* Get a consistent copy of @syslog_seq. */
+ mutex_lock(&syslog_lock);
+- newcon->seq = syslog_seq;
++ init_seq = syslog_seq;
+ mutex_unlock(&syslog_lock);
+ } else {
+ /* Begin with next message added to ringbuffer. */
+- newcon->seq = prb_next_seq(prb);
++ init_seq = prb_next_seq(prb);
+
+ /*
+ * If any enabled boot consoles are due to be unregistered
+@@ -3396,7 +3398,7 @@ static void console_init_seq(struct cons
+ * Flush all consoles and set the console to start at
+ * the next unprinted sequence number.
+ */
+- if (!console_flush_all(true, &newcon->seq, &handover)) {
++ if (!console_flush_all(true, &init_seq, &handover)) {
+ /*
+ * Flushing failed. Just choose the lowest
+ * sequence of the enabled boot consoles.
+@@ -3409,19 +3411,30 @@ static void console_init_seq(struct cons
+ if (handover)
+ console_lock();
+
+- newcon->seq = prb_next_seq(prb);
++ init_seq = prb_next_seq(prb);
+ for_each_console(con) {
+- if ((con->flags & CON_BOOT) &&
+- (con->flags & CON_ENABLED) &&
+- con->seq < newcon->seq) {
+- newcon->seq = con->seq;
++ u64 seq;
++
++ if (!(con->flags & CON_BOOT) ||
++ !(con->flags & CON_ENABLED)) {
++ continue;
+ }
++
++ if (con->flags & CON_NBCON)
++ seq = nbcon_seq_read(con);
++ else
++ seq = con->seq;
++
++ if (seq < init_seq)
++ init_seq = seq;
+ }
+ }
+
+ console_unlock();
+ }
+ }
++
++ return init_seq;
+ }
+
+ #define console_first() \
+@@ -3453,6 +3466,7 @@ void register_console(struct console *ne
+ struct console *con;
+ bool bootcon_registered = false;
+ bool realcon_registered = false;
++ u64 init_seq;
+ int err;
+
+ console_list_lock();
+@@ -3530,10 +3544,13 @@ void register_console(struct console *ne
+ }
+
+ newcon->dropped = 0;
+- console_init_seq(newcon, bootcon_registered);
++ init_seq = get_init_console_seq(newcon, bootcon_registered);
+
+- if (newcon->flags & CON_NBCON)
+- nbcon_init(newcon);
++ if (newcon->flags & CON_NBCON) {
++ nbcon_init(newcon, init_seq);
++ } else {
++ newcon->seq = init_seq;
++ }
+
+ /*
+ * Put this console in the list - keep the