1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
|
From: John Ogness <john.ogness@linutronix.de>
Date: Fri, 20 Oct 2023 10:01:58 +0000
Subject: [PATCH 41/46] printk: nbcon: Provide function to reacquire ownership
Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.9/older/patches-6.9-rt5.tar.xz
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>
---
include/linux/console.h | 7 +++++++
kernel/printk/nbcon.c | 41 +++++++++++++++++++++++++++++++++++++++++
2 files changed, 48 insertions(+)
--- a/include/linux/console.h
+++ b/include/linux/console.h
@@ -373,6 +373,11 @@ 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() 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
* on the console ownership for synchronization.
@@ -591,6 +596,7 @@ extern void nbcon_cpu_emergency_flush(vo
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) { }
@@ -598,6 +604,7 @@ static inline void nbcon_cpu_emergency_f
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;
--- a/kernel/printk/nbcon.c
+++ b/kernel/printk/nbcon.c
@@ -839,6 +839,38 @@ bool nbcon_exit_unsafe(struct nbcon_writ
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
* @use_atomic: True if the write_atomic callback is to be used
@@ -944,6 +976,15 @@ static bool nbcon_emit_next_record(struc
nbcon_context_release(ctxt);
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
|