summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBob Moore <robert.moore@intel.com>2015-08-25 10:28:26 +0800
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2015-08-25 23:11:30 +0200
commit4712f71b609d1805b958c0c355b16a995b11ab6e (patch)
treefdc5478b85a78859f593691124051cdf3e338a3b
parent40913fe6ea3b733564f0b580cf6c51f5d8fa8158 (diff)
downloadlinux-4712f71b609d1805b958c0c355b16a995b11ab6e.tar.bz2
ACPICA: Correctly cleanup after a ACPI table load failure
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>
-rw-r--r--drivers/acpi/acpica/exresnte.c2
-rw-r--r--drivers/acpi/acpica/exresolv.c16
-rw-r--r--drivers/acpi/acpica/nseval.c1
-rw-r--r--drivers/acpi/acpica/nsload.c16
-rw-r--r--drivers/acpi/acpica/tbxfload.c29
-rw-r--r--include/acpi/acexcep.h7
6 files changed, 59 insertions, 12 deletions
diff --git a/drivers/acpi/acpica/exresnte.c b/drivers/acpi/acpica/exresnte.c
index c7e3b929aa85..1b372ef69308 100644
--- a/drivers/acpi/acpica/exresnte.c
+++ b/drivers/acpi/acpica/exresnte.c
@@ -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);
}
/*
diff --git a/drivers/acpi/acpica/exresolv.c b/drivers/acpi/acpica/exresolv.c
index b6b7f3af29e4..7b109128b035 100644
--- a/drivers/acpi/acpica/exresolv.c
+++ b/drivers/acpi/acpica/exresolv.c
@@ -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:
diff --git a/drivers/acpi/acpica/nseval.c b/drivers/acpi/acpica/nseval.c
index 80670cb32b5a..88822b7a958f 100644
--- a/drivers/acpi/acpica/nseval.c
+++ b/drivers/acpi/acpica/nseval.c
@@ -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;
}
diff --git a/drivers/acpi/acpica/nsload.c b/drivers/acpi/acpica/nsload.c
index bd6cd4a81316..14ab83668207 100644
--- a/drivers/acpi/acpica/nsload.c
+++ b/drivers/acpi/acpica/nsload.c
@@ -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:
diff --git a/drivers/acpi/acpica/tbxfload.c b/drivers/acpi/acpica/tbxfload.c
index 9682d40ca6ff..7862cf04a164 100644
--- a/drivers/acpi/acpica/tbxfload.c
+++ b/drivers/acpi/acpica/tbxfload.c
@@ -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);
diff --git a/include/acpi/acexcep.h b/include/acpi/acexcep.h
index 11c3a011dcbf..9f20eb4acaa6 100644
--- a/include/acpi/acexcep.h
+++ b/include/acpi/acexcep.h
@@ -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[] = {