| From: John Ogness <john.ogness@linutronix.de> |
| Date: Tue, 12 Feb 2019 15:29:56 +0100 |
| Subject: [PATCH 18/25] console: add write_atomic interface |
| |
| Add a write_atomic callback to the console. This is an optional |
| function for console drivers. The function must be atomic (including |
| NMI safe) for writing to the console. |
| |
| Console drivers must still implement the write callback. The |
| write_atomic callback will only be used for emergency messages. |
| |
| Creating an NMI safe write_atomic that must synchronize with write |
| requires a careful implementation of the console driver. To aid with |
| the implementation, a set of console_atomic_* functions are provided: |
| |
| void console_atomic_lock(unsigned int *flags); |
| void console_atomic_unlock(unsigned int flags); |
| |
| These functions synchronize using the processor-reentrant cpu lock of |
| the printk buffer. |
| |
| Signed-off-by: John Ogness <john.ogness@linutronix.de> |
| Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> |
| --- |
| include/linux/console.h | 4 ++++ |
| kernel/printk/printk.c | 12 ++++++++++++ |
| 2 files changed, 16 insertions(+) |
| |
| --- a/include/linux/console.h |
| +++ b/include/linux/console.h |
| @@ -144,6 +144,7 @@ static inline int con_debug_leave(void) |
| struct console { |
| char name[16]; |
| void (*write)(struct console *, const char *, unsigned); |
| + void (*write_atomic)(struct console *, const char *, unsigned); |
| int (*read)(struct console *, char *, unsigned); |
| struct tty_driver *(*device)(struct console *, int *); |
| void (*unblank)(void); |
| @@ -234,4 +235,7 @@ extern void console_init(void); |
| void dummycon_register_output_notifier(struct notifier_block *nb); |
| void dummycon_unregister_output_notifier(struct notifier_block *nb); |
| |
| +extern void console_atomic_lock(unsigned int *flags); |
| +extern void console_atomic_unlock(unsigned int flags); |
| + |
| #endif /* _LINUX_CONSOLE_H */ |
| --- a/kernel/printk/printk.c |
| +++ b/kernel/printk/printk.c |
| @@ -3045,3 +3045,15 @@ void kmsg_dump_rewind(struct kmsg_dumper |
| } |
| EXPORT_SYMBOL_GPL(kmsg_dump_rewind); |
| #endif |
| + |
| +void console_atomic_lock(unsigned int *flags) |
| +{ |
| + prb_lock(&printk_cpulock, flags); |
| +} |
| +EXPORT_SYMBOL(console_atomic_lock); |
| + |
| +void console_atomic_unlock(unsigned int flags) |
| +{ |
| + prb_unlock(&printk_cpulock, flags); |
| +} |
| +EXPORT_SYMBOL(console_atomic_unlock); |