diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c index b4b04bbc6f41..aa3c0be51845 100644 --- a/kernel/printk/printk.c +++ b/kernel/printk/printk.c @@ -3474,6 +3474,7 @@ void register_console(struct console *newcon) struct console *con; bool bootcon_registered = false; bool realcon_registered = false; + unsigned long flags; int err; console_list_lock(); @@ -3565,6 +3566,19 @@ void register_console(struct console *newcon) newcon->seq = 0; } + /* + * If another context is actively using the hardware of this new + * console, it will not be aware of the nbcon synchronization. This + * is a risk that two contexts could access the hardware + * simultaneously if this new console is used for atomic printing + * and the other context is still using the hardware. + * + * Use the driver synchronization to ensure that the hardware is not + * in use while this new console transitions to being registered. + */ + if ((newcon->flags & CON_NBCON) && newcon->write_atomic) + newcon->device_lock(newcon, &flags); + /* * Put this console in the list - keep the * preferred driver at the head of the list. @@ -3589,6 +3603,10 @@ void register_console(struct console *newcon) * register_console() completes. */ + /* This new console is now registered. */ + if ((newcon->flags & CON_NBCON) && newcon->write_atomic) + newcon->device_unlock(newcon, flags); + console_sysfs_notify(); /*