printk: nbcon: Provide function to reacquire ownership

BugLink: https://bugs.launchpad.net/bugs/2060704

Contexts may become nbcon owners for various reasons, not just
for printing. Indeed, the port->lock wrapper takes ownership
for anything relating to the hardware.

Since ownership can be lost at any time due to handover or
takeover, a context _should_ be prepared to back out
immediately and carefully. However, there are many scenarios
where the context _must_ reacquire ownership in order to
finalize or revert hardware changes.

One such example is when interrupts are disabled by a context.
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() for exactly this purpose.

Note that for printing contexts, after a successful reacquire
the context will have no output buffer because that has been
lost. nbcon_reacquire() cannot be used to resume printing.

Signed-off-by: John Ogness <john.ogness@linutronix.de>
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Signed-off-by: Kevin Becker <kevin.becker@canonical.com>
This commit is contained in:
John Ogness
2023-10-20 10:01:58 +00:00
committed by Kevin Becker
parent 7cdfa7fb25
commit 9f0985dcf8
2 changed files with 48 additions and 0 deletions
+7
View File
@@ -371,6 +371,11 @@ struct console {
* functions are also points of possible ownership transfer. If
* either function returns false, ownership has been lost.
*
* If the driver must reacquire ownership in order to finalize or
* revert hardware changes, nbcon_reacquire() can be used. However,
* on reacquire the buffer content is no longer available. A
* reacquire cannot be used to resume printing.
*
* This callback can be called from any context (including NMI).
* Therefore it must avoid usage of any locking and instead rely
* on the console ownership for synchronization.
@@ -595,12 +600,14 @@ extern void nbcon_cpu_emergency_exit(void);
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(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(struct nbcon_write_context *wctxt) { }
#endif
extern int console_set_on_cmdline;
+41
View File
@@ -838,6 +838,38 @@ bool nbcon_exit_unsafe(struct nbcon_write_context *wctxt)
}
EXPORT_SYMBOL_GPL(nbcon_exit_unsafe);
/**
* nbcon_reacquire - Reacquire a console after losing ownership
* @wctxt: The write context that was handed to the write function
*
* Since ownership can be lost at any time due to handover or takeover, a
* printing context _should_ be prepared to back out immediately and
* carefully. However, there are many scenarios where the context _must_
* reacquire ownership in order to finalize or revert hardware changes.
*
* This function allows a context to reacquire ownership using the same
* priority as its previous ownership.
*
* Note that for printing contexts, after a successful reacquire the
* context will have no output buffer because that has been lost. This
* function cannot be used to resume printing.
*/
void nbcon_reacquire(struct nbcon_write_context *wctxt)
{
struct nbcon_context *ctxt = &ACCESS_PRIVATE(wctxt, ctxt);
struct console *con = ctxt->console;
struct nbcon_state cur;
while (!nbcon_context_try_acquire(ctxt))
cpu_relax();
wctxt->outbuf = NULL;
wctxt->len = 0;
nbcon_state_read(con, &cur);
wctxt->unsafe_takeover = cur.unsafe_takeover;
}
EXPORT_SYMBOL_GPL(nbcon_reacquire);
/**
* nbcon_emit_next_record - Emit a record in the acquired context
* @wctxt: The write context that will be handed to the write function
@@ -945,6 +977,15 @@ static bool nbcon_emit_next_record(struct nbcon_write_context *wctxt, bool use_a
return false;
}
if (!wctxt->outbuf) {
/*
* Ownership was lost and reacquired by the driver.
* Handle it as if ownership was lost and try to continue.
*/
nbcon_context_release(ctxt);
return false;
}
/*
* Since any dropped message was successfully output, reset the
* dropped count for the console.