summaryrefslogtreecommitdiffstats
path: root/drivers/acpi/acpica
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2009-12-10 04:57:06 +0100
committerLinus Torvalds <torvalds@linux-foundation.org>2009-12-10 04:57:06 +0100
commit3067e02f8f3ae2f3f02ba76400d03b8bcb4942b0 (patch)
tree761e19d279b27a03714a6673811e76e0b1cf2081 /drivers/acpi/acpica
parentMerge branch 'hwmon-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/g... (diff)
parentACPICA: Update version to 20091112. (diff)
downloadlinux-3067e02f8f3ae2f3f02ba76400d03b8bcb4942b0.tar.xz
linux-3067e02f8f3ae2f3f02ba76400d03b8bcb4942b0.zip
Merge branch 'acpica' of git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux-acpi-2.6
* 'acpica' of git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux-acpi-2.6: ACPICA: Update version to 20091112. ACPICA: Add additional module-level code support ACPICA: Deploy new create integer interface where appropriate ACPICA: New internal utility function to create Integer objects ACPICA: Add repair for predefined methods that must return sorted lists ACPICA: Fix possible fault if return Package objects contain NULL elements ACPICA: Add post-order callback to acpi_walk_namespace ACPICA: Change package length error message to an info message ACPICA: Reduce severity of predefined repair messages, Warning to Info ACPICA: Update version to 20091013 ACPICA: Fix possible memory leak for Scope ASL operator ACPICA: Remove possibility of executing _REG methods twice ACPICA: Add repair for bad _MAT buffers ACPICA: Add repair for bad _BIF/_BIX packages
Diffstat (limited to 'drivers/acpi/acpica')
-rw-r--r--drivers/acpi/acpica/Makefile2
-rw-r--r--drivers/acpi/acpica/acmacros.h3
-rw-r--r--drivers/acpi/acpica/acnamesp.h16
-rw-r--r--drivers/acpi/acpica/acutils.h7
-rw-r--r--drivers/acpi/acpica/dsinit.c2
-rw-r--r--drivers/acpi/acpica/dsmthdat.c4
-rw-r--r--drivers/acpi/acpica/dsobject.c8
-rw-r--r--drivers/acpi/acpica/dswload.c50
-rw-r--r--drivers/acpi/acpica/evgpeblk.c8
-rw-r--r--drivers/acpi/acpica/evregion.c81
-rw-r--r--drivers/acpi/acpica/exconfig.c4
-rw-r--r--drivers/acpi/acpica/exconvrt.c3
-rw-r--r--drivers/acpi/acpica/exfield.c3
-rw-r--r--drivers/acpi/acpica/exoparg1.c38
-rw-r--r--drivers/acpi/acpica/exoparg6.c7
-rw-r--r--drivers/acpi/acpica/nsdump.c4
-rw-r--r--drivers/acpi/acpica/nsdumpdv.c3
-rw-r--r--drivers/acpi/acpica/nseval.c50
-rw-r--r--drivers/acpi/acpica/nsinit.c8
-rw-r--r--drivers/acpi/acpica/nspredef.c49
-rw-r--r--drivers/acpi/acpica/nsrepair.c114
-rw-r--r--drivers/acpi/acpica/nsrepair2.c540
-rw-r--r--drivers/acpi/acpica/nswalk.c200
-rw-r--r--drivers/acpi/acpica/nsxfeval.c32
-rw-r--r--drivers/acpi/acpica/psloop.c32
-rw-r--r--drivers/acpi/acpica/psparse.c8
-rw-r--r--drivers/acpi/acpica/psxface.c4
-rw-r--r--drivers/acpi/acpica/utmisc.c42
-rw-r--r--drivers/acpi/acpica/utobject.c29
29 files changed, 1110 insertions, 241 deletions
diff --git a/drivers/acpi/acpica/Makefile b/drivers/acpi/acpica/Makefile
index e7973bc16846..7423052ece5a 100644
--- a/drivers/acpi/acpica/Makefile
+++ b/drivers/acpi/acpica/Makefile
@@ -28,7 +28,7 @@ acpi-$(ACPI_FUTURE_USAGE) += hwtimer.o
acpi-y += nsaccess.o nsload.o nssearch.o nsxfeval.o \
nsalloc.o nseval.o nsnames.o nsutils.o nsxfname.o \
nsdump.o nsinit.o nsobject.o nswalk.o nsxfobj.o \
- nsparse.o nspredef.o nsrepair.o
+ nsparse.o nspredef.o nsrepair.o nsrepair2.o
acpi-$(ACPI_FUTURE_USAGE) += nsdumpdv.o
diff --git a/drivers/acpi/acpica/acmacros.h b/drivers/acpi/acpica/acmacros.h
index 3acd9c6760ea..7d9ba6e57554 100644
--- a/drivers/acpi/acpica/acmacros.h
+++ b/drivers/acpi/acpica/acmacros.h
@@ -341,6 +341,7 @@
#define ACPI_ERROR_NAMESPACE(s, e) acpi_ns_report_error (AE_INFO, s, e);
#define ACPI_ERROR_METHOD(s, n, p, e) acpi_ns_report_method_error (AE_INFO, s, n, p, e);
#define ACPI_WARN_PREDEFINED(plist) acpi_ut_predefined_warning plist
+#define ACPI_INFO_PREDEFINED(plist) acpi_ut_predefined_info plist
#else
@@ -349,6 +350,8 @@
#define ACPI_ERROR_NAMESPACE(s, e)
#define ACPI_ERROR_METHOD(s, n, p, e)
#define ACPI_WARN_PREDEFINED(plist)
+#define ACPI_INFO_PREDEFINED(plist)
+
#endif /* ACPI_NO_ERROR_MESSAGES */
/*
diff --git a/drivers/acpi/acpica/acnamesp.h b/drivers/acpi/acpica/acnamesp.h
index 09a2764c734b..ab83919dda61 100644
--- a/drivers/acpi/acpica/acnamesp.h
+++ b/drivers/acpi/acpica/acnamesp.h
@@ -104,7 +104,8 @@ acpi_ns_walk_namespace(acpi_object_type type,
acpi_handle start_object,
u32 max_depth,
u32 flags,
- acpi_walk_callback user_function,
+ acpi_walk_callback pre_order_visit,
+ acpi_walk_callback post_order_visit,
void *context, void **return_value);
struct acpi_namespace_node *acpi_ns_get_next_node(struct acpi_namespace_node
@@ -272,7 +273,8 @@ acpi_ns_get_attached_data(struct acpi_namespace_node *node,
acpi_object_handler handler, void **data);
/*
- * nsrepair - return object repair for predefined methods/objects
+ * nsrepair - General return object repair for all
+ * predefined methods/objects
*/
acpi_status
acpi_ns_repair_object(struct acpi_predefined_data *data,
@@ -285,6 +287,16 @@ acpi_ns_repair_package_list(struct acpi_predefined_data *data,
union acpi_operand_object **obj_desc_ptr);
/*
+ * nsrepair2 - Return object repair for specific
+ * predefined methods/objects
+ */
+acpi_status
+acpi_ns_complex_repairs(struct acpi_predefined_data *data,
+ struct acpi_namespace_node *node,
+ acpi_status validate_status,
+ union acpi_operand_object **return_object_ptr);
+
+/*
* nssearch - Namespace searching and entry
*/
acpi_status
diff --git a/drivers/acpi/acpica/acutils.h b/drivers/acpi/acpica/acutils.h
index 863a264b829e..3a451a21a3f9 100644
--- a/drivers/acpi/acpica/acutils.h
+++ b/drivers/acpi/acpica/acutils.h
@@ -386,6 +386,8 @@ u8 acpi_ut_valid_internal_object(void *object);
union acpi_operand_object *acpi_ut_create_package_object(u32 count);
+union acpi_operand_object *acpi_ut_create_integer_object(u64 value);
+
union acpi_operand_object *acpi_ut_create_buffer_object(acpi_size buffer_size);
union acpi_operand_object *acpi_ut_create_string_object(acpi_size string_size);
@@ -481,6 +483,11 @@ acpi_ut_predefined_warning(const char *module_name,
char *pathname,
u8 node_flags, const char *format, ...);
+void ACPI_INTERNAL_VAR_XFACE
+acpi_ut_predefined_info(const char *module_name,
+ u32 line_number,
+ char *pathname, u8 node_flags, const char *format, ...);
+
/* Values for Base above (16=Hex, 10=Decimal) */
#define ACPI_ANY_BASE 0
diff --git a/drivers/acpi/acpica/dsinit.c b/drivers/acpi/acpica/dsinit.c
index 3aae13f30c5e..f23fa0be6fc2 100644
--- a/drivers/acpi/acpica/dsinit.c
+++ b/drivers/acpi/acpica/dsinit.c
@@ -192,7 +192,7 @@ acpi_ds_initialize_objects(u32 table_index,
status =
acpi_ns_walk_namespace(ACPI_TYPE_ANY, start_node, ACPI_UINT32_MAX,
ACPI_NS_WALK_UNLOCK, acpi_ds_init_one_object,
- &info, NULL);
+ NULL, &info, NULL);
if (ACPI_FAILURE(status)) {
ACPI_EXCEPTION((AE_INFO, status, "During WalkNamespace"));
}
diff --git a/drivers/acpi/acpica/dsmthdat.c b/drivers/acpi/acpica/dsmthdat.c
index 7d077bb2f525..0ba19f84ad82 100644
--- a/drivers/acpi/acpica/dsmthdat.c
+++ b/drivers/acpi/acpica/dsmthdat.c
@@ -409,13 +409,11 @@ acpi_ds_method_data_get_value(u8 type,
/* If slack enabled, init the local_x/arg_x to an Integer of value zero */
if (acpi_gbl_enable_interpreter_slack) {
- object =
- acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);
+ object = acpi_ut_create_integer_object((u64) 0);
if (!object) {
return_ACPI_STATUS(AE_NO_MEMORY);
}
- object->integer.value = 0;
node->object = object;
}
diff --git a/drivers/acpi/acpica/dsobject.c b/drivers/acpi/acpica/dsobject.c
index 507e1f0bbdfd..9bc1ba076347 100644
--- a/drivers/acpi/acpica/dsobject.c
+++ b/drivers/acpi/acpica/dsobject.c
@@ -486,7 +486,7 @@ acpi_ds_build_internal_package_obj(struct acpi_walk_state *walk_state,
*
* Note: technically, this is an error, from ACPI spec: "It is an error
* for NumElements to be less than the number of elements in the
- * PackageList". However, we just print an error message and
+ * PackageList". However, we just print a message and
* no exception is returned. This provides Windows compatibility. Some
* BIOSs will alter the num_elements on the fly, creating this type
* of ill-formed package object.
@@ -510,9 +510,9 @@ acpi_ds_build_internal_package_obj(struct acpi_walk_state *walk_state,
arg = arg->common.next;
}
- ACPI_WARNING((AE_INFO,
- "Package List length (0x%X) larger than NumElements count (0x%X), truncated\n",
- i, element_count));
+ ACPI_INFO((AE_INFO,
+ "Actual Package length (0x%X) is larger than NumElements field (0x%X), truncated\n",
+ i, element_count));
} else if (i < element_count) {
/*
* Arg list (elements) was exhausted, but we did not reach num_elements count.
diff --git a/drivers/acpi/acpica/dswload.c b/drivers/acpi/acpica/dswload.c
index 6de3a99d4cd4..10fc78517843 100644
--- a/drivers/acpi/acpica/dswload.c
+++ b/drivers/acpi/acpica/dswload.c
@@ -639,26 +639,42 @@ acpi_ds_load2_begin_op(struct acpi_walk_state *walk_state,
break;
case AML_SCOPE_OP:
- /*
- * The Path is an object reference to an existing object.
- * Don't enter the name into the namespace, but look it up
- * for use later.
- */
- status =
- acpi_ns_lookup(walk_state->scope_info, buffer_ptr,
- object_type, ACPI_IMODE_EXECUTE,
- ACPI_NS_SEARCH_PARENT, walk_state, &(node));
- if (ACPI_FAILURE(status)) {
-#ifdef ACPI_ASL_COMPILER
- if (status == AE_NOT_FOUND) {
- status = AE_OK;
- } else {
- ACPI_ERROR_NAMESPACE(buffer_ptr, status);
+
+ /* Special case for Scope(\) -> refers to the Root node */
+
+ if (op && (op->named.node == acpi_gbl_root_node)) {
+ node = op->named.node;
+
+ status =
+ acpi_ds_scope_stack_push(node, object_type,
+ walk_state);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
+ } else {
+ /*
+ * The Path is an object reference to an existing object.
+ * Don't enter the name into the namespace, but look it up
+ * for use later.
+ */
+ status =
+ acpi_ns_lookup(walk_state->scope_info, buffer_ptr,
+ object_type, ACPI_IMODE_EXECUTE,
+ ACPI_NS_SEARCH_PARENT, walk_state,
+ &(node));
+ if (ACPI_FAILURE(status)) {
+#ifdef ACPI_ASL_COMPILER
+ if (status == AE_NOT_FOUND) {
+ status = AE_OK;
+ } else {
+ ACPI_ERROR_NAMESPACE(buffer_ptr,
+ status);
+ }
#else
- ACPI_ERROR_NAMESPACE(buffer_ptr, status);
+ ACPI_ERROR_NAMESPACE(buffer_ptr, status);
#endif
- return_ACPI_STATUS(status);
+ return_ACPI_STATUS(status);
+ }
}
/*
diff --git a/drivers/acpi/acpica/evgpeblk.c b/drivers/acpi/acpica/evgpeblk.c
index a60aaa7635f3..247920900187 100644
--- a/drivers/acpi/acpica/evgpeblk.c
+++ b/drivers/acpi/acpica/evgpeblk.c
@@ -945,8 +945,8 @@ acpi_ev_create_gpe_block(struct acpi_namespace_node *gpe_device,
status = acpi_ns_walk_namespace(ACPI_TYPE_METHOD, gpe_device,
ACPI_UINT32_MAX, ACPI_NS_WALK_NO_UNLOCK,
- acpi_ev_save_method_info, gpe_block,
- NULL);
+ acpi_ev_save_method_info, NULL,
+ gpe_block, NULL);
/* Return the new block */
@@ -1022,8 +1022,8 @@ acpi_ev_initialize_gpe_block(struct acpi_namespace_node *gpe_device,
status =
acpi_ns_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
ACPI_UINT32_MAX, ACPI_NS_WALK_UNLOCK,
- acpi_ev_match_prw_and_gpe, &gpe_info,
- NULL);
+ acpi_ev_match_prw_and_gpe, NULL,
+ &gpe_info, NULL);
}
/*
diff --git a/drivers/acpi/acpica/evregion.c b/drivers/acpi/acpica/evregion.c
index 98c7f9c62653..0bc807c33a56 100644
--- a/drivers/acpi/acpica/evregion.c
+++ b/drivers/acpi/acpica/evregion.c
@@ -51,6 +51,10 @@
ACPI_MODULE_NAME("evregion")
/* Local prototypes */
+static u8
+acpi_ev_has_default_handler(struct acpi_namespace_node *node,
+ acpi_adr_space_type space_id);
+
static acpi_status
acpi_ev_reg_run(acpi_handle obj_handle,
u32 level, void *context, void **return_value);
@@ -142,6 +146,50 @@ acpi_status acpi_ev_install_region_handlers(void)
/*******************************************************************************
*
+ * FUNCTION: acpi_ev_has_default_handler
+ *
+ * PARAMETERS: Node - Namespace node for the device
+ * space_id - The address space ID
+ *
+ * RETURN: TRUE if default handler is installed, FALSE otherwise
+ *
+ * DESCRIPTION: Check if the default handler is installed for the requested
+ * space ID.
+ *
+ ******************************************************************************/
+
+static u8
+acpi_ev_has_default_handler(struct acpi_namespace_node *node,
+ acpi_adr_space_type space_id)
+{
+ union acpi_operand_object *obj_desc;
+ union acpi_operand_object *handler_obj;
+
+ /* Must have an existing internal object */
+
+ obj_desc = acpi_ns_get_attached_object(node);
+ if (obj_desc) {
+ handler_obj = obj_desc->device.handler;
+
+ /* Walk the linked list of handlers for this object */
+
+ while (handler_obj) {
+ if (handler_obj->address_space.space_id == space_id) {
+ if (handler_obj->address_space.handler_flags &
+ ACPI_ADDR_HANDLER_DEFAULT_INSTALLED) {
+ return (TRUE);
+ }
+ }
+
+ handler_obj = handler_obj->address_space.next;
+ }
+ }
+
+ return (FALSE);
+}
+
+/*******************************************************************************
+ *
* FUNCTION: acpi_ev_initialize_op_regions
*
* PARAMETERS: None
@@ -169,12 +217,18 @@ acpi_status acpi_ev_initialize_op_regions(void)
for (i = 0; i < ACPI_NUM_DEFAULT_SPACES; i++) {
/*
- * TBD: Make sure handler is the DEFAULT handler, otherwise
- * _REG will have already been run.
+ * Make sure the installed handler is the DEFAULT handler. If not the
+ * default, the _REG methods will have already been run (when the
+ * handler was installed)
*/
- status = acpi_ev_execute_reg_methods(acpi_gbl_root_node,
- acpi_gbl_default_address_spaces
- [i]);
+ if (acpi_ev_has_default_handler(acpi_gbl_root_node,
+ acpi_gbl_default_address_spaces
+ [i])) {
+ status =
+ acpi_ev_execute_reg_methods(acpi_gbl_root_node,
+ acpi_gbl_default_address_spaces
+ [i]);
+ }
}
(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
@@ -235,23 +289,20 @@ acpi_ev_execute_reg_method(union acpi_operand_object *region_obj, u32 function)
* connection status 1 for connecting the handler, 0 for disconnecting
* the handler (Passed as a parameter)
*/
- args[0] = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);
+ args[0] =
+ acpi_ut_create_integer_object((u64) region_obj->region.space_id);
if (!args[0]) {
status = AE_NO_MEMORY;
goto cleanup1;
}
- args[1] = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);
+ args[1] = acpi_ut_create_integer_object((u64) function);
if (!args[1]) {
status = AE_NO_MEMORY;
goto cleanup2;
}
- /* Setup the parameter objects */
-
- args[0]->integer.value = region_obj->region.space_id;
- args[1]->integer.value = function;
- args[2] = NULL;
+ args[2] = NULL; /* Terminate list */
/* Execute the method, no return value */
@@ -971,8 +1022,8 @@ acpi_ev_install_space_handler(struct acpi_namespace_node * node,
*/
status = acpi_ns_walk_namespace(ACPI_TYPE_ANY, node, ACPI_UINT32_MAX,
ACPI_NS_WALK_UNLOCK,
- acpi_ev_install_handler, handler_obj,
- NULL);
+ acpi_ev_install_handler, NULL,
+ handler_obj, NULL);
unlock_and_exit:
return_ACPI_STATUS(status);
@@ -1008,7 +1059,7 @@ acpi_ev_execute_reg_methods(struct acpi_namespace_node *node,
*/
status = acpi_ns_walk_namespace(ACPI_TYPE_ANY, node, ACPI_UINT32_MAX,
ACPI_NS_WALK_UNLOCK, acpi_ev_reg_run,
- &space_id, NULL);
+ NULL, &space_id, NULL);
return_ACPI_STATUS(status);
}
diff --git a/drivers/acpi/acpica/exconfig.c b/drivers/acpi/acpica/exconfig.c
index 24afef81af39..46adfa541cbc 100644
--- a/drivers/acpi/acpica/exconfig.c
+++ b/drivers/acpi/acpica/exconfig.c
@@ -170,14 +170,12 @@ acpi_ex_load_table_op(struct acpi_walk_state *walk_state,
/* Table not found, return an Integer=0 and AE_OK */
- ddb_handle = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);
+ ddb_handle = acpi_ut_create_integer_object((u64) 0);
if (!ddb_handle) {
return_ACPI_STATUS(AE_NO_MEMORY);
}
- ddb_handle->integer.value = 0;
*return_desc = ddb_handle;
-
return_ACPI_STATUS(AE_OK);
}
diff --git a/drivers/acpi/acpica/exconvrt.c b/drivers/acpi/acpica/exconvrt.c
index 37d0d39e60a6..51d5f224f9fa 100644
--- a/drivers/acpi/acpica/exconvrt.c
+++ b/drivers/acpi/acpica/exconvrt.c
@@ -167,7 +167,7 @@ acpi_ex_convert_to_integer(union acpi_operand_object *obj_desc,
/* Create a new integer */
- return_desc = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);
+ return_desc = acpi_ut_create_integer_object(result);
if (!return_desc) {
return_ACPI_STATUS(AE_NO_MEMORY);
}
@@ -177,7 +177,6 @@ acpi_ex_convert_to_integer(union acpi_operand_object *obj_desc,
/* Save the Result */
- return_desc->integer.value = result;
acpi_ex_truncate_for32bit_table(return_desc);
*result_desc = return_desc;
return_ACPI_STATUS(AE_OK);
diff --git a/drivers/acpi/acpica/exfield.c b/drivers/acpi/acpica/exfield.c
index 0b33d6c887b9..1588a2d660e7 100644
--- a/drivers/acpi/acpica/exfield.c
+++ b/drivers/acpi/acpica/exfield.c
@@ -162,13 +162,12 @@ acpi_ex_read_data_from_field(struct acpi_walk_state *walk_state,
} else {
/* Field will fit within an Integer (normal case) */
- buffer_desc = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);
+ buffer_desc = acpi_ut_create_integer_object((u64) 0);
if (!buffer_desc) {
return_ACPI_STATUS(AE_NO_MEMORY);
}
length = acpi_gbl_integer_byte_width;
- buffer_desc->integer.value = 0;
buffer = &buffer_desc->integer.value;
}
diff --git a/drivers/acpi/acpica/exoparg1.c b/drivers/acpi/acpica/exoparg1.c
index 9635d21e568d..752fe48b2d20 100644
--- a/drivers/acpi/acpica/exoparg1.c
+++ b/drivers/acpi/acpica/exoparg1.c
@@ -100,12 +100,12 @@ acpi_status acpi_ex_opcode_0A_0T_1R(struct acpi_walk_state *walk_state)
/* Create a return object of type Integer */
- return_desc = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);
+ return_desc =
+ acpi_ut_create_integer_object(acpi_os_get_timer());
if (!return_desc) {
status = AE_NO_MEMORY;
goto cleanup;
}
- return_desc->integer.value = acpi_os_get_timer();
break;
default: /* Unknown opcode */
@@ -599,7 +599,7 @@ acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state)
switch (walk_state->opcode) {
case AML_LNOT_OP: /* LNot (Operand) */
- return_desc = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);
+ return_desc = acpi_ut_create_integer_object((u64) 0);
if (!return_desc) {
status = AE_NO_MEMORY;
goto cleanup;
@@ -702,13 +702,11 @@ acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state)
/* Allocate a descriptor to hold the type. */
- return_desc = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);
+ return_desc = acpi_ut_create_integer_object((u64) type);
if (!return_desc) {
status = AE_NO_MEMORY;
goto cleanup;
}
-
- return_desc->integer.value = type;
break;
case AML_SIZE_OF_OP: /* size_of (source_object) */
@@ -777,13 +775,11 @@ acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state)
* Now that we have the size of the object, create a result
* object to hold the value
*/
- return_desc = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);
+ return_desc = acpi_ut_create_integer_object(value);
if (!return_desc) {
status = AE_NO_MEMORY;
goto cleanup;
}
-
- return_desc->integer.value = value;
break;
case AML_REF_OF_OP: /* ref_of (source_object) */
@@ -946,24 +942,24 @@ acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state)
* NOTE: index into a buffer is NOT a pointer to a
* sub-buffer of the main buffer, it is only a pointer to a
* single element (byte) of the buffer!
+ *
+ * Since we are returning the value of the buffer at the
+ * indexed location, we don't need to add an additional
+ * reference to the buffer itself.
*/
return_desc =
- acpi_ut_create_internal_object
- (ACPI_TYPE_INTEGER);
+ acpi_ut_create_integer_object((u64)
+ temp_desc->
+ buffer.
+ pointer
+ [operand
+ [0]->
+ reference.
+ value]);
if (!return_desc) {
status = AE_NO_MEMORY;
goto cleanup;
}
-
- /*
- * Since we are returning the value of the buffer at the
- * indexed location, we don't need to add an additional
- * reference to the buffer itself.
- */
- return_desc->integer.value =
- temp_desc->buffer.
- pointer[operand[0]->reference.
- value];
break;
case ACPI_TYPE_PACKAGE:
diff --git a/drivers/acpi/acpica/exoparg6.c b/drivers/acpi/acpica/exoparg6.c
index ae43f7670a6c..295542e6bd51 100644
--- a/drivers/acpi/acpica/exoparg6.c
+++ b/drivers/acpi/acpica/exoparg6.c
@@ -253,18 +253,15 @@ acpi_status acpi_ex_opcode_6A_0T_1R(struct acpi_walk_state * walk_state)
}
/* Create an integer for the return value */
+ /* Default return value is ACPI_INTEGER_MAX if no match found */
- return_desc = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);
+ return_desc = acpi_ut_create_integer_object(ACPI_INTEGER_MAX);
if (!return_desc) {
status = AE_NO_MEMORY;
goto cleanup;
}
- /* Default return value if no match found */
-
- return_desc->integer.value = ACPI_INTEGER_MAX;
-
/*
* Examine each element until a match is found. Both match conditions
* must be satisfied for a match to occur. Within the loop,
diff --git a/drivers/acpi/acpica/nsdump.c b/drivers/acpi/acpica/nsdump.c
index 2bad613db73a..2deb986861ca 100644
--- a/drivers/acpi/acpica/nsdump.c
+++ b/drivers/acpi/acpica/nsdump.c
@@ -634,8 +634,8 @@ acpi_ns_dump_objects(acpi_object_type type,
(void)acpi_ns_walk_namespace(type, start_handle, max_depth,
ACPI_NS_WALK_NO_UNLOCK |
ACPI_NS_WALK_TEMP_NODES,
- acpi_ns_dump_one_object, (void *)&info,
- NULL);
+ acpi_ns_dump_one_object, NULL,
+ (void *)&info, NULL);
}
#endif /* ACPI_FUTURE_USAGE */
diff --git a/drivers/acpi/acpica/nsdumpdv.c b/drivers/acpi/acpica/nsdumpdv.c
index 0fe87f1aef16..36be7f0e97ec 100644
--- a/drivers/acpi/acpica/nsdumpdv.c
+++ b/drivers/acpi/acpica/nsdumpdv.c
@@ -131,7 +131,8 @@ void acpi_ns_dump_root_devices(void)
status = acpi_ns_walk_namespace(ACPI_TYPE_DEVICE, sys_bus_handle,
ACPI_UINT32_MAX, ACPI_NS_WALK_NO_UNLOCK,
- acpi_ns_dump_one_device, NULL, NULL);
+ acpi_ns_dump_one_device, NULL, NULL,
+ NULL);
}
#endif
diff --git a/drivers/acpi/acpica/nseval.c b/drivers/acpi/acpica/nseval.c
index 846d1132feb1..f771e978c403 100644
--- a/drivers/acpi/acpica/nseval.c
+++ b/drivers/acpi/acpica/nseval.c
@@ -366,33 +366,49 @@ static void
acpi_ns_exec_module_code(union acpi_operand_object *method_obj,
struct acpi_evaluate_info *info)
{
- union acpi_operand_object *root_obj;
+ union acpi_operand_object *parent_obj;
+ struct acpi_namespace_node *parent_node;
+ acpi_object_type type;
acpi_status status;
ACPI_FUNCTION_TRACE(ns_exec_module_code);
+ /*
+ * Get the parent node. We cheat by using the next_object field
+ * of the method object descriptor.
+ */
+ parent_node = ACPI_CAST_PTR(struct acpi_namespace_node,
+ method_obj->method.next_object);
+ type = acpi_ns_get_type(parent_node);
+
+ /* Must clear next_object (acpi_ns_attach_object needs the field) */
+
+ method_obj->method.next_object = NULL;
+
/* Initialize the evaluation information block */
ACPI_MEMSET(info, 0, sizeof(struct acpi_evaluate_info));
- info->prefix_node = acpi_gbl_root_node;
+ info->prefix_node = parent_node;
/*
- * Get the currently attached root object. Add a reference, because the
+ * Get the currently attached parent object. Add a reference, because the
* ref count will be decreased when the method object is installed to
- * the root node.
+ * the parent node.
*/
- root_obj = acpi_ns_get_attached_object(acpi_gbl_root_node);
- acpi_ut_add_reference(root_obj);
+ parent_obj = acpi_ns_get_attached_object(parent_node);
+ if (parent_obj) {
+ acpi_ut_add_reference(parent_obj);
+ }
- /* Install the method (module-level code) in the root node */
+ /* Install the method (module-level code) in the parent node */
- status = acpi_ns_attach_object(acpi_gbl_root_node, method_obj,
+ status = acpi_ns_attach_object(parent_node, method_obj,
ACPI_TYPE_METHOD);
if (ACPI_FAILURE(status)) {
goto exit;
}
- /* Execute the root node as a control method */
+ /* Execute the parent node as a control method */
status = acpi_ns_evaluate(info);
@@ -401,15 +417,19 @@ acpi_ns_exec_module_code(union acpi_operand_object *method_obj,
/* Detach the temporary method object */
- acpi_ns_detach_object(acpi_gbl_root_node);
+ acpi_ns_detach_object(parent_node);
- /* Restore the original root object */
+ /* Restore the original parent object */
- status =
- acpi_ns_attach_object(acpi_gbl_root_node, root_obj,
- ACPI_TYPE_DEVICE);
+ if (parent_obj) {
+ status = acpi_ns_attach_object(parent_node, parent_obj, type);
+ } else {
+ parent_node->type = (u8)type;
+ }
exit:
- acpi_ut_remove_reference(root_obj);
+ if (parent_obj) {
+ acpi_ut_remove_reference(parent_obj);
+ }
return_VOID;
}
diff --git a/drivers/acpi/acpica/nsinit.c b/drivers/acpi/acpica/nsinit.c
index 1d5b360eb25b..4f8abac231d2 100644
--- a/drivers/acpi/acpica/nsinit.c
+++ b/drivers/acpi/acpica/nsinit.c
@@ -96,7 +96,7 @@ acpi_status acpi_ns_initialize_objects(void)
/* Walk entire namespace from the supplied root */
status = acpi_walk_namespace(ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
- ACPI_UINT32_MAX, acpi_ns_init_one_object,
+ ACPI_UINT32_MAX, acpi_ns_init_one_object, NULL,
&info, NULL);
if (ACPI_FAILURE(status)) {
ACPI_EXCEPTION((AE_INFO, status, "During WalkNamespace"));
@@ -156,7 +156,8 @@ acpi_status acpi_ns_initialize_devices(void)
status = acpi_ns_walk_namespace(ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
ACPI_UINT32_MAX, FALSE,
- acpi_ns_find_ini_methods, &info, NULL);
+ acpi_ns_find_ini_methods, NULL, &info,
+ NULL);
if (ACPI_FAILURE(status)) {
goto error_exit;
}
@@ -189,7 +190,8 @@ acpi_status acpi_ns_initialize_devices(void)
status = acpi_ns_walk_namespace(ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
ACPI_UINT32_MAX, FALSE,
- acpi_ns_init_one_device, &info, NULL);
+ acpi_ns_init_one_device, NULL, &info,
+ NULL);
ACPI_FREE(info.evaluate_info);
if (ACPI_FAILURE(status)) {
diff --git a/drivers/acpi/acpica/nspredef.c b/drivers/acpi/acpica/nspredef.c
index f8427afeebdf..b05f42903c86 100644
--- a/drivers/acpi/acpica/nspredef.c
+++ b/drivers/acpi/acpica/nspredef.c
@@ -232,6 +232,12 @@ acpi_ns_check_predefined_names(struct acpi_namespace_node *node,
status = acpi_ns_check_package(data, return_object_ptr);
}
+ /*
+ * Perform additional, more complicated repairs on a per-name
+ * basis.
+ */
+ status = acpi_ns_complex_repairs(data, node, status, return_object_ptr);
+
check_validation_status:
/*
* If the object validation failed or if we successfully repaired one
@@ -601,7 +607,8 @@ acpi_ns_check_package(struct acpi_predefined_data *data,
* there is only one entry). We may be able to repair this by
* wrapping the returned Package with a new outer Package.
*/
- if ((*elements)->common.type != ACPI_TYPE_PACKAGE) {
+ if (*elements
+ && ((*elements)->common.type != ACPI_TYPE_PACKAGE)) {
/* Create the new outer package and populate it */
@@ -673,6 +680,7 @@ acpi_ns_check_package_list(struct acpi_predefined_data *data,
union acpi_operand_object *sub_package;
union acpi_operand_object **sub_elements;
acpi_status status;
+ u8 non_trailing_null = FALSE;
u32 expected_count;
u32 i;
u32 j;
@@ -680,6 +688,45 @@ acpi_ns_check_package_list(struct acpi_predefined_data *data,
/* Validate each sub-Package in the parent Package */
for (i = 0; i < count; i++) {
+ /*
+ * Handling for NULL package elements. For now, we will simply allow
+ * a parent package with trailing NULL elements. This can happen if
+ * the package was defined to be longer than the initializer list.
+ * This is legal as per the ACPI specification. It is often used
+ * to allow for dynamic initialization of a Package.
+ *
+ * A future enhancement may be to simply truncate the package to
+ * remove the trailing NULL elements.
+ */
+ if (!(*elements)) {
+ if (!non_trailing_null) {
+
+ /* Ensure the remaining elements are all NULL */
+
+ for (j = 1; j < (count - i + 1); j++) {
+ if (elements[j]) {
+ non_trailing_null = TRUE;
+ }
+ }
+
+ if (!non_trailing_null) {
+
+ /* Ignore the trailing NULL elements */
+
+ return (AE_OK);
+ }
+ }
+
+ /* There are trailing non-null elements, issue warning */
+
+ ACPI_WARN_PREDEFINED((AE_INFO, data->pathname,
+ data->node_flags,
+ "Found NULL element at package index %u",
+ i));
+ elements++;
+ continue;
+ }
+
sub_package = *elements;
sub_elements = sub_package->package.elements;
diff --git a/drivers/acpi/acpica/nsrepair.c b/drivers/acpi/acpica/nsrepair.c
index db2b2a99c3a8..d563f1a564a7 100644
--- a/drivers/acpi/acpica/nsrepair.c
+++ b/drivers/acpi/acpica/nsrepair.c
@@ -44,6 +44,7 @@
#include <acpi/acpi.h>
#include "accommon.h"
#include "acnamesp.h"
+#include "acinterp.h"
#include "acpredef.h"
#define _COMPONENT ACPI_NAMESPACE
@@ -76,7 +77,13 @@ acpi_ns_repair_object(struct acpi_predefined_data *data,
union acpi_operand_object *return_object = *return_object_ptr;
union acpi_operand_object *new_object;
acpi_size length;
+ acpi_status status;
+ /*
+ * At this point, we know that the type of the returned object was not
+ * one of the expected types for this predefined name. Attempt to
+ * repair the object. Only a limited number of repairs are possible.
+ */
switch (return_object->common.type) {
case ACPI_TYPE_BUFFER:
@@ -111,43 +118,94 @@ acpi_ns_repair_object(struct acpi_predefined_data *data,
*/
ACPI_MEMCPY(new_object->string.pointer,
return_object->buffer.pointer, length);
+ break;
- /*
- * If the original object is a package element, we need to:
- * 1. Set the reference count of the new object to match the
- * reference count of the old object.
- * 2. Decrement the reference count of the original object.
- */
- if (package_index != ACPI_NOT_PACKAGE_ELEMENT) {
- new_object->common.reference_count =
- return_object->common.reference_count;
+ case ACPI_TYPE_INTEGER:
+
+ /* 1) Does the method/object legally return a buffer? */
+
+ if (expected_btypes & ACPI_RTYPE_BUFFER) {
+ /*
+ * Convert the Integer to a packed-byte buffer. _MAT needs
+ * this sometimes, if a read has been performed on a Field
+ * object that is less than or equal to the global integer
+ * size (32 or 64 bits).
+ */
+ status =
+ acpi_ex_convert_to_buffer(return_object,
+ &new_object);
+ if (ACPI_FAILURE(status)) {
+ return (status);
+ }
+ }
- if (return_object->common.reference_count > 1) {
- return_object->common.reference_count--;
+ /* 2) Does the method/object legally return a string? */
+
+ else if (expected_btypes & ACPI_RTYPE_STRING) {
+ /*
+ * The only supported Integer-to-String conversion is to convert
+ * an integer of value 0 to a NULL string. The last element of
+ * _BIF and _BIX packages occasionally need this fix.
+ */
+ if (return_object->integer.value != 0) {
+ return (AE_AML_OPERAND_TYPE);
}
- ACPI_WARN_PREDEFINED((AE_INFO, data->pathname,
- data->node_flags,
- "Converted Buffer to expected String at index %u",
- package_index));
+ /* Allocate a new NULL string object */
+
+ new_object = acpi_ut_create_string_object(0);
+ if (!new_object) {
+ return (AE_NO_MEMORY);
+ }
} else {
- ACPI_WARN_PREDEFINED((AE_INFO, data->pathname,
- data->node_flags,
- "Converted Buffer to expected String"));
+ return (AE_AML_OPERAND_TYPE);
}
+ break;
- /* Delete old object, install the new return object */
+ default:
- acpi_ut_remove_reference(return_object);
- *return_object_ptr = new_object;
- data->flags |= ACPI_OBJECT_REPAIRED;
- return (AE_OK);
+ /* We cannot repair this object */
- default:
- break;
+ return (AE_AML_OPERAND_TYPE);
+ }
+
+ /* Object was successfully repaired */
+
+ /*
+ * If the original object is a package element, we need to:
+ * 1. Set the reference count of the new object to match the
+ * reference count of the old object.
+ * 2. Decrement the reference count of the original object.
+ */
+ if (package_index != ACPI_NOT_PACKAGE_ELEMENT) {
+ new_object->common.reference_count =
+ return_object->common.reference_count;
+
+ if (return_object->common.reference_count > 1) {
+ return_object->common.reference_count--;
+ }
+
+ ACPI_INFO_PREDEFINED((AE_INFO, data->pathname, data->node_flags,
+ "Converted %s to expected %s at index %u",
+ acpi_ut_get_object_type_name
+ (return_object),
+ acpi_ut_get_object_type_name(new_object),
+ package_index));
+ } else {
+ ACPI_INFO_PREDEFINED((AE_INFO, data->pathname, data->node_flags,
+ "Converted %s to expected %s",
+ acpi_ut_get_object_type_name
+ (return_object),
+ acpi_ut_get_object_type_name
+ (new_object)));
}
- return (AE_AML_OPERAND_TYPE);
+ /* Delete old object, install the new return object */
+
+ acpi_ut_remove_reference(return_object);
+ *return_object_ptr = new_object;
+ data->flags |= ACPI_OBJECT_REPAIRED;
+ return (AE_OK);
}
/*******************************************************************************
@@ -196,8 +254,8 @@ acpi_ns_repair_package_list(struct acpi_predefined_data *data,
*obj_desc_ptr = pkg_obj_desc;
data->flags |= ACPI_OBJECT_REPAIRED;
- ACPI_WARN_PREDEFINED((AE_INFO, data->pathname, data->node_flags,
- "Incorrectly formed Package, attempting repair"));
+ ACPI_INFO_PREDEFINED((AE_INFO, data->pathname, data->node_flags,
+ "Repaired Incorrectly formed Package"));
return (AE_OK);
}
diff --git a/drivers/acpi/acpica/nsrepair2.c b/drivers/acpi/acpica/nsrepair2.c
new file mode 100644
index 000000000000..d07b68613818
--- /dev/null
+++ b/drivers/acpi/acpica/nsrepair2.c
@@ -0,0 +1,540 @@
+/******************************************************************************
+ *
+ * Module Name: nsrepair2 - Repair for objects returned by specific
+ * predefined methods
+ *
+ *****************************************************************************/
+
+/*
+ * Copyright (C) 2000 - 2009, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions, and the following disclaimer,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * substantially similar to the "NO WARRANTY" disclaimer below
+ * ("Disclaimer") and any redistribution must be conditioned upon
+ * including a substantially similar Disclaimer requirement for further
+ * binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ * of any contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#include <acpi/acpi.h>
+#include "accommon.h"
+#include "acnamesp.h"
+
+#define _COMPONENT ACPI_NAMESPACE
+ACPI_MODULE_NAME("nsrepair2")
+
+/*
+ * Information structure and handler for ACPI predefined names that can
+ * be repaired on a per-name basis.
+ */
+typedef
+acpi_status(*acpi_repair_function) (struct acpi_predefined_data *data,
+ union acpi_operand_object **return_object_ptr);
+
+typedef struct acpi_repair_info {
+ char name[ACPI_NAME_SIZE];
+ acpi_repair_function repair_function;
+
+} acpi_repair_info;
+
+/* Local prototypes */
+
+static const struct acpi_repair_info *acpi_ns_match_repairable_name(struct
+ acpi_namespace_node
+ *node);
+
+static acpi_status
+acpi_ns_repair_ALR(struct acpi_predefined_data *data,
+ union acpi_operand_object **return_object_ptr);
+
+static acpi_status
+acpi_ns_repair_PSS(struct acpi_predefined_data *data,
+ union acpi_operand_object **return_object_ptr);
+
+static acpi_status
+acpi_ns_repair_TSS(struct acpi_predefined_data *data,
+ union acpi_operand_object **return_object_ptr);
+
+static acpi_status
+acpi_ns_check_sorted_list(struct acpi_predefined_data *data,
+ union acpi_operand_object *return_object,
+ u32 expected_count,
+ u32 sort_index,
+ u8 sort_direction, char *sort_key_name);
+
+static acpi_status
+acpi_ns_remove_null_elements(union acpi_operand_object *package);
+
+static acpi_status
+acpi_ns_sort_list(union acpi_operand_object **elements,
+ u32 count, u32 index, u8 sort_direction);
+
+/* Values for sort_direction above */
+
+#define ACPI_SORT_ASCENDING 0
+#define ACPI_SORT_DESCENDING 1
+
+/*
+ * This table contains the names of the predefined methods for which we can
+ * perform more complex repairs.
+ *
+ * _ALR: Sort the list ascending by ambient_illuminance if necessary
+ * _PSS: Sort the list descending by Power if necessary
+ * _TSS: Sort the list descending by Power if necessary
+ */
+static const struct acpi_repair_info acpi_ns_repairable_names[] = {
+ {"_ALR", acpi_ns_repair_ALR},
+ {"_PSS", acpi_ns_repair_PSS},
+ {"_TSS", acpi_ns_repair_TSS},
+ {{0, 0, 0, 0}, NULL} /* Table terminator */
+};
+
+/******************************************************************************
+ *
+ * FUNCTION: acpi_ns_complex_repairs
+ *
+ * PARAMETERS: Data - Pointer to validation data structure
+ * Node - Namespace node for the method/object
+ * validate_status - Original status of earlier validation
+ * return_object_ptr - Pointer to the object returned from the
+ * evaluation of a method or object
+ *
+ * RETURN: Status. AE_OK if repair was successful. If name is not
+ * matched, validate_status is returned.
+ *
+ * DESCRIPTION: Attempt to repair/convert a return object of a type that was
+ * not expected.
+ *
+ *****************************************************************************/
+
+acpi_status
+acpi_ns_complex_repairs(struct acpi_predefined_data *data,
+ struct acpi_namespace_node *node,
+ acpi_status validate_status,
+ union acpi_operand_object **return_object_ptr)
+{
+ const struct acpi_repair_info *predefined;
+ acpi_status status;
+
+ /* Check if this name is in the list of repairable names */
+
+ predefined = acpi_ns_match_repairable_name(node);
+ if (!predefined) {
+ return (validate_status);
+ }
+
+ status = predefined->repair_function(data, return_object_ptr);
+ return (status);
+}
+
+/******************************************************************************
+ *
+ * FUNCTION: acpi_ns_match_repairable_name
+ *
+ * PARAMETERS: Node - Namespace node for the method/object
+ *
+ * RETURN: Pointer to entry in repair table. NULL indicates not found.
+ *
+ * DESCRIPTION: Check an object name against the repairable object list.
+ *
+ *****************************************************************************/
+
+static const struct acpi_repair_info *acpi_ns_match_repairable_name(struct
+ acpi_namespace_node
+ *node)
+{
+ const struct acpi_repair_info *this_name;
+
+ /* Search info table for a repairable predefined method/object name */
+
+ this_name = acpi_ns_repairable_names;
+ while (this_name->repair_function) {
+ if (ACPI_COMPARE_NAME(node->name.ascii, this_name->name)) {
+ return (this_name);
+ }
+ this_name++;
+ }
+
+ return (NULL); /* Not found */
+}
+
+/******************************************************************************
+ *
+ * FUNCTION: acpi_ns_repair_ALR
+ *
+ * PARAMETERS: Data - Pointer to validation data structure
+ * return_object_ptr - Pointer to the object returned from the
+ * evaluation of a method or object
+ *
+ * RETURN: Status. AE_OK if object is OK or was repaired successfully
+ *
+ * DESCRIPTION: Repair for the _ALR object. If necessary, sort the object list
+ * ascending by the ambient illuminance values.
+ *
+ *****************************************************************************/
+
+static acpi_status
+acpi_ns_repair_ALR(struct acpi_predefined_data *data,
+ union acpi_operand_object **return_object_ptr)
+{
+ union acpi_operand_object *return_object = *return_object_ptr;
+ acpi_status status;
+
+ status = acpi_ns_check_sorted_list(data, return_object, 2, 1,
+ ACPI_SORT_ASCENDING,
+ "AmbientIlluminance");
+
+ return (status);
+}
+
+/******************************************************************************
+ *
+ * FUNCTION: acpi_ns_repair_TSS
+ *
+ * PARAMETERS: Data - Pointer to validation data structure
+ * return_object_ptr - Pointer to the object returned from the
+ * evaluation of a method or object
+ *
+ * RETURN: Status. AE_OK if object is OK or was repaired successfully
+ *
+ * DESCRIPTION: Repair for the _TSS object. If necessary, sort the object list
+ * descending by the power dissipation values.
+ *
+ *****************************************************************************/
+
+static acpi_status
+acpi_ns_repair_TSS(struct acpi_predefined_data *data,
+ union acpi_operand_object **return_object_ptr)
+{
+ union acpi_operand_object *return_object = *return_object_ptr;
+ acpi_status status;
+
+ status = acpi_ns_check_sorted_list(data, return_object, 5, 1,
+ ACPI_SORT_DESCENDING,
+ "PowerDissipation");
+
+ return (status);
+}
+
+/******************************************************************************
+ *
+ * FUNCTION: acpi_ns_repair_PSS
+ *
+ * PARAMETERS: Data - Pointer to validation data structure
+ * return_object_ptr - Pointer to the object returned from the
+ * evaluation of a method or object
+ *
+ * RETURN: Status. AE_OK if object is OK or was repaired successfully
+ *
+ * DESCRIPTION: Repair for the _PSS object. If necessary, sort the object list
+ * by the CPU frequencies. Check that the power dissipation values
+ * are all proportional to CPU frequency (i.e., sorting by
+ * frequency should be the same as sorting by power.)
+ *
+ *****************************************************************************/
+
+static acpi_status
+acpi_ns_repair_PSS(struct acpi_predefined_data *data,
+ union acpi_operand_object **return_object_ptr)
+{
+ union acpi_operand_object *return_object = *return_object_ptr;
+ union acpi_operand_object **outer_elements;
+ u32 outer_element_count;
+ union acpi_operand_object **elements;
+ union acpi_operand_object *obj_desc;
+ u32 previous_value;
+ acpi_status status;
+ u32 i;
+
+ /*
+ * Entries (sub-packages) in the _PSS Package must be sorted by power
+ * dissipation, in descending order. If it appears that the list is
+ * incorrectly sorted, sort it. We sort by cpu_frequency, since this
+ * should be proportional to the power.
+ */
+ status = acpi_ns_check_sorted_list(data, return_object, 6, 0,
+ ACPI_SORT_DESCENDING,
+ "CpuFrequency");
+ if (ACPI_FAILURE(status)) {
+ return (status);
+ }
+
+ /*
+ * We now know the list is correctly sorted by CPU frequency. Check if
+ * the power dissipation values are proportional.
+ */
+ previous_value = ACPI_UINT32_MAX;
+ outer_elements = return_object->package.elements;
+ outer_element_count = return_object->package.count;
+
+ for (i = 0; i < outer_element_count; i++) {
+ elements = (*outer_elements)->package.elements;
+ obj_desc = elements[1]; /* Index1 = power_dissipation */
+
+ if ((u32) obj_desc->integer.value > previous_value) {
+ ACPI_WARN_PREDEFINED((AE_INFO, data->pathname,
+ data->node_flags,
+ "SubPackage[%u,%u] - suspicious power dissipation values",
+ i - 1, i));
+ }
+
+ previous_value = (u32) obj_desc->integer.value;
+ outer_elements++;
+ }
+
+ return (AE_OK);
+}
+
+/******************************************************************************
+ *
+ * FUNCTION: acpi_ns_check_sorted_list
+ *
+ * PARAMETERS: Data - Pointer to validation data structure
+ * return_object - Pointer to the top-level returned object
+ * expected_count - Minimum length of each sub-package
+ * sort_index - Sub-package entry to sort on
+ * sort_direction - Ascending or descending
+ * sort_key_name - Name of the sort_index field
+ *
+ * RETURN: Status. AE_OK if the list is valid and is sorted correctly or
+ * has been repaired by sorting the list.
+ *
+ * DESCRIPTION: Check if the package list is valid and sorted correctly by the
+ * sort_index. If not, then sort the list.
+ *
+ *****************************************************************************/
+
+static acpi_status
+acpi_ns_check_sorted_list(struct acpi_predefined_data *data,
+ union acpi_operand_object *return_object,
+ u32 expected_count,
+ u32 sort_index,
+ u8 sort_direction, char *sort_key_name)
+{
+ u32 outer_element_count;
+ union acpi_operand_object **outer_elements;
+ union acpi_operand_object **elements;
+ union acpi_operand_object *obj_desc;
+ u32 i;
+ u32 previous_value;
+ acpi_status status;
+
+ /* The top-level object must be a package */
+
+ if (return_object->common.type != ACPI_TYPE_PACKAGE) {
+ return (AE_AML_OPERAND_TYPE);
+ }
+
+ /*
+ * Detect any NULL package elements and remove them from the
+ * package.
+ *
+ * TBD: We may want to do this for all predefined names that
+ * return a variable-length package of packages.
+ */
+ status = acpi_ns_remove_null_elements(return_object);
+ if (status == AE_NULL_ENTRY) {
+ ACPI_INFO_PREDEFINED((AE_INFO, data->pathname, data->node_flags,
+ "NULL elements removed from package"));
+
+ /* Exit if package is now zero length */
+
+ if (!return_object->package.count) {
+ return (AE_NULL_ENTRY);
+ }
+ }
+
+ outer_elements = return_object->package.elements;
+ outer_element_count = return_object->package.count;
+ if (!outer_element_count) {
+ return (AE_AML_PACKAGE_LIMIT);
+ }
+
+ previous_value = 0;
+ if (sort_direction == ACPI_SORT_DESCENDING) {
+ previous_value = ACPI_UINT32_MAX;
+ }
+
+ /* Examine each subpackage */
+
+ for (i = 0; i < outer_element_count; i++) {
+
+ /* Each element of the top-level package must also be a package */
+
+ if ((*outer_elements)->common.type != ACPI_TYPE_PACKAGE) {
+ return (AE_AML_OPERAND_TYPE);
+ }
+
+ /* Each sub-package must have the minimum length */
+
+ if ((*outer_elements)->package.count < expected_count) {
+ return (AE_AML_PACKAGE_LIMIT);
+ }
+
+ elements = (*outer_elements)->package.elements;
+ obj_desc = elements[sort_index];
+
+ if (obj_desc->common.type != ACPI_TYPE_INTEGER) {
+ return (AE_AML_OPERAND_TYPE);
+ }
+
+ /*
+ * The list must be sorted in the specified order. If we detect a
+ * discrepancy, issue a warning and sort the entire list
+ */
+ if (((sort_direction == ACPI_SORT_ASCENDING) &&
+ (obj_desc->integer.value < previous_value)) ||
+ ((sort_direction == ACPI_SORT_DESCENDING) &&
+ (obj_desc->integer.value > previous_value))) {
+ status =
+ acpi_ns_sort_list(return_object->package.elements,
+ outer_element_count, sort_index,
+ sort_direction);
+ if (ACPI_FAILURE(status)) {
+ return (status);
+ }
+
+ data->flags |= ACPI_OBJECT_REPAIRED;
+
+ ACPI_INFO_PREDEFINED((AE_INFO, data->pathname,
+ data->node_flags,
+ "Repaired unsorted list - now sorted by %s",
+ sort_key_name));
+ return (AE_OK);
+ }
+
+ previous_value = (u32) obj_desc->integer.value;
+ outer_elements++;
+ }
+
+ return (AE_OK);
+}
+
+/******************************************************************************
+ *
+ * FUNCTION: acpi_ns_remove_null_elements
+ *
+ * PARAMETERS: obj_desc - A Package object
+ *
+ * RETURN: Status. AE_NULL_ENTRY means that one or more elements were
+ * removed.
+ *
+ * DESCRIPTION: Remove all NULL package elements and update the package count.
+ *
+ *****************************************************************************/
+
+static acpi_status
+acpi_ns_remove_null_elements(union acpi_operand_object *obj_desc)
+{
+ union acpi_operand_object **source;
+ union acpi_operand_object **dest;
+ acpi_status status = AE_OK;
+ u32 count;
+ u32 new_count;
+ u32 i;
+
+ count = obj_desc->package.count;
+ new_count = count;
+
+ source = obj_desc->package.elements;
+ dest = source;
+
+ /* Examine all elements of the package object */
+
+ for (i = 0; i < count; i++) {
+ if (!*source) {
+ status = AE_NULL_ENTRY;
+ new_count--;
+ } else {
+ *dest = *source;
+ dest++;
+ }
+ source++;
+ }
+
+ if (status == AE_NULL_ENTRY) {
+
+ /* NULL terminate list and update the package count */
+
+ *dest = NULL;
+ obj_desc->package.count = new_count;
+ }
+
+ return (status);
+}
+
+/******************************************************************************
+ *
+ * FUNCTION: acpi_ns_sort_list
+ *
+ * PARAMETERS: Elements - Package object element list
+ * Count - Element count for above
+ * Index - Sort by which package element
+ * sort_direction - Ascending or Descending sort
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Sort the objects that are in a package element list.
+ *
+ * NOTE: Assumes that all NULL elements have been removed from the package.
+ *
+ *****************************************************************************/
+
+static acpi_status
+acpi_ns_sort_list(union acpi_operand_object **elements,
+ u32 count, u32 index, u8 sort_direction)
+{
+ union acpi_operand_object *obj_desc1;
+ union acpi_operand_object *obj_desc2;
+ union acpi_operand_object *temp_obj;
+ u32 i;
+ u32 j;
+
+ /* Simple bubble sort */
+
+ for (i = 1; i < count; i++) {
+ for (j = (count - 1); j >= i; j--) {
+ obj_desc1 = elements[j - 1]->package.elements[index];
+ obj_desc2 = elements[j]->package.elements[index];
+
+ if (((sort_direction == ACPI_SORT_ASCENDING) &&
+ (obj_desc1->integer.value >
+ obj_desc2->integer.value))
+ || ((sort_direction == ACPI_SORT_DESCENDING)
+ && (obj_desc1->integer.value <
+ obj_desc2->integer.value))) {
+ temp_obj = elements[j - 1];
+ elements[j - 1] = elements[j];
+ elements[j] = temp_obj;
+ }
+ }
+ }
+
+ return (AE_OK);
+}
diff --git a/drivers/acpi/acpica/nswalk.c b/drivers/acpi/acpica/nswalk.c
index 35539df5c75d..d7e6b52b4482 100644
--- a/drivers/acpi/acpica/nswalk.c
+++ b/drivers/acpi/acpica/nswalk.c
@@ -165,24 +165,27 @@ struct acpi_namespace_node *acpi_ns_get_next_node_typed(acpi_object_type type,
* max_depth - Depth to which search is to reach
* Flags - Whether to unlock the NS before invoking
* the callback routine
- * user_function - Called when an object of "Type" is found
- * Context - Passed to user function
- * return_value - from the user_function if terminated early.
- * Otherwise, returns NULL.
+ * pre_order_visit - Called during tree pre-order visit
+ * when an object of "Type" is found
+ * post_order_visit - Called during tree post-order visit
+ * when an object of "Type" is found
+ * Context - Passed to user function(s) above
+ * return_value - from the user_function if terminated
+ * early. Otherwise, returns NULL.
* RETURNS: Status
*
* DESCRIPTION: Performs a modified depth-first walk of the namespace tree,
* starting (and ending) at the node specified by start_handle.
- * The user_function is called whenever a node that matches
- * the type parameter is found. If the user function returns
+ * The callback function is called whenever a node that matches
+ * the type parameter is found. If the callback function returns
* a non-zero value, the search is terminated immediately and
* this value is returned to the caller.
*
* The point of this procedure is to provide a generic namespace
* walk routine that can be called from multiple places to
- * provide multiple services; the User Function can be tailored
- * to each task, whether it is a print function, a compare
- * function, etc.
+ * provide multiple services; the callback function(s) can be
+ * tailored to each task, whether it is a print function,
+ * a compare function, etc.
*
******************************************************************************/
@@ -191,7 +194,8 @@ acpi_ns_walk_namespace(acpi_object_type type,
acpi_handle start_node,
u32 max_depth,
u32 flags,
- acpi_walk_callback user_function,
+ acpi_walk_callback pre_order_visit,
+ acpi_walk_callback post_order_visit,
void *context, void **return_value)
{
acpi_status status;
@@ -200,6 +204,7 @@ acpi_ns_walk_namespace(acpi_object_type type,
struct acpi_namespace_node *parent_node;
acpi_object_type child_type;
u32 level;
+ u8 node_previously_visited = FALSE;
ACPI_FUNCTION_TRACE(ns_walk_namespace);
@@ -212,7 +217,7 @@ acpi_ns_walk_namespace(acpi_object_type type,
/* Null child means "get first node" */
parent_node = start_node;
- child_node = NULL;
+ child_node = acpi_ns_get_next_node(parent_node, NULL);
child_type = ACPI_TYPE_ANY;
level = 1;
@@ -221,102 +226,129 @@ acpi_ns_walk_namespace(acpi_object_type type,
* started. When Level is zero, the loop is done because we have
* bubbled up to (and passed) the original parent handle (start_entry)
*/
- while (level > 0) {
+ while (level > 0 && child_node) {
+ status = AE_OK;
- /* Get the next node in this scope. Null if not found */
+ /* Found next child, get the type if we are not searching for ANY */
- status = AE_OK;
- child_node = acpi_ns_get_next_node(parent_node, child_node);
- if (child_node) {
+ if (type != ACPI_TYPE_ANY) {
+ child_type = child_node->type;
+ }
- /* Found next child, get the type if we are not searching for ANY */
+ /*
+ * Ignore all temporary namespace nodes (created during control
+ * method execution) unless told otherwise. These temporary nodes
+ * can cause a race condition because they can be deleted during
+ * the execution of the user function (if the namespace is
+ * unlocked before invocation of the user function.) Only the
+ * debugger namespace dump will examine the temporary nodes.
+ */
+ if ((child_node->flags & ANOBJ_TEMPORARY) &&
+ !(flags & ACPI_NS_WALK_TEMP_NODES)) {
+ status = AE_CTRL_DEPTH;
+ }
- if (type != ACPI_TYPE_ANY) {
- child_type = child_node->type;
- }
+ /* Type must match requested type */
+ else if (child_type == type) {
/*
- * Ignore all temporary namespace nodes (created during control
- * method execution) unless told otherwise. These temporary nodes
- * can cause a race condition because they can be deleted during
- * the execution of the user function (if the namespace is
- * unlocked before invocation of the user function.) Only the
- * debugger namespace dump will examine the temporary nodes.
+ * Found a matching node, invoke the user callback function.
+ * Unlock the namespace if flag is set.
*/
- if ((child_node->flags & ANOBJ_TEMPORARY) &&
- !(flags & ACPI_NS_WALK_TEMP_NODES)) {
- status = AE_CTRL_DEPTH;
+ if (flags & ACPI_NS_WALK_UNLOCK) {
+ mutex_status =
+ acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
+ if (ACPI_FAILURE(mutex_status)) {
+ return_ACPI_STATUS(mutex_status);
+ }
}
- /* Type must match requested type */
-
- else if (child_type == type) {
- /*
- * Found a matching node, invoke the user callback function.
- * Unlock the namespace if flag is set.
- */
- if (flags & ACPI_NS_WALK_UNLOCK) {
- mutex_status =
- acpi_ut_release_mutex
- (ACPI_MTX_NAMESPACE);
- if (ACPI_FAILURE(mutex_status)) {
- return_ACPI_STATUS
- (mutex_status);
- }
+ /*
+ * Invoke the user function, either pre-order or post-order
+ * or both.
+ */
+ if (!node_previously_visited) {
+ if (pre_order_visit) {
+ status =
+ pre_order_visit(child_node, level,
+ context,
+ return_value);
}
+ } else {
+ if (post_order_visit) {
+ status =
+ post_order_visit(child_node, level,
+ context,
+ return_value);
+ }
+ }
- status =
- user_function(child_node, level, context,
- return_value);
-
- if (flags & ACPI_NS_WALK_UNLOCK) {
- mutex_status =
- acpi_ut_acquire_mutex
- (ACPI_MTX_NAMESPACE);
- if (ACPI_FAILURE(mutex_status)) {
- return_ACPI_STATUS
- (mutex_status);
- }
+ if (flags & ACPI_NS_WALK_UNLOCK) {
+ mutex_status =
+ acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
+ if (ACPI_FAILURE(mutex_status)) {
+ return_ACPI_STATUS(mutex_status);
}
+ }
- switch (status) {
- case AE_OK:
- case AE_CTRL_DEPTH:
+ switch (status) {
+ case AE_OK:
+ case AE_CTRL_DEPTH:
- /* Just keep going */
- break;
+ /* Just keep going */
+ break;
- case AE_CTRL_TERMINATE:
+ case AE_CTRL_TERMINATE:
- /* Exit now, with OK status */
+ /* Exit now, with OK status */
- return_ACPI_STATUS(AE_OK);
+ return_ACPI_STATUS(AE_OK);
- default:
+ default:
- /* All others are valid exceptions */
+ /* All others are valid exceptions */
- return_ACPI_STATUS(status);
- }
+ return_ACPI_STATUS(status);
+ }
+ }
+
+ /*
+ * Depth first search: Attempt to go down another level in the
+ * namespace if we are allowed to. Don't go any further if we have
+ * reached the caller specified maximum depth or if the user
+ * function has specified that the maximum depth has been reached.
+ */
+ if (!node_previously_visited &&
+ (level < max_depth) && (status != AE_CTRL_DEPTH)) {
+ if (child_node->child) {
+
+ /* There is at least one child of this node, visit it */
+
+ level++;
+ parent_node = child_node;
+ child_node =
+ acpi_ns_get_next_node(parent_node, NULL);
+ continue;
}
+ }
- /*
- * Depth first search: Attempt to go down another level in the
- * namespace if we are allowed to. Don't go any further if we have
- * reached the caller specified maximum depth or if the user
- * function has specified that the maximum depth has been reached.
- */
- if ((level < max_depth) && (status != AE_CTRL_DEPTH)) {
- if (child_node->child) {
+ /* No more children, re-visit this node */
- /* There is at least one child of this node, visit it */
+ if (!node_previously_visited) {
+ node_previously_visited = TRUE;
+ continue;
+ }
- level++;
- parent_node = child_node;
- child_node = NULL;
- }
- }
- } else {
+ /* No more children, visit peers */
+
+ child_node = acpi_ns_get_next_node(parent_node, child_node);
+ if (child_node) {
+ node_previously_visited = FALSE;
+ }
+
+ /* No peers, re-visit parent */
+
+ else {
/*
* No more children of this node (acpi_ns_get_next_node failed), go
* back upwards in the namespace tree to the node's parent.
@@ -324,6 +356,8 @@ acpi_ns_walk_namespace(acpi_object_type type,
level--;
child_node = parent_node;
parent_node = acpi_ns_get_parent_node(parent_node);
+
+ node_previously_visited = TRUE;
}
}
diff --git a/drivers/acpi/acpica/nsxfeval.c b/drivers/acpi/acpica/nsxfeval.c
index 4929dbdbc8f0..f2bd1da77001 100644
--- a/drivers/acpi/acpica/nsxfeval.c
+++ b/drivers/acpi/acpica/nsxfeval.c
@@ -433,8 +433,11 @@ static void acpi_ns_resolve_references(struct acpi_evaluate_info *info)
* PARAMETERS: Type - acpi_object_type to search for
* start_object - Handle in namespace where search begins
* max_depth - Depth to which search is to reach
- * user_function - Called when an object of "Type" is found
- * Context - Passed to user function
+ * pre_order_visit - Called during tree pre-order visit
+ * when an object of "Type" is found
+ * post_order_visit - Called during tree post-order visit
+ * when an object of "Type" is found
+ * Context - Passed to user function(s) above
* return_value - Location where return value of
* user_function is put if terminated early
*
@@ -443,16 +446,16 @@ static void acpi_ns_resolve_references(struct acpi_evaluate_info *info)
*
* DESCRIPTION: Performs a modified depth-first walk of the namespace tree,
* starting (and ending) at the object specified by start_handle.
- * The user_function is called whenever an object that matches
- * the type parameter is found. If the user function returns
+ * The callback function is called whenever an object that matches
+ * the type parameter is found. If the callback function returns
* a non-zero value, the search is terminated immediately and this
* value is returned to the caller.
*
* The point of this procedure is to provide a generic namespace
* walk routine that can be called from multiple places to
- * provide multiple services; the User Function can be tailored
- * to each task, whether it is a print function, a compare
- * function, etc.
+ * provide multiple services; the callback function(s) can be
+ * tailored to each task, whether it is a print function,
+ * a compare function, etc.
*
******************************************************************************/
@@ -460,7 +463,8 @@ acpi_status
acpi_walk_namespace(acpi_object_type type,
acpi_handle start_object,
u32 max_depth,
- acpi_walk_callback user_function,
+ acpi_walk_callback pre_order_visit,
+ acpi_walk_callback post_order_visit,
void *context, void **return_value)
{
acpi_status status;
@@ -469,7 +473,8 @@ acpi_walk_namespace(acpi_object_type type,
/* Parameter validation */
- if ((type > ACPI_TYPE_LOCAL_MAX) || (!max_depth) || (!user_function)) {
+ if ((type > ACPI_TYPE_LOCAL_MAX) ||
+ (!max_depth) || (!pre_order_visit && !post_order_visit)) {
return_ACPI_STATUS(AE_BAD_PARAMETER);
}
@@ -501,8 +506,9 @@ acpi_walk_namespace(acpi_object_type type,
}
status = acpi_ns_walk_namespace(type, start_object, max_depth,
- ACPI_NS_WALK_UNLOCK, user_function,
- context, return_value);
+ ACPI_NS_WALK_UNLOCK, pre_order_visit,
+ post_order_visit, context,
+ return_value);
(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
@@ -681,8 +687,8 @@ acpi_get_devices(const char *HID,
status = acpi_ns_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
ACPI_UINT32_MAX, ACPI_NS_WALK_UNLOCK,
- acpi_ns_get_device_callback, &info,
- return_value);
+ acpi_ns_get_device_callback, NULL,
+ &info, return_value);
(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
return_ACPI_STATUS(status);
diff --git a/drivers/acpi/acpica/psloop.c b/drivers/acpi/acpica/psloop.c
index cd7995b3aed4..0988e4a8901d 100644
--- a/drivers/acpi/acpica/psloop.c
+++ b/drivers/acpi/acpica/psloop.c
@@ -87,7 +87,8 @@ acpi_ps_complete_final_op(struct acpi_walk_state *walk_state,
union acpi_parse_object *op, acpi_status status);
static void
-acpi_ps_link_module_code(u8 *aml_start, u32 aml_length, acpi_owner_id owner_id);
+acpi_ps_link_module_code(union acpi_parse_object *parent_op,
+ u8 *aml_start, u32 aml_length, acpi_owner_id owner_id);
/*******************************************************************************
*
@@ -479,11 +480,14 @@ acpi_ps_get_arguments(struct acpi_walk_state *walk_state,
*/
if (walk_state->pass_number ==
ACPI_IMODE_LOAD_PASS1) {
- acpi_ps_link_module_code(aml_op_start,
- walk_state->
+ acpi_ps_link_module_code(op->common.
+ parent,
+ aml_op_start,
+ (u32)
+ (walk_state->
parser_state.
pkg_end -
- aml_op_start,
+ aml_op_start),
walk_state->
owner_id);
}
@@ -598,7 +602,8 @@ acpi_ps_get_arguments(struct acpi_walk_state *walk_state,
*
* FUNCTION: acpi_ps_link_module_code
*
- * PARAMETERS: aml_start - Pointer to the AML
+ * PARAMETERS: parent_op - Parent parser op
+ * aml_start - Pointer to the AML
* aml_length - Length of executable AML
* owner_id - owner_id of module level code
*
@@ -611,11 +616,13 @@ acpi_ps_get_arguments(struct acpi_walk_state *walk_state,
******************************************************************************/
static void
-acpi_ps_link_module_code(u8 *aml_start, u32 aml_length, acpi_owner_id owner_id)
+acpi_ps_link_module_code(union acpi_parse_object *parent_op,
+ u8 *aml_start, u32 aml_length, acpi_owner_id owner_id)
{
union acpi_operand_object *prev;
union acpi_operand_object *next;
union acpi_operand_object *method_obj;
+ struct acpi_namespace_node *parent_node;
/* Get the tail of the list */
@@ -639,11 +646,24 @@ acpi_ps_link_module_code(u8 *aml_start, u32 aml_length, acpi_owner_id owner_id)
return;
}
+ if (parent_op->common.node) {
+ parent_node = parent_op->common.node;
+ } else {
+ parent_node = acpi_gbl_root_node;
+ }
+
method_obj->method.aml_start = aml_start;
method_obj->method.aml_length = aml_length;
method_obj->method.owner_id = owner_id;
method_obj->method.flags |= AOPOBJ_MODULE_LEVEL;
+ /*
+ * Save the parent node in next_object. This is cheating, but we
+ * don't want to expand the method object.
+ */
+ method_obj->method.next_object =
+ ACPI_CAST_PTR(union acpi_operand_object, parent_node);
+
if (!prev) {
acpi_gbl_module_code_list = method_obj;
} else {
diff --git a/drivers/acpi/acpica/psparse.c b/drivers/acpi/acpica/psparse.c
index 70838e9b608c..4df8f139026c 100644
--- a/drivers/acpi/acpica/psparse.c
+++ b/drivers/acpi/acpica/psparse.c
@@ -610,17 +610,13 @@ acpi_status acpi_ps_parse_aml(struct acpi_walk_state *walk_state)
implicit_return_obj) {
previous_walk_state->
implicit_return_obj =
- acpi_ut_create_internal_object
- (ACPI_TYPE_INTEGER);
+ acpi_ut_create_integer_object
+ ((u64) 0);
if (!previous_walk_state->
implicit_return_obj) {
return_ACPI_STATUS
(AE_NO_MEMORY);
}
-
- previous_walk_state->
- implicit_return_obj->
- integer.value = 0;
}
/* Restart the calling control method */
diff --git a/drivers/acpi/acpica/psxface.c b/drivers/acpi/acpica/psxface.c
index dd9731c29a79..12934ad6da8e 100644
--- a/drivers/acpi/acpica/psxface.c
+++ b/drivers/acpi/acpica/psxface.c
@@ -306,14 +306,12 @@ acpi_status acpi_ps_execute_method(struct acpi_evaluate_info *info)
*/
if (acpi_gbl_enable_interpreter_slack) {
walk_state->implicit_return_obj =
- acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);
+ acpi_ut_create_integer_object((u64) 0);
if (!walk_state->implicit_return_obj) {
status = AE_NO_MEMORY;
acpi_ds_delete_walk_state(walk_state);
goto cleanup;
}
-
- walk_state->implicit_return_obj->integer.value = 0;
}
/* Parse the AML */
diff --git a/drivers/acpi/acpica/utmisc.c b/drivers/acpi/acpica/utmisc.c
index 61f6315fce9f..6c6a5137b728 100644
--- a/drivers/acpi/acpica/utmisc.c
+++ b/drivers/acpi/acpica/utmisc.c
@@ -1161,3 +1161,45 @@ acpi_ut_predefined_warning(const char *module_name,
ACPI_COMMON_MSG_SUFFIX;
va_end(args);
}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ut_predefined_info
+ *
+ * PARAMETERS: module_name - Caller's module name (for error output)
+ * line_number - Caller's line number (for error output)
+ * Pathname - Full pathname to the node
+ * node_flags - From Namespace node for the method/object
+ * Format - Printf format string + additional args
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Info messages for the predefined validation module. Messages
+ * are only emitted the first time a problem with a particular
+ * method/object is detected. This prevents a flood of
+ * messages for methods that are repeatedly evaluated.
+ *
+ ******************************************************************************/
+
+void ACPI_INTERNAL_VAR_XFACE
+acpi_ut_predefined_info(const char *module_name,
+ u32 line_number,
+ char *pathname, u8 node_flags, const char *format, ...)
+{
+ va_list args;
+
+ /*
+ * Warning messages for this method/object will be disabled after the
+ * first time a validation fails or an object is successfully repaired.
+ */
+ if (node_flags & ANOBJ_EVALUATED) {
+ return;
+ }
+
+ acpi_os_printf("ACPI Info for %s: ", pathname);
+
+ va_start(args, format);
+ acpi_os_vprintf(format, args);
+ ACPI_COMMON_MSG_SUFFIX;
+ va_end(args);
+}
diff --git a/drivers/acpi/acpica/utobject.c b/drivers/acpi/acpica/utobject.c
index 0207b625274a..42e658b543f1 100644
--- a/drivers/acpi/acpica/utobject.c
+++ b/drivers/acpi/acpica/utobject.c
@@ -190,6 +190,35 @@ union acpi_operand_object *acpi_ut_create_package_object(u32 count)
/*******************************************************************************
*
+ * FUNCTION: acpi_ut_create_integer_object
+ *
+ * PARAMETERS: initial_value - Initial value for the integer
+ *
+ * RETURN: Pointer to a new Integer object, null on failure
+ *
+ * DESCRIPTION: Create an initialized integer object
+ *
+ ******************************************************************************/
+
+union acpi_operand_object *acpi_ut_create_integer_object(u64 initial_value)
+{
+ union acpi_operand_object *integer_desc;
+
+ ACPI_FUNCTION_TRACE(ut_create_integer_object);
+
+ /* Create and initialize a new integer object */
+
+ integer_desc = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);
+ if (!integer_desc) {
+ return_PTR(NULL);
+ }
+
+ integer_desc->integer.value = initial_value;
+ return_PTR(integer_desc);
+}
+
+/*******************************************************************************
+ *
* FUNCTION: acpi_ut_create_buffer_object
*
* PARAMETERS: buffer_size - Size of buffer to be created