v6.7-rc5-rt5
Subsystems (3)
Dear RT folks!
I'm pleased to announce the v6.7-rc5-rt5 patch set.
Changes since v6.7-rc5-rt4:
- Update the printk code to the latest version which has been posted upstream for review.
Known issues
Pierre Gondois reported crashes on ARM64 together with "rtla timerlat hist" as trigger. It is not yet understood. The report is at
https://lore.kernel.org/[email protected]
The delta patch against v6.7-rc5-rt4 is appended below and can be found here:
https://cdn.kernel.org/pub/linux/kernel/projects/rt/6.7/incr/patch-6.7-rc5-rt4-rt5.patch.xz
You can get this release via the git tree at:
https://git.kernel.org/pub/scm/linux/kernel/git/rt/linux-rt-devel.git v6.7-rc5-rt5
The RT patch against v6.7-rc5 can be found here:
https://cdn.kernel.org/pub/linux/kernel/projects/rt/6.7/older/patch-6.7-rc5-rt5.patch.xz
The split quilt queue is available at:
https://cdn.kernel.org/pub/linux/kernel/projects/rt/6.7/older/patches-6.7-rc5-rt5.tar.xz
Sebastian
drivers/tty/serial/8250/8250_core.c +13 -3
@@ -617,9 +617,18 @@ static bool univ8250_console_write_thread(struct console *co, return serial8250_console_write_thread(up, wctxt); } -static struct uart_port *univ8250_console_uart_port (struct console *con) +static void univ8250_console_driver_enter (struct console *con,unsigned long *flags) { -return &serial8250_ports[con->index].port; +struct uart_port *up = &serial8250_ports[con->index].port; + +__uart_port_lock_irqsave (up, flags); +} + +static void univ8250_console_driver_exit (struct console *con,unsigned long flags) +{ +struct uart_port *up = &serial8250_ports[con->index].port; + +__uart_port_unlock_irqrestore (up, flags); }#endif /* CONFIG_SERIAL_8250_LEGACY_CONSOLE */
@@ -727,8 +736,9 @@ static struct console univ8250_console = {#else .write_atomic = univ8250_console_write_atomic, .write_thread = univ8250_console_write_thread, + .driver_enter = univ8250_console_driver_enter, + .driver_exit = univ8250_console_driver_exit, .flags = CON_PRINTBUFFER | CON_ANYTIME | CON_NBCON, - .uart_port = univ8250_console_uart_port, #endif .device = uart_console_device, .setup = univ8250_console_setup,
drivers/tty/serial/8250/8250_port.c +14 -22
@@ -3509,13 +3509,11 @@ bool serial8250_console_write_thread(struct uart_8250_port *up,if (!nbcon_enter_unsafe (wctxt))return false; -/* -* First save the IER then disable the interrupts -*/ +/* First save IER then disable the interrupts. */ ier =serial_port_in (port,UART_IER );serial8250_clear_IER (up); -/* check scratch reg to see if port powered off during system sleep */ +/* Check scratch reg if port powered off during system sleep. */ if (up->canary && (up->canary !=serial_port_in (port,UART_SCR ))) {serial8250_console_restore (up); up->canary =0 ;
@@ -3563,30 +3561,25 @@ bool serial8250_console_write_thread(struct uart_8250_port *up,while (!nbcon_enter_unsafe (wctxt))nbcon_reacquire (wctxt); -/* -* Finally, wait for transmitter to become empty -* and restore the IER -*/ +/* Finally, wait for transmitter to become empty and restore IER. */ wait_for_xmitr (up,UART_LSR_BOTH_EMPTY ); -if (em485) {mdelay (port->rs485.delay_rts_after_send);if (em485->tx_stopped) up->rs485_stop_tx (up); } -serial_port_out (port,UART_IER , ier);/* -* The receive handling will happen properly because the -* receive ready bit will still be set; it is not cleared -* on read. However, modem control will not, we must -* call it if we have saved something in the saved flags -* while processing with interrupts off. +* The receive handling will happen properly because the receive ready +* bit will still be set; it is not cleared on read. However, modem +* control will not, we must call it if we have saved something in the +* saved flags while processing with interrupts off. */ if (up->msr_saved_flags)serial8250_modem_status (up); +/* Success if no handover/takeover and message fully printed. */ return (nbcon_exit_unsafe (wctxt) && done); }
@@ -3606,12 +3599,14 @@ bool serial8250_console_write_atomic(struct uart_8250_port *up,return false;/* -* First save the IER then disable the interrupts +* First save IER then disable the interrupts. The special variant to +* clear IER is used because atomic printing may occur without holding +* the port lock. */ ier =serial_port_in (port,UART_IER );__serial8250_clear_IER (up); -/* check scratch reg to see if port powered off during system sleep */ +/* Check scratch reg if port powered off during system sleep. */ if (up->canary && (up->canary !=serial_port_in (port,UART_SCR ))) {serial8250_console_restore (up); up->canary =0 ;
@@ -3621,14 +3616,11 @@ bool serial8250_console_write_atomic(struct uart_8250_port *up,uart_console_write (port,"\n" ,1 , serial8250_console_putchar);uart_console_write (port, wctxt->outbuf, wctxt->len, serial8250_console_putchar); -/* -* Finally, wait for transmitter to become empty -* and restore the IER -*/ +/* Finally, wait for transmitter to become empty and restore IER. */ wait_for_xmitr (up,UART_LSR_BOTH_EMPTY ); -serial_port_out (port,UART_IER , ier); +/* Success if no handover/takeover. */ return nbcon_exit_unsafe(wctxt); }#endif /* CONFIG_SERIAL_8250_LEGACY_CONSOLE */
include/linux/console.h +4 -2
@@ -306,7 +306,8 @@ struct nbcon_write_context {* * @write_atomic: Write callback for atomic context * @write_thread: Write callback for non-atomic context -* @uart_port: Callback to provide the associated uart port +* @driver_enter: Callback to begin synchronization with driver code +* @driver_exit: Callback to finish synchronization with driver code * @nbcon_state: State for nbcon consoles * @nbcon_seq: Sequence number of the next record for nbcon to print * @pbufs: Pointer to nbcon private buffer
@@ -339,7 +340,8 @@ struct console { struct nbcon_write_context *wctxt);bool (*write_thread)(struct console *con,struct nbcon_write_context *wctxt); -struct uart_port * (*uart_port)(struct console *con); +void (*driver_enter)(struct console *con,unsigned long *flags); +void (*driver_exit)(struct console *con,unsigned long flags);atomic_t __private nbcon_state;atomic_long_t __private nbcon_seq;struct printk_buffers *pbufs;
include/linux/printk.h +9 -4
@@ -197,8 +197,9 @@ void show_regs_print_info(const char *log_lvl); extern asmlinkage void dump_stack_lvl(const char *log_lvl) __cold; extern asmlinkage void dump_stack(void) __cold;void printk_trigger_flush (void ); -extern void nbcon_handle_port_lock (struct uart_port *up); -extern void nbcon_handle_port_unlock (struct uart_port *up); +void printk_legacy_allow_panic_sync (void ); +extern void nbcon_acquire (struct uart_port *up); +extern void nbcon_release (struct uart_port *up);void nbcon_atomic_flush_unsafe (void );#else static inline __printf(1, 0)
@@ -280,11 +281,15 @@ static inline void printk_trigger_flush(void) { } -static inline void nbcon_handle_port_lock (struct uart_port *up) +static inline void printk_legacy_allow_panic_sync (void ) { } -static inline void nbcon_handle_port_unlock (struct uart_port *up) +static inline void nbcon_acquire (struct uart_port *up) +{ +} + +static inline void nbcon_release (struct uart_port *up) { }
include/linux/serial_core.h +20 -8
@@ -595,7 +595,7 @@ struct uart_port {static inline void uart_port_lock (struct uart_port *up) {spin_lock (&up->lock); -nbcon_handle_port_lock (up); +nbcon_acquire (up); }/**
@@ -605,7 +605,7 @@ static inline void uart_port_lock(struct uart_port *up)static inline void uart_port_lock_irq (struct uart_port *up) {spin_lock_irq (&up->lock); -nbcon_handle_port_lock (up); +nbcon_acquire (up); }/**
@@ -616,7 +616,7 @@ static inline void uart_port_lock_irq(struct uart_port *up)static inline void uart_port_lock_irqsave (struct uart_port *up,unsigned long *flags) {spin_lock_irqsave (&up->lock, *flags); -nbcon_handle_port_lock (up); +nbcon_acquire (up); }/**
@@ -630,7 +630,7 @@ static inline bool uart_port_trylock(struct uart_port *up)if (!spin_trylock (&up->lock))return false; -nbcon_handle_port_lock (up); +nbcon_acquire (up);return true; }
@@ -646,7 +646,7 @@ static inline bool uart_port_trylock_irqsave(struct uart_port *up, unsigned longif (!spin_trylock_irqsave (&up->lock, *flags))return false; -nbcon_handle_port_lock (up); +nbcon_acquire (up);return true; }
@@ -656,7 +656,7 @@ static inline bool uart_port_trylock_irqsave(struct uart_port *up, unsigned long*/ static inline void uart_port_unlock (struct uart_port *up) { -nbcon_handle_port_unlock (up); +nbcon_release (up);spin_unlock (&up->lock); }
@@ -666,7 +666,7 @@ static inline void uart_port_unlock(struct uart_port *up)*/ static inline void uart_port_unlock_irq (struct uart_port *up) { -nbcon_handle_port_unlock (up); +nbcon_release (up);spin_unlock_irq (&up->lock); }
@@ -677,7 +677,19 @@ static inline void uart_port_unlock_irq(struct uart_port *up)*/ static inline void uart_port_unlock_irqrestore (struct uart_port *up,unsigned long flags) { -nbcon_handle_port_unlock (up); +nbcon_release (up); +spin_unlock_irqrestore (&up->lock, flags); +} + +/* Only for use in the console->driver_enter() callback. */ +static inline void __uart_port_lock_irqsave (struct uart_port *up,unsigned long *flags) +{ +spin_lock_irqsave (&up->lock, *flags); +} + +/* Only for use in the console->driver_exit() callback. */ +static inline void __uart_port_unlock_irqrestore (struct uart_port *up,unsigned long flags) +{spin_unlock_irqrestore (&up->lock, flags); }
kernel/panic.c +8 -0
@@ -370,6 +370,8 @@ void panic(const char *fmt, ...)*/ atomic_notifier_call_chain (&panic_notifier_list,0 , buf); +printk_legacy_allow_panic_sync (); +panic_print_sys_info (false);kmsg_dump (KMSG_DUMP_PANIC );
@@ -447,6 +449,12 @@ void panic(const char *fmt, ...)/* Do not scroll important messages printed above */ suppress_printk =1 ; +/* +* The final messages may not have been printed if in a context that +* defers printing (such as NMI) and irq_work is not available. +* Explicitly flush the kernel log buffer one last time. +*/ +console_flush_on_panic (CONSOLE_FLUSH_PENDING );nbcon_atomic_flush_unsafe ();local_irq_enable ();
kernel/printk/internal.h +8 -4
@@ -82,6 +82,8 @@ void defer_console_output(void);u16 printk_parse_prefix (const char *text,int *level,enum printk_info_flags *flags); +void console_lock_spinning_enable (void ); +int console_lock_spinning_disable_and_check (int cookie);u64 nbcon_seq_read (struct console *con);void nbcon_seq_force (struct console *con,u64 seq);
@@ -90,7 +92,7 @@ void nbcon_init(struct console *con);void nbcon_free (struct console *con);enum nbcon_prio nbcon_get_default_prio (void );void nbcon_atomic_flush_all (void ); -bool nbcon_atomic_emit_next_record (struct console *con); +bool nbcon_atomic_emit_next_record (struct console *con,bool *handover,int cookie);void nbcon_kthread_create (struct console *con);void nbcon_wake_threads (void );void nbcon_legacy_kthread_create (void );
@@ -143,7 +145,7 @@ static inline void nbcon_kthread_wake(struct console *con)* Guarantee any new records can be seen by tasks preparing to wait * before this context checks if the rcuwait is empty. * -* The full memory barrier in rcuwait_wake_up() pairs with the full +* The full memory barrier in rcuwait_wake_up() pairs with the full * memory barrier within set_current_state() of * ___rcuwait_wait_event(), which is called after prepare_to_rcuwait() * adds the waiter but before it has checked the wait condition.
@@ -180,9 +182,11 @@ static inline void nbcon_init(struct console *con) { }static inline void nbcon_free (struct console *con) { }static inline enum nbcon_prio nbcon_get_default_prio (void ) {return NBCON_PRIO_NONE ; }static inline void nbcon_atomic_flush_all (void ) { } -static bool nbcon_atomic_emit_next_record (struct console *con) {return false; } +static inline bool nbcon_atomic_emit_next_record (struct console *con,bool *handover, +int cookie) {return false; } -static inline bool console_is_usable (struct console *con,short flags,bool use_atomic) {return false; } +static inline bool console_is_usable (struct console *con,short flags, +bool use_atomic) {return false; }#endif /* CONFIG_PRINTK */
kernel/printk/nbcon.c +103 -128
458 lines not on this page · raw message
kernel/printk/printk.c +148 -116
453 lines not on this page · raw message
kernel/printk/printk_ringbuffer.c +47 -40
183 lines not on this page · raw message
kernel/printk/printk_ringbuffer.h +33 -0
@@ -392,8 +392,41 @@ bool prb_read_valid(struct printk_ringbuffer *rb, u64 seq,bool prb_read_valid_info (struct printk_ringbuffer *rb,u64 seq,struct printk_info *info,unsigned int *line_count); +u64 prb_first_seq (struct printk_ringbuffer *rb);u64 prb_first_valid_seq (struct printk_ringbuffer *rb);u64 prb_next_seq (struct printk_ringbuffer *rb);u64 prb_next_reserve_seq (struct printk_ringbuffer *rb); +#ifdef CONFIG_64BIT + +#define __u64seq_to_ulseq (u64seq) (u64seq) +#define __ulseq_to_u64seq (rb, ulseq) (ulseq) + +#else /* CONFIG_64BIT */ + +#define __u64seq_to_ulseq (u64seq) ((u32)u64seq) + +static inline u64 __ulseq_to_u64seq (struct printk_ringbuffer *rb,u32 ulseq) +{ +u64 rb_first_seq =prb_first_seq (rb); +u64 seq; + +/* +* The provided sequence is only the lower 32 bits of the ringbuffer +* sequence. It needs to be expanded to 64bit. Get the first sequence +* number from the ringbuffer and fold it. +* +* Having a 32bit representation in the console is sufficient. +* If a console ever gets more than 2^31 records behind +* the ringbuffer then this is the least of the problems. +* +* Also the access to the ring buffer is always safe. +*/ + seq = rb_first_seq - (s32)((u32 )rb_first_seq - ulseq); + +return seq; +} + +#endif /* CONFIG_64BIT */ +#endif /* _KERNEL_PRINTK_RINGBUFFER_H */
localversion-rt +1 -1
@@ -1 +1 @@ --rt4 +-rt5