diff options
Diffstat (limited to 'drivers/acpi/dispatcher/dsobject.c')
-rw-r--r-- | drivers/acpi/dispatcher/dsobject.c | 101 |
1 files changed, 78 insertions, 23 deletions
diff --git a/drivers/acpi/dispatcher/dsobject.c b/drivers/acpi/dispatcher/dsobject.c index 954ac8ce958a..1022e38994c2 100644 --- a/drivers/acpi/dispatcher/dsobject.c +++ b/drivers/acpi/dispatcher/dsobject.c | |||
@@ -5,7 +5,7 @@ | |||
5 | *****************************************************************************/ | 5 | *****************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2007, R. Byron Moore | 8 | * Copyright (C) 2000 - 2008, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
@@ -157,7 +157,9 @@ acpi_ds_build_internal_object(struct acpi_walk_state *walk_state, | |||
157 | * will remain as named references. This behavior is not described | 157 | * will remain as named references. This behavior is not described |
158 | * in the ACPI spec, but it appears to be an oversight. | 158 | * in the ACPI spec, but it appears to be an oversight. |
159 | */ | 159 | */ |
160 | obj_desc = (union acpi_operand_object *)op->common.node; | 160 | obj_desc = |
161 | ACPI_CAST_PTR(union acpi_operand_object, | ||
162 | op->common.node); | ||
161 | 163 | ||
162 | status = | 164 | status = |
163 | acpi_ex_resolve_node_to_value(ACPI_CAST_INDIRECT_PTR | 165 | acpi_ex_resolve_node_to_value(ACPI_CAST_INDIRECT_PTR |
@@ -172,7 +174,19 @@ acpi_ds_build_internal_object(struct acpi_walk_state *walk_state, | |||
172 | switch (op->common.node->type) { | 174 | switch (op->common.node->type) { |
173 | /* | 175 | /* |
174 | * For these types, we need the actual node, not the subobject. | 176 | * For these types, we need the actual node, not the subobject. |
175 | * However, the subobject got an extra reference count above. | 177 | * However, the subobject did not get an extra reference count above. |
178 | * | ||
179 | * TBD: should ex_resolve_node_to_value be changed to fix this? | ||
180 | */ | ||
181 | case ACPI_TYPE_DEVICE: | ||
182 | case ACPI_TYPE_THERMAL: | ||
183 | |||
184 | acpi_ut_add_reference(op->common.node->object); | ||
185 | |||
186 | /*lint -fallthrough */ | ||
187 | /* | ||
188 | * For these types, we need the actual node, not the subobject. | ||
189 | * The subobject got an extra reference count in ex_resolve_node_to_value. | ||
176 | */ | 190 | */ |
177 | case ACPI_TYPE_MUTEX: | 191 | case ACPI_TYPE_MUTEX: |
178 | case ACPI_TYPE_METHOD: | 192 | case ACPI_TYPE_METHOD: |
@@ -180,25 +194,15 @@ acpi_ds_build_internal_object(struct acpi_walk_state *walk_state, | |||
180 | case ACPI_TYPE_PROCESSOR: | 194 | case ACPI_TYPE_PROCESSOR: |
181 | case ACPI_TYPE_EVENT: | 195 | case ACPI_TYPE_EVENT: |
182 | case ACPI_TYPE_REGION: | 196 | case ACPI_TYPE_REGION: |
183 | case ACPI_TYPE_DEVICE: | ||
184 | case ACPI_TYPE_THERMAL: | ||
185 | 197 | ||
186 | obj_desc = | 198 | /* We will create a reference object for these types below */ |
187 | (union acpi_operand_object *)op->common. | ||
188 | node; | ||
189 | break; | 199 | break; |
190 | 200 | ||
191 | default: | 201 | default: |
192 | break; | 202 | /* |
193 | } | 203 | * All other types - the node was resolved to an actual |
194 | 204 | * object, we are done. | |
195 | /* | 205 | */ |
196 | * If above resolved to an operand object, we are done. Otherwise, | ||
197 | * we have a NS node, we must create the package entry as a named | ||
198 | * reference. | ||
199 | */ | ||
200 | if (ACPI_GET_DESCRIPTOR_TYPE(obj_desc) != | ||
201 | ACPI_DESC_TYPE_NAMED) { | ||
202 | goto exit; | 206 | goto exit; |
203 | } | 207 | } |
204 | } | 208 | } |
@@ -223,7 +227,7 @@ acpi_ds_build_internal_object(struct acpi_walk_state *walk_state, | |||
223 | 227 | ||
224 | exit: | 228 | exit: |
225 | *obj_desc_ptr = obj_desc; | 229 | *obj_desc_ptr = obj_desc; |
226 | return_ACPI_STATUS(AE_OK); | 230 | return_ACPI_STATUS(status); |
227 | } | 231 | } |
228 | 232 | ||
229 | /******************************************************************************* | 233 | /******************************************************************************* |
@@ -369,7 +373,9 @@ acpi_ds_build_internal_package_obj(struct acpi_walk_state *walk_state, | |||
369 | union acpi_parse_object *parent; | 373 | union acpi_parse_object *parent; |
370 | union acpi_operand_object *obj_desc = NULL; | 374 | union acpi_operand_object *obj_desc = NULL; |
371 | acpi_status status = AE_OK; | 375 | acpi_status status = AE_OK; |
372 | acpi_native_uint i; | 376 | unsigned i; |
377 | u16 index; | ||
378 | u16 reference_count; | ||
373 | 379 | ||
374 | ACPI_FUNCTION_TRACE(ds_build_internal_package_obj); | 380 | ACPI_FUNCTION_TRACE(ds_build_internal_package_obj); |
375 | 381 | ||
@@ -447,13 +453,60 @@ acpi_ds_build_internal_package_obj(struct acpi_walk_state *walk_state, | |||
447 | package. | 453 | package. |
448 | elements[i]); | 454 | elements[i]); |
449 | } | 455 | } |
456 | |||
457 | if (*obj_desc_ptr) { | ||
458 | |||
459 | /* Existing package, get existing reference count */ | ||
460 | |||
461 | reference_count = | ||
462 | (*obj_desc_ptr)->common.reference_count; | ||
463 | if (reference_count > 1) { | ||
464 | |||
465 | /* Make new element ref count match original ref count */ | ||
466 | |||
467 | for (index = 0; index < (reference_count - 1); | ||
468 | index++) { | ||
469 | acpi_ut_add_reference((obj_desc-> | ||
470 | package. | ||
471 | elements[i])); | ||
472 | } | ||
473 | } | ||
474 | } | ||
475 | |||
450 | arg = arg->common.next; | 476 | arg = arg->common.next; |
451 | } | 477 | } |
452 | 478 | ||
453 | if (!arg) { | 479 | /* Check for match between num_elements and actual length of package_list */ |
480 | |||
481 | if (arg) { | ||
482 | /* | ||
483 | * num_elements was exhausted, but there are remaining elements in the | ||
484 | * package_list. | ||
485 | * | ||
486 | * Note: technically, this is an error, from ACPI spec: "It is an error | ||
487 | * for NumElements to be less than the number of elements in the | ||
488 | * PackageList". However, for now, we just print an error message and | ||
489 | * no exception is returned. | ||
490 | */ | ||
491 | while (arg) { | ||
492 | |||
493 | /* Find out how many elements there really are */ | ||
494 | |||
495 | i++; | ||
496 | arg = arg->common.next; | ||
497 | } | ||
498 | |||
499 | ACPI_ERROR((AE_INFO, | ||
500 | "Package List length (%X) larger than NumElements count (%X), truncated\n", | ||
501 | i, element_count)); | ||
502 | } else if (i < element_count) { | ||
503 | /* | ||
504 | * Arg list (elements) was exhausted, but we did not reach num_elements count. | ||
505 | * Note: this is not an error, the package is padded out with NULLs. | ||
506 | */ | ||
454 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | 507 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, |
455 | "Package List length larger than NumElements count (%X), truncated\n", | 508 | "Package List length (%X) smaller than NumElements count (%X), padded with null elements\n", |
456 | element_count)); | 509 | i, element_count)); |
457 | } | 510 | } |
458 | 511 | ||
459 | obj_desc->package.flags |= AOPOBJ_DATA_VALID; | 512 | obj_desc->package.flags |= AOPOBJ_DATA_VALID; |
@@ -721,6 +774,8 @@ acpi_ds_init_object_from_op(struct acpi_walk_state *walk_state, | |||
721 | /* Node was saved in Op */ | 774 | /* Node was saved in Op */ |
722 | 775 | ||
723 | obj_desc->reference.node = op->common.node; | 776 | obj_desc->reference.node = op->common.node; |
777 | obj_desc->reference.object = | ||
778 | op->common.node->object; | ||
724 | } | 779 | } |
725 | 780 | ||
726 | obj_desc->reference.opcode = opcode; | 781 | obj_desc->reference.opcode = opcode; |