summaryrefslogtreecommitdiffstats
path: root/debian/patches-rt/0040-printk-nbcon-Show-replay-message-on-takeover.patch
diff options
context:
space:
mode:
Diffstat (limited to 'debian/patches-rt/0040-printk-nbcon-Show-replay-message-on-takeover.patch')
-rw-r--r--debian/patches-rt/0040-printk-nbcon-Show-replay-message-on-takeover.patch135
1 files changed, 135 insertions, 0 deletions
diff --git a/debian/patches-rt/0040-printk-nbcon-Show-replay-message-on-takeover.patch b/debian/patches-rt/0040-printk-nbcon-Show-replay-message-on-takeover.patch
new file mode 100644
index 000000000..ab1046954
--- /dev/null
+++ b/debian/patches-rt/0040-printk-nbcon-Show-replay-message-on-takeover.patch
@@ -0,0 +1,135 @@
+From: John Ogness <john.ogness@linutronix.de>
+Date: Mon, 25 Mar 2024 21:00:40 +0000
+Subject: [PATCH 40/48] printk: nbcon: Show replay message on takeover
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.8/older/patches-6.8.2-rt11.tar.xz
+
+An emergency or panic context can takeover console ownership
+while the current owner was printing a printk message. The
+atomic printer will re-print the message that the previous
+owner was printing. However, this can look confusing to the
+user and may even seem as though a message was lost.
+
+ [3430014.1
+ [3430014.181123] usb 1-2: Product: USB Audio
+
+Add a new field @nbcon_prev_seq to struct console to track
+the sequence number to print that was assigned to the previous
+console owner. If this matches the sequence number to print
+that the current owner is assigned, then a takeover must have
+occurred. In this case, print an additional message to inform
+the user that the previous message is being printed again.
+
+ [3430014.1
+ ** replaying previous printk message **
+ [3430014.181123] usb 1-2: Product: USB Audio
+
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ include/linux/console.h | 2 ++
+ kernel/printk/internal.h | 1 +
+ kernel/printk/nbcon.c | 24 ++++++++++++++++++++++++
+ kernel/printk/printk.c | 19 +++++++++++++++++++
+ 4 files changed, 46 insertions(+)
+
+--- a/include/linux/console.h
++++ b/include/linux/console.h
+@@ -325,6 +325,7 @@ struct nbcon_drvdata {
+ *
+ * @nbcon_state: State for nbcon consoles
+ * @nbcon_seq: Sequence number of the next record for nbcon to print
++ * @nbcon_prev_seq: Seq num the previous nbcon owner was assigned to print
+ * @pbufs: Pointer to nbcon private buffer
+ * @kthread: Printer kthread for this console
+ * @rcuwait: RCU-safe wait object for @kthread waking
+@@ -441,6 +442,7 @@ struct console {
+
+ atomic_t __private nbcon_state;
+ atomic_long_t __private nbcon_seq;
++ atomic_long_t __private nbcon_prev_seq;
+
+ /**
+ * @nbcon_drvdata:
+--- a/kernel/printk/internal.h
++++ b/kernel/printk/internal.h
+@@ -222,4 +222,5 @@ bool printk_get_next_message(struct prin
+
+ #ifdef CONFIG_PRINTK
+ void console_prepend_dropped(struct printk_message *pmsg, unsigned long dropped);
++void console_prepend_replay(struct printk_message *pmsg);
+ #endif
+--- a/kernel/printk/nbcon.c
++++ b/kernel/printk/nbcon.c
+@@ -866,6 +866,7 @@ static bool nbcon_emit_next_record(struc
+ unsigned long con_dropped;
+ struct nbcon_state cur;
+ unsigned long dropped;
++ unsigned long ulseq;
+
+ /*
+ * The printk buffers are filled within an unsafe section. This
+@@ -891,6 +892,28 @@ static bool nbcon_emit_next_record(struc
+ if (dropped && !is_extended)
+ console_prepend_dropped(&pmsg, dropped);
+
++ /*
++ * If the previous owner was assigned the same record, this context
++ * has taken over ownership and is replaying the record. Prepend a
++ * message to let the user know the record is replayed.
++ */
++ ulseq = atomic_long_read(&ACCESS_PRIVATE(con, nbcon_prev_seq));
++ if (__ulseq_to_u64seq(prb, ulseq) == pmsg.seq) {
++ console_prepend_replay(&pmsg);
++ } else {
++ /*
++ * Ensure this context is still the owner before trying to
++ * update @nbcon_prev_seq. Otherwise the value in @ulseq may
++ * not be from the previous owner.
++ */
++ nbcon_state_read(con, &cur);
++ if (!nbcon_context_can_proceed(ctxt, &cur))
++ return false;
++
++ atomic_long_try_cmpxchg(&ACCESS_PRIVATE(con, nbcon_prev_seq), &ulseq,
++ __u64seq_to_ulseq(pmsg.seq));
++ }
++
+ if (!nbcon_context_exit_unsafe(ctxt))
+ return false;
+
+@@ -1524,6 +1547,7 @@ void nbcon_init(struct console *con)
+ rcuwait_init(&con->rcuwait);
+ init_irq_work(&con->irq_work, nbcon_irq_work);
+ nbcon_seq_force(con, 0);
++ atomic_long_set(&ACCESS_PRIVATE(con, nbcon_prev_seq), -1UL);
+ nbcon_state_set(con, &state);
+ nbcon_kthread_create(con);
+ }
+--- a/kernel/printk/printk.c
++++ b/kernel/printk/printk.c
+@@ -2881,6 +2881,25 @@ void console_prepend_dropped(struct prin
+ }
+
+ /*
++ * Prepend the message in @pmsg->pbufs->outbuf with a "replay message".
++ * @pmsg->outbuf_len is updated appropriately.
++ *
++ * @pmsg is the printk message to prepend.
++ */
++void console_prepend_replay(struct printk_message *pmsg)
++{
++ struct printk_buffers *pbufs = pmsg->pbufs;
++ const size_t scratchbuf_sz = sizeof(pbufs->scratchbuf);
++ char *scratchbuf = &pbufs->scratchbuf[0];
++ size_t len;
++
++ len = scnprintf(scratchbuf, scratchbuf_sz,
++ "** replaying previous printk message **\n");
++
++ __console_prepend_scratch(pmsg, len);
++}
++
++/*
+ * Read and format the specified record (or a later record if the specified
+ * record is not available).
+ *