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/dsfield.c | |
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/dsfield.c')
-rw-r--r-- | drivers/acpi/dispatcher/dsfield.c | 80 |
1 files changed, 41 insertions, 39 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 | ||