Konstantin Demin
c3d09a3e94
imported from https://salsa.debian.org/kernel-team/linux.git commit 9d5cc9d9d6501d7f1dd7e194d4b245bd0b6c6a22 version 6.11.4-1
189 lines
6.8 KiB
Diff
189 lines
6.8 KiB
Diff
From: John Ogness <john.ogness@linutronix.de>
|
|
Date: Wed, 4 Sep 2024 14:11:20 +0206
|
|
Subject: [PATCH 38/54] printk: nbcon: Add function for printers to reacquire
|
|
ownership
|
|
Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.11/older/patches-6.11-rt7.tar.xz
|
|
|
|
Since ownership can be lost at any time due to handover or
|
|
takeover, a printing context _must_ be prepared to back out
|
|
immediately and carefully. However, there are scenarios where
|
|
the printing context must reacquire ownership in order to
|
|
finalize or revert hardware changes.
|
|
|
|
One such example is when interrupts are disabled during
|
|
printing. No other context will automagically re-enable the
|
|
interrupts. For this case, the disabling context _must_
|
|
reacquire nbcon ownership so that it can re-enable the
|
|
interrupts.
|
|
|
|
Provide nbcon_reacquire_nobuf() for exactly this purpose. It
|
|
allows a printing context to reacquire ownership using the same
|
|
priority as its previous ownership.
|
|
|
|
Note that after a successful reacquire the printing context
|
|
will have no output buffer because that has been lost. This
|
|
function cannot be used to resume printing.
|
|
|
|
Signed-off-by: John Ogness <john.ogness@linutronix.de>
|
|
Reviewed-by: Petr Mladek <pmladek@suse.com>
|
|
Link: https://lore.kernel.org/r/20240904120536.115780-2-john.ogness@linutronix.de
|
|
Signed-off-by: Petr Mladek <pmladek@suse.com>
|
|
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
|
|
---
|
|
include/linux/console.h | 6 +++
|
|
kernel/printk/nbcon.c | 74 +++++++++++++++++++++++++++++++++++++++++++-----
|
|
2 files changed, 73 insertions(+), 7 deletions(-)
|
|
|
|
--- a/include/linux/console.h
|
|
+++ b/include/linux/console.h
|
|
@@ -366,6 +366,10 @@ struct console {
|
|
*
|
|
* The callback should allow the takeover whenever it is safe. It
|
|
* increases the chance to see messages when the system is in trouble.
|
|
+ * If the driver must reacquire ownership in order to finalize or
|
|
+ * revert hardware changes, nbcon_reacquire_nobuf() can be used.
|
|
+ * However, on reacquire the buffer content is no longer available. A
|
|
+ * reacquire cannot be used to resume printing.
|
|
*
|
|
* The callback can be called from any context (including NMI).
|
|
* Therefore it must avoid usage of any locking and instead rely
|
|
@@ -558,12 +562,14 @@ extern void nbcon_cpu_emergency_exit(voi
|
|
extern bool nbcon_can_proceed(struct nbcon_write_context *wctxt);
|
|
extern bool nbcon_enter_unsafe(struct nbcon_write_context *wctxt);
|
|
extern bool nbcon_exit_unsafe(struct nbcon_write_context *wctxt);
|
|
+extern void nbcon_reacquire_nobuf(struct nbcon_write_context *wctxt);
|
|
#else
|
|
static inline void nbcon_cpu_emergency_enter(void) { }
|
|
static inline void nbcon_cpu_emergency_exit(void) { }
|
|
static inline bool nbcon_can_proceed(struct nbcon_write_context *wctxt) { return false; }
|
|
static inline bool nbcon_enter_unsafe(struct nbcon_write_context *wctxt) { return false; }
|
|
static inline bool nbcon_exit_unsafe(struct nbcon_write_context *wctxt) { return false; }
|
|
+static inline void nbcon_reacquire_nobuf(struct nbcon_write_context *wctxt) { }
|
|
#endif
|
|
|
|
extern int console_set_on_cmdline;
|
|
--- a/kernel/printk/nbcon.c
|
|
+++ b/kernel/printk/nbcon.c
|
|
@@ -830,6 +830,19 @@ static bool __nbcon_context_update_unsaf
|
|
return nbcon_context_can_proceed(ctxt, &cur);
|
|
}
|
|
|
|
+static void nbcon_write_context_set_buf(struct nbcon_write_context *wctxt,
|
|
+ char *buf, unsigned int len)
|
|
+{
|
|
+ struct nbcon_context *ctxt = &ACCESS_PRIVATE(wctxt, ctxt);
|
|
+ struct console *con = ctxt->console;
|
|
+ struct nbcon_state cur;
|
|
+
|
|
+ wctxt->outbuf = buf;
|
|
+ wctxt->len = len;
|
|
+ nbcon_state_read(con, &cur);
|
|
+ wctxt->unsafe_takeover = cur.unsafe_takeover;
|
|
+}
|
|
+
|
|
/**
|
|
* nbcon_enter_unsafe - Enter an unsafe region in the driver
|
|
* @wctxt: The write context that was handed to the write function
|
|
@@ -845,8 +858,12 @@ static bool __nbcon_context_update_unsaf
|
|
bool nbcon_enter_unsafe(struct nbcon_write_context *wctxt)
|
|
{
|
|
struct nbcon_context *ctxt = &ACCESS_PRIVATE(wctxt, ctxt);
|
|
+ bool is_owner;
|
|
|
|
- return nbcon_context_enter_unsafe(ctxt);
|
|
+ is_owner = nbcon_context_enter_unsafe(ctxt);
|
|
+ if (!is_owner)
|
|
+ nbcon_write_context_set_buf(wctxt, NULL, 0);
|
|
+ return is_owner;
|
|
}
|
|
EXPORT_SYMBOL_GPL(nbcon_enter_unsafe);
|
|
|
|
@@ -865,12 +882,44 @@ EXPORT_SYMBOL_GPL(nbcon_enter_unsafe);
|
|
bool nbcon_exit_unsafe(struct nbcon_write_context *wctxt)
|
|
{
|
|
struct nbcon_context *ctxt = &ACCESS_PRIVATE(wctxt, ctxt);
|
|
+ bool ret;
|
|
|
|
- return nbcon_context_exit_unsafe(ctxt);
|
|
+ ret = nbcon_context_exit_unsafe(ctxt);
|
|
+ if (!ret)
|
|
+ nbcon_write_context_set_buf(wctxt, NULL, 0);
|
|
+ return ret;
|
|
}
|
|
EXPORT_SYMBOL_GPL(nbcon_exit_unsafe);
|
|
|
|
/**
|
|
+ * nbcon_reacquire_nobuf - Reacquire a console after losing ownership
|
|
+ * while printing
|
|
+ * @wctxt: The write context that was handed to the write callback
|
|
+ *
|
|
+ * Since ownership can be lost at any time due to handover or takeover, a
|
|
+ * printing context _must_ be prepared to back out immediately and
|
|
+ * carefully. However, there are scenarios where the printing context must
|
|
+ * reacquire ownership in order to finalize or revert hardware changes.
|
|
+ *
|
|
+ * This function allows a printing context to reacquire ownership using the
|
|
+ * same priority as its previous ownership.
|
|
+ *
|
|
+ * Note that after a successful reacquire the printing context will have no
|
|
+ * output buffer because that has been lost. This function cannot be used to
|
|
+ * resume printing.
|
|
+ */
|
|
+void nbcon_reacquire_nobuf(struct nbcon_write_context *wctxt)
|
|
+{
|
|
+ struct nbcon_context *ctxt = &ACCESS_PRIVATE(wctxt, ctxt);
|
|
+
|
|
+ while (!nbcon_context_try_acquire(ctxt))
|
|
+ cpu_relax();
|
|
+
|
|
+ nbcon_write_context_set_buf(wctxt, NULL, 0);
|
|
+}
|
|
+EXPORT_SYMBOL_GPL(nbcon_reacquire_nobuf);
|
|
+
|
|
+/**
|
|
* nbcon_emit_next_record - Emit a record in the acquired context
|
|
* @wctxt: The write context that will be handed to the write function
|
|
*
|
|
@@ -895,7 +944,6 @@ static bool nbcon_emit_next_record(struc
|
|
.pbufs = ctxt->pbufs,
|
|
};
|
|
unsigned long con_dropped;
|
|
- struct nbcon_state cur;
|
|
unsigned long dropped;
|
|
|
|
/*
|
|
@@ -930,10 +978,7 @@ static bool nbcon_emit_next_record(struc
|
|
goto update_con;
|
|
|
|
/* Initialize the write context for driver callbacks. */
|
|
- wctxt->outbuf = &pmsg.pbufs->outbuf[0];
|
|
- wctxt->len = pmsg.outbuf_len;
|
|
- nbcon_state_read(con, &cur);
|
|
- wctxt->unsafe_takeover = cur.unsafe_takeover;
|
|
+ nbcon_write_context_set_buf(wctxt, &pmsg.pbufs->outbuf[0], pmsg.outbuf_len);
|
|
|
|
if (con->write_atomic) {
|
|
con->write_atomic(con, wctxt);
|
|
@@ -947,6 +992,21 @@ static bool nbcon_emit_next_record(struc
|
|
return false;
|
|
}
|
|
|
|
+ if (!wctxt->outbuf) {
|
|
+ /*
|
|
+ * Ownership was lost and reacquired by the driver. Handle it
|
|
+ * as if ownership was lost.
|
|
+ */
|
|
+ nbcon_context_release(ctxt);
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ /*
|
|
+ * Ownership may have been lost but _not_ reacquired by the driver.
|
|
+ * This case is detected and handled when entering unsafe to update
|
|
+ * dropped/seq values.
|
|
+ */
|
|
+
|
|
/*
|
|
* Since any dropped message was successfully output, reset the
|
|
* dropped count for the console.
|