Hi, Geert,
On 19.12.2024 16:26, Geert Uytterhoeven wrote:
Hi Claudiu,
On Wed, Dec 4, 2024 at 4:58 PM Claudiu claudiu.beznea@tuxon.dev wrote:
From: Claudiu Beznea claudiu.beznea.uj@bp.renesas.com
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@vger.kernel.org Signed-off-by: Claudiu Beznea claudiu.beznea.uj@bp.renesas.com
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?
I remember I had failures with unconditional clear. I'll double check it though and adjust accordingly, if needed.
Thank you, Claudiu
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@linux-m68k.org
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