From: Geoff Levand Date: Wed, 13 Jun 2018 10:56:08 -0700 Subject: arm64/acpi: Add fixup for HPE m400 quirks Forwarded: https://patchwork.codeaurora.org/patch/547277/ Adds a new ACPI init routine acpi_fixup_m400_quirks that adds a work-around for HPE ProLiant m400 APEI firmware problems. The work-around disables APEI when CONFIG_ACPI_APEI is set and m400 firmware is detected. Without this fixup m400 systems experience errors like these on startup: [Hardware Error]: Hardware error from APEI Generic Hardware Error Source: 2 [Hardware Error]: event severity: fatal [Hardware Error]: Error 0, type: fatal [Hardware Error]: section_type: memory error [Hardware Error]: error_status: 0x0000000000001300 [Hardware Error]: error_type: 10, invalid address Kernel panic - not syncing: Fatal hardware error! Signed-off-by: Geoff Levand [bwh: Adjust context to apply to Linux 4.19] --- arch/arm64/kernel/acpi.c | 40 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 36 insertions(+), 4 deletions(-) Index: linux/arch/arm64/kernel/acpi.c =================================================================== --- linux.orig/arch/arm64/kernel/acpi.c +++ linux/arch/arm64/kernel/acpi.c @@ -32,6 +32,8 @@ #include #include +#include + int acpi_noirq = 1; /* skip ACPI IRQ initialization */ int acpi_disabled = 1; EXPORT_SYMBOL(acpi_disabled); @@ -178,6 +180,33 @@ out: } /* + * acpi_fixup_m400_quirks - Work-around for HPE ProLiant m400 APEI firmware + * problems. + */ +static void __init acpi_fixup_m400_quirks(void) +{ + acpi_status status; + struct acpi_table_header *header; +#if !defined(CONFIG_ACPI_APEI) + int hest_disable = HEST_DISABLED; +#endif + + if (!IS_ENABLED(CONFIG_ACPI_APEI) || hest_disable != HEST_ENABLED) + return; + + status = acpi_get_table(ACPI_SIG_HEST, 0, &header); + + if (ACPI_SUCCESS(status) && !strncmp(header->oem_id, "HPE ", 6) && + !strncmp(header->oem_table_id, "ProLiant", 8) && + MIDR_IMPLEMENTOR(read_cpuid_id()) == ARM_CPU_IMP_APM) { + hest_disable = HEST_DISABLED; + pr_info("Disabled APEI for m400.\n"); + } + + acpi_put_table(header); +} + +/* * acpi_boot_table_init() called from setup_arch(), always. * 1. find RSDP and get its address, and then find XSDT * 2. extract all tables and checksums them all @@ -232,11 +261,14 @@ done: if (acpi_disabled) { if (earlycon_acpi_spcr_enable) early_init_dt_scan_chosen_stdout(); - } else { - acpi_parse_spcr(earlycon_acpi_spcr_enable, true); - if (IS_ENABLED(CONFIG_ACPI_BGRT)) - acpi_table_parse(ACPI_SIG_BGRT, acpi_parse_bgrt); + return; } + + acpi_parse_spcr(earlycon_acpi_spcr_enable, true); + if (IS_ENABLED(CONFIG_ACPI_BGRT)) + acpi_table_parse(ACPI_SIG_BGRT, acpi_parse_bgrt); + + acpi_fixup_m400_quirks(); } static pgprot_t __acpi_get_writethrough_mem_attribute(void)