diff options
author | Bob Moore <robert.moore@intel.com> | 2013-09-06 02:27:15 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2013-11-29 14:11:40 -0500 |
commit | 217e7268258cf7a23196093dc828a0d0736aeb13 (patch) | |
tree | 03d9a0a204434d047ecfdb061e03c05ab0db4a78 /drivers/acpi | |
parent | 97020dadef81be7b3f1af758406a97d02c1cfa6b (diff) |
ACPICA: Fix for a Store->ArgX when ArgX contains a reference to a field.
commit 4be4be8fee2ee99a52f94f90d03d2f287ee1db86 upstream.
This change fixes a problem where a Store operation to an ArgX object
that contained a reference to a field object did not complete the
automatic dereference and then write to the actual field object.
Instead, the object type of the field object was inadvertently changed
to match the type of the source operand. The new behavior will actually
write to the field object (buffer field or field unit), thus matching
the correct ACPI-defined behavior.
Signed-off-by: Bob Moore <robert.moore@intel.com>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Signed-off-by: Lv Zheng <lv.zheng@intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/acpi')
-rw-r--r-- | drivers/acpi/acpica/exstore.c | 166 |
1 files changed, 102 insertions, 64 deletions
diff --git a/drivers/acpi/acpica/exstore.c b/drivers/acpi/acpica/exstore.c index 93c6049c2d75..b1ad39443cb6 100644 --- a/drivers/acpi/acpica/exstore.c +++ b/drivers/acpi/acpica/exstore.c | |||
@@ -57,6 +57,11 @@ acpi_ex_store_object_to_index(union acpi_operand_object *val_desc, | |||
57 | union acpi_operand_object *dest_desc, | 57 | union acpi_operand_object *dest_desc, |
58 | struct acpi_walk_state *walk_state); | 58 | struct acpi_walk_state *walk_state); |
59 | 59 | ||
60 | static acpi_status | ||
61 | acpi_ex_store_direct_to_node(union acpi_operand_object *source_desc, | ||
62 | struct acpi_namespace_node *node, | ||
63 | struct acpi_walk_state *walk_state); | ||
64 | |||
60 | /******************************************************************************* | 65 | /******************************************************************************* |
61 | * | 66 | * |
62 | * FUNCTION: acpi_ex_store | 67 | * FUNCTION: acpi_ex_store |
@@ -376,7 +381,11 @@ acpi_ex_store_object_to_index(union acpi_operand_object *source_desc, | |||
376 | * When storing into an object the data is converted to the | 381 | * When storing into an object the data is converted to the |
377 | * target object type then stored in the object. This means | 382 | * target object type then stored in the object. This means |
378 | * that the target object type (for an initialized target) will | 383 | * that the target object type (for an initialized target) will |
379 | * not be changed by a store operation. | 384 | * not be changed by a store operation. A copy_object can change |
385 | * the target type, however. | ||
386 | * | ||
387 | * The implicit_conversion flag is set to NO/FALSE only when | ||
388 | * storing to an arg_x -- as per the rules of the ACPI spec. | ||
380 | * | 389 | * |
381 | * Assumes parameters are already validated. | 390 | * Assumes parameters are already validated. |
382 | * | 391 | * |
@@ -400,7 +409,7 @@ acpi_ex_store_object_to_node(union acpi_operand_object *source_desc, | |||
400 | target_type = acpi_ns_get_type(node); | 409 | target_type = acpi_ns_get_type(node); |
401 | target_desc = acpi_ns_get_attached_object(node); | 410 | target_desc = acpi_ns_get_attached_object(node); |
402 | 411 | ||
403 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Storing %p(%s) into node %p(%s)\n", | 412 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Storing %p (%s) to node %p (%s)\n", |
404 | source_desc, | 413 | source_desc, |
405 | acpi_ut_get_object_type_name(source_desc), node, | 414 | acpi_ut_get_object_type_name(source_desc), node, |
406 | acpi_ut_get_type_name(target_type))); | 415 | acpi_ut_get_type_name(target_type))); |
@@ -414,46 +423,31 @@ acpi_ex_store_object_to_node(union acpi_operand_object *source_desc, | |||
414 | return_ACPI_STATUS(status); | 423 | return_ACPI_STATUS(status); |
415 | } | 424 | } |
416 | 425 | ||
417 | /* If no implicit conversion, drop into the default case below */ | ||
418 | |||
419 | if ((!implicit_conversion) || | ||
420 | ((walk_state->opcode == AML_COPY_OP) && | ||
421 | (target_type != ACPI_TYPE_LOCAL_REGION_FIELD) && | ||
422 | (target_type != ACPI_TYPE_LOCAL_BANK_FIELD) && | ||
423 | (target_type != ACPI_TYPE_LOCAL_INDEX_FIELD))) { | ||
424 | /* | ||
425 | * Force execution of default (no implicit conversion). Note: | ||
426 | * copy_object does not perform an implicit conversion, as per the ACPI | ||
427 | * spec -- except in case of region/bank/index fields -- because these | ||
428 | * objects must retain their original type permanently. | ||
429 | */ | ||
430 | target_type = ACPI_TYPE_ANY; | ||
431 | } | ||
432 | |||
433 | /* Do the actual store operation */ | 426 | /* Do the actual store operation */ |
434 | 427 | ||
435 | switch (target_type) { | 428 | switch (target_type) { |
436 | case ACPI_TYPE_BUFFER_FIELD: | ||
437 | case ACPI_TYPE_LOCAL_REGION_FIELD: | ||
438 | case ACPI_TYPE_LOCAL_BANK_FIELD: | ||
439 | case ACPI_TYPE_LOCAL_INDEX_FIELD: | ||
440 | |||
441 | /* For fields, copy the source data to the target field. */ | ||
442 | |||
443 | status = acpi_ex_write_data_to_field(source_desc, target_desc, | ||
444 | &walk_state->result_obj); | ||
445 | break; | ||
446 | |||
447 | case ACPI_TYPE_INTEGER: | 429 | case ACPI_TYPE_INTEGER: |
448 | case ACPI_TYPE_STRING: | 430 | case ACPI_TYPE_STRING: |
449 | case ACPI_TYPE_BUFFER: | 431 | case ACPI_TYPE_BUFFER: |
450 | 432 | ||
451 | /* | 433 | /* |
452 | * These target types are all of type Integer/String/Buffer, and | 434 | * The simple data types all support implicit source operand |
453 | * therefore support implicit conversion before the store. | 435 | * conversion before the store. |
454 | * | ||
455 | * Copy and/or convert the source object to a new target object | ||
456 | */ | 436 | */ |
437 | |||
438 | if ((walk_state->opcode == AML_COPY_OP) || !implicit_conversion) { | ||
439 | /* | ||
440 | * However, copy_object and Stores to arg_x do not perform | ||
441 | * an implicit conversion, as per the ACPI specification. | ||
442 | * A direct store is performed instead. | ||
443 | */ | ||
444 | status = acpi_ex_store_direct_to_node(source_desc, node, | ||
445 | walk_state); | ||
446 | break; | ||
447 | } | ||
448 | |||
449 | /* Store with implicit source operand conversion support */ | ||
450 | |||
457 | status = | 451 | status = |
458 | acpi_ex_store_object_to_object(source_desc, target_desc, | 452 | acpi_ex_store_object_to_object(source_desc, target_desc, |
459 | &new_desc, walk_state); | 453 | &new_desc, walk_state); |
@@ -467,13 +461,12 @@ acpi_ex_store_object_to_node(union acpi_operand_object *source_desc, | |||
467 | * the Name's type to that of the value being stored in it. | 461 | * the Name's type to that of the value being stored in it. |
468 | * source_desc reference count is incremented by attach_object. | 462 | * source_desc reference count is incremented by attach_object. |
469 | * | 463 | * |
470 | * Note: This may change the type of the node if an explicit store | 464 | * Note: This may change the type of the node if an explicit |
471 | * has been performed such that the node/object type has been | 465 | * store has been performed such that the node/object type |
472 | * changed. | 466 | * has been changed. |
473 | */ | 467 | */ |
474 | status = | 468 | status = acpi_ns_attach_object(node, new_desc, |
475 | acpi_ns_attach_object(node, new_desc, | 469 | new_desc->common.type); |
476 | new_desc->common.type); | ||
477 | 470 | ||
478 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, | 471 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, |
479 | "Store %s into %s via Convert/Attach\n", | 472 | "Store %s into %s via Convert/Attach\n", |
@@ -484,38 +477,83 @@ acpi_ex_store_object_to_node(union acpi_operand_object *source_desc, | |||
484 | } | 477 | } |
485 | break; | 478 | break; |
486 | 479 | ||
487 | default: | 480 | case ACPI_TYPE_BUFFER_FIELD: |
488 | 481 | case ACPI_TYPE_LOCAL_REGION_FIELD: | |
489 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, | 482 | case ACPI_TYPE_LOCAL_BANK_FIELD: |
490 | "Storing [%s] (%p) directly into node [%s] (%p)" | 483 | case ACPI_TYPE_LOCAL_INDEX_FIELD: |
491 | " with no implicit conversion\n", | 484 | /* |
492 | acpi_ut_get_object_type_name(source_desc), | 485 | * For all fields, always write the source data to the target |
493 | source_desc, | 486 | * field. Any required implicit source operand conversion is |
494 | acpi_ut_get_object_type_name(target_desc), | 487 | * performed in the function below as necessary. Note, field |
495 | node)); | 488 | * objects must retain their original type permanently. |
489 | */ | ||
490 | status = acpi_ex_write_data_to_field(source_desc, target_desc, | ||
491 | &walk_state->result_obj); | ||
492 | break; | ||
496 | 493 | ||
494 | default: | ||
497 | /* | 495 | /* |
498 | * No conversions for all other types. Directly store a copy of | 496 | * No conversions for all other types. Directly store a copy of |
499 | * the source object. NOTE: This is a departure from the ACPI | 497 | * the source object. This is the ACPI spec-defined behavior for |
500 | * spec, which states "If conversion is impossible, abort the | 498 | * the copy_object operator. |
501 | * running control method". | ||
502 | * | 499 | * |
503 | * This code implements "If conversion is impossible, treat the | 500 | * NOTE: For the Store operator, this is a departure from the |
504 | * Store operation as a CopyObject". | 501 | * ACPI spec, which states "If conversion is impossible, abort |
502 | * the running control method". Instead, this code implements | ||
503 | * "If conversion is impossible, treat the Store operation as | ||
504 | * a CopyObject". | ||
505 | */ | 505 | */ |
506 | status = | 506 | status = acpi_ex_store_direct_to_node(source_desc, node, |
507 | acpi_ut_copy_iobject_to_iobject(source_desc, &new_desc, | 507 | walk_state); |
508 | walk_state); | ||
509 | if (ACPI_FAILURE(status)) { | ||
510 | return_ACPI_STATUS(status); | ||
511 | } | ||
512 | |||
513 | status = | ||
514 | acpi_ns_attach_object(node, new_desc, | ||
515 | new_desc->common.type); | ||
516 | acpi_ut_remove_reference(new_desc); | ||
517 | break; | 508 | break; |
518 | } | 509 | } |
519 | 510 | ||
520 | return_ACPI_STATUS(status); | 511 | return_ACPI_STATUS(status); |
521 | } | 512 | } |
513 | |||
514 | /******************************************************************************* | ||
515 | * | ||
516 | * FUNCTION: acpi_ex_store_direct_to_node | ||
517 | * | ||
518 | * PARAMETERS: source_desc - Value to be stored | ||
519 | * node - Named object to receive the value | ||
520 | * walk_state - Current walk state | ||
521 | * | ||
522 | * RETURN: Status | ||
523 | * | ||
524 | * DESCRIPTION: "Store" an object directly to a node. This involves a copy | ||
525 | * and an attach. | ||
526 | * | ||
527 | ******************************************************************************/ | ||
528 | |||
529 | static acpi_status | ||
530 | acpi_ex_store_direct_to_node(union acpi_operand_object *source_desc, | ||
531 | struct acpi_namespace_node *node, | ||
532 | struct acpi_walk_state *walk_state) | ||
533 | { | ||
534 | acpi_status status; | ||
535 | union acpi_operand_object *new_desc; | ||
536 | |||
537 | ACPI_FUNCTION_TRACE(ex_store_direct_to_node); | ||
538 | |||
539 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, | ||
540 | "Storing [%s] (%p) directly into node [%s] (%p)" | ||
541 | " with no implicit conversion\n", | ||
542 | acpi_ut_get_object_type_name(source_desc), | ||
543 | source_desc, acpi_ut_get_type_name(node->type), | ||
544 | node)); | ||
545 | |||
546 | /* Copy the source object to a new object */ | ||
547 | |||
548 | status = | ||
549 | acpi_ut_copy_iobject_to_iobject(source_desc, &new_desc, walk_state); | ||
550 | if (ACPI_FAILURE(status)) { | ||
551 | return_ACPI_STATUS(status); | ||
552 | } | ||
553 | |||
554 | /* Attach the new object to the node */ | ||
555 | |||
556 | status = acpi_ns_attach_object(node, new_desc, new_desc->common.type); | ||
557 | acpi_ut_remove_reference(new_desc); | ||
558 | return_ACPI_STATUS(status); | ||
559 | } | ||