ACPICA: Correctly cleanup after a ACPI table load failure
authorBob Moore <robert.moore@intel.com>
Tue, 25 Aug 2015 02:28:26 +0000 (10:28 +0800)
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>
Tue, 25 Aug 2015 21:11:30 +0000 (23:11 +0200)
ACPICA commit ed7769e832de6c7ba90615480d916c85fd100422

If a table load fails, delete all namespace objects created by the
table, otherwise these objects will be uninitialized, causing
problems later. This appears to be a very rare problem.
Also handle the unitialized node problem to prevent possible
faults. ACPICA BZ 1185.

Link: https://github.com/acpica/acpica/commit/ed7769e8
Signed-off-by: Bob Moore <robert.moore@intel.com>
Signed-off-by: Lv Zheng <lv.zheng@intel.com>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
drivers/acpi/acpica/exresnte.c
drivers/acpi/acpica/exresolv.c
drivers/acpi/acpica/nseval.c
drivers/acpi/acpica/nsload.c
drivers/acpi/acpica/tbxfload.c
include/acpi/acexcep.h

index c7e3b929aa854b26be7002f661f187c9acc2dc01..1b372ef693088a3e656003f966cfe798e2e280d8 100644 (file)
@@ -126,7 +126,7 @@ acpi_ex_resolve_node_to_value(struct acpi_namespace_node **object_ptr,
        if (!source_desc) {
                ACPI_ERROR((AE_INFO, "No object attached to node [%4.4s] %p",
                            node->name.ascii, node));
-               return_ACPI_STATUS(AE_AML_NO_OPERAND);
+               return_ACPI_STATUS(AE_AML_UNINITIALIZED_NODE);
        }
 
        /*
index b6b7f3af29e440b242789d18d49aa002e4eef796..7b109128b0350f0579fdf0b96fe0c74f949887b0 100644 (file)
@@ -337,8 +337,9 @@ acpi_ex_resolve_multiple(struct acpi_walk_state *walk_state,
                         acpi_object_type * return_type,
                         union acpi_operand_object **return_desc)
 {
-       union acpi_operand_object *obj_desc = (void *)operand;
-       struct acpi_namespace_node *node;
+       union acpi_operand_object *obj_desc = ACPI_CAST_PTR(void, operand);
+       struct acpi_namespace_node *node =
+           ACPI_CAST_PTR(struct acpi_namespace_node, operand);
        acpi_object_type type;
        acpi_status status;
 
@@ -355,9 +356,7 @@ acpi_ex_resolve_multiple(struct acpi_walk_state *walk_state,
        case ACPI_DESC_TYPE_NAMED:
 
                type = ((struct acpi_namespace_node *)obj_desc)->type;
-               obj_desc =
-                   acpi_ns_get_attached_object((struct acpi_namespace_node *)
-                                               obj_desc);
+               obj_desc = acpi_ns_get_attached_object(node);
 
                /* If we had an Alias node, use the attached object for type info */
 
@@ -368,6 +367,13 @@ acpi_ex_resolve_multiple(struct acpi_walk_state *walk_state,
                                                         acpi_namespace_node *)
                                                        obj_desc);
                }
+
+               if (!obj_desc) {
+                       ACPI_ERROR((AE_INFO,
+                                   "[%4.4s] Node is unresolved or uninitialized",
+                                   acpi_ut_get_node_name(node)));
+                       return_ACPI_STATUS(AE_AML_UNINITIALIZED_NODE);
+               }
                break;
 
        default:
index 80670cb32b5a3fe9438e735d26ef1b269be1e3f7..88822b7a958f1a34b3f36952deab7b62e490705f 100644 (file)
@@ -274,6 +274,7 @@ acpi_status acpi_ns_evaluate(struct acpi_evaluate_info *info)
                acpi_ex_exit_interpreter();
 
                if (ACPI_FAILURE(status)) {
+                       info->return_object = NULL;
                        goto cleanup;
                }
 
index bd6cd4a81316cf7240a48c5f6ee1863383b17674..14ab83668207eb389b7edfe6860a472c5a6007ad 100644 (file)
@@ -111,7 +111,21 @@ acpi_ns_load_table(u32 table_index, struct acpi_namespace_node *node)
        if (ACPI_SUCCESS(status)) {
                acpi_tb_set_table_loaded_flag(table_index, TRUE);
        } else {
-               (void)acpi_tb_release_owner_id(table_index);
+               /*
+                * On error, delete any namespace objects created by this table.
+                * We cannot initialize these objects, so delete them. There are
+                * a couple of expecially bad cases:
+                * AE_ALREADY_EXISTS - namespace collision.
+                * AE_NOT_FOUND - the target of a Scope operator does not
+                * exist. This target of Scope must already exist in the
+                * namespace, as per the ACPI specification.
+                */
+               (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
+               acpi_ns_delete_namespace_by_owner(acpi_gbl_root_table_list.
+                                                 tables[table_index].owner_id);
+               acpi_tb_release_owner_id(table_index);
+
+               return_ACPI_STATUS(status);
        }
 
 unlock:
index 9682d40ca6ffe70f8c50078fc4f89172b7b37702..7862cf04a1640d8ee65d8cf1227e7458d6794d9d 100644 (file)
@@ -102,6 +102,8 @@ static acpi_status acpi_tb_load_namespace(void)
        acpi_status status;
        u32 i;
        struct acpi_table_header *new_dsdt;
+       u32 tables_loaded = 0;
+       u32 tables_failed = 0;
 
        ACPI_FUNCTION_TRACE(tb_load_namespace);
 
@@ -159,7 +161,10 @@ static acpi_status acpi_tb_load_namespace(void)
 
        status = acpi_ns_load_table(ACPI_TABLE_INDEX_DSDT, acpi_gbl_root_node);
        if (ACPI_FAILURE(status)) {
-               return_ACPI_STATUS(status);
+               ACPI_EXCEPTION((AE_INFO, status, "[DSDT] table load failed"));
+               tables_failed++;
+       } else {
+               tables_loaded++;
        }
 
        /* Load any SSDT or PSDT tables. Note: Loop leaves tables locked */
@@ -187,11 +192,29 @@ static acpi_status acpi_tb_load_namespace(void)
                /* Ignore errors while loading tables, get as many as possible */
 
                (void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
-               (void)acpi_ns_load_table(i, acpi_gbl_root_node);
+               status = acpi_ns_load_table(i, acpi_gbl_root_node);
+               if (ACPI_FAILURE(status)) {
+                       ACPI_EXCEPTION((AE_INFO, status,
+                                       "[%4.4s] table load failed",
+                                       &acpi_gbl_root_table_list.tables[i].
+                                       signature.ascii[0]));
+                       tables_failed++;
+               } else {
+                       tables_loaded++;
+               }
+
                (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
        }
 
-       ACPI_INFO((AE_INFO, "All ACPI Tables successfully acquired"));
+       if (!tables_failed) {
+               ACPI_INFO((AE_INFO,
+                          "All (%u) ACPI AML tables successfully loaded",
+                          tables_loaded));
+       } else {
+               ACPI_ERROR((AE_INFO,
+                           "%u ACPI AML tables loaded, %u failed",
+                           tables_loaded, tables_failed));
+       }
 
 unlock_and_exit:
        (void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
index 11c3a011dcbf1ba5deb7acebfb55880d51a146b9..9f20eb4acaa6054ef2362ee5eeef4576beb6c88a 100644 (file)
@@ -192,8 +192,9 @@ struct acpi_exception_info {
 #define AE_AML_BAD_RESOURCE_LENGTH      EXCEP_AML (0x001F)
 #define AE_AML_ILLEGAL_ADDRESS          EXCEP_AML (0x0020)
 #define AE_AML_INFINITE_LOOP            EXCEP_AML (0x0021)
+#define AE_AML_UNINITIALIZED_NODE       EXCEP_AML (0x0022)
 
-#define AE_CODE_AML_MAX                 0x0021
+#define AE_CODE_AML_MAX                 0x0022
 
 /*
  * Internal exceptions used for control
@@ -355,7 +356,9 @@ static const struct acpi_exception_info acpi_gbl_exception_names_aml[] = {
        EXCEP_TXT("AE_AML_ILLEGAL_ADDRESS",
                  "A memory, I/O, or PCI configuration address is invalid"),
        EXCEP_TXT("AE_AML_INFINITE_LOOP",
-                 "An apparent infinite AML While loop, method was aborted")
+                 "An apparent infinite AML While loop, method was aborted"),
+       EXCEP_TXT("AE_AML_UNINITIALIZED_NODE",
+                 "A namespace node is uninitialized or unresolved")
 };
 
 static const struct acpi_exception_info acpi_gbl_exception_names_ctrl[] = {