ACPI: APEI: explicit init of HEST and GHES in apci_init()

[ Upstream commit dc4e8c07e9 ]

From commit e147133a42 ("ACPI / APEI: Make hest.c manage the estatus
memory pool") was merged, ghes_init() relies on acpi_hest_init() to manage
the estatus memory pool. On the other hand, ghes_init() relies on
sdei_init() to detect the SDEI version and (un)register events. The
dependencies are as follows:

    ghes_init() => acpi_hest_init() => acpi_bus_init() => acpi_init()
    ghes_init() => sdei_init()

HEST is not PCI-specific and initcall ordering is implicit and not
well-defined within a level.

Based on above, remove acpi_hest_init() from acpi_pci_root_init() and
convert ghes_init() and sdei_init() from initcalls to explicit calls in the
following order:

    acpi_hest_init()
    ghes_init()
        sdei_init()

Signed-off-by: Shuai Xue <xueshuai@linux.alibaba.com>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
Shuai Xue 2022-02-27 20:25:45 +08:00 committed by Greg Kroah-Hartman
parent 6dc72d0181
commit 335852f7a9
7 changed files with 18 additions and 26 deletions

View File

@ -1457,33 +1457,35 @@ static struct platform_driver ghes_platform_driver = {
.remove = ghes_remove, .remove = ghes_remove,
}; };
static int __init ghes_init(void) void __init ghes_init(void)
{ {
int rc; int rc;
sdei_init();
if (acpi_disabled) if (acpi_disabled)
return -ENODEV; return;
switch (hest_disable) { switch (hest_disable) {
case HEST_NOT_FOUND: case HEST_NOT_FOUND:
return -ENODEV; return;
case HEST_DISABLED: case HEST_DISABLED:
pr_info(GHES_PFX "HEST is not enabled!\n"); pr_info(GHES_PFX "HEST is not enabled!\n");
return -EINVAL; return;
default: default:
break; break;
} }
if (ghes_disable) { if (ghes_disable) {
pr_info(GHES_PFX "GHES is not enabled!\n"); pr_info(GHES_PFX "GHES is not enabled!\n");
return -EINVAL; return;
} }
ghes_nmi_init_cxt(); ghes_nmi_init_cxt();
rc = platform_driver_register(&ghes_platform_driver); rc = platform_driver_register(&ghes_platform_driver);
if (rc) if (rc)
goto err; return;
rc = apei_osc_setup(); rc = apei_osc_setup();
if (rc == 0 && osc_sb_apei_support_acked) if (rc == 0 && osc_sb_apei_support_acked)
@ -1494,9 +1496,4 @@ static int __init ghes_init(void)
pr_info(GHES_PFX "APEI firmware first mode is enabled by APEI bit.\n"); pr_info(GHES_PFX "APEI firmware first mode is enabled by APEI bit.\n");
else else
pr_info(GHES_PFX "Failed to enable APEI firmware first mode.\n"); pr_info(GHES_PFX "Failed to enable APEI firmware first mode.\n");
return 0;
err:
return rc;
} }
device_initcall(ghes_init);

View File

@ -1340,6 +1340,8 @@ static int __init acpi_init(void)
pci_mmcfg_late_init(); pci_mmcfg_late_init();
acpi_iort_init(); acpi_iort_init();
acpi_hest_init();
ghes_init();
acpi_scan_init(); acpi_scan_init();
acpi_ec_init(); acpi_ec_init();
acpi_debugfs_init(); acpi_debugfs_init();

View File

@ -22,8 +22,6 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/dmi.h> #include <linux/dmi.h>
#include <linux/platform_data/x86/apple.h> #include <linux/platform_data/x86/apple.h>
#include <acpi/apei.h> /* for acpi_hest_init() */
#include "internal.h" #include "internal.h"
#define ACPI_PCI_ROOT_CLASS "pci_bridge" #define ACPI_PCI_ROOT_CLASS "pci_bridge"
@ -938,7 +936,6 @@ out_release_info:
void __init acpi_pci_root_init(void) void __init acpi_pci_root_init(void)
{ {
acpi_hest_init();
if (acpi_pci_disabled) if (acpi_pci_disabled)
return; return;

View File

@ -40,6 +40,7 @@ config ARM_SCPI_POWER_DOMAIN
config ARM_SDE_INTERFACE config ARM_SDE_INTERFACE
bool "ARM Software Delegated Exception Interface (SDEI)" bool "ARM Software Delegated Exception Interface (SDEI)"
depends on ARM64 depends on ARM64
depends on ACPI_APEI_GHES
help help
The Software Delegated Exception Interface (SDEI) is an ARM The Software Delegated Exception Interface (SDEI) is an ARM
standard for registering callbacks from the platform firmware standard for registering callbacks from the platform firmware

View File

@ -1059,14 +1059,14 @@ static bool __init sdei_present_acpi(void)
return true; return true;
} }
static int __init sdei_init(void) void __init sdei_init(void)
{ {
struct platform_device *pdev; struct platform_device *pdev;
int ret; int ret;
ret = platform_driver_register(&sdei_driver); ret = platform_driver_register(&sdei_driver);
if (ret || !sdei_present_acpi()) if (ret || !sdei_present_acpi())
return ret; return;
pdev = platform_device_register_simple(sdei_driver.driver.name, pdev = platform_device_register_simple(sdei_driver.driver.name,
0, NULL, 0); 0, NULL, 0);
@ -1076,17 +1076,8 @@ static int __init sdei_init(void)
pr_info("Failed to register ACPI:SDEI platform device %d\n", pr_info("Failed to register ACPI:SDEI platform device %d\n",
ret); ret);
} }
return ret;
} }
/*
* On an ACPI system SDEI needs to be ready before HEST:GHES tries to register
* its events. ACPI is initialised from a subsys_initcall(), GHES is initialised
* by device_initcall(). We want to be called in the middle.
*/
subsys_initcall_sync(sdei_init);
int sdei_event_handler(struct pt_regs *regs, int sdei_event_handler(struct pt_regs *regs,
struct sdei_registered_event *arg) struct sdei_registered_event *arg)
{ {

View File

@ -27,14 +27,16 @@ extern int hest_disable;
extern int erst_disable; extern int erst_disable;
#ifdef CONFIG_ACPI_APEI_GHES #ifdef CONFIG_ACPI_APEI_GHES
extern bool ghes_disable; extern bool ghes_disable;
void __init ghes_init(void);
#else #else
#define ghes_disable 1 #define ghes_disable 1
static inline void ghes_init(void) { }
#endif #endif
#ifdef CONFIG_ACPI_APEI #ifdef CONFIG_ACPI_APEI
void __init acpi_hest_init(void); void __init acpi_hest_init(void);
#else #else
static inline void acpi_hest_init(void) { return; } static inline void acpi_hest_init(void) { }
#endif #endif
typedef int (*apei_hest_func_t)(struct acpi_hest_header *hest_hdr, void *data); typedef int (*apei_hest_func_t)(struct acpi_hest_header *hest_hdr, void *data);

View File

@ -46,9 +46,11 @@ int sdei_unregister_ghes(struct ghes *ghes);
/* For use by arch code when CPU hotplug notifiers are not appropriate. */ /* For use by arch code when CPU hotplug notifiers are not appropriate. */
int sdei_mask_local_cpu(void); int sdei_mask_local_cpu(void);
int sdei_unmask_local_cpu(void); int sdei_unmask_local_cpu(void);
void __init sdei_init(void);
#else #else
static inline int sdei_mask_local_cpu(void) { return 0; } static inline int sdei_mask_local_cpu(void) { return 0; }
static inline int sdei_unmask_local_cpu(void) { return 0; } static inline int sdei_unmask_local_cpu(void) { return 0; }
static inline void sdei_init(void) { }
#endif /* CONFIG_ARM_SDE_INTERFACE */ #endif /* CONFIG_ARM_SDE_INTERFACE */