drivers/char: Panic when the requested UART fails to initialise

uart_init() cannot tell its caller that the UART the user asked for did
not come up: every failure path only printks. Arm and RISC-V carry on
into console_init_preirq() and boot without a console, rather than
refusing to boot as they do elsewhere when a user request cannot be met.

Return an error from dt_uart_init() and panic in start_xen(). An
explicit request Xen cannot satisfy should stop the boot rather than
silently degrade it, which is what start_xen() already does for the rest
of the boot configuration.

Only a path given on the command line counts as a request we have to
satisfy. Falling back to /chosen/stdout-path or acpi_uart_init()
therefore never fails. SPCR is firmware provided, the analogue of
stdout-path, and there is no ACPI equivalent of dtuart= to make an
explicit request with.

While here, decide whether the SPCR table was found from the returned
acpi_status rather than from the table pointer, which was only NULL
because the caller initialised it - acpi_get_table() writes it solely
on success.

Signed-off-by: Michal Orzel <michal.orzel@amd.com>
Reviewed-by: Ayan Kumar Halder <ayan.kumar.halder@amd.com>
This commit is contained in:
Michal Orzel committed 2026-09-15 17:13:02 +02:00
1 parent 12b136a965
commit 20ee984e1d
4 files changed
+42 -23

No files matched your search

+4 -1
View File
@@ -377,7 +377,10 @@ void asmlinkage __init noreturn start_xen(unsigned long fdt_paddr)
gic_preinit();
uart_init();
rc = uart_init();
if ( rc )
panic("Failed to initialize the requested UART (%d)\n", rc);
console_init_preirq();
console_init_ring();
+5 -1
View File
@@ -77,6 +77,7 @@ void __init noreturn start_xen(unsigned long bootcpu_id,
{
const char *cmdline;
size_t fdt_size;
int rc;
remove_identity_mapping();
@@ -149,7 +150,10 @@ void __init noreturn start_xen(unsigned long bootcpu_id,
intc_preinit();
uart_init();
rc = uart_init();
if ( rc )
panic("Failed to initialize the requested UART (%d)\n", rc);
console_init_preirq();
intc_init();
+28 -20
View File
@@ -30,15 +30,17 @@
static char __initdata opt_dtuart[256] = "";
string_param("dtuart", opt_dtuart);
static void __init dt_uart_init(void)
static int __init dt_uart_init(void)
{
struct dt_device_node *dev;
int ret;
const char *devpath = opt_dtuart;
const char *options;
char *split;
/* Set on the command line, as opposed to inherited from /chosen */
bool explicit_request = strcmp(opt_dtuart, "") != 0;
if ( !strcmp(opt_dtuart, "") )
if ( !explicit_request )
{
const struct dt_device_node *chosen = dt_find_node_by_path("/chosen");
@@ -62,7 +64,12 @@ static void __init dt_uart_init(void)
if ( !strcmp(opt_dtuart, "") )
{
printk("No dtuart path configured\n");
return;
/*
* console=dtuart is the compiled-in default, so an absent dtuart= is
* not a failed user request.
*/
return 0;
}
split = strchr(opt_dtuart, ':');
@@ -83,48 +90,49 @@ static void __init dt_uart_init(void)
if ( !dev )
{
printk("Unable to find device \"%s\"\n", devpath);
return;
return explicit_request ? -ENODEV : 0;
}
ret = device_init(dev, DEVICE_SERIAL, options);
if ( ret )
printk("Unable to initialize dtuart: %d\n", ret);
return explicit_request ? ret : 0;
}
#ifdef CONFIG_ACPI
static void __init acpi_uart_init(void)
static int __init acpi_uart_init(void)
{
struct acpi_table_spcr *spcr = NULL;
struct acpi_table_spcr *spcr;
acpi_status status;
int ret;
acpi_get_table(ACPI_SIG_SPCR, 0, (struct acpi_table_header **)&spcr);
/* SPCR is firmware provided, so nothing here is a failed user request */
status = acpi_get_table(ACPI_SIG_SPCR, 0,
(struct acpi_table_header **)&spcr);
if ( spcr == NULL )
if ( ACPI_FAILURE(status) )
{
printk("Unable to get spcr table\n");
return 0;
}
else
{
ret = acpi_device_init(DEVICE_SERIAL, NULL, spcr->interface_type);
ret = acpi_device_init(DEVICE_SERIAL, NULL, spcr->interface_type);
if ( ret )
printk("Unable to initialize acpi uart: %d\n", ret);
}
return 0;
}
#else
static void __init acpi_uart_init(void) { }
static int __init acpi_uart_init(void) { return 0; }
#endif
void __init uart_init(void)
int __init uart_init(void)
{
if ( !console_has("dtuart") )
return; /* Not for us */
return 0; /* Not for us */
if ( acpi_disabled )
dt_uart_init();
else
acpi_uart_init();
return acpi_disabled ? dt_uart_init() : acpi_uart_init();
}
/*
+5 -1
View File
@@ -170,7 +170,11 @@ void xhci_dbc_uart_init(void);
static void inline xhci_dbc_uart_init(void) {}
#endif
void uart_init(void);
/*
* Returns 0 unless a UART explicitly requested via dtuart= failed to
* initialise.
*/
int uart_init(void);
struct physdev_dbgp_op;
int dbgp_op(const struct physdev_dbgp_op *op);
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.