Commit 9f7dea87 authored by Claudiu Beznea's avatar Claudiu Beznea Committed by Greg Kroah-Hartman
Browse files

serial: sh-sci: Do not probe the serial port if its slot in sci_ports[] is in use



In the sh-sci driver, sci_ports[0] is used by earlycon. If the earlycon is
still active when sci_probe() is called and the new serial port is supposed
to map to sci_ports[0], return -EBUSY to prevent breaking the earlycon.

This situation should occurs in debug scenarios, and users should be
aware of the potential conflict.

Fixes: 0b0cced1 ("serial: sh-sci: Add CONFIG_SERIAL_EARLYCON support")
Cc: stable@vger.kernel.org
Signed-off-by: default avatarClaudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
Link: https://lore.kernel.org/r/20250116182249.3828577-4-claudiu.beznea.uj@bp.renesas.com


Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 239f1120
Loading
Loading
Loading
Loading
+23 −0
Original line number Diff line number Diff line
@@ -165,6 +165,7 @@ struct sci_port {
static struct sci_port sci_ports[SCI_NPORTS];
static unsigned long sci_ports_in_use;
static struct uart_driver sci_uart_driver;
static bool sci_uart_earlycon;

static inline struct sci_port *
to_sci_port(struct uart_port *uart)
@@ -3438,6 +3439,7 @@ static int sci_probe_single(struct platform_device *dev,
static int sci_probe(struct platform_device *dev)
{
	struct plat_sci_port *p;
	struct resource *res;
	struct sci_port *sp;
	unsigned int dev_id;
	int ret;
@@ -3467,6 +3469,26 @@ static int sci_probe(struct platform_device *dev)
	}

	sp = &sci_ports[dev_id];

	/*
	 * In case:
	 * - the probed port alias is zero (as the one used by earlycon), and
	 * - the earlycon is still active (e.g., "earlycon keep_bootcon" in
	 *   bootargs)
	 *
	 * defer the probe of this serial. This is a debug scenario and the user
	 * must be aware of it.
	 *
	 * Except when the probed port is the same as the earlycon port.
	 */

	res = platform_get_resource(dev, IORESOURCE_MEM, 0);
	if (!res)
		return -ENODEV;

	if (sci_uart_earlycon && sp == &sci_ports[0] && sp->port.mapbase != res->start)
		return dev_err_probe(&dev->dev, -EBUSY, "sci_port[0] is used by earlycon!\n");

	platform_set_drvdata(dev, sp);

	ret = sci_probe_single(dev, dev_id, p, sp);
@@ -3563,6 +3585,7 @@ static int __init early_console_setup(struct earlycon_device *device,
	port_cfg.type = type;
	sci_ports[0].cfg = &port_cfg;
	sci_ports[0].params = sci_probe_regmap(&port_cfg);
	sci_uart_earlycon = true;
	port_cfg.scscr = sci_serial_in(&sci_ports[0].port, SCSCR);
	sci_serial_out(&sci_ports[0].port, SCSCR,
		       SCSCR_RE | SCSCR_TE | port_cfg.scscr);