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>
This commit is contained in:
parent
40913fe6ea
commit
4712f71b60
6 changed files with 59 additions and 12 deletions
|
@ -126,7 +126,7 @@ acpi_ex_resolve_node_to_value(struct acpi_namespace_node **object_ptr,
|
||||||
if (!source_desc) {
|
if (!source_desc) {
|
||||||
ACPI_ERROR((AE_INFO, "No object attached to node [%4.4s] %p",
|
ACPI_ERROR((AE_INFO, "No object attached to node [%4.4s] %p",
|
||||||
node->name.ascii, node));
|
node->name.ascii, node));
|
||||||
return_ACPI_STATUS(AE_AML_NO_OPERAND);
|
return_ACPI_STATUS(AE_AML_UNINITIALIZED_NODE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -337,8 +337,9 @@ acpi_ex_resolve_multiple(struct acpi_walk_state *walk_state,
|
||||||
acpi_object_type * return_type,
|
acpi_object_type * return_type,
|
||||||
union acpi_operand_object **return_desc)
|
union acpi_operand_object **return_desc)
|
||||||
{
|
{
|
||||||
union acpi_operand_object *obj_desc = (void *)operand;
|
union acpi_operand_object *obj_desc = ACPI_CAST_PTR(void, operand);
|
||||||
struct acpi_namespace_node *node;
|
struct acpi_namespace_node *node =
|
||||||
|
ACPI_CAST_PTR(struct acpi_namespace_node, operand);
|
||||||
acpi_object_type type;
|
acpi_object_type type;
|
||||||
acpi_status status;
|
acpi_status status;
|
||||||
|
|
||||||
|
@ -355,9 +356,7 @@ acpi_ex_resolve_multiple(struct acpi_walk_state *walk_state,
|
||||||
case ACPI_DESC_TYPE_NAMED:
|
case ACPI_DESC_TYPE_NAMED:
|
||||||
|
|
||||||
type = ((struct acpi_namespace_node *)obj_desc)->type;
|
type = ((struct acpi_namespace_node *)obj_desc)->type;
|
||||||
obj_desc =
|
obj_desc = acpi_ns_get_attached_object(node);
|
||||||
acpi_ns_get_attached_object((struct acpi_namespace_node *)
|
|
||||||
obj_desc);
|
|
||||||
|
|
||||||
/* If we had an Alias node, use the attached object for type info */
|
/* 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 *)
|
acpi_namespace_node *)
|
||||||
obj_desc);
|
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;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -274,6 +274,7 @@ acpi_status acpi_ns_evaluate(struct acpi_evaluate_info *info)
|
||||||
acpi_ex_exit_interpreter();
|
acpi_ex_exit_interpreter();
|
||||||
|
|
||||||
if (ACPI_FAILURE(status)) {
|
if (ACPI_FAILURE(status)) {
|
||||||
|
info->return_object = NULL;
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -111,7 +111,21 @@ acpi_ns_load_table(u32 table_index, struct acpi_namespace_node *node)
|
||||||
if (ACPI_SUCCESS(status)) {
|
if (ACPI_SUCCESS(status)) {
|
||||||
acpi_tb_set_table_loaded_flag(table_index, TRUE);
|
acpi_tb_set_table_loaded_flag(table_index, TRUE);
|
||||||
} else {
|
} 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:
|
unlock:
|
||||||
|
|
|
@ -102,6 +102,8 @@ static acpi_status acpi_tb_load_namespace(void)
|
||||||
acpi_status status;
|
acpi_status status;
|
||||||
u32 i;
|
u32 i;
|
||||||
struct acpi_table_header *new_dsdt;
|
struct acpi_table_header *new_dsdt;
|
||||||
|
u32 tables_loaded = 0;
|
||||||
|
u32 tables_failed = 0;
|
||||||
|
|
||||||
ACPI_FUNCTION_TRACE(tb_load_namespace);
|
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);
|
status = acpi_ns_load_table(ACPI_TABLE_INDEX_DSDT, acpi_gbl_root_node);
|
||||||
if (ACPI_FAILURE(status)) {
|
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 */
|
/* 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 */
|
/* Ignore errors while loading tables, get as many as possible */
|
||||||
|
|
||||||
(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
|
(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);
|
(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:
|
unlock_and_exit:
|
||||||
(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
|
(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
|
||||||
|
|
|
@ -192,8 +192,9 @@ struct acpi_exception_info {
|
||||||
#define AE_AML_BAD_RESOURCE_LENGTH EXCEP_AML (0x001F)
|
#define AE_AML_BAD_RESOURCE_LENGTH EXCEP_AML (0x001F)
|
||||||
#define AE_AML_ILLEGAL_ADDRESS EXCEP_AML (0x0020)
|
#define AE_AML_ILLEGAL_ADDRESS EXCEP_AML (0x0020)
|
||||||
#define AE_AML_INFINITE_LOOP EXCEP_AML (0x0021)
|
#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
|
* 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",
|
EXCEP_TXT("AE_AML_ILLEGAL_ADDRESS",
|
||||||
"A memory, I/O, or PCI configuration address is invalid"),
|
"A memory, I/O, or PCI configuration address is invalid"),
|
||||||
EXCEP_TXT("AE_AML_INFINITE_LOOP",
|
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[] = {
|
static const struct acpi_exception_info acpi_gbl_exception_names_ctrl[] = {
|
||||||
|
|
Loading…
Add table
Reference in a new issue