Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932116AbbFSDjS (ORCPT ); Thu, 18 Jun 2015 23:39:18 -0400 Received: from mga14.intel.com ([192.55.52.115]:3031 "EHLO mga14.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753663AbbFSDi6 (ORCPT ); Thu, 18 Jun 2015 23:38:58 -0400 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.13,642,1427785200"; d="scan'208";a="749410690" From: Lv Zheng To: "Rafael J. Wysocki" , Len Brown Cc: Lv Zheng , Lv Zheng , , linux-acpi@vger.kernel.org, Bob Moore Subject: [PATCH 06/32] ACPICA: Hardware: Enable firmware waking vector for both 32-bit and 64-bit FACS. Date: Fri, 19 Jun 2015 11:38:45 +0800 Message-Id: <3e3103e1b2bb06a62b6b48e0e06006fd755cdffb.1434684720.git.lv.zheng@intel.com> X-Mailer: git-send-email 1.7.10 In-Reply-To: References: Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 7924 Lines: 218 ACPICA commit 368eb60778b27b6ae94d3658ddc902ca1342a963 The root cause of the reported bug might be one of the followings: 1. BIOS may favor the 64-bit firmware waking vector address when the version of the FACS is greater than 0 and Linux currently only supports resuming from the real mode, so the 64-bit firmware waking vector has never been set and might be invalid to BIOS while the commit enables higher version FACS. 2. BIOS may favor the FACS reported via the "FIRMWARE_CTRL" field in the FADT while the commit doesn't set the firmware waking vector address of the FACS reported by "FIRMWARE_CTRL", it only sets the firware waking vector address of the FACS reported by "X_FIRMWARE_CTRL". This patch excludes the cases that can trigger the bugs caused by the root cause 2. There is no handshaking mechanism can be used by OSPM to tell BIOS which FACS is currently used. Thus the FACS reported by "FIRMWARE_CTRL" may still be used by BIOS and the 0 value of the 32-bit firmware waking vector might trigger such failure. This patch enables the firmware waking vectors for both 32bit/64bit FACS tables in order to ensure we can exclude the cases that trigger the bugs caused by the root cause 2. The exclusion is split into 2 commits so that if it turns out not to be necessary, this single commit can be reverted without affecting the useful one. Lv Zheng. Link: https://bugzilla.kernel.org/show_bug.cgi?id=74021 Link: https://github.com/acpica/acpica/commit/368eb607 Reported-and-tested-by: Oswald Buddenhagen Signed-off-by: Lv Zheng Signed-off-by: Bob Moore --- drivers/acpi/acpica/acglobal.h | 2 ++ drivers/acpi/acpica/hwxfsleep.c | 72 ++++++++++++++++++++++++++++++++------- drivers/acpi/acpica/tbutils.c | 14 ++++---- 3 files changed, 69 insertions(+), 19 deletions(-) diff --git a/drivers/acpi/acpica/acglobal.h b/drivers/acpi/acpica/acglobal.h index a0c4787..53f96a3 100644 --- a/drivers/acpi/acpica/acglobal.h +++ b/drivers/acpi/acpica/acglobal.h @@ -61,6 +61,8 @@ ACPI_GLOBAL(struct acpi_table_header, acpi_gbl_original_dsdt_header); #if (!ACPI_REDUCED_HARDWARE) ACPI_GLOBAL(struct acpi_table_facs *, acpi_gbl_FACS); +ACPI_GLOBAL(struct acpi_table_facs *, acpi_gbl_facs32); +ACPI_GLOBAL(struct acpi_table_facs *, acpi_gbl_facs64); #endif /* !ACPI_REDUCED_HARDWARE */ diff --git a/drivers/acpi/acpica/hwxfsleep.c b/drivers/acpi/acpica/hwxfsleep.c index c67cd32..9a438d2 100644 --- a/drivers/acpi/acpica/hwxfsleep.c +++ b/drivers/acpi/acpica/hwxfsleep.c @@ -50,6 +50,11 @@ ACPI_MODULE_NAME("hwxfsleep") /* Local prototypes */ +static acpi_status +acpi_hw_set_firmware_waking_vector(struct acpi_table_facs *facs, + acpi_physical_address physical_address, + acpi_physical_address physical_address64); + static acpi_status acpi_hw_sleep_dispatch(u8 sleep_state, u32 function_id); /* @@ -79,9 +84,10 @@ static struct acpi_sleep_functions acpi_sleep_dispatch[] = { #if (!ACPI_REDUCED_HARDWARE) /******************************************************************************* * - * FUNCTION: acpi_set_firmware_waking_vector + * FUNCTION: acpi_hw_set_firmware_waking_vector * - * PARAMETERS: physical_address - 32-bit physical address of ACPI real mode + * PARAMETERS: facs - Pointer to FACS table + * physical_address - 32-bit physical address of ACPI real mode * entry point * physical_address64 - 64-bit physical address of ACPI protected * entry point @@ -92,11 +98,12 @@ static struct acpi_sleep_functions acpi_sleep_dispatch[] = { * ******************************************************************************/ -acpi_status -acpi_set_firmware_waking_vector(acpi_physical_address physical_address, - acpi_physical_address physical_address64) +static acpi_status +acpi_hw_set_firmware_waking_vector(struct acpi_table_facs *facs, + acpi_physical_address physical_address, + acpi_physical_address physical_address64) { - ACPI_FUNCTION_TRACE(acpi_set_firmware_waking_vector); + ACPI_FUNCTION_TRACE(acpi_hw_set_firmware_waking_vector); /* @@ -109,25 +116,66 @@ acpi_set_firmware_waking_vector(acpi_physical_address physical_address, /* Set the 32-bit vector */ - acpi_gbl_FACS->firmware_waking_vector = (u32)physical_address; + facs->firmware_waking_vector = (u32)physical_address; - if (acpi_gbl_FACS->length > 32) { - if (acpi_gbl_FACS->version >= 1) { + if (facs->length > 32) { + if (facs->version >= 1) { /* Set the 64-bit vector */ - acpi_gbl_FACS->xfirmware_waking_vector = - physical_address64; + facs->xfirmware_waking_vector = physical_address64; } else { /* Clear the 64-bit vector if it exists */ - acpi_gbl_FACS->xfirmware_waking_vector = 0; + facs->xfirmware_waking_vector = 0; } } return_ACPI_STATUS(AE_OK); } +/******************************************************************************* + * + * FUNCTION: acpi_set_firmware_waking_vector + * + * PARAMETERS: physical_address - 32-bit physical address of ACPI real mode + * entry point + * physical_address64 - 64-bit physical address of ACPI protected + * entry point + * + * RETURN: Status + * + * DESCRIPTION: Sets the firmware_waking_vector fields of the FACS + * + ******************************************************************************/ + +acpi_status +acpi_set_firmware_waking_vector(acpi_physical_address physical_address, + acpi_physical_address physical_address64) +{ + + ACPI_FUNCTION_TRACE(acpi_set_firmware_waking_vector); + + /* If Hardware Reduced flag is set, there is no FACS */ + + if (acpi_gbl_reduced_hardware) { + return (AE_OK); + } + + if (acpi_gbl_facs32) { + (void)acpi_hw_set_firmware_waking_vector(acpi_gbl_facs32, + physical_address, + physical_address64); + } + if (acpi_gbl_facs64) { + (void)acpi_hw_set_firmware_waking_vector(acpi_gbl_facs64, + physical_address, + physical_address64); + } + + return_ACPI_STATUS(AE_OK); +} + ACPI_EXPORT_SYMBOL(acpi_set_firmware_waking_vector) /******************************************************************************* diff --git a/drivers/acpi/acpica/tbutils.c b/drivers/acpi/acpica/tbutils.c index a4e6dab..6a6c5be 100644 --- a/drivers/acpi/acpica/tbutils.c +++ b/drivers/acpi/acpica/tbutils.c @@ -68,8 +68,6 @@ acpi_tb_get_root_table_entry(u8 *table_entry, u32 table_entry_size); acpi_status acpi_tb_initialize_facs(void) { - struct acpi_table_facs *facs32; - struct acpi_table_facs *facs64; /* If Hardware Reduced flag is set, there is no FACS */ @@ -81,19 +79,21 @@ acpi_status acpi_tb_initialize_facs(void) (void)acpi_get_table_by_index(ACPI_TABLE_INDEX_FACS, ACPI_CAST_INDIRECT_PTR(struct acpi_table_header, - &facs32)); + &acpi_gbl_facs32)); (void)acpi_get_table_by_index(ACPI_TABLE_INDEX_X_FACS, ACPI_CAST_INDIRECT_PTR(struct acpi_table_header, - &facs64)); - if (!facs32 && !facs64) { + &acpi_gbl_facs64)); + if (!acpi_gbl_facs32 && !acpi_gbl_facs64) { return (AE_NO_MEMORY); } if (acpi_gbl_use32_bit_facs_addresses) { - acpi_gbl_FACS = facs32 ? facs32 : facs64; + acpi_gbl_FACS = + acpi_gbl_facs32 ? acpi_gbl_facs32 : acpi_gbl_facs64; } else { - acpi_gbl_FACS = facs64 ? facs64 : facs32; + acpi_gbl_FACS = + acpi_gbl_facs64 ? acpi_gbl_facs64 : acpi_gbl_facs32; } return (AE_OK); -- 1.7.10 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/