On Fri, Oct 25, 2024 at 01:03:27PM +0206, John Ogness wrote: > Implement the necessary callbacks to switch the 8250 console driver > to perform as an nbcon console. > > Add implementations for the nbcon console callbacks (write_atomic, > write_thread, device_lock, device_unlock) and add CON_NBCON to the > initial flags. Again, use consistent style for the references to the callbacks. it may be .func, or ->func(), or something else, but make it consistent. > All register access in the callbacks are within unsafe sections. > The write callbacks allow safe handover/takeover per byte and add > a preceding newline if they take over mid-line. > > For the write_atomic() case, a new irq_work is used to defer modem > control since it may be a context that does not allow waking up > tasks. ... > +/* > + * Only to be used directly by the console write callbacks, which may not > + * require the port lock. Use serial8250_clear_IER() instead for all other > + * cases. > + */ > +static void __serial8250_clear_IER(struct uart_8250_port *up) > { > if (up->capabilities & UART_CAP_UUE) > serial_out(up, UART_IER, UART_IER_UUE); > serial_out(up, UART_IER, 0); > } > > +static inline void serial8250_clear_IER(struct uart_8250_port *up) > +{ > + __serial8250_clear_IER(up); Shouldn't this have a lockdep annotation to differentiate with the above? > +} ... > +static void serial8250_console_byte_write(struct uart_8250_port *up, > + struct nbcon_write_context *wctxt) > +{ > + const char *s = READ_ONCE(wctxt->outbuf); > + const char *end = s + READ_ONCE(wctxt->len); Is there any possibility that outbuf value be changed before we get the len and at the end we get the wrong pointer? > + struct uart_port *port = &up->port; > + > + /* > + * Write out the message. Toggle unsafe for each byte in order to give > + * another (higher priority) context the opportunity for a friendly > + * takeover. If such a takeover occurs, this must abort writing since > + * wctxt->outbuf and wctxt->len are no longer valid. > + */ > + while (s != end) { > + if (!nbcon_enter_unsafe(wctxt)) > + return; > + > + uart_console_write(port, s++, 1, serial8250_console_wait_putchar); > + > + if (!nbcon_exit_unsafe(wctxt)) > + return; > } > } ... > +/* > + * irq_work handler to perform modem control. Only triggered via > + * write_atomic() callback because it may be in a scheduler or NMI Also make same style for the callback reference in the comments. > + * context, unable to wake tasks. > + */ ... > struct uart_8250_port { > u16 lsr_save_mask; > #define MSR_SAVE_FLAGS UART_MSR_ANY_DELTA > unsigned char msr_saved_flags; > + struct irq_work modem_status_work; > + > + bool console_line_ended; /* line fully output */ > > struct uart_8250_dma *dma; > const struct uart_8250_ops *ops; Btw, have you run `pahole` on this? Perhaps there are better places for new members? -- With Best Regards, Andy Shevchenko