]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
serial: sh-sci: Do not probe the serial port if its slot in sci_ports[] is in use
authorClaudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
Thu, 16 Jan 2025 18:22:47 +0000 (20:22 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 17 Jan 2025 11:54:37 +0000 (12:54 +0100)
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: 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>
Link: https://lore.kernel.org/r/20250116182249.3828577-4-claudiu.beznea.uj@bp.renesas.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/tty/serial/sh-sci.c

index 51382e354a2d9f32b6d0236b33eb1aea0cd36b69..b85a9d425f7ebf803a648d3eb63a3091c2b5405b 100644 (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)
@@ -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);