From ef805d956320ffa36d068673d5c5eb2a7d13209b Mon Sep 17 00:00:00 2001 From: Lin Ming Date: Thu, 10 Apr 2008 19:06:41 +0400 Subject: ACPICA: Implemented full argument resolution support for the BankValue argument to BankField Previously, only constants were supported, now any TermArg may be used. http://www.acpica.org/bugzilla/show_bug.cgi?id=387 http://www.acpica.org/bugzilla/show_bug.cgi?id=393 Signed-off-by: Lin Ming Signed-off-by: Bob Moore Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown --- drivers/acpi/dispatcher/dsfield.c | 80 ++++++++++++++++++++------------------- 1 file changed, 41 insertions(+), 39 deletions(-) (limited to 'drivers/acpi/dispatcher/dsfield.c') diff --git a/drivers/acpi/dispatcher/dsfield.c b/drivers/acpi/dispatcher/dsfield.c index f049639bac35..e87f6bfbfa5c 100644 --- a/drivers/acpi/dispatcher/dsfield.c +++ b/drivers/acpi/dispatcher/dsfield.c @@ -281,11 +281,17 @@ acpi_ds_get_field_names(struct acpi_create_field_info *info, 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); + } } } @@ -399,9 +405,22 @@ 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); + /* + * During the load phase, we want to enter the name of the field into + * the namespace. During the execute phase (when we evaluate the bank_value + * operand), we want to lookup the name. + */ + if (walk_state->deferred_node) { + 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; + } + switch (walk_state->opcode) { case AML_FIELD_OP: arg = acpi_ps_get_arg(op, 2); @@ -433,10 +452,7 @@ acpi_ds_init_field_objects(union acpi_parse_object *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, - walk_state, &node); + flags, walk_state, &node); if (ACPI_FAILURE(status)) { ACPI_ERROR_NAMESPACE((char *)&arg->named.name, status); @@ -466,7 +482,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 * @@ -513,36 +529,13 @@ acpi_ds_create_bank_field(union acpi_parse_object *op, return_ACPI_STATUS(status); } - /* Third arg is the bank_value */ - - /* TBD: This arg is a term_arg, not a constant, and must be evaluated */ - + /* + * 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; - /* Currently, only the following constants are supported */ - - switch (arg->common.aml_opcode) { - case AML_ZERO_OP: - info.bank_value = 0; - break; - - case AML_ONE_OP: - info.bank_value = 1; - break; - - case AML_BYTE_OP: - case AML_WORD_OP: - case AML_DWORD_OP: - case AML_QWORD_OP: - info.bank_value = (u32) arg->common.value.integer; - break; - - default: - info.bank_value = 0; - ACPI_ERROR((AE_INFO, - "Non-constant BankValue for BankField is not implemented")); - } - /* Fourth arg is the field flags */ arg = arg->common.next; @@ -553,8 +546,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); } -- cgit v1.2.3 From cca97b81564c5edbc8700ebb64fc2b4e13dfa51f Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Thu, 10 Apr 2008 19:06:44 +0400 Subject: ACPICA: Fix for some local named nodes not marked temporary and to disallow duplicates Fixed a problem with the CreateField, CreateXXXField (Bit, Byte, Word, Dword, Qword), Field, BankField, and IndexField operators when invoked from inside an executing control method. In this case, these operators created namespace nodes that were incorrectly left marked as permanent nodes instead of temporary nodes. This could cause a problem if there is race condition between an exiting control method and a running namespace walk. (Reported by Linn Crosetto). Fixed a problem where the CreateField and CreateXXXField operators would incorrectly allow duplicate names (the name of the field) with no exception generated. Signed-off-by: Bob Moore Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown --- drivers/acpi/dispatcher/dsfield.c | 121 +++++++++++++++++++++++--------------- 1 file changed, 73 insertions(+), 48 deletions(-) (limited to 'drivers/acpi/dispatcher/dsfield.c') diff --git a/drivers/acpi/dispatcher/dsfield.c b/drivers/acpi/dispatcher/dsfield.c index e87f6bfbfa5c..0befcff19f5a 100644 --- a/drivers/acpi/dispatcher/dsfield.c +++ b/drivers/acpi/dispatcher/dsfield.c @@ -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,26 +111,30 @@ 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); @@ -136,13 +144,13 @@ acpi_ds_create_buffer_field(union acpi_parse_object *op, /* * 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); @@ -164,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; @@ -261,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, @@ -272,19 +279,16 @@ 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; /* - * 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 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)) { @@ -409,18 +413,23 @@ acpi_ds_init_field_objects(union acpi_parse_object *op, ACPI_FUNCTION_TRACE_PTR(ds_init_field_objects, op); - /* - * During the load phase, we want to enter the name of the field into - * the namespace. During the execute phase (when we evaluate the bank_value - * operand), we want to lookup the name. - */ - if (walk_state->deferred_node) { - 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)) { + 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); @@ -441,18 +450,34 @@ acpi_ds_init_field_objects(union acpi_parse_object *op, return_ACPI_STATUS(AE_BAD_PARAMETER); } + if (!arg) { + return_ACPI_STATUS(AE_AML_NO_OPERAND); + } + + /* 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 */ 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, - flags, walk_state, &node); + (char *)&arg->named.name, type, + ACPI_IMODE_LOAD_PASS1, flags, + walk_state, &node); if (ACPI_FAILURE(status)) { ACPI_ERROR_NAMESPACE((char *)&arg->named.name, status); @@ -468,7 +493,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; } -- cgit v1.2.3 From 75a44ce00b312f57264f42a0a985d17cd9994b98 Mon Sep 17 00:00:00 2001 From: Len Brown Date: Wed, 23 Apr 2008 23:00:13 -0400 Subject: ACPICA: update Intel copyright Signed-off-by: Len Brown --- drivers/acpi/dispatcher/dsfield.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/acpi/dispatcher/dsfield.c') diff --git a/drivers/acpi/dispatcher/dsfield.c b/drivers/acpi/dispatcher/dsfield.c index 0befcff19f5a..c78078315be9 100644 --- a/drivers/acpi/dispatcher/dsfield.c +++ b/drivers/acpi/dispatcher/dsfield.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without -- cgit v1.2.3