diff options
author | Lv Zheng <lv.zheng@intel.com> | 2015-12-29 07:03:08 +0100 |
---|---|---|
committer | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2016-01-01 03:47:38 +0100 |
commit | efaed9be998b5ae0afb7458e057e5f4402b43fa0 (patch) | |
tree | 3a3e2cf962955b0ec491aa534e3de2659d2050ad /drivers/acpi/acpica/evregion.c | |
parent | ACPICA: Events: Split acpi_ev_associate_reg_method() from region initializati... (diff) | |
download | linux-efaed9be998b5ae0afb7458e057e5f4402b43fa0.tar.xz linux-efaed9be998b5ae0afb7458e057e5f4402b43fa0.zip |
ACPICA: Events: Enhance acpi_ev_execute_reg_method() to ensure no _REG evaluations can happen during OS early boot stages
ACPICA commit 31178590dde82368fdb0f6b0e466b6c0add96c57
We can ensure no early _REG evaluations by ensuring the following rules in
acpi_ev_execute_reg_method():
1. If an address space handler is installed during early stage,
_REG(CONNECT) evaluations are blocked. This is achieved using
acpi_gbl_reg_methods_enabled which is renamed from
acpi_gbl_reg_methods_executed.
2. If _REG(CONNECT) has never been evalauted for the region object,
_REG(DISCONNECT) evaluations are blocked. This is achieved by a new
region object flag: AOPOBJ_REG_CONNECTED.
Note that, after applying this patch, we can ensure _REG(DISCONNECT) is
always paired to _REG(CONNECT). Lv Zheng
Link: https://github.com/acpica/acpica/commit/31178590
Signed-off-by: Lv Zheng <lv.zheng@intel.com>
Signed-off-by: Bob Moore <robert.moore@intel.com>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Diffstat (limited to 'drivers/acpi/acpica/evregion.c')
-rw-r--r-- | drivers/acpi/acpica/evregion.c | 25 |
1 files changed, 22 insertions, 3 deletions
diff --git a/drivers/acpi/acpica/evregion.c b/drivers/acpi/acpica/evregion.c index 432b81080369..cf6e8785491c 100644 --- a/drivers/acpi/acpica/evregion.c +++ b/drivers/acpi/acpica/evregion.c @@ -104,8 +104,6 @@ acpi_status acpi_ev_initialize_op_regions(void) } } - acpi_gbl_reg_methods_executed = TRUE; - (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); return_ACPI_STATUS(status); } @@ -601,7 +599,18 @@ acpi_ev_execute_reg_method(union acpi_operand_object *region_obj, u32 function) return_ACPI_STATUS(AE_NOT_EXIST); } - if (region_obj2->extra.method_REG == NULL) { + if (region_obj2->extra.method_REG == NULL || + region_obj->region.handler == NULL || + !acpi_gbl_reg_methods_enabled) { + return_ACPI_STATUS(AE_OK); + } + + /* _REG(DISCONNECT) should be paired with _REG(CONNECT) */ + + if ((function == ACPI_REG_CONNECT && + region_obj->common.flags & AOPOBJ_REG_CONNECTED) || + (function == ACPI_REG_DISCONNECT && + !(region_obj->common.flags & AOPOBJ_REG_CONNECTED))) { return_ACPI_STATUS(AE_OK); } @@ -650,6 +659,16 @@ acpi_ev_execute_reg_method(union acpi_operand_object *region_obj, u32 function) status = acpi_ns_evaluate(info); acpi_ut_remove_reference(args[1]); + if (ACPI_FAILURE(status)) { + goto cleanup2; + } + + if (function == ACPI_REG_CONNECT) { + region_obj->common.flags |= AOPOBJ_REG_CONNECTED; + } else { + region_obj->common.flags &= ~AOPOBJ_REG_CONNECTED; + } + cleanup2: acpi_ut_remove_reference(args[0]); |