aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/dispatcher/dsmethod.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/acpi/dispatcher/dsmethod.c')
-rw-r--r--drivers/acpi/dispatcher/dsmethod.c337
1 files changed, 179 insertions, 158 deletions
diff --git a/drivers/acpi/dispatcher/dsmethod.c b/drivers/acpi/dispatcher/dsmethod.c
index 36c1ca0b9adb..58ad00b31ee9 100644
--- a/drivers/acpi/dispatcher/dsmethod.c
+++ b/drivers/acpi/dispatcher/dsmethod.c
@@ -53,133 +53,6 @@ ACPI_MODULE_NAME("dsmethod")
53 53
54/******************************************************************************* 54/*******************************************************************************
55 * 55 *
56 * FUNCTION: acpi_ds_parse_method
57 *
58 * PARAMETERS: Node - Method node
59 *
60 * RETURN: Status
61 *
62 * DESCRIPTION: Parse the AML that is associated with the method.
63 *
64 * MUTEX: Assumes parser is locked
65 *
66 ******************************************************************************/
67acpi_status acpi_ds_parse_method(struct acpi_namespace_node *node)
68{
69 acpi_status status;
70 union acpi_operand_object *obj_desc;
71 union acpi_parse_object *op;
72 struct acpi_walk_state *walk_state;
73
74 ACPI_FUNCTION_TRACE_PTR("ds_parse_method", node);
75
76 /* Parameter Validation */
77
78 if (!node) {
79 return_ACPI_STATUS(AE_NULL_ENTRY);
80 }
81
82 ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
83 "**** Parsing [%4.4s] **** named_obj=%p\n",
84 acpi_ut_get_node_name(node), node));
85
86 /* Extract the method object from the method Node */
87
88 obj_desc = acpi_ns_get_attached_object(node);
89 if (!obj_desc) {
90 return_ACPI_STATUS(AE_NULL_OBJECT);
91 }
92
93 /* Create a mutex for the method if there is a concurrency limit */
94
95 if ((obj_desc->method.concurrency != ACPI_INFINITE_CONCURRENCY) &&
96 (!obj_desc->method.semaphore)) {
97 status = acpi_os_create_semaphore(obj_desc->method.concurrency,
98 obj_desc->method.concurrency,
99 &obj_desc->method.semaphore);
100 if (ACPI_FAILURE(status)) {
101 return_ACPI_STATUS(status);
102 }
103 }
104
105 /*
106 * Allocate a new parser op to be the root of the parsed
107 * method tree
108 */
109 op = acpi_ps_alloc_op(AML_METHOD_OP);
110 if (!op) {
111 return_ACPI_STATUS(AE_NO_MEMORY);
112 }
113
114 /* Init new op with the method name and pointer back to the Node */
115
116 acpi_ps_set_name(op, node->name.integer);
117 op->common.node = node;
118
119 /*
120 * Get a new owner_id for objects created by this method. Namespace
121 * objects (such as Operation Regions) can be created during the
122 * first pass parse.
123 */
124 status = acpi_ut_allocate_owner_id(&obj_desc->method.owner_id);
125 if (ACPI_FAILURE(status)) {
126 goto cleanup;
127 }
128
129 /* Create and initialize a new walk state */
130
131 walk_state =
132 acpi_ds_create_walk_state(obj_desc->method.owner_id, NULL, NULL,
133 NULL);
134 if (!walk_state) {
135 status = AE_NO_MEMORY;
136 goto cleanup2;
137 }
138
139 status = acpi_ds_init_aml_walk(walk_state, op, node,
140 obj_desc->method.aml_start,
141 obj_desc->method.aml_length, NULL, 1);
142 if (ACPI_FAILURE(status)) {
143 acpi_ds_delete_walk_state(walk_state);
144 goto cleanup2;
145 }
146
147 /*
148 * Parse the method, first pass
149 *
150 * The first pass load is where newly declared named objects are added into
151 * the namespace. Actual evaluation of the named objects (what would be
152 * called a "second pass") happens during the actual execution of the
153 * method so that operands to the named objects can take on dynamic
154 * run-time values.
155 */
156 status = acpi_ps_parse_aml(walk_state);
157 if (ACPI_FAILURE(status)) {
158 goto cleanup2;
159 }
160
161 ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
162 "**** [%4.4s] Parsed **** named_obj=%p Op=%p\n",
163 acpi_ut_get_node_name(node), node, op));
164
165 /*
166 * Delete the parse tree. We simply re-parse the method for every
167 * execution since there isn't much overhead (compared to keeping lots
168 * of parse trees around)
169 */
170 acpi_ns_delete_namespace_subtree(node);
171 acpi_ns_delete_namespace_by_owner(obj_desc->method.owner_id);
172
173 cleanup2:
174 acpi_ut_release_owner_id(&obj_desc->method.owner_id);
175
176 cleanup:
177 acpi_ps_delete_parse_tree(op);
178 return_ACPI_STATUS(status);
179}
180
181/*******************************************************************************
182 *
183 * FUNCTION: acpi_ds_begin_method_execution 56 * FUNCTION: acpi_ds_begin_method_execution
184 * 57 *
185 * PARAMETERS: method_node - Node of the method 58 * PARAMETERS: method_node - Node of the method
@@ -193,7 +66,6 @@ acpi_status acpi_ds_parse_method(struct acpi_namespace_node *node)
193 * for clearance to execute. 66 * for clearance to execute.
194 * 67 *
195 ******************************************************************************/ 68 ******************************************************************************/
196
197acpi_status 69acpi_status
198acpi_ds_begin_method_execution(struct acpi_namespace_node *method_node, 70acpi_ds_begin_method_execution(struct acpi_namespace_node *method_node,
199 union acpi_operand_object *obj_desc, 71 union acpi_operand_object *obj_desc,
@@ -545,16 +417,54 @@ void acpi_ds_terminate_control_method(struct acpi_walk_state *walk_state)
545 } 417 }
546 } 418 }
547 419
420 /*
421 * There are no more threads executing this method. Perform
422 * additional cleanup.
423 *
424 * The method Node is stored in the walk state
425 */
426 method_node = walk_state->method_node;
427
428 /* Lock namespace for possible update */
429
430 status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
431 if (ACPI_FAILURE(status)) {
432 goto exit;
433 }
434
435 /*
436 * Delete any namespace entries created immediately underneath
437 * the method
438 */
439 if (method_node->child) {
440 acpi_ns_delete_namespace_subtree(method_node);
441 }
442
443 /*
444 * Delete any namespace entries created anywhere else within
445 * the namespace by the execution of this method
446 */
447 acpi_ns_delete_namespace_by_owner(walk_state->method_desc->method.
448 owner_id);
449 status = acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
450
451 /* Are there any other threads currently executing this method? */
452
548 if (walk_state->method_desc->method.thread_count) { 453 if (walk_state->method_desc->method.thread_count) {
454 /*
455 * Additional threads. Do not release the owner_id in this case,
456 * we immediately reuse it for the next thread executing this method
457 */
549 ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, 458 ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
550 "*** Not deleting method namespace, there are still %d threads\n", 459 "*** Completed execution of one thread, %d threads remaining\n",
551 walk_state->method_desc->method. 460 walk_state->method_desc->method.
552 thread_count)); 461 thread_count));
553 } else { /* This is the last executing thread */ 462 } else {
463 /* This is the only executing thread for this method */
554 464
555 /* 465 /*
556 * Support to dynamically change a method from not_serialized to 466 * Support to dynamically change a method from not_serialized to
557 * Serialized if it appears that the method is written foolishly and 467 * Serialized if it appears that the method is incorrectly written and
558 * does not support multiple thread execution. The best example of this 468 * does not support multiple thread execution. The best example of this
559 * is if such a method creates namespace objects and blocks. A second 469 * is if such a method creates namespace objects and blocks. A second
560 * thread will fail with an AE_ALREADY_EXISTS exception 470 * thread will fail with an AE_ALREADY_EXISTS exception
@@ -570,34 +480,8 @@ void acpi_ds_terminate_control_method(struct acpi_walk_state *walk_state)
570 semaphore); 480 semaphore);
571 } 481 }
572 482
573 /* 483 /* No more threads, we can free the owner_id */
574 * There are no more threads executing this method. Perform
575 * additional cleanup.
576 *
577 * The method Node is stored in the walk state
578 */
579 method_node = walk_state->method_node;
580
581 /*
582 * Delete any namespace entries created immediately underneath
583 * the method
584 */
585 status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
586 if (ACPI_FAILURE(status)) {
587 goto exit;
588 }
589
590 if (method_node->child) {
591 acpi_ns_delete_namespace_subtree(method_node);
592 }
593 484
594 /*
595 * Delete any namespace entries created anywhere else within
596 * the namespace
597 */
598 acpi_ns_delete_namespace_by_owner(walk_state->method_desc->
599 method.owner_id);
600 status = acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
601 acpi_ut_release_owner_id(&walk_state->method_desc->method. 485 acpi_ut_release_owner_id(&walk_state->method_desc->method.
602 owner_id); 486 owner_id);
603 } 487 }
@@ -606,3 +490,140 @@ void acpi_ds_terminate_control_method(struct acpi_walk_state *walk_state)
606 (void)acpi_ut_release_mutex(ACPI_MTX_PARSER); 490 (void)acpi_ut_release_mutex(ACPI_MTX_PARSER);
607 return_VOID; 491 return_VOID;
608} 492}
493
494#ifdef ACPI_INIT_PARSE_METHODS
495 /*
496 * Note 11/2005: Removed this code to parse all methods during table
497 * load because it causes problems if there are any errors during the
498 * parse. Also, it seems like overkill and we probably don't want to
499 * abort a table load because of an issue with a single method.
500 */
501
502/*******************************************************************************
503 *
504 * FUNCTION: acpi_ds_parse_method
505 *
506 * PARAMETERS: Node - Method node
507 *
508 * RETURN: Status
509 *
510 * DESCRIPTION: Parse the AML that is associated with the method.
511 *
512 * MUTEX: Assumes parser is locked
513 *
514 ******************************************************************************/
515
516acpi_status acpi_ds_parse_method(struct acpi_namespace_node *node)
517{
518 acpi_status status;
519 union acpi_operand_object *obj_desc;
520 union acpi_parse_object *op;
521 struct acpi_walk_state *walk_state;
522
523 ACPI_FUNCTION_TRACE_PTR("ds_parse_method", node);
524
525 /* Parameter Validation */
526
527 if (!node) {
528 return_ACPI_STATUS(AE_NULL_ENTRY);
529 }
530
531 ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
532 "**** Parsing [%4.4s] **** named_obj=%p\n",
533 acpi_ut_get_node_name(node), node));
534
535 /* Extract the method object from the method Node */
536
537 obj_desc = acpi_ns_get_attached_object(node);
538 if (!obj_desc) {
539 return_ACPI_STATUS(AE_NULL_OBJECT);
540 }
541
542 /* Create a mutex for the method if there is a concurrency limit */
543
544 if ((obj_desc->method.concurrency != ACPI_INFINITE_CONCURRENCY) &&
545 (!obj_desc->method.semaphore)) {
546 status = acpi_os_create_semaphore(obj_desc->method.concurrency,
547 obj_desc->method.concurrency,
548 &obj_desc->method.semaphore);
549 if (ACPI_FAILURE(status)) {
550 return_ACPI_STATUS(status);
551 }
552 }
553
554 /*
555 * Allocate a new parser op to be the root of the parsed
556 * method tree
557 */
558 op = acpi_ps_alloc_op(AML_METHOD_OP);
559 if (!op) {
560 return_ACPI_STATUS(AE_NO_MEMORY);
561 }
562
563 /* Init new op with the method name and pointer back to the Node */
564
565 acpi_ps_set_name(op, node->name.integer);
566 op->common.node = node;
567
568 /*
569 * Get a new owner_id for objects created by this method. Namespace
570 * objects (such as Operation Regions) can be created during the
571 * first pass parse.
572 */
573 status = acpi_ut_allocate_owner_id(&obj_desc->method.owner_id);
574 if (ACPI_FAILURE(status)) {
575 goto cleanup;
576 }
577
578 /* Create and initialize a new walk state */
579
580 walk_state =
581 acpi_ds_create_walk_state(obj_desc->method.owner_id, NULL, NULL,
582 NULL);
583 if (!walk_state) {
584 status = AE_NO_MEMORY;
585 goto cleanup2;
586 }
587
588 status = acpi_ds_init_aml_walk(walk_state, op, node,
589 obj_desc->method.aml_start,
590 obj_desc->method.aml_length, NULL, 1);
591 if (ACPI_FAILURE(status)) {
592 acpi_ds_delete_walk_state(walk_state);
593 goto cleanup2;
594 }
595
596 /*
597 * Parse the method, first pass
598 *
599 * The first pass load is where newly declared named objects are added into
600 * the namespace. Actual evaluation of the named objects (what would be
601 * called a "second pass") happens during the actual execution of the
602 * method so that operands to the named objects can take on dynamic
603 * run-time values.
604 */
605 status = acpi_ps_parse_aml(walk_state);
606 if (ACPI_FAILURE(status)) {
607 goto cleanup2;
608 }
609
610 ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
611 "**** [%4.4s] Parsed **** named_obj=%p Op=%p\n",
612 acpi_ut_get_node_name(node), node, op));
613
614 /*
615 * Delete the parse tree. We simply re-parse the method for every
616 * execution since there isn't much overhead (compared to keeping lots
617 * of parse trees around)
618 */
619 acpi_ns_delete_namespace_subtree(node);
620 acpi_ns_delete_namespace_by_owner(obj_desc->method.owner_id);
621
622 cleanup2:
623 acpi_ut_release_owner_id(&obj_desc->method.owner_id);
624
625 cleanup:
626 acpi_ps_delete_parse_tree(op);
627 return_ACPI_STATUS(status);
628}
629#endif