Merge branch 'acpica' of git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux...
authorLinus Torvalds <torvalds@linux-foundation.org>
Thu, 10 Dec 2009 03:57:06 +0000 (19:57 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Thu, 10 Dec 2009 03:57:06 +0000 (19:57 -0800)
* '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

49 files changed:
arch/ia64/sn/kernel/io_acpi_init.c
arch/x86/kernel/cpu/cpufreq/longhaul.c
drivers/acpi/acpi_memhotplug.c
drivers/acpi/acpica/Makefile
drivers/acpi/acpica/acmacros.h
drivers/acpi/acpica/acnamesp.h
drivers/acpi/acpica/acutils.h
drivers/acpi/acpica/dsinit.c
drivers/acpi/acpica/dsmthdat.c
drivers/acpi/acpica/dsobject.c
drivers/acpi/acpica/dswload.c
drivers/acpi/acpica/evgpeblk.c
drivers/acpi/acpica/evregion.c
drivers/acpi/acpica/exconfig.c
drivers/acpi/acpica/exconvrt.c
drivers/acpi/acpica/exfield.c
drivers/acpi/acpica/exoparg1.c
drivers/acpi/acpica/exoparg6.c
drivers/acpi/acpica/nsdump.c
drivers/acpi/acpica/nsdumpdv.c
drivers/acpi/acpica/nseval.c
drivers/acpi/acpica/nsinit.c
drivers/acpi/acpica/nspredef.c
drivers/acpi/acpica/nsrepair.c
drivers/acpi/acpica/nsrepair2.c [new file with mode: 0644]
drivers/acpi/acpica/nswalk.c
drivers/acpi/acpica/nsxfeval.c
drivers/acpi/acpica/psloop.c
drivers/acpi/acpica/psparse.c
drivers/acpi/acpica/psxface.c
drivers/acpi/acpica/utmisc.c
drivers/acpi/acpica/utobject.c
drivers/acpi/container.c
drivers/acpi/dock.c
drivers/acpi/ec.c
drivers/acpi/glue.c
drivers/acpi/pci_slot.c
drivers/acpi/processor_core.c
drivers/acpi/scan.c
drivers/acpi/video_detect.c
drivers/gpu/drm/i915/intel_lvds.c
drivers/i2c/busses/i2c-scmi.c
drivers/pci/hotplug/acpi_pcihp.c
drivers/pci/hotplug/acpiphp_glue.c
drivers/pci/hotplug/acpiphp_ibm.c
drivers/platform/x86/intel_menlow.c
drivers/platform/x86/sony-laptop.c
drivers/platform/x86/thinkpad_acpi.c
include/acpi/acpixf.h

index fd50ff9..66f633b 100644 (file)
@@ -390,7 +390,7 @@ sn_acpi_get_pcidev_info(struct pci_dev *dev, struct pcidev_info **pcidev_info,
        pcidev_match.handle = NULL;
 
        acpi_walk_namespace(ACPI_TYPE_DEVICE, rootbus_handle, ACPI_UINT32_MAX,
-                           find_matching_device, &pcidev_match, NULL);
+                           find_matching_device, NULL, &pcidev_match, NULL);
 
        if (!pcidev_match.handle) {
                printk(KERN_ERR
index cabd2fa..7e7eea4 100644 (file)
@@ -885,7 +885,7 @@ static int __init longhaul_cpu_init(struct cpufreq_policy *policy)
 
        /* Find ACPI data for processor */
        acpi_walk_namespace(ACPI_TYPE_PROCESSOR, ACPI_ROOT_OBJECT,
-                               ACPI_UINT32_MAX, &longhaul_walk_callback,
+                               ACPI_UINT32_MAX, &longhaul_walk_callback, NULL,
                                NULL, (void *)&pr);
 
        /* Check ACPI support for C3 state */
index 28ccdbc..3597d73 100644 (file)
@@ -537,7 +537,7 @@ static int __init acpi_memory_device_init(void)
 
        status = acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
                                     ACPI_UINT32_MAX,
-                                    acpi_memory_register_notify_handler,
+                                    acpi_memory_register_notify_handler, NULL,
                                     NULL, NULL);
 
        if (ACPI_FAILURE(status)) {
@@ -561,7 +561,7 @@ static void __exit acpi_memory_device_exit(void)
         */
        status = acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
                                     ACPI_UINT32_MAX,
-                                    acpi_memory_deregister_notify_handler,
+                                    acpi_memory_deregister_notify_handler, NULL,
                                     NULL, NULL);
 
        if (ACPI_FAILURE(status))
index e7973bc..7423052 100644 (file)
@@ -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
 
index 3acd9c6..7d9ba6e 100644 (file)
 #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
 
 #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 */
 
 /*
index 09a2764..ab83919 100644 (file)
@@ -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
index 863a264..3a451a2 100644 (file)
@@ -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
index 3aae13f..f23fa0b 100644 (file)
@@ -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"));
        }
index 7d077bb..0ba19f8 100644 (file)
@@ -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;
                }
 
index 507e1f0..9bc1ba0 100644 (file)
@@ -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.
index 6de3a99..10fc785 100644 (file)
@@ -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);
+                       }
                }
 
                /*
index a60aaa7..2479209 100644 (file)
@@ -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);
        }
 
        /*
index 98c7f9c..0bc807c 100644 (file)
 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);
 }
index 24afef8..46adfa5 100644 (file)
@@ -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);
        }
 
index 37d0d39..51d5f22 100644 (file)
@@ -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);
index 0b33d6c..1588a2d 100644 (file)
@@ -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;
        }
 
index 9635d21..752fe48 100644 (file)
@@ -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:
index ae43f76..295542e 100644 (file)
@@ -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,
index 2bad613..2deb986 100644 (file)
@@ -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 */
 
index 0fe87f1..36be7f0 100644 (file)
@@ -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
index 846d113..f771e97 100644 (file)
@@ -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;
 }
index 1d5b360..4f8abac 100644 (file)
@@ -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)) {
index f8427af..b05f429 100644 (file)
@@ -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;
 
index db2b2a9..d563f1a 100644 (file)
@@ -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 (file)
index 0000000..d07b686
--- /dev/null
@@ -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);
+}
index 35539df..d7e6b52 100644 (file)
@@ -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;
                }
        }
 
index 4929dbd..f2bd1da 100644 (file)
@@ -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);
index cd7995b..0988e4a 100644 (file)
@@ -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 {
index 70838e9..4df8f13 100644 (file)
@@ -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 */
index dd9731c..12934ad 100644 (file)
@@ -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 */
index 61f6315..6c6a513 100644 (file)
@@ -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);
+}
index 0207b62..42e658b 100644 (file)
@@ -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
index 642bb30..5faf6c2 100644 (file)
@@ -258,7 +258,7 @@ static int __init acpi_container_init(void)
        acpi_walk_namespace(ACPI_TYPE_DEVICE,
                            ACPI_ROOT_OBJECT,
                            ACPI_UINT32_MAX,
-                           container_walk_namespace_cb, &action, NULL);
+                           container_walk_namespace_cb, NULL, &action, NULL);
 
        return (0);
 }
@@ -271,7 +271,7 @@ static void __exit acpi_container_exit(void)
        acpi_walk_namespace(ACPI_TYPE_DEVICE,
                            ACPI_ROOT_OBJECT,
                            ACPI_UINT32_MAX,
-                           container_walk_namespace_cb, &action, NULL);
+                           container_walk_namespace_cb, NULL, &action, NULL);
 
        acpi_bus_unregister_driver(&acpi_container_driver);
 
index 7338b6a..30be3c1 100644 (file)
@@ -1030,8 +1030,8 @@ static int dock_add(acpi_handle handle)
 
        /* Find dependent devices */
        acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
-                           ACPI_UINT32_MAX, find_dock_devices, dock_station,
-                           NULL);
+                           ACPI_UINT32_MAX, find_dock_devices, NULL,
+                           dock_station, NULL);
 
        /* add the dock station as a device dependent on itself */
        dd = alloc_dock_dependent_device(handle);
@@ -1127,11 +1127,11 @@ static int __init dock_init(void)
 
        /* look for a dock station */
        acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
-                           ACPI_UINT32_MAX, find_dock, NULL, NULL);
+                           ACPI_UINT32_MAX, find_dock, NULL, NULL, NULL);
 
        /* look for bay */
        acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
-                       ACPI_UINT32_MAX, find_bay, NULL, NULL);
+                       ACPI_UINT32_MAX, find_bay, NULL, NULL, NULL);
        if (!dock_station_count) {
                printk(KERN_INFO PREFIX "No dock devices found.\n");
                return 0;
index baef28c..75b147f 100644 (file)
@@ -820,7 +820,7 @@ static int acpi_ec_add(struct acpi_device *device)
 
        /* Find and register all query methods */
        acpi_walk_namespace(ACPI_TYPE_METHOD, ec->handle, 1,
-                           acpi_ec_register_query_methods, ec, NULL);
+                           acpi_ec_register_query_methods, NULL, ec, NULL);
 
        if (!first_ec)
                first_ec = ec;
index c6645f2..4c8fcff 100644 (file)
@@ -113,7 +113,7 @@ acpi_handle acpi_get_child(acpi_handle parent, acpi_integer address)
        if (!parent)
                return NULL;
        acpi_walk_namespace(ACPI_TYPE_DEVICE, parent,
-                           1, do_acpi_find_child, &find, NULL);
+                           1, do_acpi_find_child, NULL, &find, NULL);
        return find.handle;
 }
 
index 45da2ba..11f2197 100644 (file)
@@ -219,12 +219,12 @@ walk_p2p_bridge(acpi_handle handle, u32 lvl, void *context, void **rv)
 
        dbg("p2p bridge walk, pci_bus = %x\n", dev->subordinate->number);
        status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, (u32)1,
-                                    user_function, &child_context, NULL);
+                                    user_function, NULL, &child_context, NULL);
        if (ACPI_FAILURE(status))
                goto out;
 
        status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, (u32)1,
-                                    walk_p2p_bridge, &child_context, NULL);
+                                    walk_p2p_bridge, NULL, &child_context, NULL);
 out:
        pci_dev_put(dev);
        return AE_OK;
@@ -277,12 +277,12 @@ walk_root_bridge(acpi_handle handle, acpi_walk_callback user_function)
 
        dbg("root bridge walk, pci_bus = %x\n", pci_bus->number);
        status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, (u32)1,
-                                    user_function, &context, NULL);
+                                    user_function, NULL, &context, NULL);
        if (ACPI_FAILURE(status))
                return status;
 
        status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, (u32)1,
-                                    walk_p2p_bridge, &context, NULL);
+                                    walk_p2p_bridge, NULL, &context, NULL);
        if (ACPI_FAILURE(status))
                err("%s: walk_p2p_bridge failure - %d\n", __func__, status);
 
index ec742a4..cb4283f 100644 (file)
@@ -1102,7 +1102,7 @@ void acpi_processor_install_hotplug_notify(void)
        acpi_walk_namespace(ACPI_TYPE_PROCESSOR,
                            ACPI_ROOT_OBJECT,
                            ACPI_UINT32_MAX,
-                           processor_walk_namespace_cb, &action, NULL);
+                           processor_walk_namespace_cb, NULL, &action, NULL);
 #endif
        register_hotcpu_notifier(&acpi_cpu_notifier);
 }
@@ -1115,7 +1115,7 @@ void acpi_processor_uninstall_hotplug_notify(void)
        acpi_walk_namespace(ACPI_TYPE_PROCESSOR,
                            ACPI_ROOT_OBJECT,
                            ACPI_UINT32_MAX,
-                           processor_walk_namespace_cb, &action, NULL);
+                           processor_walk_namespace_cb, NULL, &action, NULL);
 #endif
        unregister_hotcpu_notifier(&acpi_cpu_notifier);
 }
index 14a7481..ff9f622 100644 (file)
@@ -1332,7 +1332,7 @@ static int acpi_bus_scan(acpi_handle handle, struct acpi_bus_ops *ops,
        status = acpi_bus_check_add(handle, 0, ops, &device);
        if (ACPI_SUCCESS(status))
                acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX,
-                                   acpi_bus_check_add, ops, &device);
+                                   acpi_bus_check_add, NULL, ops, &device);
 
        if (child)
                *child = device;
index 27c7772..fc2f26b 100644 (file)
@@ -101,7 +101,7 @@ long acpi_is_video_device(struct acpi_device *device)
        /* Only check for backlight functionality if one of the above hit. */
        if (video_caps)
                acpi_walk_namespace(ACPI_TYPE_DEVICE, device->handle,
-                                   ACPI_UINT32_MAX, acpi_backlight_cap_match,
+                                   ACPI_UINT32_MAX, acpi_backlight_cap_match, NULL,
                                    &video_caps, NULL);
 
        return video_caps;
@@ -151,7 +151,7 @@ long acpi_video_get_capabilities(acpi_handle graphics_handle)
        if (!graphics_handle) {
                /* Only do the global walk through all graphics devices once */
                acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
-                                   ACPI_UINT32_MAX, find_video,
+                                   ACPI_UINT32_MAX, find_video, NULL,
                                    &caps, NULL);
                /* There might be boot param flags set already... */
                acpi_video_support |= caps;
@@ -173,7 +173,7 @@ long acpi_video_get_capabilities(acpi_handle graphics_handle)
                        return 0;
                }
                acpi_walk_namespace(ACPI_TYPE_DEVICE, graphics_handle,
-                                   ACPI_UINT32_MAX, find_video,
+                                   ACPI_UINT32_MAX, find_video, NULL,
                                    &caps, NULL);
        }
        ACPI_DEBUG_PRINT((ACPI_DB_INFO, "We have 0x%lX video support %s %s\n",
index 05598ae..eb36502 100644 (file)
@@ -899,7 +899,7 @@ static int intel_lid_present(void)
 
        acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
                                ACPI_UINT32_MAX,
-                               check_lid_device, &lid_present, NULL);
+                               check_lid_device, NULL, &lid_present, NULL);
 
        return lid_present;
 }
index b4a55d4..365e0be 100644 (file)
@@ -363,7 +363,7 @@ static int acpi_smbus_cmi_add(struct acpi_device *device)
        smbus_cmi->cap_write = 0;
 
        acpi_walk_namespace(ACPI_TYPE_METHOD, smbus_cmi->handle, 1,
-                           acpi_smbus_cmi_query_methods, smbus_cmi, NULL);
+                           acpi_smbus_cmi_query_methods, NULL, smbus_cmi, NULL);
 
        if (smbus_cmi->cap_info == 0)
                goto err;
index a73028e..0f32571 100644 (file)
@@ -471,7 +471,7 @@ int acpi_pci_detect_ejectable(acpi_handle handle)
                return found;
 
        acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, 1,
-                           check_hotplug, (void *)&found, NULL);
+                           check_hotplug, NULL, (void *)&found, NULL);
        return found;
 }
 EXPORT_SYMBOL_GPL(acpi_pci_detect_ejectable);
index 58d25a1..df1b0ea 100644 (file)
@@ -266,7 +266,7 @@ static int detect_ejectable_slots(acpi_handle handle)
        int found = acpi_pci_detect_ejectable(handle);
        if (!found) {
                acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, (u32)1,
-                                   is_pci_dock_device, (void *)&found, NULL);
+                                   is_pci_dock_device, NULL, (void *)&found, NULL);
        }
        return found;
 }
@@ -281,7 +281,7 @@ static void init_bridge_misc(struct acpiphp_bridge *bridge)
 
        /* register all slot objects under this bridge */
        status = acpi_walk_namespace(ACPI_TYPE_DEVICE, bridge->handle, (u32)1,
-                                    register_slot, bridge, NULL);
+                                    register_slot, NULL, bridge, NULL);
        if (ACPI_FAILURE(status)) {
                list_del(&bridge->list);
                return;
@@ -447,7 +447,7 @@ find_p2p_bridge(acpi_handle handle, u32 lvl, void *context, void **rv)
 
        /* search P2P bridges under this p2p bridge */
        status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, (u32)1,
-                                    find_p2p_bridge, NULL, NULL);
+                                    find_p2p_bridge, NULL, NULL, NULL);
        if (ACPI_FAILURE(status))
                warn("find_p2p_bridge failed (error code = 0x%x)\n", status);
 
@@ -485,7 +485,7 @@ static int add_bridge(acpi_handle handle)
 
        /* search P2P bridges under this host bridge */
        status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, (u32)1,
-                                    find_p2p_bridge, NULL, NULL);
+                                    find_p2p_bridge, NULL, NULL, NULL);
 
        if (ACPI_FAILURE(status))
                warn("find_p2p_bridge failed (error code = 0x%x)\n", status);
@@ -573,7 +573,7 @@ cleanup_p2p_bridge(acpi_handle handle, u32 lvl, void *context, void **rv)
        /* cleanup p2p bridges under this P2P bridge
           in a depth-first manner */
        acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, (u32)1,
-                               cleanup_p2p_bridge, NULL, NULL);
+                               cleanup_p2p_bridge, NULL, NULL, NULL);
 
        bridge = acpiphp_handle_to_bridge(handle);
        if (bridge)
@@ -589,7 +589,7 @@ static void remove_bridge(acpi_handle handle)
        /* cleanup p2p bridges under this host bridge
           in a depth-first manner */
        acpi_walk_namespace(ACPI_TYPE_DEVICE, handle,
-                               (u32)1, cleanup_p2p_bridge, NULL, NULL);
+                               (u32)1, cleanup_p2p_bridge, NULL, NULL, NULL);
 
        /*
         * On root bridges with hotplug slots directly underneath (ie,
@@ -778,7 +778,7 @@ static int acpiphp_configure_ioapics(acpi_handle handle)
 {
        ioapic_add(handle, 0, NULL, NULL);
        acpi_walk_namespace(ACPI_TYPE_DEVICE, handle,
-                           ACPI_UINT32_MAX, ioapic_add, NULL, NULL);
+                           ACPI_UINT32_MAX, ioapic_add, NULL, NULL, NULL);
        return 0;
 }
 
@@ -786,7 +786,7 @@ static int acpiphp_unconfigure_ioapics(acpi_handle handle)
 {
        ioapic_remove(handle, 0, NULL, NULL);
        acpi_walk_namespace(ACPI_TYPE_DEVICE, handle,
-                           ACPI_UINT32_MAX, ioapic_remove, NULL, NULL);
+                           ACPI_UINT32_MAX, ioapic_remove, NULL, NULL, NULL);
        return 0;
 }
 
@@ -1367,7 +1367,7 @@ static void handle_hotplug_event_bridge(acpi_handle handle, u32 type, void *cont
        bridge = acpiphp_handle_to_bridge(handle);
        if (type == ACPI_NOTIFY_BUS_CHECK) {
                acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, ACPI_UINT32_MAX,
-                       count_sub_bridges, &num_sub_bridges, NULL);
+                       count_sub_bridges, NULL, &num_sub_bridges, NULL);
        }
 
        if (!bridge && !num_sub_bridges) {
@@ -1388,7 +1388,7 @@ static void handle_hotplug_event_bridge(acpi_handle handle, u32 type, void *cont
                }
                if (num_sub_bridges)
                        acpi_walk_namespace(ACPI_TYPE_DEVICE, handle,
-                               ACPI_UINT32_MAX, check_sub_bridges, NULL, NULL);
+                               ACPI_UINT32_MAX, check_sub_bridges, NULL, NULL, NULL);
                break;
 
        case ACPI_NOTIFY_DEVICE_CHECK:
@@ -1512,7 +1512,7 @@ int __init acpiphp_glue_init(void)
        int num = 0;
 
        acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
-                       ACPI_UINT32_MAX, find_root_bridges, &num, NULL);
+                       ACPI_UINT32_MAX, find_root_bridges, NULL, &num, NULL);
 
        if (num <= 0)
                return -1;
index e7be66d..aa5df48 100644 (file)
@@ -434,7 +434,7 @@ static int __init ibm_acpiphp_init(void)
        dbg("%s\n", __func__);
 
        if (acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
-                       ACPI_UINT32_MAX, ibm_find_acpi_device,
+                       ACPI_UINT32_MAX, ibm_find_acpi_device, NULL,
                        &ibm_acpi_handle, NULL) != FOUND_APCI) {
                err("%s: acpi_walk_namespace failed\n", __func__);
                retval = -ENODEV;
index 29432a5..f0a90a6 100644 (file)
@@ -510,7 +510,7 @@ static int __init intel_menlow_module_init(void)
        /* Looking for sensors in each ACPI thermal zone */
        status = acpi_walk_namespace(ACPI_TYPE_THERMAL, ACPI_ROOT_OBJECT,
                                     ACPI_UINT32_MAX,
-                                    intel_menlow_register_sensor, NULL, NULL);
+                                    intel_menlow_register_sensor, NULL, NULL, NULL);
        if (ACPI_FAILURE(status))
                return -ENODEV;
 
index a2a742c..7a2cc8a 100644 (file)
@@ -1203,7 +1203,7 @@ static int sony_nc_add(struct acpi_device *device)
 
        if (debug) {
                status = acpi_walk_namespace(ACPI_TYPE_METHOD, sony_nc_acpi_handle,
-                                            1, sony_walk_callback, NULL, NULL);
+                                            1, sony_walk_callback, NULL, NULL, NULL);
                if (ACPI_FAILURE(status)) {
                        printk(KERN_WARNING DRV_PFX "unable to walk acpi resources\n");
                        result = -ENODEV;
index edb1690..0ed8480 100644 (file)
@@ -1087,7 +1087,7 @@ static int __init tpacpi_check_std_acpi_brightness_support(void)
         */
 
        status = acpi_walk_namespace(ACPI_TYPE_METHOD, vid_handle, 3,
-                                    tpacpi_acpi_walk_find_bcl, NULL,
+                                    tpacpi_acpi_walk_find_bcl, NULL, NULL,
                                     &bcl_ptr);
 
        if (ACPI_SUCCESS(status) && bcl_levels > 2) {
index e723b0f..5e1ad3c 100644 (file)
@@ -47,7 +47,7 @@
 
 /* Current ACPICA subsystem version in YYYYMMDD format */
 
-#define ACPI_CA_VERSION                 0x20090903
+#define ACPI_CA_VERSION                 0x20091112
 
 #include "actypes.h"
 #include "actbl.h"
@@ -154,7 +154,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