Commit | Line | Data |
---|---|---|
1da177e4 LT |
1 | /****************************************************************************** |
2 | * | |
3 | * Module Name: evrgnini- ACPI address_space (op_region) init | |
4 | * | |
5 | *****************************************************************************/ | |
6 | ||
7 | /* | |
4a90c7e8 | 8 | * Copyright (C) 2000 - 2006, R. Byron Moore |
1da177e4 LT |
9 | * All rights reserved. |
10 | * | |
11 | * Redistribution and use in source and binary forms, with or without | |
12 | * modification, are permitted provided that the following conditions | |
13 | * are met: | |
14 | * 1. Redistributions of source code must retain the above copyright | |
15 | * notice, this list of conditions, and the following disclaimer, | |
16 | * without modification. | |
17 | * 2. Redistributions in binary form must reproduce at minimum a disclaimer | |
18 | * substantially similar to the "NO WARRANTY" disclaimer below | |
19 | * ("Disclaimer") and any redistribution must be conditioned upon | |
20 | * including a substantially similar Disclaimer requirement for further | |
21 | * binary redistribution. | |
22 | * 3. Neither the names of the above-listed copyright holders nor the names | |
23 | * of any contributors may be used to endorse or promote products derived | |
24 | * from this software without specific prior written permission. | |
25 | * | |
26 | * Alternatively, this software may be distributed under the terms of the | |
27 | * GNU General Public License ("GPL") version 2 as published by the Free | |
28 | * Software Foundation. | |
29 | * | |
30 | * NO WARRANTY | |
31 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
32 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
33 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR | |
34 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |
35 | * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
36 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
37 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
38 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | |
39 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING | |
40 | * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
41 | * POSSIBILITY OF SUCH DAMAGES. | |
42 | */ | |
43 | ||
1da177e4 LT |
44 | #include <acpi/acpi.h> |
45 | #include <acpi/acevents.h> | |
46 | #include <acpi/acnamesp.h> | |
47 | ||
48 | #define _COMPONENT ACPI_EVENTS | |
4be44fcd | 49 | ACPI_MODULE_NAME("evrgnini") |
1da177e4 LT |
50 | |
51 | /******************************************************************************* | |
52 | * | |
53 | * FUNCTION: acpi_ev_system_memory_region_setup | |
54 | * | |
55 | * PARAMETERS: Handle - Region we are interested in | |
56 | * Function - Start or stop | |
57 | * handler_context - Address space handler context | |
58 | * region_context - Region specific context | |
59 | * | |
60 | * RETURN: Status | |
61 | * | |
44f6c012 | 62 | * DESCRIPTION: Setup a system_memory operation region |
1da177e4 LT |
63 | * |
64 | ******************************************************************************/ | |
1da177e4 | 65 | acpi_status |
4be44fcd LB |
66 | acpi_ev_system_memory_region_setup(acpi_handle handle, |
67 | u32 function, | |
68 | void *handler_context, void **region_context) | |
1da177e4 | 69 | { |
4be44fcd LB |
70 | union acpi_operand_object *region_desc = |
71 | (union acpi_operand_object *)handle; | |
72 | struct acpi_mem_space_context *local_region_context; | |
1da177e4 | 73 | |
b229cf92 | 74 | ACPI_FUNCTION_TRACE(ev_system_memory_region_setup); |
1da177e4 LT |
75 | |
76 | if (function == ACPI_REGION_DEACTIVATE) { | |
77 | if (*region_context) { | |
793c2388 BM |
78 | local_region_context = |
79 | (struct acpi_mem_space_context *)*region_context; | |
80 | ||
81 | /* Delete a cached mapping if present */ | |
82 | ||
83 | if (local_region_context->mapped_length) { | |
84 | acpi_os_unmap_memory(local_region_context-> | |
85 | mapped_logical_address, | |
86 | local_region_context-> | |
87 | mapped_length); | |
88 | } | |
89 | ACPI_FREE(local_region_context); | |
1da177e4 LT |
90 | *region_context = NULL; |
91 | } | |
4be44fcd | 92 | return_ACPI_STATUS(AE_OK); |
1da177e4 LT |
93 | } |
94 | ||
95 | /* Create a new context */ | |
96 | ||
4be44fcd | 97 | local_region_context = |
8313524a | 98 | ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_mem_space_context)); |
1da177e4 | 99 | if (!(local_region_context)) { |
4be44fcd | 100 | return_ACPI_STATUS(AE_NO_MEMORY); |
1da177e4 LT |
101 | } |
102 | ||
103 | /* Save the region length and address for use in the handler */ | |
104 | ||
105 | local_region_context->length = region_desc->region.length; | |
106 | local_region_context->address = region_desc->region.address; | |
107 | ||
108 | *region_context = local_region_context; | |
4be44fcd | 109 | return_ACPI_STATUS(AE_OK); |
1da177e4 LT |
110 | } |
111 | ||
1da177e4 LT |
112 | /******************************************************************************* |
113 | * | |
114 | * FUNCTION: acpi_ev_io_space_region_setup | |
115 | * | |
116 | * PARAMETERS: Handle - Region we are interested in | |
117 | * Function - Start or stop | |
118 | * handler_context - Address space handler context | |
119 | * region_context - Region specific context | |
120 | * | |
121 | * RETURN: Status | |
122 | * | |
44f6c012 | 123 | * DESCRIPTION: Setup a IO operation region |
1da177e4 LT |
124 | * |
125 | ******************************************************************************/ | |
126 | ||
127 | acpi_status | |
4be44fcd LB |
128 | acpi_ev_io_space_region_setup(acpi_handle handle, |
129 | u32 function, | |
130 | void *handler_context, void **region_context) | |
1da177e4 | 131 | { |
b229cf92 | 132 | ACPI_FUNCTION_TRACE(ev_io_space_region_setup); |
1da177e4 LT |
133 | |
134 | if (function == ACPI_REGION_DEACTIVATE) { | |
135 | *region_context = NULL; | |
4be44fcd | 136 | } else { |
1da177e4 LT |
137 | *region_context = handler_context; |
138 | } | |
139 | ||
4be44fcd | 140 | return_ACPI_STATUS(AE_OK); |
1da177e4 LT |
141 | } |
142 | ||
1da177e4 LT |
143 | /******************************************************************************* |
144 | * | |
145 | * FUNCTION: acpi_ev_pci_config_region_setup | |
146 | * | |
44f6c012 | 147 | * PARAMETERS: Handle - Region we are interested in |
1da177e4 LT |
148 | * Function - Start or stop |
149 | * handler_context - Address space handler context | |
150 | * region_context - Region specific context | |
151 | * | |
152 | * RETURN: Status | |
153 | * | |
44f6c012 | 154 | * DESCRIPTION: Setup a PCI_Config operation region |
1da177e4 LT |
155 | * |
156 | * MUTEX: Assumes namespace is not locked | |
157 | * | |
158 | ******************************************************************************/ | |
159 | ||
160 | acpi_status | |
4be44fcd LB |
161 | acpi_ev_pci_config_region_setup(acpi_handle handle, |
162 | u32 function, | |
163 | void *handler_context, void **region_context) | |
1da177e4 | 164 | { |
4be44fcd LB |
165 | acpi_status status = AE_OK; |
166 | acpi_integer pci_value; | |
167 | struct acpi_pci_id *pci_id = *region_context; | |
168 | union acpi_operand_object *handler_obj; | |
169 | struct acpi_namespace_node *parent_node; | |
170 | struct acpi_namespace_node *pci_root_node; | |
171 | union acpi_operand_object *region_obj = | |
172 | (union acpi_operand_object *)handle; | |
173 | struct acpi_device_id object_hID; | |
174 | ||
b229cf92 | 175 | ACPI_FUNCTION_TRACE(ev_pci_config_region_setup); |
1da177e4 LT |
176 | |
177 | handler_obj = region_obj->region.handler; | |
178 | if (!handler_obj) { | |
179 | /* | |
180 | * No installed handler. This shouldn't happen because the dispatch | |
181 | * routine checks before we get here, but we check again just in case. | |
182 | */ | |
4be44fcd LB |
183 | ACPI_DEBUG_PRINT((ACPI_DB_OPREGION, |
184 | "Attempting to init a region %p, with no handler\n", | |
185 | region_obj)); | |
186 | return_ACPI_STATUS(AE_NOT_EXIST); | |
1da177e4 LT |
187 | } |
188 | ||
189 | *region_context = NULL; | |
190 | if (function == ACPI_REGION_DEACTIVATE) { | |
191 | if (pci_id) { | |
8313524a | 192 | ACPI_FREE(pci_id); |
1da177e4 | 193 | } |
4be44fcd | 194 | return_ACPI_STATUS(status); |
1da177e4 LT |
195 | } |
196 | ||
4be44fcd | 197 | parent_node = acpi_ns_get_parent_node(region_obj->region.node); |
1da177e4 LT |
198 | |
199 | /* | |
200 | * Get the _SEG and _BBN values from the device upon which the handler | |
201 | * is installed. | |
202 | * | |
203 | * We need to get the _SEG and _BBN objects relative to the PCI BUS device. | |
204 | * This is the device the handler has been registered to handle. | |
205 | */ | |
206 | ||
207 | /* | |
208 | * If the address_space.Node is still pointing to the root, we need | |
209 | * to scan upward for a PCI Root bridge and re-associate the op_region | |
210 | * handlers with that device. | |
211 | */ | |
212 | if (handler_obj->address_space.node == acpi_gbl_root_node) { | |
52fc0b02 | 213 | |
1da177e4 LT |
214 | /* Start search from the parent object */ |
215 | ||
216 | pci_root_node = parent_node; | |
217 | while (pci_root_node != acpi_gbl_root_node) { | |
4be44fcd LB |
218 | status = |
219 | acpi_ut_execute_HID(pci_root_node, &object_hID); | |
220 | if (ACPI_SUCCESS(status)) { | |
6f42ccf2 RM |
221 | /* |
222 | * Got a valid _HID string, check if this is a PCI root. | |
223 | * New for ACPI 3.0: check for a PCI Express root also. | |
224 | */ | |
4be44fcd LB |
225 | if (! |
226 | (ACPI_STRNCMP | |
227 | (object_hID.value, PCI_ROOT_HID_STRING, | |
228 | sizeof(PCI_ROOT_HID_STRING)) | |
229 | || | |
230 | !(ACPI_STRNCMP | |
231 | (object_hID.value, | |
232 | PCI_EXPRESS_ROOT_HID_STRING, | |
233 | sizeof(PCI_EXPRESS_ROOT_HID_STRING))))) | |
234 | { | |
52fc0b02 | 235 | |
1da177e4 LT |
236 | /* Install a handler for this PCI root bridge */ |
237 | ||
4be44fcd LB |
238 | status = |
239 | acpi_install_address_space_handler((acpi_handle) pci_root_node, ACPI_ADR_SPACE_PCI_CONFIG, ACPI_DEFAULT_HANDLER, NULL, NULL); | |
240 | if (ACPI_FAILURE(status)) { | |
1da177e4 LT |
241 | if (status == AE_SAME_HANDLER) { |
242 | /* | |
243 | * It is OK if the handler is already installed on the root | |
244 | * bridge. Still need to return a context object for the | |
245 | * new PCI_Config operation region, however. | |
246 | */ | |
247 | status = AE_OK; | |
4be44fcd | 248 | } else { |
b8e4d893 BM |
249 | ACPI_EXCEPTION((AE_INFO, |
250 | status, | |
b229cf92 | 251 | "Could not install PciConfig handler for Root Bridge %4.4s", |
b8e4d893 BM |
252 | acpi_ut_get_node_name |
253 | (pci_root_node))); | |
1da177e4 LT |
254 | } |
255 | } | |
256 | break; | |
257 | } | |
258 | } | |
259 | ||
4be44fcd | 260 | pci_root_node = acpi_ns_get_parent_node(pci_root_node); |
1da177e4 LT |
261 | } |
262 | ||
263 | /* PCI root bridge not found, use namespace root node */ | |
4be44fcd | 264 | } else { |
1da177e4 LT |
265 | pci_root_node = handler_obj->address_space.node; |
266 | } | |
267 | ||
268 | /* | |
269 | * If this region is now initialized, we are done. | |
270 | * (install_address_space_handler could have initialized it) | |
271 | */ | |
272 | if (region_obj->region.flags & AOPOBJ_SETUP_COMPLETE) { | |
4be44fcd | 273 | return_ACPI_STATUS(AE_OK); |
1da177e4 LT |
274 | } |
275 | ||
276 | /* Region is still not initialized. Create a new context */ | |
277 | ||
8313524a | 278 | pci_id = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_pci_id)); |
1da177e4 | 279 | if (!pci_id) { |
4be44fcd | 280 | return_ACPI_STATUS(AE_NO_MEMORY); |
1da177e4 LT |
281 | } |
282 | ||
283 | /* | |
284 | * For PCI_Config space access, we need the segment, bus, | |
285 | * device and function numbers. Acquire them here. | |
286 | */ | |
287 | ||
288 | /* | |
289 | * Get the PCI device and function numbers from the _ADR object | |
290 | * contained in the parent's scope. | |
291 | */ | |
4be44fcd LB |
292 | status = |
293 | acpi_ut_evaluate_numeric_object(METHOD_NAME__ADR, parent_node, | |
294 | &pci_value); | |
1da177e4 LT |
295 | |
296 | /* | |
297 | * The default is zero, and since the allocation above zeroed | |
298 | * the data, just do nothing on failure. | |
299 | */ | |
4be44fcd LB |
300 | if (ACPI_SUCCESS(status)) { |
301 | pci_id->device = ACPI_HIWORD(ACPI_LODWORD(pci_value)); | |
302 | pci_id->function = ACPI_LOWORD(ACPI_LODWORD(pci_value)); | |
1da177e4 LT |
303 | } |
304 | ||
305 | /* The PCI segment number comes from the _SEG method */ | |
306 | ||
4be44fcd LB |
307 | status = |
308 | acpi_ut_evaluate_numeric_object(METHOD_NAME__SEG, pci_root_node, | |
309 | &pci_value); | |
310 | if (ACPI_SUCCESS(status)) { | |
311 | pci_id->segment = ACPI_LOWORD(pci_value); | |
1da177e4 LT |
312 | } |
313 | ||
314 | /* The PCI bus number comes from the _BBN method */ | |
315 | ||
4be44fcd LB |
316 | status = |
317 | acpi_ut_evaluate_numeric_object(METHOD_NAME__BBN, pci_root_node, | |
318 | &pci_value); | |
319 | if (ACPI_SUCCESS(status)) { | |
320 | pci_id->bus = ACPI_LOWORD(pci_value); | |
1da177e4 LT |
321 | } |
322 | ||
323 | /* Complete this device's pci_id */ | |
324 | ||
4be44fcd | 325 | acpi_os_derive_pci_id(pci_root_node, region_obj->region.node, &pci_id); |
1da177e4 LT |
326 | |
327 | *region_context = pci_id; | |
4be44fcd | 328 | return_ACPI_STATUS(AE_OK); |
1da177e4 LT |
329 | } |
330 | ||
1da177e4 LT |
331 | /******************************************************************************* |
332 | * | |
333 | * FUNCTION: acpi_ev_pci_bar_region_setup | |
334 | * | |
335 | * PARAMETERS: Handle - Region we are interested in | |
336 | * Function - Start or stop | |
337 | * handler_context - Address space handler context | |
338 | * region_context - Region specific context | |
339 | * | |
340 | * RETURN: Status | |
341 | * | |
44f6c012 | 342 | * DESCRIPTION: Setup a pci_bAR operation region |
1da177e4 LT |
343 | * |
344 | * MUTEX: Assumes namespace is not locked | |
345 | * | |
346 | ******************************************************************************/ | |
347 | ||
348 | acpi_status | |
4be44fcd LB |
349 | acpi_ev_pci_bar_region_setup(acpi_handle handle, |
350 | u32 function, | |
351 | void *handler_context, void **region_context) | |
1da177e4 | 352 | { |
b229cf92 | 353 | ACPI_FUNCTION_TRACE(ev_pci_bar_region_setup); |
1da177e4 | 354 | |
4be44fcd | 355 | return_ACPI_STATUS(AE_OK); |
1da177e4 LT |
356 | } |
357 | ||
1da177e4 LT |
358 | /******************************************************************************* |
359 | * | |
360 | * FUNCTION: acpi_ev_cmos_region_setup | |
361 | * | |
362 | * PARAMETERS: Handle - Region we are interested in | |
363 | * Function - Start or stop | |
364 | * handler_context - Address space handler context | |
365 | * region_context - Region specific context | |
366 | * | |
367 | * RETURN: Status | |
368 | * | |
44f6c012 | 369 | * DESCRIPTION: Setup a CMOS operation region |
1da177e4 LT |
370 | * |
371 | * MUTEX: Assumes namespace is not locked | |
372 | * | |
373 | ******************************************************************************/ | |
374 | ||
375 | acpi_status | |
4be44fcd LB |
376 | acpi_ev_cmos_region_setup(acpi_handle handle, |
377 | u32 function, | |
378 | void *handler_context, void **region_context) | |
1da177e4 | 379 | { |
b229cf92 | 380 | ACPI_FUNCTION_TRACE(ev_cmos_region_setup); |
1da177e4 | 381 | |
4be44fcd | 382 | return_ACPI_STATUS(AE_OK); |
1da177e4 LT |
383 | } |
384 | ||
1da177e4 LT |
385 | /******************************************************************************* |
386 | * | |
387 | * FUNCTION: acpi_ev_default_region_setup | |
388 | * | |
389 | * PARAMETERS: Handle - Region we are interested in | |
390 | * Function - Start or stop | |
391 | * handler_context - Address space handler context | |
392 | * region_context - Region specific context | |
393 | * | |
394 | * RETURN: Status | |
395 | * | |
44f6c012 | 396 | * DESCRIPTION: Default region initialization |
1da177e4 LT |
397 | * |
398 | ******************************************************************************/ | |
399 | ||
400 | acpi_status | |
4be44fcd LB |
401 | acpi_ev_default_region_setup(acpi_handle handle, |
402 | u32 function, | |
403 | void *handler_context, void **region_context) | |
1da177e4 | 404 | { |
b229cf92 | 405 | ACPI_FUNCTION_TRACE(ev_default_region_setup); |
1da177e4 LT |
406 | |
407 | if (function == ACPI_REGION_DEACTIVATE) { | |
408 | *region_context = NULL; | |
4be44fcd | 409 | } else { |
1da177e4 LT |
410 | *region_context = handler_context; |
411 | } | |
412 | ||
4be44fcd | 413 | return_ACPI_STATUS(AE_OK); |
1da177e4 LT |
414 | } |
415 | ||
1da177e4 LT |
416 | /******************************************************************************* |
417 | * | |
418 | * FUNCTION: acpi_ev_initialize_region | |
419 | * | |
420 | * PARAMETERS: region_obj - Region we are initializing | |
421 | * acpi_ns_locked - Is namespace locked? | |
422 | * | |
423 | * RETURN: Status | |
424 | * | |
425 | * DESCRIPTION: Initializes the region, finds any _REG methods and saves them | |
426 | * for execution at a later time | |
427 | * | |
428 | * Get the appropriate address space handler for a newly | |
429 | * created region. | |
430 | * | |
431 | * This also performs address space specific initialization. For | |
432 | * example, PCI regions must have an _ADR object that contains | |
433 | * a PCI address in the scope of the definition. This address is | |
434 | * required to perform an access to PCI config space. | |
435 | * | |
436 | ******************************************************************************/ | |
437 | ||
438 | acpi_status | |
4be44fcd LB |
439 | acpi_ev_initialize_region(union acpi_operand_object *region_obj, |
440 | u8 acpi_ns_locked) | |
1da177e4 | 441 | { |
4be44fcd LB |
442 | union acpi_operand_object *handler_obj; |
443 | union acpi_operand_object *obj_desc; | |
444 | acpi_adr_space_type space_id; | |
445 | struct acpi_namespace_node *node; | |
446 | acpi_status status; | |
447 | struct acpi_namespace_node *method_node; | |
448 | acpi_name *reg_name_ptr = (acpi_name *) METHOD_NAME__REG; | |
449 | union acpi_operand_object *region_obj2; | |
1da177e4 | 450 | |
b229cf92 | 451 | ACPI_FUNCTION_TRACE_U32(ev_initialize_region, acpi_ns_locked); |
1da177e4 LT |
452 | |
453 | if (!region_obj) { | |
4be44fcd | 454 | return_ACPI_STATUS(AE_BAD_PARAMETER); |
1da177e4 LT |
455 | } |
456 | ||
457 | if (region_obj->common.flags & AOPOBJ_OBJECT_INITIALIZED) { | |
4be44fcd | 458 | return_ACPI_STATUS(AE_OK); |
1da177e4 LT |
459 | } |
460 | ||
4be44fcd | 461 | region_obj2 = acpi_ns_get_secondary_object(region_obj); |
1da177e4 | 462 | if (!region_obj2) { |
4be44fcd | 463 | return_ACPI_STATUS(AE_NOT_EXIST); |
1da177e4 LT |
464 | } |
465 | ||
4be44fcd | 466 | node = acpi_ns_get_parent_node(region_obj->region.node); |
1da177e4 LT |
467 | space_id = region_obj->region.space_id; |
468 | ||
469 | /* Setup defaults */ | |
470 | ||
471 | region_obj->region.handler = NULL; | |
472 | region_obj2->extra.method_REG = NULL; | |
473 | region_obj->common.flags &= ~(AOPOBJ_SETUP_COMPLETE); | |
474 | region_obj->common.flags |= AOPOBJ_OBJECT_INITIALIZED; | |
475 | ||
476 | /* Find any "_REG" method associated with this region definition */ | |
477 | ||
4119532c BM |
478 | status = |
479 | acpi_ns_search_one_scope(*reg_name_ptr, node, ACPI_TYPE_METHOD, | |
480 | &method_node); | |
4be44fcd | 481 | if (ACPI_SUCCESS(status)) { |
1da177e4 LT |
482 | /* |
483 | * The _REG method is optional and there can be only one per region | |
484 | * definition. This will be executed when the handler is attached | |
485 | * or removed | |
486 | */ | |
487 | region_obj2->extra.method_REG = method_node; | |
488 | } | |
489 | ||
490 | /* | |
491 | * The following loop depends upon the root Node having no parent | |
492 | * ie: acpi_gbl_root_node->parent_entry being set to NULL | |
493 | */ | |
494 | while (node) { | |
52fc0b02 | 495 | |
1da177e4 LT |
496 | /* Check to see if a handler exists */ |
497 | ||
498 | handler_obj = NULL; | |
4be44fcd | 499 | obj_desc = acpi_ns_get_attached_object(node); |
1da177e4 | 500 | if (obj_desc) { |
52fc0b02 | 501 | |
1da177e4 LT |
502 | /* Can only be a handler if the object exists */ |
503 | ||
504 | switch (node->type) { | |
505 | case ACPI_TYPE_DEVICE: | |
506 | ||
507 | handler_obj = obj_desc->device.handler; | |
508 | break; | |
509 | ||
510 | case ACPI_TYPE_PROCESSOR: | |
511 | ||
512 | handler_obj = obj_desc->processor.handler; | |
513 | break; | |
514 | ||
515 | case ACPI_TYPE_THERMAL: | |
516 | ||
517 | handler_obj = obj_desc->thermal_zone.handler; | |
518 | break; | |
519 | ||
520 | default: | |
521 | /* Ignore other objects */ | |
522 | break; | |
523 | } | |
524 | ||
525 | while (handler_obj) { | |
52fc0b02 | 526 | |
1da177e4 LT |
527 | /* Is this handler of the correct type? */ |
528 | ||
4be44fcd LB |
529 | if (handler_obj->address_space.space_id == |
530 | space_id) { | |
52fc0b02 | 531 | |
1da177e4 LT |
532 | /* Found correct handler */ |
533 | ||
4be44fcd LB |
534 | ACPI_DEBUG_PRINT((ACPI_DB_OPREGION, |
535 | "Found handler %p for region %p in obj %p\n", | |
536 | handler_obj, | |
537 | region_obj, | |
538 | obj_desc)); | |
1da177e4 | 539 | |
4be44fcd LB |
540 | status = |
541 | acpi_ev_attach_region(handler_obj, | |
542 | region_obj, | |
543 | acpi_ns_locked); | |
1da177e4 LT |
544 | |
545 | /* | |
546 | * Tell all users that this region is usable by running the _REG | |
547 | * method | |
548 | */ | |
549 | if (acpi_ns_locked) { | |
4be44fcd LB |
550 | status = |
551 | acpi_ut_release_mutex | |
552 | (ACPI_MTX_NAMESPACE); | |
553 | if (ACPI_FAILURE(status)) { | |
554 | return_ACPI_STATUS | |
555 | (status); | |
1da177e4 LT |
556 | } |
557 | } | |
558 | ||
4be44fcd LB |
559 | status = |
560 | acpi_ev_execute_reg_method | |
561 | (region_obj, 1); | |
1da177e4 LT |
562 | |
563 | if (acpi_ns_locked) { | |
4be44fcd LB |
564 | status = |
565 | acpi_ut_acquire_mutex | |
566 | (ACPI_MTX_NAMESPACE); | |
567 | if (ACPI_FAILURE(status)) { | |
568 | return_ACPI_STATUS | |
569 | (status); | |
1da177e4 LT |
570 | } |
571 | } | |
572 | ||
4be44fcd | 573 | return_ACPI_STATUS(AE_OK); |
1da177e4 LT |
574 | } |
575 | ||
576 | /* Try next handler in the list */ | |
577 | ||
578 | handler_obj = handler_obj->address_space.next; | |
579 | } | |
580 | } | |
581 | ||
582 | /* | |
583 | * This node does not have the handler we need; | |
584 | * Pop up one level | |
585 | */ | |
4be44fcd | 586 | node = acpi_ns_get_parent_node(node); |
1da177e4 LT |
587 | } |
588 | ||
589 | /* If we get here, there is no handler for this region */ | |
590 | ||
4be44fcd | 591 | ACPI_DEBUG_PRINT((ACPI_DB_OPREGION, |
b229cf92 | 592 | "No handler for RegionType %s(%X) (RegionObj %p)\n", |
4be44fcd LB |
593 | acpi_ut_get_region_name(space_id), space_id, |
594 | region_obj)); | |
1da177e4 | 595 | |
4be44fcd | 596 | return_ACPI_STATUS(AE_NOT_EXIST); |
1da177e4 | 597 | } |