diff options
author | Prarit Bhargava <prarit@redhat.com> | 2018-01-18 10:09:51 -0500 |
---|---|---|
committer | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2018-02-07 05:39:58 -0500 |
commit | 0231d00082f61cfe03f2b7c27e5356f8cdf0312c (patch) | |
tree | 24f036cb972640ccdeed395a55d1c37571fcb3db | |
parent | 890674343bb2d546825f713542b1e199f0728732 (diff) |
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: Prarit Bhargava <prarit@redhat.com>
Acked-by: Ingo Molnar <mingo@kernel.org>
Reviewed-by: Mark Salter <msalter@redhat.com>
Tested-by: Mark Salter <msalter@redhat.com>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
-rw-r--r-- | Documentation/admin-guide/kernel-parameters.txt | 9 | ||||
-rw-r--r-- | arch/arm64/kernel/acpi.c | 4 | ||||
-rw-r--r-- | arch/x86/kernel/acpi/boot.c | 3 | ||||
-rw-r--r-- | drivers/acpi/Kconfig | 7 | ||||
-rw-r--r-- | drivers/acpi/spcr.c | 29 | ||||
-rw-r--r-- | drivers/tty/serial/earlycon.c | 15 | ||||
-rw-r--r-- | include/linux/acpi.h | 7 | ||||
-rw-r--r-- | include/linux/serial_core.h | 4 |
8 files changed, 44 insertions, 34 deletions
diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt index 1bdcf572c2ac..aecb1c8ef675 100644 --- a/Documentation/admin-guide/kernel-parameters.txt +++ b/Documentation/admin-guide/kernel-parameters.txt | |||
@@ -917,9 +917,12 @@ | |||
917 | 917 | ||
918 | earlycon= [KNL] Output early console device and options. | 918 | earlycon= [KNL] Output early console device and options. |
919 | 919 | ||
920 | When used with no options, the early console is | 920 | [ARM64] The early console is determined by the |
921 | determined by the stdout-path property in device | 921 | stdout-path property in device tree's chosen node, |
922 | tree's chosen node. | 922 | or determined by the ACPI SPCR table. |
923 | |||
924 | [X86] When used with no options the early console is | ||
925 | determined by the ACPI SPCR table. | ||
923 | 926 | ||
924 | cdns,<addr>[,options] | 927 | cdns,<addr>[,options] |
925 | Start an early, polled-mode console on a Cadence | 928 | Start an early, polled-mode console on a Cadence |
diff --git a/arch/arm64/kernel/acpi.c b/arch/arm64/kernel/acpi.c index b3162715ed78..2aa5609def27 100644 --- a/arch/arm64/kernel/acpi.c +++ b/arch/arm64/kernel/acpi.c | |||
@@ -230,10 +230,10 @@ void __init acpi_boot_table_init(void) | |||
230 | 230 | ||
231 | done: | 231 | done: |
232 | if (acpi_disabled) { | 232 | if (acpi_disabled) { |
233 | if (earlycon_init_is_deferred) | 233 | if (earlycon_acpi_spcr_enable) |
234 | early_init_dt_scan_chosen_stdout(); | 234 | early_init_dt_scan_chosen_stdout(); |
235 | } else { | 235 | } else { |
236 | parse_spcr(earlycon_init_is_deferred); | 236 | acpi_parse_spcr(earlycon_acpi_spcr_enable, true); |
237 | if (IS_ENABLED(CONFIG_ACPI_BGRT)) | 237 | if (IS_ENABLED(CONFIG_ACPI_BGRT)) |
238 | acpi_table_parse(ACPI_SIG_BGRT, acpi_parse_bgrt); | 238 | acpi_table_parse(ACPI_SIG_BGRT, acpi_parse_bgrt); |
239 | } | 239 | } |
diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c index ec3a286163c3..2aa92094b59d 100644 --- a/arch/x86/kernel/acpi/boot.c +++ b/arch/x86/kernel/acpi/boot.c | |||
@@ -36,6 +36,7 @@ | |||
36 | #include <linux/ioport.h> | 36 | #include <linux/ioport.h> |
37 | #include <linux/pci.h> | 37 | #include <linux/pci.h> |
38 | #include <linux/efi-bgrt.h> | 38 | #include <linux/efi-bgrt.h> |
39 | #include <linux/serial_core.h> | ||
39 | 40 | ||
40 | #include <asm/e820/api.h> | 41 | #include <asm/e820/api.h> |
41 | #include <asm/irqdomain.h> | 42 | #include <asm/irqdomain.h> |
@@ -1625,6 +1626,8 @@ int __init acpi_boot_init(void) | |||
1625 | if (!acpi_noirq) | 1626 | if (!acpi_noirq) |
1626 | x86_init.pci.init = pci_acpi_init; | 1627 | x86_init.pci.init = pci_acpi_init; |
1627 | 1628 | ||
1629 | /* Do not enable ACPI SPCR console by default */ | ||
1630 | acpi_parse_spcr(earlycon_acpi_spcr_enable, false); | ||
1628 | return 0; | 1631 | return 0; |
1629 | } | 1632 | } |
1630 | 1633 | ||
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index 46505396869e..ddcb5f40e8ee 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig | |||
@@ -79,7 +79,12 @@ config ACPI_DEBUGGER_USER | |||
79 | endif | 79 | endif |
80 | 80 | ||
81 | config ACPI_SPCR_TABLE | 81 | config ACPI_SPCR_TABLE |
82 | bool | 82 | bool "ACPI Serial Port Console Redirection Support" |
83 | default y if X86 | ||
84 | help | ||
85 | Enable support for Serial Port Console Redirection (SPCR) Table. | ||
86 | This table provides information about the configuration of the | ||
87 | earlycon console. | ||
83 | 88 | ||
84 | config ACPI_LPIT | 89 | config ACPI_LPIT |
85 | bool | 90 | bool |
diff --git a/drivers/acpi/spcr.c b/drivers/acpi/spcr.c index 324b35bfe781..89e97d21a89c 100644 --- a/drivers/acpi/spcr.c +++ b/drivers/acpi/spcr.c | |||
@@ -21,7 +21,7 @@ | |||
21 | * occasionally getting stuck as 1. To avoid the potential for a hang, check | 21 | * occasionally getting stuck as 1. To avoid the potential for a hang, check |
22 | * TXFE == 0 instead of BUSY == 1. This may not be suitable for all UART | 22 | * TXFE == 0 instead of BUSY == 1. This may not be suitable for all UART |
23 | * implementations, so only do so if an affected platform is detected in | 23 | * implementations, so only do so if an affected platform is detected in |
24 | * parse_spcr(). | 24 | * acpi_parse_spcr(). |
25 | */ | 25 | */ |
26 | bool qdf2400_e44_present; | 26 | bool qdf2400_e44_present; |
27 | EXPORT_SYMBOL(qdf2400_e44_present); | 27 | EXPORT_SYMBOL(qdf2400_e44_present); |
@@ -74,19 +74,21 @@ static bool xgene_8250_erratum_present(struct acpi_table_spcr *tb) | |||
74 | } | 74 | } |
75 | 75 | ||
76 | /** | 76 | /** |
77 | * parse_spcr() - parse ACPI SPCR table and add preferred console | 77 | * acpi_parse_spcr() - parse ACPI SPCR table and add preferred console |
78 | * | 78 | * |
79 | * @earlycon: set up earlycon for the console specified by the table | 79 | * @enable_earlycon: set up earlycon for the console specified by the table |
80 | * @enable_console: setup the console specified by the table. | ||
80 | * | 81 | * |
81 | * For the architectures with support for ACPI, CONFIG_ACPI_SPCR_TABLE may be | 82 | * For the architectures with support for ACPI, CONFIG_ACPI_SPCR_TABLE may be |
82 | * defined to parse ACPI SPCR table. As a result of the parsing preferred | 83 | * defined to parse ACPI SPCR table. As a result of the parsing preferred |
83 | * console is registered and if @earlycon is true, earlycon is set up. | 84 | * console is registered and if @enable_earlycon is true, earlycon is set up. |
85 | * If @enable_console is true the system console is also configured. | ||
84 | * | 86 | * |
85 | * When CONFIG_ACPI_SPCR_TABLE is defined, this function should be called | 87 | * When CONFIG_ACPI_SPCR_TABLE is defined, this function should be called |
86 | * from arch initialization code as soon as the DT/ACPI decision is made. | 88 | * from arch initialization code as soon as the DT/ACPI decision is made. |
87 | * | 89 | * |
88 | */ | 90 | */ |
89 | int __init parse_spcr(bool earlycon) | 91 | int __init acpi_parse_spcr(bool enable_earlycon, bool enable_console) |
90 | { | 92 | { |
91 | static char opts[64]; | 93 | static char opts[64]; |
92 | struct acpi_table_spcr *table; | 94 | struct acpi_table_spcr *table; |
@@ -105,11 +107,8 @@ int __init parse_spcr(bool earlycon) | |||
105 | if (ACPI_FAILURE(status)) | 107 | if (ACPI_FAILURE(status)) |
106 | return -ENOENT; | 108 | return -ENOENT; |
107 | 109 | ||
108 | if (table->header.revision < 2) { | 110 | if (table->header.revision < 2) |
109 | err = -ENOENT; | 111 | pr_info("SPCR table version %d\n", table->header.revision); |
110 | pr_err("wrong table version\n"); | ||
111 | goto done; | ||
112 | } | ||
113 | 112 | ||
114 | if (table->serial_port.space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) { | 113 | if (table->serial_port.space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) { |
115 | switch (ACPI_ACCESS_BIT_WIDTH(( | 114 | switch (ACPI_ACCESS_BIT_WIDTH(( |
@@ -185,7 +184,7 @@ int __init parse_spcr(bool earlycon) | |||
185 | */ | 184 | */ |
186 | if (qdf2400_erratum_44_present(&table->header)) { | 185 | if (qdf2400_erratum_44_present(&table->header)) { |
187 | qdf2400_e44_present = true; | 186 | qdf2400_e44_present = true; |
188 | if (earlycon) | 187 | if (enable_earlycon) |
189 | uart = "qdf2400_e44"; | 188 | uart = "qdf2400_e44"; |
190 | } | 189 | } |
191 | 190 | ||
@@ -205,11 +204,13 @@ int __init parse_spcr(bool earlycon) | |||
205 | 204 | ||
206 | pr_info("console: %s\n", opts); | 205 | pr_info("console: %s\n", opts); |
207 | 206 | ||
208 | if (earlycon) | 207 | if (enable_earlycon) |
209 | setup_earlycon(opts); | 208 | setup_earlycon(opts); |
210 | 209 | ||
211 | err = add_preferred_console(uart, 0, opts + strlen(uart) + 1); | 210 | if (enable_console) |
212 | 211 | err = add_preferred_console(uart, 0, opts + strlen(uart) + 1); | |
212 | else | ||
213 | err = 0; | ||
213 | done: | 214 | done: |
214 | acpi_put_table((struct acpi_table_header *)table); | 215 | acpi_put_table((struct acpi_table_header *)table); |
215 | return err; | 216 | return err; |
diff --git a/drivers/tty/serial/earlycon.c b/drivers/tty/serial/earlycon.c index 4c8b80f1c688..870e84fb6e39 100644 --- a/drivers/tty/serial/earlycon.c +++ b/drivers/tty/serial/earlycon.c | |||
@@ -197,25 +197,20 @@ int __init setup_earlycon(char *buf) | |||
197 | } | 197 | } |
198 | 198 | ||
199 | /* | 199 | /* |
200 | * When CONFIG_ACPI_SPCR_TABLE is defined, "earlycon" without parameters in | 200 | * This defers the initialization of the early console until after ACPI has |
201 | * command line does not start DT earlycon immediately, instead it defers | 201 | * been initialized. |
202 | * starting it until DT/ACPI decision is made. At that time if ACPI is enabled | ||
203 | * call parse_spcr(), else call early_init_dt_scan_chosen_stdout() | ||
204 | */ | 202 | */ |
205 | bool earlycon_init_is_deferred __initdata; | 203 | bool earlycon_acpi_spcr_enable __initdata; |
206 | 204 | ||
207 | /* early_param wrapper for setup_earlycon() */ | 205 | /* early_param wrapper for setup_earlycon() */ |
208 | static int __init param_setup_earlycon(char *buf) | 206 | static int __init param_setup_earlycon(char *buf) |
209 | { | 207 | { |
210 | int err; | 208 | int err; |
211 | 209 | ||
212 | /* | 210 | /* Just 'earlycon' is a valid param for devicetree and ACPI SPCR. */ |
213 | * Just 'earlycon' is a valid param for devicetree earlycons; | ||
214 | * don't generate a warning from parse_early_params() in that case | ||
215 | */ | ||
216 | if (!buf || !buf[0]) { | 211 | if (!buf || !buf[0]) { |
217 | if (IS_ENABLED(CONFIG_ACPI_SPCR_TABLE)) { | 212 | if (IS_ENABLED(CONFIG_ACPI_SPCR_TABLE)) { |
218 | earlycon_init_is_deferred = true; | 213 | earlycon_acpi_spcr_enable = true; |
219 | return 0; | 214 | return 0; |
220 | } else if (!buf) { | 215 | } else if (!buf) { |
221 | return early_init_dt_scan_chosen_stdout(); | 216 | return early_init_dt_scan_chosen_stdout(); |
diff --git a/include/linux/acpi.h b/include/linux/acpi.h index b8f4c3c776e5..e6b98a32495f 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h | |||
@@ -1249,9 +1249,12 @@ static inline bool acpi_has_watchdog(void) { return false; } | |||
1249 | 1249 | ||
1250 | #ifdef CONFIG_ACPI_SPCR_TABLE | 1250 | #ifdef CONFIG_ACPI_SPCR_TABLE |
1251 | extern bool qdf2400_e44_present; | 1251 | extern bool qdf2400_e44_present; |
1252 | int parse_spcr(bool earlycon); | 1252 | int acpi_parse_spcr(bool enable_earlycon, bool enable_console); |
1253 | #else | 1253 | #else |
1254 | static inline int parse_spcr(bool earlycon) { return 0; } | 1254 | static inline int acpi_parse_spcr(bool enable_earlycon, bool enable_console) |
1255 | { | ||
1256 | return 0; | ||
1257 | } | ||
1255 | #endif | 1258 | #endif |
1256 | 1259 | ||
1257 | #if IS_ENABLED(CONFIG_ACPI_GENERIC_GSI) | 1260 | #if IS_ENABLED(CONFIG_ACPI_GENERIC_GSI) |
diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h index 37b044e78333..aefd0e5115da 100644 --- a/include/linux/serial_core.h +++ b/include/linux/serial_core.h | |||
@@ -376,10 +376,10 @@ extern int of_setup_earlycon(const struct earlycon_id *match, | |||
376 | const char *options); | 376 | const char *options); |
377 | 377 | ||
378 | #ifdef CONFIG_SERIAL_EARLYCON | 378 | #ifdef CONFIG_SERIAL_EARLYCON |
379 | extern bool earlycon_init_is_deferred __initdata; | 379 | extern bool earlycon_acpi_spcr_enable __initdata; |
380 | int setup_earlycon(char *buf); | 380 | int setup_earlycon(char *buf); |
381 | #else | 381 | #else |
382 | static const bool earlycon_init_is_deferred; | 382 | static const bool earlycon_acpi_spcr_enable; |
383 | static inline int setup_earlycon(char *buf) { return 0; } | 383 | static inline int setup_earlycon(char *buf) { return 0; } |
384 | #endif | 384 | #endif |
385 | 385 | ||