Merge git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb-2.6
[pandora-kernel.git] / drivers / acpi / dispatcher / dsfield.c
index a6d77ef..f988a5e 100644 (file)
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2006, R. Byron Moore
+ * Copyright (C) 2000 - 2008, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -89,12 +89,16 @@ acpi_ds_create_buffer_field(union acpi_parse_object *op,
 
        ACPI_FUNCTION_TRACE(ds_create_buffer_field);
 
-       /* Get the name_string argument */
-
+       /*
+        * Get the name_string argument (name of the new buffer_field)
+        */
        if (op->common.aml_opcode == AML_CREATE_FIELD_OP) {
+
+               /* For create_field, name is the 4th argument */
+
                arg = acpi_ps_get_arg(op, 3);
        } else {
-               /* Create Bit/Byte/Word/Dword field */
+               /* For all other create_xXXField operators, name is the 3rd argument */
 
                arg = acpi_ps_get_arg(op, 2);
        }
@@ -107,41 +111,46 @@ acpi_ds_create_buffer_field(union acpi_parse_object *op,
                node = walk_state->deferred_node;
                status = AE_OK;
        } else {
-               /*
-                * During the load phase, we want to enter the name of the field into
-                * the namespace.  During the execute phase (when we evaluate the size
-                * operand), we want to lookup the name
-                */
-               if (walk_state->parse_flags & ACPI_PARSE_EXECUTE) {
-                       flags = ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE;
-               } else {
-                       flags = ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE |
-                           ACPI_NS_ERROR_IF_FOUND;
+               /* Execute flag should always be set when this function is entered */
+
+               if (!(walk_state->parse_flags & ACPI_PARSE_EXECUTE)) {
+                       return_ACPI_STATUS(AE_AML_INTERNAL);
                }
 
-               /*
-                * Enter the name_string into the namespace
-                */
+               /* Creating new namespace node, should not already exist */
+
+               flags = ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE |
+                   ACPI_NS_ERROR_IF_FOUND;
+
+               /* Mark node temporary if we are executing a method */
+
+               if (walk_state->method_node) {
+                       flags |= ACPI_NS_TEMPORARY;
+               }
+
+               /* Enter the name_string into the namespace */
+
                status =
                    acpi_ns_lookup(walk_state->scope_info,
                                   arg->common.value.string, ACPI_TYPE_ANY,
                                   ACPI_IMODE_LOAD_PASS1, flags, walk_state,
-                                  &(node));
+                                  &node);
                if (ACPI_FAILURE(status)) {
                        ACPI_ERROR_NAMESPACE(arg->common.value.string, status);
                        return_ACPI_STATUS(status);
                }
        }
 
-       /* We could put the returned object (Node) on the object stack for later,
+       /*
+        * We could put the returned object (Node) on the object stack for later,
         * but for now, we will put it in the "op" object that the parser uses,
-        * so we can get it again at the end of this scope
+        * so we can get it again at the end of this scope.
         */
        op->common.node = node;
 
        /*
         * If there is no object attached to the node, this node was just created
-        * and we need to create the field object.  Otherwise, this was a lookup
+        * and we need to create the field object. Otherwise, this was a lookup
         * of an existing node and we don't want to create the field object again.
         */
        obj_desc = acpi_ns_get_attached_object(node);
@@ -163,9 +172,8 @@ acpi_ds_create_buffer_field(union acpi_parse_object *op,
        }
 
        /*
-        * Remember location in AML stream of the field unit
-        * opcode and operands -- since the buffer and index
-        * operands must be evaluated.
+        * Remember location in AML stream of the field unit opcode and operands --
+        * since the buffer and index operands must be evaluated.
         */
        second_desc = obj_desc->common.next_object;
        second_desc->extra.aml_start = op->named.data;
@@ -260,7 +268,7 @@ acpi_ds_get_field_names(struct acpi_create_field_info *info,
 
                case AML_INT_NAMEDFIELD_OP:
 
-                       /* Lookup the name */
+                       /* Lookup the name, it should already exist */
 
                        status = acpi_ns_lookup(walk_state->scope_info,
                                                (char *)&arg->named.name,
@@ -271,20 +279,23 @@ acpi_ds_get_field_names(struct acpi_create_field_info *info,
                        if (ACPI_FAILURE(status)) {
                                ACPI_ERROR_NAMESPACE((char *)&arg->named.name,
                                                     status);
-                               if (status != AE_ALREADY_EXISTS) {
-                                       return_ACPI_STATUS(status);
-                               }
-
-                               /* Already exists, ignore error */
+                               return_ACPI_STATUS(status);
                        } else {
                                arg->common.node = info->field_node;
                                info->field_bit_length = arg->common.value.size;
 
-                               /* Create and initialize an object for the new Field Node */
-
-                               status = acpi_ex_prep_field_value(info);
-                               if (ACPI_FAILURE(status)) {
-                                       return_ACPI_STATUS(status);
+                               /*
+                                * If there is no object attached to the node, this node was
+                                * just created and we need to create the field object.
+                                * Otherwise, this was a lookup of an existing node and we
+                                * don't want to create the field object again.
+                                */
+                               if (!acpi_ns_get_attached_object
+                                   (info->field_node)) {
+                                       status = acpi_ex_prep_field_value(info);
+                                       if (ACPI_FAILURE(status)) {
+                                               return_ACPI_STATUS(status);
+                                       }
                                }
                        }
 
@@ -398,9 +409,27 @@ acpi_ds_init_field_objects(union acpi_parse_object *op,
        union acpi_parse_object *arg = NULL;
        struct acpi_namespace_node *node;
        u8 type = 0;
+       u32 flags;
 
        ACPI_FUNCTION_TRACE_PTR(ds_init_field_objects, op);
 
+       /* Execute flag should always be set when this function is entered */
+
+       if (!(walk_state->parse_flags & ACPI_PARSE_EXECUTE)) {
+               if (walk_state->parse_flags & ACPI_PARSE_DEFERRED_OP) {
+
+                       /* bank_field Op is deferred, just return OK */
+
+                       return_ACPI_STATUS(AE_OK);
+               }
+
+               return_ACPI_STATUS(AE_AML_INTERNAL);
+       }
+
+       /*
+        * Get the field_list argument for this opcode. This is the start of the
+        * list of field elements.
+        */
        switch (walk_state->opcode) {
        case AML_FIELD_OP:
                arg = acpi_ps_get_arg(op, 2);
@@ -421,20 +450,30 @@ acpi_ds_init_field_objects(union acpi_parse_object *op,
                return_ACPI_STATUS(AE_BAD_PARAMETER);
        }
 
+       /* Creating new namespace node(s), should not already exist */
+
+       flags = ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE |
+           ACPI_NS_ERROR_IF_FOUND;
+
+       /* Mark node(s) temporary if we are executing a method */
+
+       if (walk_state->method_node) {
+               flags |= ACPI_NS_TEMPORARY;
+       }
+
        /*
         * Walk the list of entries in the field_list
+        * Note: field_list can be of zero length. In this case, Arg will be NULL.
         */
        while (arg) {
-
-               /* Ignore OFFSET and ACCESSAS terms here */
-
+               /*
+                * Ignore OFFSET and ACCESSAS terms here; we are only interested in the
+                * field names in order to enter them into the namespace.
+                */
                if (arg->common.aml_opcode == AML_INT_NAMEDFIELD_OP) {
                        status = acpi_ns_lookup(walk_state->scope_info,
-                                               (char *)&arg->named.name,
-                                               type, ACPI_IMODE_LOAD_PASS1,
-                                               ACPI_NS_NO_UPSEARCH |
-                                               ACPI_NS_DONT_OPEN_SCOPE |
-                                               ACPI_NS_ERROR_IF_FOUND,
+                                               (char *)&arg->named.name, type,
+                                               ACPI_IMODE_LOAD_PASS1, flags,
                                                walk_state, &node);
                        if (ACPI_FAILURE(status)) {
                                ACPI_ERROR_NAMESPACE((char *)&arg->named.name,
@@ -451,7 +490,7 @@ acpi_ds_init_field_objects(union acpi_parse_object *op,
                        arg->common.node = node;
                }
 
-               /* Move to next field in the list */
+               /* Get the next field element in the list */
 
                arg = arg->common.next;
        }
@@ -465,7 +504,7 @@ acpi_ds_init_field_objects(union acpi_parse_object *op,
  *
  * PARAMETERS:  Op              - Op containing the Field definition and args
  *              region_node     - Object for the containing Operation Region
- *  `           walk_state      - Current method state
+ *              walk_state      - Current method state
  *
  * RETURN:      Status
  *
@@ -512,10 +551,12 @@ acpi_ds_create_bank_field(union acpi_parse_object *op,
                return_ACPI_STATUS(status);
        }
 
-       /* Third arg is the bank_value */
-
+       /*
+        * Third arg is the bank_value
+        * This arg is a term_arg, not a constant
+        * It will be evaluated later, by acpi_ds_eval_bank_field_operands
+        */
        arg = arg->common.next;
-       info.bank_value = (u32) arg->common.value.integer;
 
        /* Fourth arg is the field flags */
 
@@ -527,8 +568,17 @@ acpi_ds_create_bank_field(union acpi_parse_object *op,
        info.field_type = ACPI_TYPE_LOCAL_BANK_FIELD;
        info.region_node = region_node;
 
-       status = acpi_ds_get_field_names(&info, walk_state, arg->common.next);
+       /*
+        * Use Info.data_register_node to store bank_field Op
+        * It's safe because data_register_node will never be used when create bank field
+        * We store aml_start and aml_length in the bank_field Op for late evaluation
+        * Used in acpi_ex_prep_field_value(Info)
+        *
+        * TBD: Or, should we add a field in struct acpi_create_field_info, like "void *ParentOp"?
+        */
+       info.data_register_node = (struct acpi_namespace_node *)op;
 
+       status = acpi_ds_get_field_names(&info, walk_state, arg->common.next);
        return_ACPI_STATUS(status);
 }