| From b064a8fa77dfead647564c46ac8fc5b13bd1ab73 Mon Sep 17 00:00:00 2001 |
| From: "Rafael J. Wysocki" <rafael.j.wysocki@intel.com> |
| Date: Wed, 10 Jun 2015 01:33:36 +0200 |
| Subject: ACPI / init: Switch over platform to the ACPI mode later |
| |
| From: "Rafael J. Wysocki" <rafael.j.wysocki@intel.com> |
| |
| commit b064a8fa77dfead647564c46ac8fc5b13bd1ab73 upstream. |
| |
| Commit 73f7d1ca3263 "ACPI / init: Run acpi_early_init() before |
| timekeeping_init()" moved the ACPI subsystem initialization, |
| including the ACPI mode enabling, to an earlier point in the |
| initialization sequence, to allow the timekeeping subsystem |
| use ACPI early. Unfortunately, that resulted in boot regressions |
| on some systems and the early ACPI initialization was moved toward |
| its original position in the kernel initialization code by commit |
| c4e1acbb35e4 "ACPI / init: Invoke early ACPI initialization later". |
| |
| However, that turns out to be insufficient, as boot is still broken |
| on the Tyan S8812 mainboard. |
| |
| To fix that issue, split the ACPI early initialization code into |
| two pieces so the majority of it still located in acpi_early_init() |
| and the part switching over the platform into the ACPI mode goes into |
| a new function, acpi_subsystem_init(), executed at the original early |
| ACPI initialization spot. |
| |
| That fixes the Tyan S8812 boot problem, but still allows ACPI |
| tables to be loaded earlier which is useful to the EFI code in |
| efi_enter_virtual_mode(). |
| |
| Link: https://bugzilla.kernel.org/show_bug.cgi?id=97141 |
| Fixes: 73f7d1ca3263 "ACPI / init: Run acpi_early_init() before timekeeping_init()" |
| Reported-and-tested-by: Marius Tolzmann <tolzmann@molgen.mpg.de> |
| Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> |
| Acked-by: Toshi Kani <toshi.kani@hp.com> |
| Reviewed-by: Hanjun Guo <hanjun.guo@linaro.org> |
| Reviewed-by: Lee, Chun-Yi <jlee@suse.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| drivers/acpi/bus.c | 56 +++++++++++++++++++++++++++++++++++++-------------- |
| include/linux/acpi.h | 2 + |
| init/main.c | 1 |
| 3 files changed, 44 insertions(+), 15 deletions(-) |
| |
| --- a/drivers/acpi/bus.c |
| +++ b/drivers/acpi/bus.c |
| @@ -467,6 +467,16 @@ static int __init acpi_bus_init_irq(void |
| return 0; |
| } |
| |
| +/** |
| + * acpi_early_init - Initialize ACPICA and populate the ACPI namespace. |
| + * |
| + * The ACPI tables are accessible after this, but the handling of events has not |
| + * been initialized and the global lock is not available yet, so AML should not |
| + * be executed at this point. |
| + * |
| + * Doing this before switching the EFI runtime services to virtual mode allows |
| + * the EfiBootServices memory to be freed slightly earlier on boot. |
| + */ |
| void __init acpi_early_init(void) |
| { |
| acpi_status status; |
| @@ -530,26 +540,42 @@ void __init acpi_early_init(void) |
| acpi_gbl_FADT.sci_interrupt = acpi_sci_override_gsi; |
| } |
| #endif |
| + return; |
| + |
| + error0: |
| + disable_acpi(); |
| +} |
| + |
| +/** |
| + * acpi_subsystem_init - Finalize the early initialization of ACPI. |
| + * |
| + * Switch over the platform to the ACPI mode (if possible), initialize the |
| + * handling of ACPI events, install the interrupt and global lock handlers. |
| + * |
| + * Doing this too early is generally unsafe, but at the same time it needs to be |
| + * done before all things that really depend on ACPI. The right spot appears to |
| + * be before finalizing the EFI initialization. |
| + */ |
| +void __init acpi_subsystem_init(void) |
| +{ |
| + acpi_status status; |
| + |
| + if (acpi_disabled) |
| + return; |
| |
| status = acpi_enable_subsystem(~ACPI_NO_ACPI_ENABLE); |
| if (ACPI_FAILURE(status)) { |
| printk(KERN_ERR PREFIX "Unable to enable ACPI\n"); |
| - goto error0; |
| + disable_acpi(); |
| + } else { |
| + /* |
| + * If the system is using ACPI then we can be reasonably |
| + * confident that any regulators are managed by the firmware |
| + * so tell the regulator core it has everything it needs to |
| + * know. |
| + */ |
| + regulator_has_full_constraints(); |
| } |
| - |
| - /* |
| - * If the system is using ACPI then we can be reasonably |
| - * confident that any regulators are managed by the firmware |
| - * so tell the regulator core it has everything it needs to |
| - * know. |
| - */ |
| - regulator_has_full_constraints(); |
| - |
| - return; |
| - |
| - error0: |
| - disable_acpi(); |
| - return; |
| } |
| |
| static int __init acpi_bus_init(void) |
| --- a/include/linux/acpi.h |
| +++ b/include/linux/acpi.h |
| @@ -428,6 +428,7 @@ extern acpi_status acpi_pci_osc_control_ |
| #define ACPI_OST_SC_INSERT_NOT_SUPPORTED 0x82 |
| |
| extern void acpi_early_init(void); |
| +extern void acpi_subsystem_init(void); |
| |
| extern int acpi_nvs_register(__u64 start, __u64 size); |
| |
| @@ -477,6 +478,7 @@ static inline const char *acpi_dev_name( |
| } |
| |
| static inline void acpi_early_init(void) { } |
| +static inline void acpi_subsystem_init(void) { } |
| |
| static inline int early_acpi_boot_init(void) |
| { |
| --- a/init/main.c |
| +++ b/init/main.c |
| @@ -661,6 +661,7 @@ asmlinkage __visible void __init start_k |
| |
| check_bugs(); |
| |
| + acpi_subsystem_init(); |
| sfi_init_late(); |
| |
| if (efi_enabled(EFI_RUNTIME_SERVICES)) { |