diff options
author | Lin Ming <ming.m.lin@intel.com> | 2008-04-10 11:06:41 -0400 |
---|---|---|
committer | Len Brown <len.brown@intel.com> | 2008-04-22 14:29:28 -0400 |
commit | ef805d956320ffa36d068673d5c5eb2a7d13209b (patch) | |
tree | efc621915bc0909d99f523551c062390cc3afa0b /drivers/acpi/dispatcher | |
parent | 57345ee6b807d32e5eecf724a463378b80cc261c (diff) |
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 <ming.m.lin@intel.com>
Signed-off-by: Bob Moore <robert.moore@intel.com>
Signed-off-by: Alexey Starikovskiy <astarikovskiy@suse.de>
Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers/acpi/dispatcher')
-rw-r--r-- | drivers/acpi/dispatcher/dsfield.c | 80 | ||||
-rw-r--r-- | drivers/acpi/dispatcher/dsopcode.c | 144 | ||||
-rw-r--r-- | drivers/acpi/dispatcher/dsutils.c | 4 | ||||
-rw-r--r-- | drivers/acpi/dispatcher/dswexec.c | 11 |
4 files changed, 199 insertions, 40 deletions
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, | |||
281 | arg->common.node = info->field_node; | 281 | arg->common.node = info->field_node; |
282 | info->field_bit_length = arg->common.value.size; | 282 | info->field_bit_length = arg->common.value.size; |
283 | 283 | ||
284 | /* Create and initialize an object for the new Field Node */ | 284 | /* |
285 | 285 | * If there is no object attached to the node, this node was just created | |
286 | status = acpi_ex_prep_field_value(info); | 286 | * and we need to create the field object. Otherwise, this was a lookup |
287 | if (ACPI_FAILURE(status)) { | 287 | * of an existing node and we don't want to create the field object again. |
288 | return_ACPI_STATUS(status); | 288 | */ |
289 | if (!acpi_ns_get_attached_object | ||
290 | (info->field_node)) { | ||
291 | status = acpi_ex_prep_field_value(info); | ||
292 | if (ACPI_FAILURE(status)) { | ||
293 | return_ACPI_STATUS(status); | ||
294 | } | ||
289 | } | 295 | } |
290 | } | 296 | } |
291 | 297 | ||
@@ -399,9 +405,22 @@ acpi_ds_init_field_objects(union acpi_parse_object *op, | |||
399 | union acpi_parse_object *arg = NULL; | 405 | union acpi_parse_object *arg = NULL; |
400 | struct acpi_namespace_node *node; | 406 | struct acpi_namespace_node *node; |
401 | u8 type = 0; | 407 | u8 type = 0; |
408 | u32 flags; | ||
402 | 409 | ||
403 | ACPI_FUNCTION_TRACE_PTR(ds_init_field_objects, op); | 410 | ACPI_FUNCTION_TRACE_PTR(ds_init_field_objects, op); |
404 | 411 | ||
412 | /* | ||
413 | * During the load phase, we want to enter the name of the field into | ||
414 | * the namespace. During the execute phase (when we evaluate the bank_value | ||
415 | * operand), we want to lookup the name. | ||
416 | */ | ||
417 | if (walk_state->deferred_node) { | ||
418 | flags = ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE; | ||
419 | } else { | ||
420 | flags = ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE | | ||
421 | ACPI_NS_ERROR_IF_FOUND; | ||
422 | } | ||
423 | |||
405 | switch (walk_state->opcode) { | 424 | switch (walk_state->opcode) { |
406 | case AML_FIELD_OP: | 425 | case AML_FIELD_OP: |
407 | arg = acpi_ps_get_arg(op, 2); | 426 | arg = acpi_ps_get_arg(op, 2); |
@@ -433,10 +452,7 @@ acpi_ds_init_field_objects(union acpi_parse_object *op, | |||
433 | status = acpi_ns_lookup(walk_state->scope_info, | 452 | status = acpi_ns_lookup(walk_state->scope_info, |
434 | (char *)&arg->named.name, | 453 | (char *)&arg->named.name, |
435 | type, ACPI_IMODE_LOAD_PASS1, | 454 | type, ACPI_IMODE_LOAD_PASS1, |
436 | ACPI_NS_NO_UPSEARCH | | 455 | flags, walk_state, &node); |
437 | ACPI_NS_DONT_OPEN_SCOPE | | ||
438 | ACPI_NS_ERROR_IF_FOUND, | ||
439 | walk_state, &node); | ||
440 | if (ACPI_FAILURE(status)) { | 456 | if (ACPI_FAILURE(status)) { |
441 | ACPI_ERROR_NAMESPACE((char *)&arg->named.name, | 457 | ACPI_ERROR_NAMESPACE((char *)&arg->named.name, |
442 | status); | 458 | status); |
@@ -466,7 +482,7 @@ acpi_ds_init_field_objects(union acpi_parse_object *op, | |||
466 | * | 482 | * |
467 | * PARAMETERS: Op - Op containing the Field definition and args | 483 | * PARAMETERS: Op - Op containing the Field definition and args |
468 | * region_node - Object for the containing Operation Region | 484 | * region_node - Object for the containing Operation Region |
469 | * ` walk_state - Current method state | 485 | * walk_state - Current method state |
470 | * | 486 | * |
471 | * RETURN: Status | 487 | * RETURN: Status |
472 | * | 488 | * |
@@ -513,36 +529,13 @@ acpi_ds_create_bank_field(union acpi_parse_object *op, | |||
513 | return_ACPI_STATUS(status); | 529 | return_ACPI_STATUS(status); |
514 | } | 530 | } |
515 | 531 | ||
516 | /* Third arg is the bank_value */ | 532 | /* |
517 | 533 | * Third arg is the bank_value | |
518 | /* TBD: This arg is a term_arg, not a constant, and must be evaluated */ | 534 | * This arg is a term_arg, not a constant |
519 | 535 | * It will be evaluated later, by acpi_ds_eval_bank_field_operands | |
536 | */ | ||
520 | arg = arg->common.next; | 537 | arg = arg->common.next; |
521 | 538 | ||
522 | /* Currently, only the following constants are supported */ | ||
523 | |||
524 | switch (arg->common.aml_opcode) { | ||
525 | case AML_ZERO_OP: | ||
526 | info.bank_value = 0; | ||
527 | break; | ||
528 | |||
529 | case AML_ONE_OP: | ||
530 | info.bank_value = 1; | ||
531 | break; | ||
532 | |||
533 | case AML_BYTE_OP: | ||
534 | case AML_WORD_OP: | ||
535 | case AML_DWORD_OP: | ||
536 | case AML_QWORD_OP: | ||
537 | info.bank_value = (u32) arg->common.value.integer; | ||
538 | break; | ||
539 | |||
540 | default: | ||
541 | info.bank_value = 0; | ||
542 | ACPI_ERROR((AE_INFO, | ||
543 | "Non-constant BankValue for BankField is not implemented")); | ||
544 | } | ||
545 | |||
546 | /* Fourth arg is the field flags */ | 539 | /* Fourth arg is the field flags */ |
547 | 540 | ||
548 | arg = arg->common.next; | 541 | arg = arg->common.next; |
@@ -553,8 +546,17 @@ acpi_ds_create_bank_field(union acpi_parse_object *op, | |||
553 | info.field_type = ACPI_TYPE_LOCAL_BANK_FIELD; | 546 | info.field_type = ACPI_TYPE_LOCAL_BANK_FIELD; |
554 | info.region_node = region_node; | 547 | info.region_node = region_node; |
555 | 548 | ||
556 | status = acpi_ds_get_field_names(&info, walk_state, arg->common.next); | 549 | /* |
550 | * Use Info.data_register_node to store bank_field Op | ||
551 | * It's safe because data_register_node will never be used when create bank field | ||
552 | * We store aml_start and aml_length in the bank_field Op for late evaluation | ||
553 | * Used in acpi_ex_prep_field_value(Info) | ||
554 | * | ||
555 | * TBD: Or, should we add a field in struct acpi_create_field_info, like "void *ParentOp"? | ||
556 | */ | ||
557 | info.data_register_node = (struct acpi_namespace_node *)op; | ||
557 | 558 | ||
559 | status = acpi_ds_get_field_names(&info, walk_state, arg->common.next); | ||
558 | return_ACPI_STATUS(status); | 560 | return_ACPI_STATUS(status); |
559 | } | 561 | } |
560 | 562 | ||
diff --git a/drivers/acpi/dispatcher/dsopcode.c b/drivers/acpi/dispatcher/dsopcode.c index a3f29798d1d1..35a7efdb5ad9 100644 --- a/drivers/acpi/dispatcher/dsopcode.c +++ b/drivers/acpi/dispatcher/dsopcode.c | |||
@@ -220,6 +220,50 @@ acpi_ds_get_buffer_field_arguments(union acpi_operand_object *obj_desc) | |||
220 | 220 | ||
221 | /******************************************************************************* | 221 | /******************************************************************************* |
222 | * | 222 | * |
223 | * FUNCTION: acpi_ds_get_bank_field_arguments | ||
224 | * | ||
225 | * PARAMETERS: obj_desc - A valid bank_field object | ||
226 | * | ||
227 | * RETURN: Status. | ||
228 | * | ||
229 | * DESCRIPTION: Get bank_field bank_value. This implements the late | ||
230 | * evaluation of these field attributes. | ||
231 | * | ||
232 | ******************************************************************************/ | ||
233 | |||
234 | acpi_status | ||
235 | acpi_ds_get_bank_field_arguments(union acpi_operand_object *obj_desc) | ||
236 | { | ||
237 | union acpi_operand_object *extra_desc; | ||
238 | struct acpi_namespace_node *node; | ||
239 | acpi_status status; | ||
240 | |||
241 | ACPI_FUNCTION_TRACE_PTR(ds_get_bank_field_arguments, obj_desc); | ||
242 | |||
243 | if (obj_desc->common.flags & AOPOBJ_DATA_VALID) { | ||
244 | return_ACPI_STATUS(AE_OK); | ||
245 | } | ||
246 | |||
247 | /* Get the AML pointer (method object) and bank_field node */ | ||
248 | |||
249 | extra_desc = acpi_ns_get_secondary_object(obj_desc); | ||
250 | node = obj_desc->bank_field.node; | ||
251 | |||
252 | ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname | ||
253 | (ACPI_TYPE_LOCAL_BANK_FIELD, node, NULL)); | ||
254 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "[%4.4s] BankField Arg Init\n", | ||
255 | acpi_ut_get_node_name(node))); | ||
256 | |||
257 | /* Execute the AML code for the term_arg arguments */ | ||
258 | |||
259 | status = acpi_ds_execute_arguments(node, acpi_ns_get_parent_node(node), | ||
260 | extra_desc->extra.aml_length, | ||
261 | extra_desc->extra.aml_start); | ||
262 | return_ACPI_STATUS(status); | ||
263 | } | ||
264 | |||
265 | /******************************************************************************* | ||
266 | * | ||
223 | * FUNCTION: acpi_ds_get_buffer_arguments | 267 | * FUNCTION: acpi_ds_get_buffer_arguments |
224 | * | 268 | * |
225 | * PARAMETERS: obj_desc - A valid Buffer object | 269 | * PARAMETERS: obj_desc - A valid Buffer object |
@@ -987,6 +1031,106 @@ acpi_ds_eval_data_object_operands(struct acpi_walk_state *walk_state, | |||
987 | 1031 | ||
988 | /******************************************************************************* | 1032 | /******************************************************************************* |
989 | * | 1033 | * |
1034 | * FUNCTION: acpi_ds_eval_bank_field_operands | ||
1035 | * | ||
1036 | * PARAMETERS: walk_state - Current walk | ||
1037 | * Op - A valid bank_field Op object | ||
1038 | * | ||
1039 | * RETURN: Status | ||
1040 | * | ||
1041 | * DESCRIPTION: Get bank_field bank_value | ||
1042 | * Called from acpi_ds_exec_end_op during bank_field parse tree walk | ||
1043 | * | ||
1044 | ******************************************************************************/ | ||
1045 | |||
1046 | acpi_status | ||
1047 | acpi_ds_eval_bank_field_operands(struct acpi_walk_state *walk_state, | ||
1048 | union acpi_parse_object *op) | ||
1049 | { | ||
1050 | acpi_status status; | ||
1051 | union acpi_operand_object *obj_desc; | ||
1052 | union acpi_operand_object *operand_desc; | ||
1053 | struct acpi_namespace_node *node; | ||
1054 | union acpi_parse_object *next_op; | ||
1055 | union acpi_parse_object *arg; | ||
1056 | |||
1057 | ACPI_FUNCTION_TRACE_PTR(ds_eval_bank_field_operands, op); | ||
1058 | |||
1059 | /* | ||
1060 | * This is where we evaluate the bank_value field of the | ||
1061 | * bank_field declaration | ||
1062 | */ | ||
1063 | |||
1064 | /* next_op points to the op that holds the Region */ | ||
1065 | |||
1066 | next_op = op->common.value.arg; | ||
1067 | |||
1068 | /* next_op points to the op that holds the Bank Register */ | ||
1069 | |||
1070 | next_op = next_op->common.next; | ||
1071 | |||
1072 | /* next_op points to the op that holds the Bank Value */ | ||
1073 | |||
1074 | next_op = next_op->common.next; | ||
1075 | |||
1076 | /* | ||
1077 | * Set proper index into operand stack for acpi_ds_obj_stack_push | ||
1078 | * invoked inside acpi_ds_create_operand. | ||
1079 | * | ||
1080 | * We use walk_state->Operands[0] to store the evaluated bank_value | ||
1081 | */ | ||
1082 | walk_state->operand_index = 0; | ||
1083 | |||
1084 | status = acpi_ds_create_operand(walk_state, next_op, 0); | ||
1085 | if (ACPI_FAILURE(status)) { | ||
1086 | return_ACPI_STATUS(status); | ||
1087 | } | ||
1088 | |||
1089 | status = acpi_ex_resolve_to_value(&walk_state->operands[0], walk_state); | ||
1090 | if (ACPI_FAILURE(status)) { | ||
1091 | return_ACPI_STATUS(status); | ||
1092 | } | ||
1093 | |||
1094 | ACPI_DUMP_OPERANDS(ACPI_WALK_OPERANDS, ACPI_IMODE_EXECUTE, | ||
1095 | acpi_ps_get_opcode_name(op->common.aml_opcode), | ||
1096 | 1, "after AcpiExResolveOperands"); | ||
1097 | |||
1098 | /* | ||
1099 | * Get the bank_value operand and save it | ||
1100 | * (at Top of stack) | ||
1101 | */ | ||
1102 | operand_desc = walk_state->operands[0]; | ||
1103 | |||
1104 | /* Arg points to the start Bank Field */ | ||
1105 | |||
1106 | arg = acpi_ps_get_arg(op, 4); | ||
1107 | while (arg) { | ||
1108 | |||
1109 | /* Ignore OFFSET and ACCESSAS terms here */ | ||
1110 | |||
1111 | if (arg->common.aml_opcode == AML_INT_NAMEDFIELD_OP) { | ||
1112 | node = arg->common.node; | ||
1113 | |||
1114 | obj_desc = acpi_ns_get_attached_object(node); | ||
1115 | if (!obj_desc) { | ||
1116 | return_ACPI_STATUS(AE_NOT_EXIST); | ||
1117 | } | ||
1118 | |||
1119 | obj_desc->bank_field.value = | ||
1120 | (u32) operand_desc->integer.value; | ||
1121 | } | ||
1122 | |||
1123 | /* Move to next field in the list */ | ||
1124 | |||
1125 | arg = arg->common.next; | ||
1126 | } | ||
1127 | |||
1128 | acpi_ut_remove_reference(operand_desc); | ||
1129 | return_ACPI_STATUS(status); | ||
1130 | } | ||
1131 | |||
1132 | /******************************************************************************* | ||
1133 | * | ||
990 | * FUNCTION: acpi_ds_exec_begin_control_op | 1134 | * FUNCTION: acpi_ds_exec_begin_control_op |
991 | * | 1135 | * |
992 | * PARAMETERS: walk_list - The list that owns the walk stack | 1136 | * PARAMETERS: walk_list - The list that owns the walk stack |
diff --git a/drivers/acpi/dispatcher/dsutils.c b/drivers/acpi/dispatcher/dsutils.c index 97d01dcdc972..f6c28d7b46c5 100644 --- a/drivers/acpi/dispatcher/dsutils.c +++ b/drivers/acpi/dispatcher/dsutils.c | |||
@@ -278,7 +278,9 @@ acpi_ds_is_result_used(union acpi_parse_object * op, | |||
278 | AML_VAR_PACKAGE_OP) | 278 | AML_VAR_PACKAGE_OP) |
279 | || (op->common.parent->common.aml_opcode == AML_BUFFER_OP) | 279 | || (op->common.parent->common.aml_opcode == AML_BUFFER_OP) |
280 | || (op->common.parent->common.aml_opcode == | 280 | || (op->common.parent->common.aml_opcode == |
281 | AML_INT_EVAL_SUBTREE_OP)) { | 281 | AML_INT_EVAL_SUBTREE_OP) |
282 | || (op->common.parent->common.aml_opcode == | ||
283 | AML_BANK_FIELD_OP)) { | ||
282 | /* | 284 | /* |
283 | * These opcodes allow term_arg(s) as operands and therefore | 285 | * These opcodes allow term_arg(s) as operands and therefore |
284 | * the operands can be method calls. The result is used. | 286 | * the operands can be method calls. The result is used. |
diff --git a/drivers/acpi/dispatcher/dswexec.c b/drivers/acpi/dispatcher/dswexec.c index 8ba4bb36af9f..bfe4450fa588 100644 --- a/drivers/acpi/dispatcher/dswexec.c +++ b/drivers/acpi/dispatcher/dswexec.c | |||
@@ -652,6 +652,17 @@ acpi_status acpi_ds_exec_end_op(struct acpi_walk_state *walk_state) | |||
652 | if (ACPI_FAILURE(status)) { | 652 | if (ACPI_FAILURE(status)) { |
653 | break; | 653 | break; |
654 | } | 654 | } |
655 | } else if (op->common.aml_opcode == AML_BANK_FIELD_OP) { | ||
656 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, | ||
657 | "Executing BankField Op=%p\n", | ||
658 | op)); | ||
659 | |||
660 | status = | ||
661 | acpi_ds_eval_bank_field_operands(walk_state, | ||
662 | op); | ||
663 | if (ACPI_FAILURE(status)) { | ||
664 | break; | ||
665 | } | ||
655 | } | 666 | } |
656 | break; | 667 | break; |
657 | 668 | ||