diff options
Diffstat (limited to 'drivers/acpi/dispatcher')
-rw-r--r-- | drivers/acpi/dispatcher/dsmethod.c | 23 | ||||
-rw-r--r-- | drivers/acpi/dispatcher/dsmthdat.c | 6 | ||||
-rw-r--r-- | drivers/acpi/dispatcher/dswload.c | 41 |
3 files changed, 56 insertions, 14 deletions
diff --git a/drivers/acpi/dispatcher/dsmethod.c b/drivers/acpi/dispatcher/dsmethod.c index 651f2b68531b..e348db0e541e 100644 --- a/drivers/acpi/dispatcher/dsmethod.c +++ b/drivers/acpi/dispatcher/dsmethod.c | |||
@@ -385,6 +385,7 @@ acpi_ds_restart_control_method(struct acpi_walk_state *walk_state, | |||
385 | union acpi_operand_object *return_desc) | 385 | union acpi_operand_object *return_desc) |
386 | { | 386 | { |
387 | acpi_status status; | 387 | acpi_status status; |
388 | int same_as_implicit_return; | ||
388 | 389 | ||
389 | ACPI_FUNCTION_TRACE_PTR(ds_restart_control_method, walk_state); | 390 | ACPI_FUNCTION_TRACE_PTR(ds_restart_control_method, walk_state); |
390 | 391 | ||
@@ -402,6 +403,11 @@ acpi_ds_restart_control_method(struct acpi_walk_state *walk_state, | |||
402 | 403 | ||
403 | if (return_desc) { | 404 | if (return_desc) { |
404 | 405 | ||
406 | /* Is the implicit return object the same as the return desc? */ | ||
407 | |||
408 | same_as_implicit_return = | ||
409 | (walk_state->implicit_return_obj == return_desc); | ||
410 | |||
405 | /* Are we actually going to use the return value? */ | 411 | /* Are we actually going to use the return value? */ |
406 | 412 | ||
407 | if (walk_state->return_used) { | 413 | if (walk_state->return_used) { |
@@ -422,18 +428,23 @@ acpi_ds_restart_control_method(struct acpi_walk_state *walk_state, | |||
422 | } | 428 | } |
423 | 429 | ||
424 | /* | 430 | /* |
425 | * The following code is the | 431 | * The following code is the optional support for the so-called |
426 | * optional support for a so-called "implicit return". Some AML code | 432 | * "implicit return". Some AML code assumes that the last value of the |
427 | * assumes that the last value of the method is "implicitly" returned | 433 | * method is "implicitly" returned to the caller, in the absence of an |
428 | * to the caller. Just save the last result as the return value. | 434 | * explicit return value. |
435 | * | ||
436 | * Just save the last result of the method as the return value. | ||
437 | * | ||
429 | * NOTE: this is optional because the ASL language does not actually | 438 | * NOTE: this is optional because the ASL language does not actually |
430 | * support this behavior. | 439 | * support this behavior. |
431 | */ | 440 | */ |
432 | else if (!acpi_ds_do_implicit_return | 441 | else if (!acpi_ds_do_implicit_return |
433 | (return_desc, walk_state, FALSE)) { | 442 | (return_desc, walk_state, FALSE) |
443 | || same_as_implicit_return) { | ||
434 | /* | 444 | /* |
435 | * Delete the return value if it will not be used by the | 445 | * Delete the return value if it will not be used by the |
436 | * calling method | 446 | * calling method or remove one reference if the explicit return |
447 | * is the same as the implicit return value. | ||
437 | */ | 448 | */ |
438 | acpi_ut_remove_reference(return_desc); | 449 | acpi_ut_remove_reference(return_desc); |
439 | } | 450 | } |
diff --git a/drivers/acpi/dispatcher/dsmthdat.c b/drivers/acpi/dispatcher/dsmthdat.c index b47c54fad86d..459160ff9058 100644 --- a/drivers/acpi/dispatcher/dsmthdat.c +++ b/drivers/acpi/dispatcher/dsmthdat.c | |||
@@ -336,7 +336,7 @@ acpi_ds_method_data_set_value(u16 opcode, | |||
336 | * Increment ref count so object can't be deleted while installed. | 336 | * Increment ref count so object can't be deleted while installed. |
337 | * NOTE: We do not copy the object in order to preserve the call by | 337 | * NOTE: We do not copy the object in order to preserve the call by |
338 | * reference semantics of ACPI Control Method invocation. | 338 | * reference semantics of ACPI Control Method invocation. |
339 | * (See ACPI specification 2.0_c) | 339 | * (See ACPI Specification 2.0_c) |
340 | */ | 340 | */ |
341 | acpi_ut_add_reference(object); | 341 | acpi_ut_add_reference(object); |
342 | 342 | ||
@@ -351,7 +351,7 @@ acpi_ds_method_data_set_value(u16 opcode, | |||
351 | * FUNCTION: acpi_ds_method_data_get_value | 351 | * FUNCTION: acpi_ds_method_data_get_value |
352 | * | 352 | * |
353 | * PARAMETERS: Opcode - Either AML_LOCAL_OP or AML_ARG_OP | 353 | * PARAMETERS: Opcode - Either AML_LOCAL_OP or AML_ARG_OP |
354 | * Index - which local_var or argument to get | 354 | * Index - Which local_var or argument to get |
355 | * walk_state - Current walk state object | 355 | * walk_state - Current walk state object |
356 | * dest_desc - Where Arg or Local value is returned | 356 | * dest_desc - Where Arg or Local value is returned |
357 | * | 357 | * |
@@ -459,7 +459,7 @@ acpi_ds_method_data_get_value(u16 opcode, | |||
459 | * FUNCTION: acpi_ds_method_data_delete_value | 459 | * FUNCTION: acpi_ds_method_data_delete_value |
460 | * | 460 | * |
461 | * PARAMETERS: Opcode - Either AML_LOCAL_OP or AML_ARG_OP | 461 | * PARAMETERS: Opcode - Either AML_LOCAL_OP or AML_ARG_OP |
462 | * Index - which local_var or argument to delete | 462 | * Index - Which local_var or argument to delete |
463 | * walk_state - Current walk state object | 463 | * walk_state - Current walk state object |
464 | * | 464 | * |
465 | * RETURN: None | 465 | * RETURN: None |
diff --git a/drivers/acpi/dispatcher/dswload.c b/drivers/acpi/dispatcher/dswload.c index a8deb700cf33..35074399c617 100644 --- a/drivers/acpi/dispatcher/dswload.c +++ b/drivers/acpi/dispatcher/dswload.c | |||
@@ -178,12 +178,12 @@ acpi_ds_load1_begin_op(struct acpi_walk_state * walk_state, | |||
178 | * Target of Scope() not found. Generate an External for it, and | 178 | * Target of Scope() not found. Generate an External for it, and |
179 | * insert the name into the namespace. | 179 | * insert the name into the namespace. |
180 | */ | 180 | */ |
181 | acpi_dm_add_to_external_list(path); | 181 | acpi_dm_add_to_external_list(path, ACPI_TYPE_DEVICE, 0); |
182 | status = | 182 | status = |
183 | acpi_ns_lookup(walk_state->scope_info, path, | 183 | acpi_ns_lookup(walk_state->scope_info, path, |
184 | object_type, ACPI_IMODE_LOAD_PASS1, | 184 | object_type, ACPI_IMODE_LOAD_PASS1, |
185 | ACPI_NS_SEARCH_PARENT, walk_state, | 185 | ACPI_NS_SEARCH_PARENT, walk_state, |
186 | &(node)); | 186 | &node); |
187 | } | 187 | } |
188 | #endif | 188 | #endif |
189 | if (ACPI_FAILURE(status)) { | 189 | if (ACPI_FAILURE(status)) { |
@@ -301,10 +301,41 @@ acpi_ds_load1_begin_op(struct acpi_walk_state * walk_state, | |||
301 | status = | 301 | status = |
302 | acpi_ns_lookup(walk_state->scope_info, path, object_type, | 302 | acpi_ns_lookup(walk_state->scope_info, path, object_type, |
303 | ACPI_IMODE_LOAD_PASS1, flags, walk_state, | 303 | ACPI_IMODE_LOAD_PASS1, flags, walk_state, |
304 | &(node)); | 304 | &node); |
305 | if (ACPI_FAILURE(status)) { | 305 | if (ACPI_FAILURE(status)) { |
306 | ACPI_ERROR_NAMESPACE(path, status); | 306 | if (status == AE_ALREADY_EXISTS) { |
307 | return_ACPI_STATUS(status); | 307 | |
308 | /* The name already exists in this scope */ | ||
309 | |||
310 | if (node->flags & ANOBJ_IS_EXTERNAL) { | ||
311 | /* | ||
312 | * Allow one create on an object or segment that was | ||
313 | * previously declared External | ||
314 | */ | ||
315 | node->flags &= ~ANOBJ_IS_EXTERNAL; | ||
316 | node->type = (u8) object_type; | ||
317 | |||
318 | /* Just retyped a node, probably will need to open a scope */ | ||
319 | |||
320 | if (acpi_ns_opens_scope(object_type)) { | ||
321 | status = | ||
322 | acpi_ds_scope_stack_push | ||
323 | (node, object_type, | ||
324 | walk_state); | ||
325 | if (ACPI_FAILURE(status)) { | ||
326 | return_ACPI_STATUS | ||
327 | (status); | ||
328 | } | ||
329 | } | ||
330 | status = AE_OK; | ||
331 | } | ||
332 | } | ||
333 | |||
334 | if (ACPI_FAILURE(status)) { | ||
335 | |||
336 | ACPI_ERROR_NAMESPACE(path, status); | ||
337 | return_ACPI_STATUS(status); | ||
338 | } | ||
308 | } | 339 | } |
309 | break; | 340 | break; |
310 | } | 341 | } |