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

commit 9f7dea875cc7f9c1a56a5c688290634a59cd1420 upstream.

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: 0b0cced19a ("serial: sh-sci: Add CONFIG_SERIAL_EARLYCON support")
Cc: stable@vger.kernel.org
Signed-off-by: Claudiu 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: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
Claudiu Beznea 2025-01-16 20:22:47 +02:00 committed by Greg Kroah-Hartman
parent cf174b3c1b
commit 77c97ed7c8

View File

@ -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)
@ -3318,6 +3319,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;
@ -3347,6 +3349,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);
@ -3445,6 +3467,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);