diff options
Diffstat (limited to 'drivers/acpi/dispatcher/dsmethod.c')
-rw-r--r-- | drivers/acpi/dispatcher/dsmethod.c | 67 |
1 files changed, 42 insertions, 25 deletions
diff --git a/drivers/acpi/dispatcher/dsmethod.c b/drivers/acpi/dispatcher/dsmethod.c index 9fc3f4c033eb..e344c06ed33f 100644 --- a/drivers/acpi/dispatcher/dsmethod.c +++ b/drivers/acpi/dispatcher/dsmethod.c | |||
@@ -58,12 +58,11 @@ | |||
58 | * | 58 | * |
59 | * FUNCTION: acpi_ds_parse_method | 59 | * FUNCTION: acpi_ds_parse_method |
60 | * | 60 | * |
61 | * PARAMETERS: obj_handle - Method node | 61 | * PARAMETERS: Node - Method node |
62 | * | 62 | * |
63 | * RETURN: Status | 63 | * RETURN: Status |
64 | * | 64 | * |
65 | * DESCRIPTION: Call the parser and parse the AML that is associated with the | 65 | * DESCRIPTION: Parse the AML that is associated with the method. |
66 | * method. | ||
67 | * | 66 | * |
68 | * MUTEX: Assumes parser is locked | 67 | * MUTEX: Assumes parser is locked |
69 | * | 68 | * |
@@ -71,31 +70,28 @@ | |||
71 | 70 | ||
72 | acpi_status | 71 | acpi_status |
73 | acpi_ds_parse_method ( | 72 | acpi_ds_parse_method ( |
74 | acpi_handle obj_handle) | 73 | struct acpi_namespace_node *node) |
75 | { | 74 | { |
76 | acpi_status status; | 75 | acpi_status status; |
77 | union acpi_operand_object *obj_desc; | 76 | union acpi_operand_object *obj_desc; |
78 | union acpi_parse_object *op; | 77 | union acpi_parse_object *op; |
79 | struct acpi_namespace_node *node; | ||
80 | acpi_owner_id owner_id; | ||
81 | struct acpi_walk_state *walk_state; | 78 | struct acpi_walk_state *walk_state; |
82 | 79 | ||
83 | 80 | ||
84 | ACPI_FUNCTION_TRACE_PTR ("ds_parse_method", obj_handle); | 81 | ACPI_FUNCTION_TRACE_PTR ("ds_parse_method", node); |
85 | 82 | ||
86 | 83 | ||
87 | /* Parameter Validation */ | 84 | /* Parameter Validation */ |
88 | 85 | ||
89 | if (!obj_handle) { | 86 | if (!node) { |
90 | return_ACPI_STATUS (AE_NULL_ENTRY); | 87 | return_ACPI_STATUS (AE_NULL_ENTRY); |
91 | } | 88 | } |
92 | 89 | ||
93 | ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "**** Parsing [%4.4s] **** named_obj=%p\n", | 90 | ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "**** Parsing [%4.4s] **** named_obj=%p\n", |
94 | acpi_ut_get_node_name (obj_handle), obj_handle)); | 91 | acpi_ut_get_node_name (node), node)); |
95 | 92 | ||
96 | /* Extract the method object from the method Node */ | 93 | /* Extract the method object from the method Node */ |
97 | 94 | ||
98 | node = (struct acpi_namespace_node *) obj_handle; | ||
99 | obj_desc = acpi_ns_get_attached_object (node); | 95 | obj_desc = acpi_ns_get_attached_object (node); |
100 | if (!obj_desc) { | 96 | if (!obj_desc) { |
101 | return_ACPI_STATUS (AE_NULL_OBJECT); | 97 | return_ACPI_STATUS (AE_NULL_OBJECT); |
@@ -132,14 +128,18 @@ acpi_ds_parse_method ( | |||
132 | * objects (such as Operation Regions) can be created during the | 128 | * objects (such as Operation Regions) can be created during the |
133 | * first pass parse. | 129 | * first pass parse. |
134 | */ | 130 | */ |
135 | owner_id = acpi_ut_allocate_owner_id (ACPI_OWNER_TYPE_METHOD); | 131 | status = acpi_ut_allocate_owner_id (&obj_desc->method.owner_id); |
136 | obj_desc->method.owning_id = owner_id; | 132 | if (ACPI_FAILURE (status)) { |
133 | goto cleanup; | ||
134 | } | ||
137 | 135 | ||
138 | /* Create and initialize a new walk state */ | 136 | /* Create and initialize a new walk state */ |
139 | 137 | ||
140 | walk_state = acpi_ds_create_walk_state (owner_id, NULL, NULL, NULL); | 138 | walk_state = acpi_ds_create_walk_state ( |
139 | obj_desc->method.owner_id, NULL, NULL, NULL); | ||
141 | if (!walk_state) { | 140 | if (!walk_state) { |
142 | return_ACPI_STATUS (AE_NO_MEMORY); | 141 | status = AE_NO_MEMORY; |
142 | goto cleanup2; | ||
143 | } | 143 | } |
144 | 144 | ||
145 | status = acpi_ds_init_aml_walk (walk_state, op, node, | 145 | status = acpi_ds_init_aml_walk (walk_state, op, node, |
@@ -147,7 +147,7 @@ acpi_ds_parse_method ( | |||
147 | obj_desc->method.aml_length, NULL, 1); | 147 | obj_desc->method.aml_length, NULL, 1); |
148 | if (ACPI_FAILURE (status)) { | 148 | if (ACPI_FAILURE (status)) { |
149 | acpi_ds_delete_walk_state (walk_state); | 149 | acpi_ds_delete_walk_state (walk_state); |
150 | return_ACPI_STATUS (status); | 150 | goto cleanup2; |
151 | } | 151 | } |
152 | 152 | ||
153 | /* | 153 | /* |
@@ -161,13 +161,25 @@ acpi_ds_parse_method ( | |||
161 | */ | 161 | */ |
162 | status = acpi_ps_parse_aml (walk_state); | 162 | status = acpi_ps_parse_aml (walk_state); |
163 | if (ACPI_FAILURE (status)) { | 163 | if (ACPI_FAILURE (status)) { |
164 | return_ACPI_STATUS (status); | 164 | goto cleanup2; |
165 | } | 165 | } |
166 | 166 | ||
167 | ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, | 167 | ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, |
168 | "**** [%4.4s] Parsed **** named_obj=%p Op=%p\n", | 168 | "**** [%4.4s] Parsed **** named_obj=%p Op=%p\n", |
169 | acpi_ut_get_node_name (obj_handle), obj_handle, op)); | 169 | acpi_ut_get_node_name (node), node, op)); |
170 | |||
171 | /* | ||
172 | * Delete the parse tree. We simply re-parse the method for every | ||
173 | * execution since there isn't much overhead (compared to keeping lots | ||
174 | * of parse trees around) | ||
175 | */ | ||
176 | acpi_ns_delete_namespace_subtree (node); | ||
177 | acpi_ns_delete_namespace_by_owner (obj_desc->method.owner_id); | ||
178 | |||
179 | cleanup2: | ||
180 | acpi_ut_release_owner_id (&obj_desc->method.owner_id); | ||
170 | 181 | ||
182 | cleanup: | ||
171 | acpi_ps_delete_parse_tree (op); | 183 | acpi_ps_delete_parse_tree (op); |
172 | return_ACPI_STATUS (status); | 184 | return_ACPI_STATUS (status); |
173 | } | 185 | } |
@@ -263,7 +275,7 @@ acpi_ds_call_control_method ( | |||
263 | { | 275 | { |
264 | acpi_status status; | 276 | acpi_status status; |
265 | struct acpi_namespace_node *method_node; | 277 | struct acpi_namespace_node *method_node; |
266 | struct acpi_walk_state *next_walk_state; | 278 | struct acpi_walk_state *next_walk_state = NULL; |
267 | union acpi_operand_object *obj_desc; | 279 | union acpi_operand_object *obj_desc; |
268 | struct acpi_parameter_info info; | 280 | struct acpi_parameter_info info; |
269 | u32 i; | 281 | u32 i; |
@@ -287,20 +299,23 @@ acpi_ds_call_control_method ( | |||
287 | return_ACPI_STATUS (AE_NULL_OBJECT); | 299 | return_ACPI_STATUS (AE_NULL_OBJECT); |
288 | } | 300 | } |
289 | 301 | ||
290 | obj_desc->method.owning_id = acpi_ut_allocate_owner_id (ACPI_OWNER_TYPE_METHOD); | 302 | status = acpi_ut_allocate_owner_id (&obj_desc->method.owner_id); |
303 | if (ACPI_FAILURE (status)) { | ||
304 | return_ACPI_STATUS (status); | ||
305 | } | ||
291 | 306 | ||
292 | /* Init for new method, wait on concurrency semaphore */ | 307 | /* Init for new method, wait on concurrency semaphore */ |
293 | 308 | ||
294 | status = acpi_ds_begin_method_execution (method_node, obj_desc, | 309 | status = acpi_ds_begin_method_execution (method_node, obj_desc, |
295 | this_walk_state->method_node); | 310 | this_walk_state->method_node); |
296 | if (ACPI_FAILURE (status)) { | 311 | if (ACPI_FAILURE (status)) { |
297 | return_ACPI_STATUS (status); | 312 | goto cleanup; |
298 | } | 313 | } |
299 | 314 | ||
300 | if (!(obj_desc->method.method_flags & AML_METHOD_INTERNAL_ONLY)) { | 315 | if (!(obj_desc->method.method_flags & AML_METHOD_INTERNAL_ONLY)) { |
301 | /* 1) Parse: Create a new walk state for the preempting walk */ | 316 | /* 1) Parse: Create a new walk state for the preempting walk */ |
302 | 317 | ||
303 | next_walk_state = acpi_ds_create_walk_state (obj_desc->method.owning_id, | 318 | next_walk_state = acpi_ds_create_walk_state (obj_desc->method.owner_id, |
304 | op, obj_desc, NULL); | 319 | op, obj_desc, NULL); |
305 | if (!next_walk_state) { | 320 | if (!next_walk_state) { |
306 | return_ACPI_STATUS (AE_NO_MEMORY); | 321 | return_ACPI_STATUS (AE_NO_MEMORY); |
@@ -330,7 +345,7 @@ acpi_ds_call_control_method ( | |||
330 | 345 | ||
331 | /* 2) Execute: Create a new state for the preempting walk */ | 346 | /* 2) Execute: Create a new state for the preempting walk */ |
332 | 347 | ||
333 | next_walk_state = acpi_ds_create_walk_state (obj_desc->method.owning_id, | 348 | next_walk_state = acpi_ds_create_walk_state (obj_desc->method.owner_id, |
334 | NULL, obj_desc, thread); | 349 | NULL, obj_desc, thread); |
335 | if (!next_walk_state) { | 350 | if (!next_walk_state) { |
336 | status = AE_NO_MEMORY; | 351 | status = AE_NO_MEMORY; |
@@ -381,6 +396,7 @@ acpi_ds_call_control_method ( | |||
381 | /* On error, we must delete the new walk state */ | 396 | /* On error, we must delete the new walk state */ |
382 | 397 | ||
383 | cleanup: | 398 | cleanup: |
399 | acpi_ut_release_owner_id (&obj_desc->method.owner_id); | ||
384 | if (next_walk_state && (next_walk_state->method_desc)) { | 400 | if (next_walk_state && (next_walk_state->method_desc)) { |
385 | /* Decrement the thread count on the method parse tree */ | 401 | /* Decrement the thread count on the method parse tree */ |
386 | 402 | ||
@@ -552,8 +568,7 @@ acpi_ds_terminate_control_method ( | |||
552 | */ | 568 | */ |
553 | if ((walk_state->method_desc->method.concurrency == 1) && | 569 | if ((walk_state->method_desc->method.concurrency == 1) && |
554 | (!walk_state->method_desc->method.semaphore)) { | 570 | (!walk_state->method_desc->method.semaphore)) { |
555 | status = acpi_os_create_semaphore (1, | 571 | status = acpi_os_create_semaphore (1, 1, |
556 | 1, | ||
557 | &walk_state->method_desc->method.semaphore); | 572 | &walk_state->method_desc->method.semaphore); |
558 | } | 573 | } |
559 | 574 | ||
@@ -582,8 +597,10 @@ acpi_ds_terminate_control_method ( | |||
582 | * Delete any namespace entries created anywhere else within | 597 | * Delete any namespace entries created anywhere else within |
583 | * the namespace | 598 | * the namespace |
584 | */ | 599 | */ |
585 | acpi_ns_delete_namespace_by_owner (walk_state->method_desc->method.owning_id); | 600 | acpi_ns_delete_namespace_by_owner (walk_state->method_desc->method.owner_id); |
586 | status = acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); | 601 | status = acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); |
602 | acpi_ut_release_owner_id (&walk_state->method_desc->method.owner_id); | ||
603 | |||
587 | if (ACPI_FAILURE (status)) { | 604 | if (ACPI_FAILURE (status)) { |
588 | return_ACPI_STATUS (status); | 605 | return_ACPI_STATUS (status); |
589 | } | 606 | } |