Hi Claudiu, On Wed, Dec 4, 2024 at 4:58 PM Claudiu <claudiu.beznea@xxxxxxxxx> wrote: > From: Claudiu Beznea <claudiu.beznea.uj@xxxxxxxxxxxxxx> > > The early_console_setup() function initializes sci_ports[0].port with an > object of type struct uart_port obtained from the struct earlycon_device > passed as an argument to early_console_setup(). > > Later, during serial port probing, the serial port used as earlycon > (e.g., port A) might be remapped to a different position in the sci_ports[] > array, and a different serial port (e.g., port B) might be assigned to slot > 0. For example: > > sci_ports[0] = port B > sci_ports[X] = port A > > In this scenario, the new port mapped at index zero (port B) retains the > data associated with the earlycon configuration. Consequently, after the > Linux boot process, any access to the serial port now mapped to > sci_ports[0] (port B) will block the original earlycon port (port A). > > To address this, introduce an early_console_exit() function to clean up > sci_ports[0] when earlycon is exited. > > To prevent the cleanup of sci_ports[0] while the serial device is still > being used by earlycon, introduce the struct sci_port::probing flag and > account for it in early_console_exit(). > > Fixes: 0b0cced19ab1 ("serial: sh-sci: Add CONFIG_SERIAL_EARLYCON support") > Cc: stable@xxxxxxxxxxxxxxx > Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@xxxxxxxxxxxxxx> > --- > > Changes since the integrated patch: > - adjust the commit message to address Geert comments at [1] > - Introduce the struct sci_port::probing flag to prevent the cleanup > of sci_ports[0] while the serial device is still being used by earlycon Thanks for the update! > --- a/drivers/tty/serial/sh-sci.c > +++ b/drivers/tty/serial/sh-sci.c > @@ -159,6 +159,7 @@ struct sci_port { > bool autorts; > bool tx_occurred; > bool earlycon; > + bool probing; This is only used in sci_ports[0], so it can be a single global flag, instead of a flag embedded in each sci_port structure. > }; > > #define SCI_NPORTS CONFIG_SERIAL_SH_SCI_NR_UARTS > @@ -3386,7 +3387,8 @@ static struct plat_sci_port *sci_parse_dt(struct platform_device *pdev, > static int sci_probe_single(struct platform_device *dev, > unsigned int index, > struct plat_sci_port *p, > - struct sci_port *sciport) > + struct sci_port *sciport, > + struct resource *sci_res) > { > int ret; > > @@ -3433,12 +3435,15 @@ static int sci_probe_single(struct platform_device *dev, > sciport->port.flags |= UPF_HARD_FLOW; > } > > - ret = uart_add_one_port(&sci_uart_driver, &sciport->port); > - if (ret) { > - return ret; > + if (sci_ports[0].earlycon && sci_ports[0].port.mapbase == sci_res->start) { > + /* > + * Skip cleanup up the sci_port[0] in early_console_exit(), this Double up > + * port is the same as the earlycon one. > + */ > + sci_ports[0].probing = true; > } > > - return 0; > + return uart_add_one_port(&sci_uart_driver, &sciport->port); > } > > static int sci_probe(struct platform_device *dev) > @@ -3496,7 +3501,7 @@ static int sci_probe(struct platform_device *dev) > > platform_set_drvdata(dev, sp); > > - ret = sci_probe_single(dev, dev_id, p, sp); > + ret = sci_probe_single(dev, dev_id, p, sp, res); > if (ret) > return ret; > > @@ -3579,6 +3584,20 @@ sh_early_platform_init_buffer("earlyprintk", &sci_driver, > #ifdef CONFIG_SERIAL_SH_SCI_EARLYCON > static struct plat_sci_port port_cfg; > > +static int early_console_exit(struct console *co) > +{ > + struct sci_port *sci_port = &sci_ports[0]; > + > + /* > + * Clean the slot used by earlycon. A new SCI device might > + * map to this slot. > + */ > + if (sci_port->earlycon && !sci_port->probing) > + memset(sci_port, 0, sizeof(*sci_port)); Aha, so this clears sci_port.earlycon, too (cfr. my comment on PATCH 4/6). Still, I don't think this is sufficient: shouldn't sci_port.earlycon be cleared unconditionally? > + > + return 0; > +} > + > static int __init early_console_setup(struct earlycon_device *device, > int type) > { > @@ -3596,6 +3615,8 @@ static int __init early_console_setup(struct earlycon_device *device, > SCSCR_RE | SCSCR_TE | port_cfg.scscr); > > device->con->write = serial_console_write; > + device->con->exit = early_console_exit; > + > return 0; > } > static int __init sci_early_console_setup(struct earlycon_device *device, Gr{oetje,eeting}s, Geert -- Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@xxxxxxxxxxxxxx In personal conversations with technical people, I call myself a hacker. But when I'm talking to journalists I just say "programmer" or something like that. -- Linus Torvalds