Commit 0231d000 authored by Prarit Bhargava's avatar Prarit Bhargava Committed by Rafael J. Wysocki

ACPI: SPCR: Make SPCR available to x86

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: default avatarPrarit Bhargava <prarit@redhat.com>
Acked-by: default avatarIngo Molnar <mingo@kernel.org>
Reviewed-by: default avatarMark Salter <msalter@redhat.com>
Tested-by: default avatarMark Salter <msalter@redhat.com>
Signed-off-by: default avatarRafael J. Wysocki <rafael.j.wysocki@intel.com>
parent 89067434
...@@ -917,9 +917,12 @@ ...@@ -917,9 +917,12 @@
earlycon= [KNL] Output early console device and options. earlycon= [KNL] Output early console device and options.
When used with no options, the early console is [ARM64] The early console is determined by the
determined by the stdout-path property in device stdout-path property in device tree's chosen node,
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] cdns,<addr>[,options]
Start an early, polled-mode console on a Cadence Start an early, polled-mode console on a Cadence
......
...@@ -230,10 +230,10 @@ void __init acpi_boot_table_init(void) ...@@ -230,10 +230,10 @@ void __init acpi_boot_table_init(void)
done: done:
if (acpi_disabled) { if (acpi_disabled) {
if (earlycon_init_is_deferred) if (earlycon_acpi_spcr_enable)
early_init_dt_scan_chosen_stdout(); early_init_dt_scan_chosen_stdout();
} else { } else {
parse_spcr(earlycon_init_is_deferred); acpi_parse_spcr(earlycon_acpi_spcr_enable, true);
if (IS_ENABLED(CONFIG_ACPI_BGRT)) if (IS_ENABLED(CONFIG_ACPI_BGRT))
acpi_table_parse(ACPI_SIG_BGRT, acpi_parse_bgrt); acpi_table_parse(ACPI_SIG_BGRT, acpi_parse_bgrt);
} }
......
...@@ -36,6 +36,7 @@ ...@@ -36,6 +36,7 @@
#include <linux/ioport.h> #include <linux/ioport.h>
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/efi-bgrt.h> #include <linux/efi-bgrt.h>
#include <linux/serial_core.h>
#include <asm/e820/api.h> #include <asm/e820/api.h>
#include <asm/irqdomain.h> #include <asm/irqdomain.h>
...@@ -1625,6 +1626,8 @@ int __init acpi_boot_init(void) ...@@ -1625,6 +1626,8 @@ int __init acpi_boot_init(void)
if (!acpi_noirq) if (!acpi_noirq)
x86_init.pci.init = pci_acpi_init; 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; return 0;
} }
......
...@@ -79,7 +79,12 @@ config ACPI_DEBUGGER_USER ...@@ -79,7 +79,12 @@ config ACPI_DEBUGGER_USER
endif endif
config ACPI_SPCR_TABLE 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 config ACPI_LPIT
bool bool
......
...@@ -21,7 +21,7 @@ ...@@ -21,7 +21,7 @@
* occasionally getting stuck as 1. To avoid the potential for a hang, check * 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 * 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 * implementations, so only do so if an affected platform is detected in
* parse_spcr(). * acpi_parse_spcr().
*/ */
bool qdf2400_e44_present; bool qdf2400_e44_present;
EXPORT_SYMBOL(qdf2400_e44_present); EXPORT_SYMBOL(qdf2400_e44_present);
...@@ -74,19 +74,21 @@ static bool xgene_8250_erratum_present(struct acpi_table_spcr *tb) ...@@ -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 * 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 * 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 * 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. * 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]; static char opts[64];
struct acpi_table_spcr *table; struct acpi_table_spcr *table;
...@@ -105,11 +107,8 @@ int __init parse_spcr(bool earlycon) ...@@ -105,11 +107,8 @@ int __init parse_spcr(bool earlycon)
if (ACPI_FAILURE(status)) if (ACPI_FAILURE(status))
return -ENOENT; return -ENOENT;
if (table->header.revision < 2) { if (table->header.revision < 2)
err = -ENOENT; pr_info("SPCR table version %d\n", table->header.revision);
pr_err("wrong table version\n");
goto done;
}
if (table->serial_port.space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) { if (table->serial_port.space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) {
switch (ACPI_ACCESS_BIT_WIDTH(( switch (ACPI_ACCESS_BIT_WIDTH((
...@@ -185,7 +184,7 @@ int __init parse_spcr(bool earlycon) ...@@ -185,7 +184,7 @@ int __init parse_spcr(bool earlycon)
*/ */
if (qdf2400_erratum_44_present(&table->header)) { if (qdf2400_erratum_44_present(&table->header)) {
qdf2400_e44_present = true; qdf2400_e44_present = true;
if (earlycon) if (enable_earlycon)
uart = "qdf2400_e44"; uart = "qdf2400_e44";
} }
...@@ -205,11 +204,13 @@ int __init parse_spcr(bool earlycon) ...@@ -205,11 +204,13 @@ int __init parse_spcr(bool earlycon)
pr_info("console: %s\n", opts); pr_info("console: %s\n", opts);
if (earlycon) if (enable_earlycon)
setup_earlycon(opts); 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: done:
acpi_put_table((struct acpi_table_header *)table); acpi_put_table((struct acpi_table_header *)table);
return err; return err;
......
...@@ -197,25 +197,20 @@ int __init setup_earlycon(char *buf) ...@@ -197,25 +197,20 @@ int __init setup_earlycon(char *buf)
} }
/* /*
* When CONFIG_ACPI_SPCR_TABLE is defined, "earlycon" without parameters in * This defers the initialization of the early console until after ACPI has
* command line does not start DT earlycon immediately, instead it defers * been initialized.
* 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()
*/ */
bool earlycon_init_is_deferred __initdata; bool earlycon_acpi_spcr_enable __initdata;
/* early_param wrapper for setup_earlycon() */ /* early_param wrapper for setup_earlycon() */
static int __init param_setup_earlycon(char *buf) static int __init param_setup_earlycon(char *buf)
{ {
int err; int err;
/* /* Just 'earlycon' is a valid param for devicetree and ACPI SPCR. */
* Just 'earlycon' is a valid param for devicetree earlycons;
* don't generate a warning from parse_early_params() in that case
*/
if (!buf || !buf[0]) { if (!buf || !buf[0]) {
if (IS_ENABLED(CONFIG_ACPI_SPCR_TABLE)) { if (IS_ENABLED(CONFIG_ACPI_SPCR_TABLE)) {
earlycon_init_is_deferred = true; earlycon_acpi_spcr_enable = true;
return 0; return 0;
} else if (!buf) { } else if (!buf) {
return early_init_dt_scan_chosen_stdout(); return early_init_dt_scan_chosen_stdout();
......
...@@ -1249,9 +1249,12 @@ static inline bool acpi_has_watchdog(void) { return false; } ...@@ -1249,9 +1249,12 @@ static inline bool acpi_has_watchdog(void) { return false; }
#ifdef CONFIG_ACPI_SPCR_TABLE #ifdef CONFIG_ACPI_SPCR_TABLE
extern bool qdf2400_e44_present; extern bool qdf2400_e44_present;
int parse_spcr(bool earlycon); int acpi_parse_spcr(bool enable_earlycon, bool enable_console);
#else #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 #endif
#if IS_ENABLED(CONFIG_ACPI_GENERIC_GSI) #if IS_ENABLED(CONFIG_ACPI_GENERIC_GSI)
......
...@@ -376,10 +376,10 @@ extern int of_setup_earlycon(const struct earlycon_id *match, ...@@ -376,10 +376,10 @@ extern int of_setup_earlycon(const struct earlycon_id *match,
const char *options); const char *options);
#ifdef CONFIG_SERIAL_EARLYCON #ifdef CONFIG_SERIAL_EARLYCON
extern bool earlycon_init_is_deferred __initdata; extern bool earlycon_acpi_spcr_enable __initdata;
int setup_earlycon(char *buf); int setup_earlycon(char *buf);
#else #else
static const bool earlycon_init_is_deferred; static const bool earlycon_acpi_spcr_enable;
static inline int setup_earlycon(char *buf) { return 0; } static inline int setup_earlycon(char *buf) { return 0; }
#endif #endif
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment