diff options
Diffstat (limited to 'drivers/acpi/dispatcher/dsmethod.c')
-rw-r--r-- | drivers/acpi/dispatcher/dsmethod.c | 69 |
1 files changed, 38 insertions, 31 deletions
diff --git a/drivers/acpi/dispatcher/dsmethod.c b/drivers/acpi/dispatcher/dsmethod.c index 77fcfc3070db..36c1ca0b9adb 100644 --- a/drivers/acpi/dispatcher/dsmethod.c +++ b/drivers/acpi/dispatcher/dsmethod.c | |||
@@ -207,6 +207,13 @@ acpi_ds_begin_method_execution(struct acpi_namespace_node *method_node, | |||
207 | return_ACPI_STATUS(AE_NULL_ENTRY); | 207 | return_ACPI_STATUS(AE_NULL_ENTRY); |
208 | } | 208 | } |
209 | 209 | ||
210 | /* Prevent wraparound of thread count */ | ||
211 | |||
212 | if (obj_desc->method.thread_count == ACPI_UINT8_MAX) { | ||
213 | ACPI_REPORT_ERROR(("Method reached maximum reentrancy limit (255)\n")); | ||
214 | return_ACPI_STATUS(AE_AML_METHOD_LIMIT); | ||
215 | } | ||
216 | |||
210 | /* | 217 | /* |
211 | * If there is a concurrency limit on this method, we need to | 218 | * If there is a concurrency limit on this method, we need to |
212 | * obtain a unit from the method semaphore. | 219 | * obtain a unit from the method semaphore. |
@@ -237,6 +244,18 @@ acpi_ds_begin_method_execution(struct acpi_namespace_node *method_node, | |||
237 | } | 244 | } |
238 | 245 | ||
239 | /* | 246 | /* |
247 | * Allocate an Owner ID for this method, only if this is the first thread | ||
248 | * to begin concurrent execution. We only need one owner_id, even if the | ||
249 | * method is invoked recursively. | ||
250 | */ | ||
251 | if (!obj_desc->method.owner_id) { | ||
252 | status = acpi_ut_allocate_owner_id(&obj_desc->method.owner_id); | ||
253 | if (ACPI_FAILURE(status)) { | ||
254 | return_ACPI_STATUS(status); | ||
255 | } | ||
256 | } | ||
257 | |||
258 | /* | ||
240 | * Increment the method parse tree thread count since it has been | 259 | * Increment the method parse tree thread count since it has been |
241 | * reentered one more time (even if it is the same thread) | 260 | * reentered one more time (even if it is the same thread) |
242 | */ | 261 | */ |
@@ -289,11 +308,6 @@ acpi_ds_call_control_method(struct acpi_thread_state *thread, | |||
289 | return_ACPI_STATUS(AE_NULL_OBJECT); | 308 | return_ACPI_STATUS(AE_NULL_OBJECT); |
290 | } | 309 | } |
291 | 310 | ||
292 | status = acpi_ut_allocate_owner_id(&obj_desc->method.owner_id); | ||
293 | if (ACPI_FAILURE(status)) { | ||
294 | return_ACPI_STATUS(status); | ||
295 | } | ||
296 | |||
297 | /* Init for new method, wait on concurrency semaphore */ | 311 | /* Init for new method, wait on concurrency semaphore */ |
298 | 312 | ||
299 | status = acpi_ds_begin_method_execution(method_node, obj_desc, | 313 | status = acpi_ds_begin_method_execution(method_node, obj_desc, |
@@ -345,9 +359,8 @@ acpi_ds_call_control_method(struct acpi_thread_state *thread, | |||
345 | } | 359 | } |
346 | /* | 360 | /* |
347 | * The resolved arguments were put on the previous walk state's operand | 361 | * The resolved arguments were put on the previous walk state's operand |
348 | * stack. Operands on the previous walk state stack always | 362 | * stack. Operands on the previous walk state stack always |
349 | * start at index 0. | 363 | * start at index 0. Also, null terminate the list of arguments |
350 | * Null terminate the list of arguments | ||
351 | */ | 364 | */ |
352 | this_walk_state->operands[this_walk_state->num_operands] = NULL; | 365 | this_walk_state->operands[this_walk_state->num_operands] = NULL; |
353 | 366 | ||
@@ -380,21 +393,20 @@ acpi_ds_call_control_method(struct acpi_thread_state *thread, | |||
380 | 393 | ||
381 | if (obj_desc->method.method_flags & AML_METHOD_INTERNAL_ONLY) { | 394 | if (obj_desc->method.method_flags & AML_METHOD_INTERNAL_ONLY) { |
382 | status = obj_desc->method.implementation(next_walk_state); | 395 | status = obj_desc->method.implementation(next_walk_state); |
383 | return_ACPI_STATUS(status); | ||
384 | } | 396 | } |
385 | 397 | ||
386 | return_ACPI_STATUS(AE_OK); | 398 | return_ACPI_STATUS(status); |
387 | |||
388 | /* On error, we must delete the new walk state */ | ||
389 | 399 | ||
390 | cleanup: | 400 | cleanup: |
391 | acpi_ut_release_owner_id(&obj_desc->method.owner_id); | 401 | /* Decrement the thread count on the method parse tree */ |
392 | if (next_walk_state && (next_walk_state->method_desc)) { | ||
393 | /* Decrement the thread count on the method parse tree */ | ||
394 | 402 | ||
403 | if (next_walk_state && (next_walk_state->method_desc)) { | ||
395 | next_walk_state->method_desc->method.thread_count--; | 404 | next_walk_state->method_desc->method.thread_count--; |
396 | } | 405 | } |
397 | (void)acpi_ds_terminate_control_method(next_walk_state); | 406 | |
407 | /* On error, we must delete the new walk state */ | ||
408 | |||
409 | acpi_ds_terminate_control_method(next_walk_state); | ||
398 | acpi_ds_delete_walk_state(next_walk_state); | 410 | acpi_ds_delete_walk_state(next_walk_state); |
399 | return_ACPI_STATUS(status); | 411 | return_ACPI_STATUS(status); |
400 | } | 412 | } |
@@ -479,7 +491,7 @@ acpi_ds_restart_control_method(struct acpi_walk_state *walk_state, | |||
479 | * | 491 | * |
480 | * PARAMETERS: walk_state - State of the method | 492 | * PARAMETERS: walk_state - State of the method |
481 | * | 493 | * |
482 | * RETURN: Status | 494 | * RETURN: None |
483 | * | 495 | * |
484 | * DESCRIPTION: Terminate a control method. Delete everything that the method | 496 | * DESCRIPTION: Terminate a control method. Delete everything that the method |
485 | * created, delete all locals and arguments, and delete the parse | 497 | * created, delete all locals and arguments, and delete the parse |
@@ -487,7 +499,7 @@ acpi_ds_restart_control_method(struct acpi_walk_state *walk_state, | |||
487 | * | 499 | * |
488 | ******************************************************************************/ | 500 | ******************************************************************************/ |
489 | 501 | ||
490 | acpi_status acpi_ds_terminate_control_method(struct acpi_walk_state *walk_state) | 502 | void acpi_ds_terminate_control_method(struct acpi_walk_state *walk_state) |
491 | { | 503 | { |
492 | union acpi_operand_object *obj_desc; | 504 | union acpi_operand_object *obj_desc; |
493 | struct acpi_namespace_node *method_node; | 505 | struct acpi_namespace_node *method_node; |
@@ -496,14 +508,14 @@ acpi_status acpi_ds_terminate_control_method(struct acpi_walk_state *walk_state) | |||
496 | ACPI_FUNCTION_TRACE_PTR("ds_terminate_control_method", walk_state); | 508 | ACPI_FUNCTION_TRACE_PTR("ds_terminate_control_method", walk_state); |
497 | 509 | ||
498 | if (!walk_state) { | 510 | if (!walk_state) { |
499 | return (AE_BAD_PARAMETER); | 511 | return_VOID; |
500 | } | 512 | } |
501 | 513 | ||
502 | /* The current method object was saved in the walk state */ | 514 | /* The current method object was saved in the walk state */ |
503 | 515 | ||
504 | obj_desc = walk_state->method_desc; | 516 | obj_desc = walk_state->method_desc; |
505 | if (!obj_desc) { | 517 | if (!obj_desc) { |
506 | return_ACPI_STATUS(AE_OK); | 518 | return_VOID; |
507 | } | 519 | } |
508 | 520 | ||
509 | /* Delete all arguments and locals */ | 521 | /* Delete all arguments and locals */ |
@@ -517,7 +529,7 @@ acpi_status acpi_ds_terminate_control_method(struct acpi_walk_state *walk_state) | |||
517 | */ | 529 | */ |
518 | status = acpi_ut_acquire_mutex(ACPI_MTX_PARSER); | 530 | status = acpi_ut_acquire_mutex(ACPI_MTX_PARSER); |
519 | if (ACPI_FAILURE(status)) { | 531 | if (ACPI_FAILURE(status)) { |
520 | return_ACPI_STATUS(status); | 532 | return_VOID; |
521 | } | 533 | } |
522 | 534 | ||
523 | /* Signal completion of the execution of this method if necessary */ | 535 | /* Signal completion of the execution of this method if necessary */ |
@@ -528,7 +540,6 @@ acpi_status acpi_ds_terminate_control_method(struct acpi_walk_state *walk_state) | |||
528 | semaphore, 1); | 540 | semaphore, 1); |
529 | if (ACPI_FAILURE(status)) { | 541 | if (ACPI_FAILURE(status)) { |
530 | ACPI_REPORT_ERROR(("Could not signal method semaphore\n")); | 542 | ACPI_REPORT_ERROR(("Could not signal method semaphore\n")); |
531 | status = AE_OK; | ||
532 | 543 | ||
533 | /* Ignore error and continue cleanup */ | 544 | /* Ignore error and continue cleanup */ |
534 | } | 545 | } |
@@ -539,9 +550,8 @@ acpi_status acpi_ds_terminate_control_method(struct acpi_walk_state *walk_state) | |||
539 | "*** Not deleting method namespace, there are still %d threads\n", | 550 | "*** Not deleting method namespace, there are still %d threads\n", |
540 | walk_state->method_desc->method. | 551 | walk_state->method_desc->method. |
541 | thread_count)); | 552 | thread_count)); |
542 | } | 553 | } else { /* This is the last executing thread */ |
543 | 554 | ||
544 | if (!walk_state->method_desc->method.thread_count) { | ||
545 | /* | 555 | /* |
546 | * Support to dynamically change a method from not_serialized to | 556 | * Support to dynamically change a method from not_serialized to |
547 | * Serialized if it appears that the method is written foolishly and | 557 | * Serialized if it appears that the method is written foolishly and |
@@ -574,7 +584,7 @@ acpi_status acpi_ds_terminate_control_method(struct acpi_walk_state *walk_state) | |||
574 | */ | 584 | */ |
575 | status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); | 585 | status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); |
576 | if (ACPI_FAILURE(status)) { | 586 | if (ACPI_FAILURE(status)) { |
577 | return_ACPI_STATUS(status); | 587 | goto exit; |
578 | } | 588 | } |
579 | 589 | ||
580 | if (method_node->child) { | 590 | if (method_node->child) { |
@@ -590,12 +600,9 @@ acpi_status acpi_ds_terminate_control_method(struct acpi_walk_state *walk_state) | |||
590 | status = acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); | 600 | status = acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); |
591 | acpi_ut_release_owner_id(&walk_state->method_desc->method. | 601 | acpi_ut_release_owner_id(&walk_state->method_desc->method. |
592 | owner_id); | 602 | owner_id); |
593 | |||
594 | if (ACPI_FAILURE(status)) { | ||
595 | return_ACPI_STATUS(status); | ||
596 | } | ||
597 | } | 603 | } |
598 | 604 | ||
599 | status = acpi_ut_release_mutex(ACPI_MTX_PARSER); | 605 | exit: |
600 | return_ACPI_STATUS(status); | 606 | (void)acpi_ut_release_mutex(ACPI_MTX_PARSER); |
607 | return_VOID; | ||
601 | } | 608 | } |