diff options
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.patch | 135 |
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 0000000000..ab1046954b --- /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). + * |