ACPICA: Events: Enhance acpi_ev_execute_reg_method() to ensure no _REG evaluations...
authorLv Zheng <lv.zheng@intel.com>
Tue, 29 Dec 2015 06:03:08 +0000 (14:03 +0800)
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>
Fri, 1 Jan 2016 02:47:38 +0000 (03:47 +0100)
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>
drivers/acpi/acpica/acglobal.h
drivers/acpi/acpica/acobject.h
drivers/acpi/acpica/evregion.c
drivers/acpi/acpica/evxfregn.c
drivers/acpi/acpica/excreate.c
drivers/acpi/acpica/utinit.c
drivers/acpi/acpica/utxfinit.c

index ef0abf4ef9acf16214ab6a5ce6bdf5153d02237a..73462cac41d285341f459eadf590f9588d854098 100644 (file)
@@ -165,7 +165,7 @@ ACPI_GLOBAL(u8, acpi_gbl_next_owner_id_offset);
 
 /* Initialization sequencing */
 
-ACPI_GLOBAL(u8, acpi_gbl_reg_methods_executed);
+ACPI_INIT_GLOBAL(u8, acpi_gbl_reg_methods_enabled, FALSE);
 
 /* Misc */
 
index 0bd02c4a5f759ec8a4062a292c9f6dfc3424f18e..2b154cfbe136691b887cef179b974fb99f3af84d 100644 (file)
 #define AOPOBJ_AML_CONSTANT         0x01       /* Integer is an AML constant */
 #define AOPOBJ_STATIC_POINTER       0x02       /* Data is part of an ACPI table, don't delete */
 #define AOPOBJ_DATA_VALID           0x04       /* Object is initialized and data is valid */
-#define AOPOBJ_OBJECT_INITIALIZED   0x08       /* Region is initialized, _REG was run */
-#define AOPOBJ_SETUP_COMPLETE       0x10       /* Region setup is complete */
-#define AOPOBJ_INVALID              0x20       /* Host OS won't allow a Region address */
+#define AOPOBJ_OBJECT_INITIALIZED   0x08       /* Region is initialized */
+#define AOPOBJ_REG_CONNECTED        0x10       /* _REG was run */
+#define AOPOBJ_SETUP_COMPLETE       0x20       /* Region setup is complete */
+#define AOPOBJ_INVALID              0x40       /* Host OS won't allow a Region address */
 
 /******************************************************************************
  *
index 432b81080369e1e13f7d6114156e161b3da00f11..cf6e8785491c380267dea15eb6118f9eb2dc1612 100644 (file)
@@ -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]);
 
index 3c905085fe5a9983cc97efc94dfeae601ec41a6e..29f9f3999dfcbcd9912153d407f81fd89bed1c6e 100644 (file)
@@ -112,39 +112,6 @@ acpi_install_address_space_handler(acpi_handle device,
                goto unlock_and_exit;
        }
 
-       /*
-        * For the default space_IDs, (the IDs for which there are default region handlers
-        * installed) Only execute the _REG methods if the global initialization _REG
-        * methods have already been run (via acpi_initialize_objects). In other words,
-        * we will defer the execution of the _REG methods for these space_IDs until
-        * execution of acpi_initialize_objects. This is done because we need the handlers
-        * for the default spaces (mem/io/pci/table) to be installed before we can run
-        * any control methods (or _REG methods). There is known BIOS code that depends
-        * on this.
-        *
-        * For all other space_IDs, we can safely execute the _REG methods immediately.
-        * This means that for IDs like embedded_controller, this function should be called
-        * only after acpi_enable_subsystem has been called.
-        */
-       switch (space_id) {
-       case ACPI_ADR_SPACE_SYSTEM_MEMORY:
-       case ACPI_ADR_SPACE_SYSTEM_IO:
-       case ACPI_ADR_SPACE_PCI_CONFIG:
-       case ACPI_ADR_SPACE_DATA_TABLE:
-
-               if (!acpi_gbl_reg_methods_executed) {
-
-                       /* We will defer execution of the _REG methods for this space */
-
-                       goto unlock_and_exit;
-               }
-               break;
-
-       default:
-
-               break;
-       }
-
        /* Run all _REG methods for this address space */
 
        status = acpi_ev_execute_reg_methods(node, space_id);
index 6a1396e313b15a7665b520f6ebdf36692235690b..46be5a276863294fdf01dd8a9d3b3213bdd7bfa6 100644 (file)
@@ -345,7 +345,8 @@ acpi_ex_create_region(u8 * aml_start,
        obj_desc->region.node = node;
        obj_desc->region.handler = NULL;
        obj_desc->common.flags &=
-           ~(AOPOBJ_SETUP_COMPLETE | AOPOBJ_OBJECT_INITIALIZED);
+           ~(AOPOBJ_SETUP_COMPLETE | AOPOBJ_REG_CONNECTED |
+             AOPOBJ_OBJECT_INITIALIZED);
 
        /* Install the new region object in the parent Node */
 
index ccd0745f011e886619dd2b891e51d23df372e08a..fd82a122785e5207fe244966514ec715206544d6 100644 (file)
@@ -206,7 +206,6 @@ acpi_status acpi_ut_init_globals(void)
        acpi_gbl_next_owner_id_offset = 0;
        acpi_gbl_debugger_configuration = DEBUGGER_THREADING;
        acpi_gbl_osi_mutex = NULL;
-       acpi_gbl_reg_methods_executed = FALSE;
        acpi_gbl_max_loop_iterations = 0xFFFF;
 
        /* Hardware oriented */
index 7d8eb602bbbe890a7e0e0c2deffc8bef532c5ce6..1c7ed4986963d999a2d9957ec9e99cbb9fd89792 100644 (file)
@@ -267,6 +267,7 @@ acpi_status __init acpi_initialize_objects(u32 flags)
         * initialized, even if they contain executable AML (see the call to
         * acpi_ns_initialize_objects below).
         */
+       acpi_gbl_reg_methods_enabled = TRUE;
        if (!(flags & ACPI_NO_ADDRESS_SPACE_INIT)) {
                ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
                                  "[Init] Executing _REG OpRegion methods\n"));