diff options
Diffstat (limited to 'drivers/acpi/dispatcher/dsmethod.c')
-rw-r--r-- | drivers/acpi/dispatcher/dsmethod.c | 404 |
1 files changed, 208 insertions, 196 deletions
diff --git a/drivers/acpi/dispatcher/dsmethod.c b/drivers/acpi/dispatcher/dsmethod.c index 9fc3f4c033eb..36c1ca0b9adb 100644 --- a/drivers/acpi/dispatcher/dsmethod.c +++ b/drivers/acpi/dispatcher/dsmethod.c | |||
@@ -41,7 +41,6 @@ | |||
41 | * POSSIBILITY OF SUCH DAMAGES. | 41 | * POSSIBILITY OF SUCH DAMAGES. |
42 | */ | 42 | */ |
43 | 43 | ||
44 | |||
45 | #include <acpi/acpi.h> | 44 | #include <acpi/acpi.h> |
46 | #include <acpi/acparser.h> | 45 | #include <acpi/acparser.h> |
47 | #include <acpi/amlcode.h> | 46 | #include <acpi/amlcode.h> |
@@ -49,67 +48,57 @@ | |||
49 | #include <acpi/acinterp.h> | 48 | #include <acpi/acinterp.h> |
50 | #include <acpi/acnamesp.h> | 49 | #include <acpi/acnamesp.h> |
51 | 50 | ||
52 | |||
53 | #define _COMPONENT ACPI_DISPATCHER | 51 | #define _COMPONENT ACPI_DISPATCHER |
54 | ACPI_MODULE_NAME ("dsmethod") | 52 | ACPI_MODULE_NAME("dsmethod") |
55 | |||
56 | 53 | ||
57 | /******************************************************************************* | 54 | /******************************************************************************* |
58 | * | 55 | * |
59 | * FUNCTION: acpi_ds_parse_method | 56 | * FUNCTION: acpi_ds_parse_method |
60 | * | 57 | * |
61 | * PARAMETERS: obj_handle - Method node | 58 | * PARAMETERS: Node - Method node |
62 | * | 59 | * |
63 | * RETURN: Status | 60 | * RETURN: Status |
64 | * | 61 | * |
65 | * DESCRIPTION: Call the parser and parse the AML that is associated with the | 62 | * DESCRIPTION: Parse the AML that is associated with the method. |
66 | * method. | ||
67 | * | 63 | * |
68 | * MUTEX: Assumes parser is locked | 64 | * MUTEX: Assumes parser is locked |
69 | * | 65 | * |
70 | ******************************************************************************/ | 66 | ******************************************************************************/ |
71 | 67 | acpi_status acpi_ds_parse_method(struct acpi_namespace_node *node) | |
72 | acpi_status | ||
73 | acpi_ds_parse_method ( | ||
74 | acpi_handle obj_handle) | ||
75 | { | 68 | { |
76 | acpi_status status; | 69 | acpi_status status; |
77 | union acpi_operand_object *obj_desc; | 70 | union acpi_operand_object *obj_desc; |
78 | union acpi_parse_object *op; | 71 | union acpi_parse_object *op; |
79 | struct acpi_namespace_node *node; | 72 | struct acpi_walk_state *walk_state; |
80 | acpi_owner_id owner_id; | ||
81 | struct acpi_walk_state *walk_state; | ||
82 | |||
83 | |||
84 | ACPI_FUNCTION_TRACE_PTR ("ds_parse_method", obj_handle); | ||
85 | 73 | ||
74 | ACPI_FUNCTION_TRACE_PTR("ds_parse_method", node); | ||
86 | 75 | ||
87 | /* Parameter Validation */ | 76 | /* Parameter Validation */ |
88 | 77 | ||
89 | if (!obj_handle) { | 78 | if (!node) { |
90 | return_ACPI_STATUS (AE_NULL_ENTRY); | 79 | return_ACPI_STATUS(AE_NULL_ENTRY); |
91 | } | 80 | } |
92 | 81 | ||
93 | ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "**** Parsing [%4.4s] **** named_obj=%p\n", | 82 | ACPI_DEBUG_PRINT((ACPI_DB_PARSE, |
94 | acpi_ut_get_node_name (obj_handle), obj_handle)); | 83 | "**** Parsing [%4.4s] **** named_obj=%p\n", |
84 | acpi_ut_get_node_name(node), node)); | ||
95 | 85 | ||
96 | /* Extract the method object from the method Node */ | 86 | /* Extract the method object from the method Node */ |
97 | 87 | ||
98 | node = (struct acpi_namespace_node *) obj_handle; | 88 | obj_desc = acpi_ns_get_attached_object(node); |
99 | obj_desc = acpi_ns_get_attached_object (node); | ||
100 | if (!obj_desc) { | 89 | if (!obj_desc) { |
101 | return_ACPI_STATUS (AE_NULL_OBJECT); | 90 | return_ACPI_STATUS(AE_NULL_OBJECT); |
102 | } | 91 | } |
103 | 92 | ||
104 | /* Create a mutex for the method if there is a concurrency limit */ | 93 | /* Create a mutex for the method if there is a concurrency limit */ |
105 | 94 | ||
106 | if ((obj_desc->method.concurrency != ACPI_INFINITE_CONCURRENCY) && | 95 | if ((obj_desc->method.concurrency != ACPI_INFINITE_CONCURRENCY) && |
107 | (!obj_desc->method.semaphore)) { | 96 | (!obj_desc->method.semaphore)) { |
108 | status = acpi_os_create_semaphore (obj_desc->method.concurrency, | 97 | status = acpi_os_create_semaphore(obj_desc->method.concurrency, |
109 | obj_desc->method.concurrency, | 98 | obj_desc->method.concurrency, |
110 | &obj_desc->method.semaphore); | 99 | &obj_desc->method.semaphore); |
111 | if (ACPI_FAILURE (status)) { | 100 | if (ACPI_FAILURE(status)) { |
112 | return_ACPI_STATUS (status); | 101 | return_ACPI_STATUS(status); |
113 | } | 102 | } |
114 | } | 103 | } |
115 | 104 | ||
@@ -117,14 +106,14 @@ acpi_ds_parse_method ( | |||
117 | * Allocate a new parser op to be the root of the parsed | 106 | * Allocate a new parser op to be the root of the parsed |
118 | * method tree | 107 | * method tree |
119 | */ | 108 | */ |
120 | op = acpi_ps_alloc_op (AML_METHOD_OP); | 109 | op = acpi_ps_alloc_op(AML_METHOD_OP); |
121 | if (!op) { | 110 | if (!op) { |
122 | return_ACPI_STATUS (AE_NO_MEMORY); | 111 | return_ACPI_STATUS(AE_NO_MEMORY); |
123 | } | 112 | } |
124 | 113 | ||
125 | /* Init new op with the method name and pointer back to the Node */ | 114 | /* Init new op with the method name and pointer back to the Node */ |
126 | 115 | ||
127 | acpi_ps_set_name (op, node->name.integer); | 116 | acpi_ps_set_name(op, node->name.integer); |
128 | op->common.node = node; | 117 | op->common.node = node; |
129 | 118 | ||
130 | /* | 119 | /* |
@@ -132,22 +121,27 @@ acpi_ds_parse_method ( | |||
132 | * objects (such as Operation Regions) can be created during the | 121 | * objects (such as Operation Regions) can be created during the |
133 | * first pass parse. | 122 | * first pass parse. |
134 | */ | 123 | */ |
135 | owner_id = acpi_ut_allocate_owner_id (ACPI_OWNER_TYPE_METHOD); | 124 | status = acpi_ut_allocate_owner_id(&obj_desc->method.owner_id); |
136 | obj_desc->method.owning_id = owner_id; | 125 | if (ACPI_FAILURE(status)) { |
126 | goto cleanup; | ||
127 | } | ||
137 | 128 | ||
138 | /* Create and initialize a new walk state */ | 129 | /* Create and initialize a new walk state */ |
139 | 130 | ||
140 | walk_state = acpi_ds_create_walk_state (owner_id, NULL, NULL, NULL); | 131 | walk_state = |
132 | acpi_ds_create_walk_state(obj_desc->method.owner_id, NULL, NULL, | ||
133 | NULL); | ||
141 | if (!walk_state) { | 134 | if (!walk_state) { |
142 | return_ACPI_STATUS (AE_NO_MEMORY); | 135 | status = AE_NO_MEMORY; |
136 | goto cleanup2; | ||
143 | } | 137 | } |
144 | 138 | ||
145 | status = acpi_ds_init_aml_walk (walk_state, op, node, | 139 | status = acpi_ds_init_aml_walk(walk_state, op, node, |
146 | obj_desc->method.aml_start, | 140 | obj_desc->method.aml_start, |
147 | obj_desc->method.aml_length, NULL, 1); | 141 | obj_desc->method.aml_length, NULL, 1); |
148 | if (ACPI_FAILURE (status)) { | 142 | if (ACPI_FAILURE(status)) { |
149 | acpi_ds_delete_walk_state (walk_state); | 143 | acpi_ds_delete_walk_state(walk_state); |
150 | return_ACPI_STATUS (status); | 144 | goto cleanup2; |
151 | } | 145 | } |
152 | 146 | ||
153 | /* | 147 | /* |
@@ -159,19 +153,30 @@ acpi_ds_parse_method ( | |||
159 | * method so that operands to the named objects can take on dynamic | 153 | * method so that operands to the named objects can take on dynamic |
160 | * run-time values. | 154 | * run-time values. |
161 | */ | 155 | */ |
162 | status = acpi_ps_parse_aml (walk_state); | 156 | status = acpi_ps_parse_aml(walk_state); |
163 | if (ACPI_FAILURE (status)) { | 157 | if (ACPI_FAILURE(status)) { |
164 | return_ACPI_STATUS (status); | 158 | goto cleanup2; |
165 | } | 159 | } |
166 | 160 | ||
167 | ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, | 161 | ACPI_DEBUG_PRINT((ACPI_DB_PARSE, |
168 | "**** [%4.4s] Parsed **** named_obj=%p Op=%p\n", | 162 | "**** [%4.4s] Parsed **** named_obj=%p Op=%p\n", |
169 | acpi_ut_get_node_name (obj_handle), obj_handle, op)); | 163 | acpi_ut_get_node_name(node), node, op)); |
170 | 164 | ||
171 | acpi_ps_delete_parse_tree (op); | 165 | /* |
172 | return_ACPI_STATUS (status); | 166 | * Delete the parse tree. We simply re-parse the method for every |
173 | } | 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); | ||
174 | 175 | ||
176 | cleanup: | ||
177 | acpi_ps_delete_parse_tree(op); | ||
178 | return_ACPI_STATUS(status); | ||
179 | } | ||
175 | 180 | ||
176 | /******************************************************************************* | 181 | /******************************************************************************* |
177 | * | 182 | * |
@@ -190,19 +195,23 @@ acpi_ds_parse_method ( | |||
190 | ******************************************************************************/ | 195 | ******************************************************************************/ |
191 | 196 | ||
192 | acpi_status | 197 | acpi_status |
193 | acpi_ds_begin_method_execution ( | 198 | acpi_ds_begin_method_execution(struct acpi_namespace_node *method_node, |
194 | struct acpi_namespace_node *method_node, | 199 | union acpi_operand_object *obj_desc, |
195 | union acpi_operand_object *obj_desc, | 200 | struct acpi_namespace_node *calling_method_node) |
196 | struct acpi_namespace_node *calling_method_node) | ||
197 | { | 201 | { |
198 | acpi_status status = AE_OK; | 202 | acpi_status status = AE_OK; |
199 | 203 | ||
204 | ACPI_FUNCTION_TRACE_PTR("ds_begin_method_execution", method_node); | ||
200 | 205 | ||
201 | ACPI_FUNCTION_TRACE_PTR ("ds_begin_method_execution", method_node); | 206 | if (!method_node) { |
207 | return_ACPI_STATUS(AE_NULL_ENTRY); | ||
208 | } | ||
202 | 209 | ||
210 | /* Prevent wraparound of thread count */ | ||
203 | 211 | ||
204 | if (!method_node) { | 212 | if (obj_desc->method.thread_count == ACPI_UINT8_MAX) { |
205 | return_ACPI_STATUS (AE_NULL_ENTRY); | 213 | ACPI_REPORT_ERROR(("Method reached maximum reentrancy limit (255)\n")); |
214 | return_ACPI_STATUS(AE_AML_METHOD_LIMIT); | ||
206 | } | 215 | } |
207 | 216 | ||
208 | /* | 217 | /* |
@@ -219,8 +228,9 @@ acpi_ds_begin_method_execution ( | |||
219 | * thread that is making recursive method calls. | 228 | * thread that is making recursive method calls. |
220 | */ | 229 | */ |
221 | if (method_node == calling_method_node) { | 230 | if (method_node == calling_method_node) { |
222 | if (obj_desc->method.thread_count >= obj_desc->method.concurrency) { | 231 | if (obj_desc->method.thread_count >= |
223 | return_ACPI_STATUS (AE_AML_METHOD_LIMIT); | 232 | obj_desc->method.concurrency) { |
233 | return_ACPI_STATUS(AE_AML_METHOD_LIMIT); | ||
224 | } | 234 | } |
225 | } | 235 | } |
226 | 236 | ||
@@ -228,8 +238,21 @@ acpi_ds_begin_method_execution ( | |||
228 | * Get a unit from the method semaphore. This releases the | 238 | * Get a unit from the method semaphore. This releases the |
229 | * interpreter if we block | 239 | * interpreter if we block |
230 | */ | 240 | */ |
231 | status = acpi_ex_system_wait_semaphore (obj_desc->method.semaphore, | 241 | status = |
232 | ACPI_WAIT_FOREVER); | 242 | acpi_ex_system_wait_semaphore(obj_desc->method.semaphore, |
243 | ACPI_WAIT_FOREVER); | ||
244 | } | ||
245 | |||
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 | } | ||
233 | } | 256 | } |
234 | 257 | ||
235 | /* | 258 | /* |
@@ -237,10 +260,9 @@ acpi_ds_begin_method_execution ( | |||
237 | * reentered one more time (even if it is the same thread) | 260 | * reentered one more time (even if it is the same thread) |
238 | */ | 261 | */ |
239 | obj_desc->method.thread_count++; | 262 | obj_desc->method.thread_count++; |
240 | return_ACPI_STATUS (status); | 263 | return_ACPI_STATUS(status); |
241 | } | 264 | } |
242 | 265 | ||
243 | |||
244 | /******************************************************************************* | 266 | /******************************************************************************* |
245 | * | 267 | * |
246 | * FUNCTION: acpi_ds_call_control_method | 268 | * FUNCTION: acpi_ds_call_control_method |
@@ -256,101 +278,99 @@ acpi_ds_begin_method_execution ( | |||
256 | ******************************************************************************/ | 278 | ******************************************************************************/ |
257 | 279 | ||
258 | acpi_status | 280 | acpi_status |
259 | acpi_ds_call_control_method ( | 281 | acpi_ds_call_control_method(struct acpi_thread_state *thread, |
260 | struct acpi_thread_state *thread, | 282 | struct acpi_walk_state *this_walk_state, |
261 | struct acpi_walk_state *this_walk_state, | 283 | union acpi_parse_object *op) |
262 | union acpi_parse_object *op) | ||
263 | { | 284 | { |
264 | acpi_status status; | 285 | acpi_status status; |
265 | struct acpi_namespace_node *method_node; | 286 | struct acpi_namespace_node *method_node; |
266 | struct acpi_walk_state *next_walk_state; | 287 | struct acpi_walk_state *next_walk_state = NULL; |
267 | union acpi_operand_object *obj_desc; | 288 | union acpi_operand_object *obj_desc; |
268 | struct acpi_parameter_info info; | 289 | struct acpi_parameter_info info; |
269 | u32 i; | 290 | u32 i; |
270 | |||
271 | 291 | ||
272 | ACPI_FUNCTION_TRACE_PTR ("ds_call_control_method", this_walk_state); | 292 | ACPI_FUNCTION_TRACE_PTR("ds_call_control_method", this_walk_state); |
273 | 293 | ||
274 | ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Execute method %p, currentstate=%p\n", | 294 | ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, |
275 | this_walk_state->prev_op, this_walk_state)); | 295 | "Execute method %p, currentstate=%p\n", |
296 | this_walk_state->prev_op, this_walk_state)); | ||
276 | 297 | ||
277 | /* | 298 | /* |
278 | * Get the namespace entry for the control method we are about to call | 299 | * Get the namespace entry for the control method we are about to call |
279 | */ | 300 | */ |
280 | method_node = this_walk_state->method_call_node; | 301 | method_node = this_walk_state->method_call_node; |
281 | if (!method_node) { | 302 | if (!method_node) { |
282 | return_ACPI_STATUS (AE_NULL_ENTRY); | 303 | return_ACPI_STATUS(AE_NULL_ENTRY); |
283 | } | 304 | } |
284 | 305 | ||
285 | obj_desc = acpi_ns_get_attached_object (method_node); | 306 | obj_desc = acpi_ns_get_attached_object(method_node); |
286 | if (!obj_desc) { | 307 | if (!obj_desc) { |
287 | return_ACPI_STATUS (AE_NULL_OBJECT); | 308 | return_ACPI_STATUS(AE_NULL_OBJECT); |
288 | } | 309 | } |
289 | 310 | ||
290 | obj_desc->method.owning_id = acpi_ut_allocate_owner_id (ACPI_OWNER_TYPE_METHOD); | ||
291 | |||
292 | /* Init for new method, wait on concurrency semaphore */ | 311 | /* Init for new method, wait on concurrency semaphore */ |
293 | 312 | ||
294 | status = acpi_ds_begin_method_execution (method_node, obj_desc, | 313 | status = acpi_ds_begin_method_execution(method_node, obj_desc, |
295 | this_walk_state->method_node); | 314 | this_walk_state->method_node); |
296 | if (ACPI_FAILURE (status)) { | 315 | if (ACPI_FAILURE(status)) { |
297 | return_ACPI_STATUS (status); | 316 | goto cleanup; |
298 | } | 317 | } |
299 | 318 | ||
300 | if (!(obj_desc->method.method_flags & AML_METHOD_INTERNAL_ONLY)) { | 319 | if (!(obj_desc->method.method_flags & AML_METHOD_INTERNAL_ONLY)) { |
301 | /* 1) Parse: Create a new walk state for the preempting walk */ | 320 | /* 1) Parse: Create a new walk state for the preempting walk */ |
302 | 321 | ||
303 | next_walk_state = acpi_ds_create_walk_state (obj_desc->method.owning_id, | 322 | next_walk_state = |
304 | op, obj_desc, NULL); | 323 | acpi_ds_create_walk_state(obj_desc->method.owner_id, op, |
324 | obj_desc, NULL); | ||
305 | if (!next_walk_state) { | 325 | if (!next_walk_state) { |
306 | return_ACPI_STATUS (AE_NO_MEMORY); | 326 | return_ACPI_STATUS(AE_NO_MEMORY); |
307 | } | 327 | } |
308 | 328 | ||
309 | /* Create and init a Root Node */ | 329 | /* Create and init a Root Node */ |
310 | 330 | ||
311 | op = acpi_ps_create_scope_op (); | 331 | op = acpi_ps_create_scope_op(); |
312 | if (!op) { | 332 | if (!op) { |
313 | status = AE_NO_MEMORY; | 333 | status = AE_NO_MEMORY; |
314 | goto cleanup; | 334 | goto cleanup; |
315 | } | 335 | } |
316 | 336 | ||
317 | status = acpi_ds_init_aml_walk (next_walk_state, op, method_node, | 337 | status = acpi_ds_init_aml_walk(next_walk_state, op, method_node, |
318 | obj_desc->method.aml_start, obj_desc->method.aml_length, | 338 | obj_desc->method.aml_start, |
319 | NULL, 1); | 339 | obj_desc->method.aml_length, |
320 | if (ACPI_FAILURE (status)) { | 340 | NULL, 1); |
321 | acpi_ds_delete_walk_state (next_walk_state); | 341 | if (ACPI_FAILURE(status)) { |
342 | acpi_ds_delete_walk_state(next_walk_state); | ||
322 | goto cleanup; | 343 | goto cleanup; |
323 | } | 344 | } |
324 | 345 | ||
325 | /* Begin AML parse */ | 346 | /* Begin AML parse */ |
326 | 347 | ||
327 | status = acpi_ps_parse_aml (next_walk_state); | 348 | status = acpi_ps_parse_aml(next_walk_state); |
328 | acpi_ps_delete_parse_tree (op); | 349 | acpi_ps_delete_parse_tree(op); |
329 | } | 350 | } |
330 | 351 | ||
331 | /* 2) Execute: Create a new state for the preempting walk */ | 352 | /* 2) Execute: Create a new state for the preempting walk */ |
332 | 353 | ||
333 | next_walk_state = acpi_ds_create_walk_state (obj_desc->method.owning_id, | 354 | next_walk_state = acpi_ds_create_walk_state(obj_desc->method.owner_id, |
334 | NULL, obj_desc, thread); | 355 | NULL, obj_desc, thread); |
335 | if (!next_walk_state) { | 356 | if (!next_walk_state) { |
336 | status = AE_NO_MEMORY; | 357 | status = AE_NO_MEMORY; |
337 | goto cleanup; | 358 | goto cleanup; |
338 | } | 359 | } |
339 | /* | 360 | /* |
340 | * 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 |
341 | * stack. Operands on the previous walk state stack always | 362 | * stack. Operands on the previous walk state stack always |
342 | * start at index 0. | 363 | * start at index 0. Also, null terminate the list of arguments |
343 | * Null terminate the list of arguments | ||
344 | */ | 364 | */ |
345 | this_walk_state->operands [this_walk_state->num_operands] = NULL; | 365 | this_walk_state->operands[this_walk_state->num_operands] = NULL; |
346 | 366 | ||
347 | info.parameters = &this_walk_state->operands[0]; | 367 | info.parameters = &this_walk_state->operands[0]; |
348 | info.parameter_type = ACPI_PARAM_ARGS; | 368 | info.parameter_type = ACPI_PARAM_ARGS; |
349 | 369 | ||
350 | status = acpi_ds_init_aml_walk (next_walk_state, NULL, method_node, | 370 | status = acpi_ds_init_aml_walk(next_walk_state, NULL, method_node, |
351 | obj_desc->method.aml_start, obj_desc->method.aml_length, | 371 | obj_desc->method.aml_start, |
352 | &info, 3); | 372 | obj_desc->method.aml_length, &info, 3); |
353 | if (ACPI_FAILURE (status)) { | 373 | if (ACPI_FAILURE(status)) { |
354 | goto cleanup; | 374 | goto cleanup; |
355 | } | 375 | } |
356 | 376 | ||
@@ -359,38 +379,37 @@ acpi_ds_call_control_method ( | |||
359 | * (they were copied to new objects) | 379 | * (they were copied to new objects) |
360 | */ | 380 | */ |
361 | for (i = 0; i < obj_desc->method.param_count; i++) { | 381 | for (i = 0; i < obj_desc->method.param_count; i++) { |
362 | acpi_ut_remove_reference (this_walk_state->operands [i]); | 382 | acpi_ut_remove_reference(this_walk_state->operands[i]); |
363 | this_walk_state->operands [i] = NULL; | 383 | this_walk_state->operands[i] = NULL; |
364 | } | 384 | } |
365 | 385 | ||
366 | /* Clear the operand stack */ | 386 | /* Clear the operand stack */ |
367 | 387 | ||
368 | this_walk_state->num_operands = 0; | 388 | this_walk_state->num_operands = 0; |
369 | 389 | ||
370 | ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, | 390 | ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, |
371 | "Starting nested execution, newstate=%p\n", next_walk_state)); | 391 | "Starting nested execution, newstate=%p\n", |
392 | next_walk_state)); | ||
372 | 393 | ||
373 | if (obj_desc->method.method_flags & AML_METHOD_INTERNAL_ONLY) { | 394 | if (obj_desc->method.method_flags & AML_METHOD_INTERNAL_ONLY) { |
374 | status = obj_desc->method.implementation (next_walk_state); | 395 | status = obj_desc->method.implementation(next_walk_state); |
375 | return_ACPI_STATUS (status); | ||
376 | } | 396 | } |
377 | 397 | ||
378 | return_ACPI_STATUS (AE_OK); | 398 | return_ACPI_STATUS(status); |
379 | |||
380 | 399 | ||
381 | /* On error, we must delete the new walk state */ | 400 | cleanup: |
401 | /* Decrement the thread count on the method parse tree */ | ||
382 | 402 | ||
383 | cleanup: | ||
384 | if (next_walk_state && (next_walk_state->method_desc)) { | 403 | if (next_walk_state && (next_walk_state->method_desc)) { |
385 | /* Decrement the thread count on the method parse tree */ | 404 | next_walk_state->method_desc->method.thread_count--; |
386 | |||
387 | next_walk_state->method_desc->method.thread_count--; | ||
388 | } | 405 | } |
389 | (void) acpi_ds_terminate_control_method (next_walk_state); | ||
390 | acpi_ds_delete_walk_state (next_walk_state); | ||
391 | return_ACPI_STATUS (status); | ||
392 | } | ||
393 | 406 | ||
407 | /* On error, we must delete the new walk state */ | ||
408 | |||
409 | acpi_ds_terminate_control_method(next_walk_state); | ||
410 | acpi_ds_delete_walk_state(next_walk_state); | ||
411 | return_ACPI_STATUS(status); | ||
412 | } | ||
394 | 413 | ||
395 | /******************************************************************************* | 414 | /******************************************************************************* |
396 | * | 415 | * |
@@ -407,25 +426,22 @@ cleanup: | |||
407 | ******************************************************************************/ | 426 | ******************************************************************************/ |
408 | 427 | ||
409 | acpi_status | 428 | acpi_status |
410 | acpi_ds_restart_control_method ( | 429 | acpi_ds_restart_control_method(struct acpi_walk_state *walk_state, |
411 | struct acpi_walk_state *walk_state, | 430 | union acpi_operand_object *return_desc) |
412 | union acpi_operand_object *return_desc) | ||
413 | { | 431 | { |
414 | acpi_status status; | 432 | acpi_status status; |
415 | 433 | ||
434 | ACPI_FUNCTION_TRACE_PTR("ds_restart_control_method", walk_state); | ||
416 | 435 | ||
417 | ACPI_FUNCTION_TRACE_PTR ("ds_restart_control_method", walk_state); | 436 | ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, |
437 | "****Restart [%4.4s] Op %p return_value_from_callee %p\n", | ||
438 | (char *)&walk_state->method_node->name, | ||
439 | walk_state->method_call_op, return_desc)); | ||
418 | 440 | ||
419 | 441 | ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, | |
420 | ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, | 442 | " return_from_this_method_used?=%X res_stack %p Walk %p\n", |
421 | "****Restart [%4.4s] Op %p return_value_from_callee %p\n", | 443 | walk_state->return_used, |
422 | (char *) &walk_state->method_node->name, walk_state->method_call_op, | 444 | walk_state->results, walk_state)); |
423 | return_desc)); | ||
424 | |||
425 | ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, | ||
426 | " return_from_this_method_used?=%X res_stack %p Walk %p\n", | ||
427 | walk_state->return_used, | ||
428 | walk_state->results, walk_state)); | ||
429 | 445 | ||
430 | /* Did the called method return a value? */ | 446 | /* Did the called method return a value? */ |
431 | 447 | ||
@@ -435,10 +451,10 @@ acpi_ds_restart_control_method ( | |||
435 | if (walk_state->return_used) { | 451 | if (walk_state->return_used) { |
436 | /* Save the return value from the previous method */ | 452 | /* Save the return value from the previous method */ |
437 | 453 | ||
438 | status = acpi_ds_result_push (return_desc, walk_state); | 454 | status = acpi_ds_result_push(return_desc, walk_state); |
439 | if (ACPI_FAILURE (status)) { | 455 | if (ACPI_FAILURE(status)) { |
440 | acpi_ut_remove_reference (return_desc); | 456 | acpi_ut_remove_reference(return_desc); |
441 | return_ACPI_STATUS (status); | 457 | return_ACPI_STATUS(status); |
442 | } | 458 | } |
443 | 459 | ||
444 | /* | 460 | /* |
@@ -456,26 +472,26 @@ acpi_ds_restart_control_method ( | |||
456 | * NOTE: this is optional because the ASL language does not actually | 472 | * NOTE: this is optional because the ASL language does not actually |
457 | * support this behavior. | 473 | * support this behavior. |
458 | */ | 474 | */ |
459 | else if (!acpi_ds_do_implicit_return (return_desc, walk_state, FALSE)) { | 475 | else if (!acpi_ds_do_implicit_return |
476 | (return_desc, walk_state, FALSE)) { | ||
460 | /* | 477 | /* |
461 | * Delete the return value if it will not be used by the | 478 | * Delete the return value if it will not be used by the |
462 | * calling method | 479 | * calling method |
463 | */ | 480 | */ |
464 | acpi_ut_remove_reference (return_desc); | 481 | acpi_ut_remove_reference(return_desc); |
465 | } | 482 | } |
466 | } | 483 | } |
467 | 484 | ||
468 | return_ACPI_STATUS (AE_OK); | 485 | return_ACPI_STATUS(AE_OK); |
469 | } | 486 | } |
470 | 487 | ||
471 | |||
472 | /******************************************************************************* | 488 | /******************************************************************************* |
473 | * | 489 | * |
474 | * FUNCTION: acpi_ds_terminate_control_method | 490 | * FUNCTION: acpi_ds_terminate_control_method |
475 | * | 491 | * |
476 | * PARAMETERS: walk_state - State of the method | 492 | * PARAMETERS: walk_state - State of the method |
477 | * | 493 | * |
478 | * RETURN: Status | 494 | * RETURN: None |
479 | * | 495 | * |
480 | * DESCRIPTION: Terminate a control method. Delete everything that the method | 496 | * DESCRIPTION: Terminate a control method. Delete everything that the method |
481 | * created, delete all locals and arguments, and delete the parse | 497 | * created, delete all locals and arguments, and delete the parse |
@@ -483,63 +499,59 @@ acpi_ds_restart_control_method ( | |||
483 | * | 499 | * |
484 | ******************************************************************************/ | 500 | ******************************************************************************/ |
485 | 501 | ||
486 | acpi_status | 502 | void acpi_ds_terminate_control_method(struct acpi_walk_state *walk_state) |
487 | acpi_ds_terminate_control_method ( | ||
488 | struct acpi_walk_state *walk_state) | ||
489 | { | 503 | { |
490 | union acpi_operand_object *obj_desc; | 504 | union acpi_operand_object *obj_desc; |
491 | struct acpi_namespace_node *method_node; | 505 | struct acpi_namespace_node *method_node; |
492 | acpi_status status; | 506 | acpi_status status; |
493 | |||
494 | |||
495 | ACPI_FUNCTION_TRACE_PTR ("ds_terminate_control_method", walk_state); | ||
496 | 507 | ||
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 */ |
510 | 522 | ||
511 | acpi_ds_method_data_delete_all (walk_state); | 523 | acpi_ds_method_data_delete_all(walk_state); |
512 | 524 | ||
513 | /* | 525 | /* |
514 | * Lock the parser while we terminate this method. | 526 | * Lock the parser while we terminate this method. |
515 | * If this is the last thread executing the method, | 527 | * If this is the last thread executing the method, |
516 | * we have additional cleanup to perform | 528 | * we have additional cleanup to perform |
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 */ |
524 | 536 | ||
525 | if (walk_state->method_desc->method.semaphore) { | 537 | if (walk_state->method_desc->method.semaphore) { |
526 | status = acpi_os_signal_semaphore ( | 538 | status = |
527 | walk_state->method_desc->method.semaphore, 1); | 539 | acpi_os_signal_semaphore(walk_state->method_desc->method. |
528 | if (ACPI_FAILURE (status)) { | 540 | semaphore, 1); |
529 | ACPI_REPORT_ERROR (("Could not signal method semaphore\n")); | 541 | if (ACPI_FAILURE(status)) { |
530 | status = AE_OK; | 542 | ACPI_REPORT_ERROR(("Could not signal method semaphore\n")); |
531 | 543 | ||
532 | /* Ignore error and continue cleanup */ | 544 | /* Ignore error and continue cleanup */ |
533 | } | 545 | } |
534 | } | 546 | } |
535 | 547 | ||
536 | if (walk_state->method_desc->method.thread_count) { | 548 | if (walk_state->method_desc->method.thread_count) { |
537 | ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, | 549 | ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, |
538 | "*** Not deleting method namespace, there are still %d threads\n", | 550 | "*** Not deleting method namespace, there are still %d threads\n", |
539 | walk_state->method_desc->method.thread_count)); | 551 | walk_state->method_desc->method. |
540 | } | 552 | thread_count)); |
553 | } else { /* This is the last executing thread */ | ||
541 | 554 | ||
542 | if (!walk_state->method_desc->method.thread_count) { | ||
543 | /* | 555 | /* |
544 | * Support to dynamically change a method from not_serialized to | 556 | * Support to dynamically change a method from not_serialized to |
545 | * Serialized if it appears that the method is written foolishly and | 557 | * Serialized if it appears that the method is written foolishly and |
@@ -551,10 +563,11 @@ acpi_ds_terminate_control_method ( | |||
551 | * before creating the synchronization semaphore. | 563 | * before creating the synchronization semaphore. |
552 | */ | 564 | */ |
553 | if ((walk_state->method_desc->method.concurrency == 1) && | 565 | if ((walk_state->method_desc->method.concurrency == 1) && |
554 | (!walk_state->method_desc->method.semaphore)) { | 566 | (!walk_state->method_desc->method.semaphore)) { |
555 | status = acpi_os_create_semaphore (1, | 567 | status = acpi_os_create_semaphore(1, 1, |
556 | 1, | 568 | &walk_state-> |
557 | &walk_state->method_desc->method.semaphore); | 569 | method_desc->method. |
570 | semaphore); | ||
558 | } | 571 | } |
559 | 572 | ||
560 | /* | 573 | /* |
@@ -569,28 +582,27 @@ acpi_ds_terminate_control_method ( | |||
569 | * Delete any namespace entries created immediately underneath | 582 | * Delete any namespace entries created immediately underneath |
570 | * the method | 583 | * the method |
571 | */ | 584 | */ |
572 | status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE); | 585 | status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); |
573 | if (ACPI_FAILURE (status)) { | 586 | if (ACPI_FAILURE(status)) { |
574 | return_ACPI_STATUS (status); | 587 | goto exit; |
575 | } | 588 | } |
576 | 589 | ||
577 | if (method_node->child) { | 590 | if (method_node->child) { |
578 | acpi_ns_delete_namespace_subtree (method_node); | 591 | acpi_ns_delete_namespace_subtree(method_node); |
579 | } | 592 | } |
580 | 593 | ||
581 | /* | 594 | /* |
582 | * Delete any namespace entries created anywhere else within | 595 | * Delete any namespace entries created anywhere else within |
583 | * the namespace | 596 | * the namespace |
584 | */ | 597 | */ |
585 | acpi_ns_delete_namespace_by_owner (walk_state->method_desc->method.owning_id); | 598 | acpi_ns_delete_namespace_by_owner(walk_state->method_desc-> |
586 | status = acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); | 599 | method.owner_id); |
587 | if (ACPI_FAILURE (status)) { | 600 | status = acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); |
588 | return_ACPI_STATUS (status); | 601 | acpi_ut_release_owner_id(&walk_state->method_desc->method. |
589 | } | 602 | owner_id); |
590 | } | 603 | } |
591 | 604 | ||
592 | status = acpi_ut_release_mutex (ACPI_MTX_PARSER); | 605 | exit: |
593 | return_ACPI_STATUS (status); | 606 | (void)acpi_ut_release_mutex(ACPI_MTX_PARSER); |
607 | return_VOID; | ||
594 | } | 608 | } |
595 | |||
596 | |||