From: John Ogness <john.ogness@linutronix.de> Date: Wed, 22 Nov 2023 11:23:43 +0000 Subject: [PATCH 07/48] printk: Properly deal with nbcon consoles on seq init If a non-boot console is registering and boot consoles exist, the consoles are flushed before being unregistered. This allows the non-boot console to continue where the boot console left off. If for whatever reason flushing fails, the lowest seq found from any of the enabled boot consoles is used. Until now con->seq was checked. However, if it is an nbcon boot console, the function nbcon_seq_read() must be used to read seq because con->seq is not updated for nbcon consoles. Check if it is an nbcon boot console and if so call nbcon_seq_read() to read seq. Also setup the nbcon sequence number and reset the legacy sequence number from register_console() (rather than in nbcon_init() and nbcon_seq_force()). This removes all legacy sequence handling from nbcon.c so the code is easier to follow and maintain. Signed-off-by: John Ogness <john.ogness@linutronix.de> Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> --- kernel/printk/nbcon.c | 7 +------ kernel/printk/printk.c | 29 ++++++++++++++++++++++++----- 2 files changed, 25 insertions(+), 11 deletions(-) Index: linux-6.8.2-rt10/kernel/printk/nbcon.c =================================================================== @ linux-6.8.2-rt10/kernel/printk/nbcon.c:175 @ void nbcon_seq_force(struct console *con u64 valid_seq = max_t(u64, seq, prb_first_valid_seq(prb)); atomic_long_set(&ACCESS_PRIVATE(con, nbcon_seq), __u64seq_to_ulseq(valid_seq)); - - /* Clear con->seq since nbcon consoles use con->nbcon_seq instead. */ - con->seq = 0; } /** @ linux-6.8.2-rt10/kernel/printk/nbcon.c:964 @ bool nbcon_alloc(struct console *con) * * nbcon_alloc() *must* be called and succeed before this function * is called. - * - * This function expects that the legacy @con->seq has been set. */ void nbcon_init(struct console *con) { @ linux-6.8.2-rt10/kernel/printk/nbcon.c:972 @ void nbcon_init(struct console *con) /* nbcon_alloc() must have been called and successful! */ BUG_ON(!con->pbufs); - nbcon_seq_force(con, con->seq); + nbcon_seq_force(con, 0); nbcon_state_set(con, &state); } Index: linux-6.8.2-rt10/kernel/printk/printk.c =================================================================== --- linux-6.8.2-rt10.orig/kernel/printk/printk.c +++ linux-6.8.2-rt10/kernel/printk/printk.c @ linux-6.8.2-rt10/kernel/printk/nbcon.c:3356 @ static void try_enable_default_console(s newcon->flags |= CON_CONSDEV; } +/* Set @newcon->seq to the first record this console should print. */ static void console_init_seq(struct console *newcon, bool bootcon_registered) { struct console *con; @ linux-6.8.2-rt10/kernel/printk/nbcon.c:3405 @ static void console_init_seq(struct cons newcon->seq = prb_next_seq(prb); for_each_console(con) { - if ((con->flags & CON_BOOT) && - (con->flags & CON_ENABLED) && - con->seq < newcon->seq) { - newcon->seq = con->seq; + u64 seq; + + if (!((con->flags & CON_BOOT) && + (con->flags & CON_ENABLED))) { + continue; } + + if (con->flags & CON_NBCON) + seq = nbcon_seq_read(con); + else + seq = con->seq; + + if (seq < newcon->seq) + newcon->seq = seq; } } @ linux-6.8.2-rt10/kernel/printk/nbcon.c:3535 @ void register_console(struct console *ne newcon->dropped = 0; console_init_seq(newcon, bootcon_registered); - if (newcon->flags & CON_NBCON) + if (newcon->flags & CON_NBCON) { nbcon_init(newcon); + /* + * nbcon consoles have their own sequence counter. The legacy + * sequence counter is reset so that it is clear it is not + * being used. + */ + nbcon_seq_force(newcon, newcon->seq); + newcon->seq = 0; + } + /* * Put this console in the list - keep the * preferred driver at the head of the list.