Skip to content

Commit

Permalink
ACPI: SPCR: Make SPCR available to x86
Browse files Browse the repository at this point in the history
SPCR is currently only enabled or ARM64 and x86 can use SPCR to setup
an early console.

General fixes include updating Documentation & Kconfig (for x86),
updating comments, and changing parse_spcr() to acpi_parse_spcr(),
and earlycon_init_is_deferred to earlycon_acpi_spcr_enable to be
more descriptive.

On x86, many systems have a valid SPCR table but the table version is
not 2 so the table version check must be a warning.

On ARM64 when the kernel parameter earlycon is used both the early console
and console are enabled.  On x86, only the earlycon should be enabled by
by default.  Modify acpi_parse_spcr() to allow options for initializing
the early console and console separately.

Signed-off-by: Prarit Bhargava <[email protected]>
Acked-by: Ingo Molnar <[email protected]>
Reviewed-by: Mark Salter <[email protected]>
Tested-by: Mark Salter <[email protected]>
Signed-off-by: Rafael J. Wysocki <[email protected]>
  • Loading branch information
prarit authored and rafaeljw committed Feb 7, 2018
1 parent 8906743 commit 0231d00
Show file tree
Hide file tree
Showing 8 changed files with 44 additions and 34 deletions.
9 changes: 6 additions & 3 deletions Documentation/admin-guide/kernel-parameters.txt
Original file line number Diff line number Diff line change
Expand Up @@ -917,9 +917,12 @@

earlycon= [KNL] Output early console device and options.

When used with no options, the early console is
determined by the stdout-path property in device
tree's chosen node.
[ARM64] The early console is determined by the
stdout-path property in device tree's chosen node,
or determined by the ACPI SPCR table.

[X86] When used with no options the early console is
determined by the ACPI SPCR table.

cdns,<addr>[,options]
Start an early, polled-mode console on a Cadence
Expand Down
4 changes: 2 additions & 2 deletions arch/arm64/kernel/acpi.c
Original file line number Diff line number Diff line change
Expand Up @@ -230,10 +230,10 @@ void __init acpi_boot_table_init(void)

done:
if (acpi_disabled) {
if (earlycon_init_is_deferred)
if (earlycon_acpi_spcr_enable)
early_init_dt_scan_chosen_stdout();
} else {
parse_spcr(earlycon_init_is_deferred);
acpi_parse_spcr(earlycon_acpi_spcr_enable, true);
if (IS_ENABLED(CONFIG_ACPI_BGRT))
acpi_table_parse(ACPI_SIG_BGRT, acpi_parse_bgrt);
}
Expand Down
3 changes: 3 additions & 0 deletions arch/x86/kernel/acpi/boot.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
#include <linux/ioport.h>
#include <linux/pci.h>
#include <linux/efi-bgrt.h>
#include <linux/serial_core.h>

#include <asm/e820/api.h>
#include <asm/irqdomain.h>
Expand Down Expand Up @@ -1625,6 +1626,8 @@ int __init acpi_boot_init(void)
if (!acpi_noirq)
x86_init.pci.init = pci_acpi_init;

/* Do not enable ACPI SPCR console by default */
acpi_parse_spcr(earlycon_acpi_spcr_enable, false);
return 0;
}

Expand Down
7 changes: 6 additions & 1 deletion drivers/acpi/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,12 @@ config ACPI_DEBUGGER_USER
endif

config ACPI_SPCR_TABLE
bool
bool "ACPI Serial Port Console Redirection Support"
default y if X86
help
Enable support for Serial Port Console Redirection (SPCR) Table.
This table provides information about the configuration of the
earlycon console.

config ACPI_LPIT
bool
Expand Down
29 changes: 15 additions & 14 deletions drivers/acpi/spcr.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
* occasionally getting stuck as 1. To avoid the potential for a hang, check
* TXFE == 0 instead of BUSY == 1. This may not be suitable for all UART
* implementations, so only do so if an affected platform is detected in
* parse_spcr().
* acpi_parse_spcr().
*/
bool qdf2400_e44_present;
EXPORT_SYMBOL(qdf2400_e44_present);
Expand Down Expand Up @@ -74,19 +74,21 @@ static bool xgene_8250_erratum_present(struct acpi_table_spcr *tb)
}

/**
* parse_spcr() - parse ACPI SPCR table and add preferred console
* acpi_parse_spcr() - parse ACPI SPCR table and add preferred console
*
* @earlycon: set up earlycon for the console specified by the table
* @enable_earlycon: set up earlycon for the console specified by the table
* @enable_console: setup the console specified by the table.
*
* For the architectures with support for ACPI, CONFIG_ACPI_SPCR_TABLE may be
* defined to parse ACPI SPCR table. As a result of the parsing preferred
* console is registered and if @earlycon is true, earlycon is set up.
* console is registered and if @enable_earlycon is true, earlycon is set up.
* If @enable_console is true the system console is also configured.
*
* When CONFIG_ACPI_SPCR_TABLE is defined, this function should be called
* from arch initialization code as soon as the DT/ACPI decision is made.
*
*/
int __init parse_spcr(bool earlycon)
int __init acpi_parse_spcr(bool enable_earlycon, bool enable_console)
{
static char opts[64];
struct acpi_table_spcr *table;
Expand All @@ -105,11 +107,8 @@ int __init parse_spcr(bool earlycon)
if (ACPI_FAILURE(status))
return -ENOENT;

if (table->header.revision < 2) {
err = -ENOENT;
pr_err("wrong table version\n");
goto done;
}
if (table->header.revision < 2)
pr_info("SPCR table version %d\n", table->header.revision);

if (table->serial_port.space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) {
switch (ACPI_ACCESS_BIT_WIDTH((
Expand Down Expand Up @@ -185,7 +184,7 @@ int __init parse_spcr(bool earlycon)
*/
if (qdf2400_erratum_44_present(&table->header)) {
qdf2400_e44_present = true;
if (earlycon)
if (enable_earlycon)
uart = "qdf2400_e44";
}

Expand All @@ -205,11 +204,13 @@ int __init parse_spcr(bool earlycon)

pr_info("console: %s\n", opts);

if (earlycon)
if (enable_earlycon)
setup_earlycon(opts);

err = add_preferred_console(uart, 0, opts + strlen(uart) + 1);

if (enable_console)
err = add_preferred_console(uart, 0, opts + strlen(uart) + 1);
else
err = 0;
done:
acpi_put_table((struct acpi_table_header *)table);
return err;
Expand Down
15 changes: 5 additions & 10 deletions drivers/tty/serial/earlycon.c
Original file line number Diff line number Diff line change
Expand Up @@ -197,25 +197,20 @@ int __init setup_earlycon(char *buf)
}

/*
* When CONFIG_ACPI_SPCR_TABLE is defined, "earlycon" without parameters in
* command line does not start DT earlycon immediately, instead it defers
* starting it until DT/ACPI decision is made. At that time if ACPI is enabled
* call parse_spcr(), else call early_init_dt_scan_chosen_stdout()
* This defers the initialization of the early console until after ACPI has
* been initialized.
*/
bool earlycon_init_is_deferred __initdata;
bool earlycon_acpi_spcr_enable __initdata;

/* early_param wrapper for setup_earlycon() */
static int __init param_setup_earlycon(char *buf)
{
int err;

/*
* Just 'earlycon' is a valid param for devicetree earlycons;
* don't generate a warning from parse_early_params() in that case
*/
/* Just 'earlycon' is a valid param for devicetree and ACPI SPCR. */
if (!buf || !buf[0]) {
if (IS_ENABLED(CONFIG_ACPI_SPCR_TABLE)) {
earlycon_init_is_deferred = true;
earlycon_acpi_spcr_enable = true;
return 0;
} else if (!buf) {
return early_init_dt_scan_chosen_stdout();
Expand Down
7 changes: 5 additions & 2 deletions include/linux/acpi.h
Original file line number Diff line number Diff line change
Expand Up @@ -1249,9 +1249,12 @@ static inline bool acpi_has_watchdog(void) { return false; }

#ifdef CONFIG_ACPI_SPCR_TABLE
extern bool qdf2400_e44_present;
int parse_spcr(bool earlycon);
int acpi_parse_spcr(bool enable_earlycon, bool enable_console);
#else
static inline int parse_spcr(bool earlycon) { return 0; }
static inline int acpi_parse_spcr(bool enable_earlycon, bool enable_console)
{
return 0;
}
#endif

#if IS_ENABLED(CONFIG_ACPI_GENERIC_GSI)
Expand Down
4 changes: 2 additions & 2 deletions include/linux/serial_core.h
Original file line number Diff line number Diff line change
Expand Up @@ -376,10 +376,10 @@ extern int of_setup_earlycon(const struct earlycon_id *match,
const char *options);

#ifdef CONFIG_SERIAL_EARLYCON
extern bool earlycon_init_is_deferred __initdata;
extern bool earlycon_acpi_spcr_enable __initdata;
int setup_earlycon(char *buf);
#else
static const bool earlycon_init_is_deferred;
static const bool earlycon_acpi_spcr_enable;
static inline int setup_earlycon(char *buf) { return 0; }
#endif

Expand Down

0 comments on commit 0231d00

Please sign in to comment.