1 | /****************************************************************************** |
2 | * |
3 | * Module Name: evrgnini- ACPI AddressSpace (OpRegion) init |
4 | * |
5 | *****************************************************************************/ |
6 | |
7 | /* |
8 | * Copyright (C) 2000 - 2016, Intel Corp. |
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 | |
44 | #include "acpi.h" |
45 | #include "accommon.h" |
46 | #include "acevents.h" |
47 | #include "acnamesp.h" |
48 | |
49 | #define _COMPONENT ACPI_EVENTS |
50 | ACPI_MODULE_NAME ("evrgnini" ) |
51 | |
52 | /* Local prototypes */ |
53 | |
54 | static BOOLEAN |
55 | AcpiEvIsPciRootBridge ( |
56 | ACPI_NAMESPACE_NODE *Node); |
57 | |
58 | |
59 | /******************************************************************************* |
60 | * |
61 | * FUNCTION: AcpiEvSystemMemoryRegionSetup |
62 | * |
63 | * PARAMETERS: Handle - Region we are interested in |
64 | * Function - Start or stop |
65 | * HandlerContext - Address space handler context |
66 | * RegionContext - Region specific context |
67 | * |
68 | * RETURN: Status |
69 | * |
70 | * DESCRIPTION: Setup a SystemMemory operation region |
71 | * |
72 | ******************************************************************************/ |
73 | |
74 | ACPI_STATUS |
75 | AcpiEvSystemMemoryRegionSetup ( |
76 | ACPI_HANDLE Handle, |
77 | UINT32 Function, |
78 | void *HandlerContext, |
79 | void **RegionContext) |
80 | { |
81 | ACPI_OPERAND_OBJECT *RegionDesc = (ACPI_OPERAND_OBJECT *) Handle; |
82 | ACPI_MEM_SPACE_CONTEXT *LocalRegionContext; |
83 | |
84 | |
85 | ACPI_FUNCTION_TRACE (EvSystemMemoryRegionSetup); |
86 | |
87 | |
88 | if (Function == ACPI_REGION_DEACTIVATE) |
89 | { |
90 | if (*RegionContext) |
91 | { |
92 | LocalRegionContext = (ACPI_MEM_SPACE_CONTEXT *) *RegionContext; |
93 | |
94 | /* Delete a cached mapping if present */ |
95 | |
96 | if (LocalRegionContext->MappedLength) |
97 | { |
98 | AcpiOsUnmapMemory (LocalRegionContext->MappedLogicalAddress, |
99 | LocalRegionContext->MappedLength); |
100 | } |
101 | ACPI_FREE (LocalRegionContext); |
102 | *RegionContext = NULL; |
103 | } |
104 | return_ACPI_STATUS (AE_OK); |
105 | } |
106 | |
107 | /* Create a new context */ |
108 | |
109 | LocalRegionContext = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_MEM_SPACE_CONTEXT)); |
110 | if (!(LocalRegionContext)) |
111 | { |
112 | return_ACPI_STATUS (AE_NO_MEMORY); |
113 | } |
114 | |
115 | /* Save the region length and address for use in the handler */ |
116 | |
117 | LocalRegionContext->Length = RegionDesc->Region.Length; |
118 | LocalRegionContext->Address = RegionDesc->Region.Address; |
119 | |
120 | *RegionContext = LocalRegionContext; |
121 | return_ACPI_STATUS (AE_OK); |
122 | } |
123 | |
124 | |
125 | /******************************************************************************* |
126 | * |
127 | * FUNCTION: AcpiEvIoSpaceRegionSetup |
128 | * |
129 | * PARAMETERS: Handle - Region we are interested in |
130 | * Function - Start or stop |
131 | * HandlerContext - Address space handler context |
132 | * RegionContext - Region specific context |
133 | * |
134 | * RETURN: Status |
135 | * |
136 | * DESCRIPTION: Setup a IO operation region |
137 | * |
138 | ******************************************************************************/ |
139 | |
140 | ACPI_STATUS |
141 | AcpiEvIoSpaceRegionSetup ( |
142 | ACPI_HANDLE Handle, |
143 | UINT32 Function, |
144 | void *HandlerContext, |
145 | void **RegionContext) |
146 | { |
147 | ACPI_FUNCTION_TRACE (EvIoSpaceRegionSetup); |
148 | |
149 | |
150 | if (Function == ACPI_REGION_DEACTIVATE) |
151 | { |
152 | *RegionContext = NULL; |
153 | } |
154 | else |
155 | { |
156 | *RegionContext = HandlerContext; |
157 | } |
158 | |
159 | return_ACPI_STATUS (AE_OK); |
160 | } |
161 | |
162 | |
163 | /******************************************************************************* |
164 | * |
165 | * FUNCTION: AcpiEvPciConfigRegionSetup |
166 | * |
167 | * PARAMETERS: Handle - Region we are interested in |
168 | * Function - Start or stop |
169 | * HandlerContext - Address space handler context |
170 | * RegionContext - Region specific context |
171 | * |
172 | * RETURN: Status |
173 | * |
174 | * DESCRIPTION: Setup a PCI_Config operation region |
175 | * |
176 | * MUTEX: Assumes namespace is not locked |
177 | * |
178 | ******************************************************************************/ |
179 | |
180 | ACPI_STATUS |
181 | AcpiEvPciConfigRegionSetup ( |
182 | ACPI_HANDLE Handle, |
183 | UINT32 Function, |
184 | void *HandlerContext, |
185 | void **RegionContext) |
186 | { |
187 | ACPI_STATUS Status = AE_OK; |
188 | UINT64 PciValue; |
189 | ACPI_PCI_ID *PciId = *RegionContext; |
190 | ACPI_OPERAND_OBJECT *HandlerObj; |
191 | ACPI_NAMESPACE_NODE *ParentNode; |
192 | ACPI_NAMESPACE_NODE *PciRootNode; |
193 | ACPI_NAMESPACE_NODE *PciDeviceNode; |
194 | ACPI_OPERAND_OBJECT *RegionObj = (ACPI_OPERAND_OBJECT *) Handle; |
195 | |
196 | |
197 | ACPI_FUNCTION_TRACE (EvPciConfigRegionSetup); |
198 | |
199 | |
200 | HandlerObj = RegionObj->Region.Handler; |
201 | if (!HandlerObj) |
202 | { |
203 | /* |
204 | * No installed handler. This shouldn't happen because the dispatch |
205 | * routine checks before we get here, but we check again just in case. |
206 | */ |
207 | ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION, |
208 | "Attempting to init a region %p, with no handler\n" , RegionObj)); |
209 | return_ACPI_STATUS (AE_NOT_EXIST); |
210 | } |
211 | |
212 | *RegionContext = NULL; |
213 | if (Function == ACPI_REGION_DEACTIVATE) |
214 | { |
215 | if (PciId) |
216 | { |
217 | ACPI_FREE (PciId); |
218 | } |
219 | return_ACPI_STATUS (Status); |
220 | } |
221 | |
222 | ParentNode = RegionObj->Region.Node->Parent; |
223 | |
224 | /* |
225 | * Get the _SEG and _BBN values from the device upon which the handler |
226 | * is installed. |
227 | * |
228 | * We need to get the _SEG and _BBN objects relative to the PCI BUS device. |
229 | * This is the device the handler has been registered to handle. |
230 | */ |
231 | |
232 | /* |
233 | * If the AddressSpace.Node is still pointing to the root, we need |
234 | * to scan upward for a PCI Root bridge and re-associate the OpRegion |
235 | * handlers with that device. |
236 | */ |
237 | if (HandlerObj->AddressSpace.Node == AcpiGbl_RootNode) |
238 | { |
239 | /* Start search from the parent object */ |
240 | |
241 | PciRootNode = ParentNode; |
242 | while (PciRootNode != AcpiGbl_RootNode) |
243 | { |
244 | /* Get the _HID/_CID in order to detect a RootBridge */ |
245 | |
246 | if (AcpiEvIsPciRootBridge (PciRootNode)) |
247 | { |
248 | /* Install a handler for this PCI root bridge */ |
249 | |
250 | Status = AcpiInstallAddressSpaceHandler ( |
251 | (ACPI_HANDLE) PciRootNode, |
252 | ACPI_ADR_SPACE_PCI_CONFIG, |
253 | ACPI_DEFAULT_HANDLER, NULL, NULL); |
254 | if (ACPI_FAILURE (Status)) |
255 | { |
256 | if (Status == AE_SAME_HANDLER) |
257 | { |
258 | /* |
259 | * It is OK if the handler is already installed on the |
260 | * root bridge. Still need to return a context object |
261 | * for the new PCI_Config operation region, however. |
262 | */ |
263 | Status = AE_OK; |
264 | } |
265 | else |
266 | { |
267 | ACPI_EXCEPTION ((AE_INFO, Status, |
268 | "Could not install PciConfig handler " |
269 | "for Root Bridge %4.4s" , |
270 | AcpiUtGetNodeName (PciRootNode))); |
271 | } |
272 | } |
273 | break; |
274 | } |
275 | |
276 | PciRootNode = PciRootNode->Parent; |
277 | } |
278 | |
279 | /* PCI root bridge not found, use namespace root node */ |
280 | } |
281 | else |
282 | { |
283 | PciRootNode = HandlerObj->AddressSpace.Node; |
284 | } |
285 | |
286 | /* |
287 | * If this region is now initialized, we are done. |
288 | * (InstallAddressSpaceHandler could have initialized it) |
289 | */ |
290 | if (RegionObj->Region.Flags & AOPOBJ_SETUP_COMPLETE) |
291 | { |
292 | return_ACPI_STATUS (AE_OK); |
293 | } |
294 | |
295 | /* Region is still not initialized. Create a new context */ |
296 | |
297 | PciId = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_PCI_ID)); |
298 | if (!PciId) |
299 | { |
300 | return_ACPI_STATUS (AE_NO_MEMORY); |
301 | } |
302 | |
303 | /* |
304 | * For PCI_Config space access, we need the segment, bus, device and |
305 | * function numbers. Acquire them here. |
306 | * |
307 | * Find the parent device object. (This allows the operation region to be |
308 | * within a subscope under the device, such as a control method.) |
309 | */ |
310 | PciDeviceNode = RegionObj->Region.Node; |
311 | while (PciDeviceNode && (PciDeviceNode->Type != ACPI_TYPE_DEVICE)) |
312 | { |
313 | PciDeviceNode = PciDeviceNode->Parent; |
314 | } |
315 | |
316 | if (!PciDeviceNode) |
317 | { |
318 | ACPI_FREE (PciId); |
319 | return_ACPI_STATUS (AE_AML_OPERAND_TYPE); |
320 | } |
321 | |
322 | /* |
323 | * Get the PCI device and function numbers from the _ADR object |
324 | * contained in the parent's scope. |
325 | */ |
326 | Status = AcpiUtEvaluateNumericObject (METHOD_NAME__ADR, |
327 | PciDeviceNode, &PciValue); |
328 | |
329 | /* |
330 | * The default is zero, and since the allocation above zeroed the data, |
331 | * just do nothing on failure. |
332 | */ |
333 | if (ACPI_SUCCESS (Status)) |
334 | { |
335 | PciId->Device = ACPI_HIWORD (ACPI_LODWORD (PciValue)); |
336 | PciId->Function = ACPI_LOWORD (ACPI_LODWORD (PciValue)); |
337 | } |
338 | |
339 | /* The PCI segment number comes from the _SEG method */ |
340 | |
341 | Status = AcpiUtEvaluateNumericObject (METHOD_NAME__SEG, |
342 | PciRootNode, &PciValue); |
343 | if (ACPI_SUCCESS (Status)) |
344 | { |
345 | PciId->Segment = ACPI_LOWORD (PciValue); |
346 | } |
347 | |
348 | /* The PCI bus number comes from the _BBN method */ |
349 | |
350 | Status = AcpiUtEvaluateNumericObject (METHOD_NAME__BBN, |
351 | PciRootNode, &PciValue); |
352 | if (ACPI_SUCCESS (Status)) |
353 | { |
354 | PciId->Bus = ACPI_LOWORD (PciValue); |
355 | } |
356 | |
357 | /* Complete/update the PCI ID for this device */ |
358 | |
359 | Status = AcpiHwDerivePciId (PciId, PciRootNode, RegionObj->Region.Node); |
360 | if (ACPI_FAILURE (Status)) |
361 | { |
362 | ACPI_FREE (PciId); |
363 | return_ACPI_STATUS (Status); |
364 | } |
365 | |
366 | *RegionContext = PciId; |
367 | return_ACPI_STATUS (AE_OK); |
368 | } |
369 | |
370 | |
371 | /******************************************************************************* |
372 | * |
373 | * FUNCTION: AcpiEvIsPciRootBridge |
374 | * |
375 | * PARAMETERS: Node - Device node being examined |
376 | * |
377 | * RETURN: TRUE if device is a PCI/PCI-Express Root Bridge |
378 | * |
379 | * DESCRIPTION: Determine if the input device represents a PCI Root Bridge by |
380 | * examining the _HID and _CID for the device. |
381 | * |
382 | ******************************************************************************/ |
383 | |
384 | static BOOLEAN |
385 | AcpiEvIsPciRootBridge ( |
386 | ACPI_NAMESPACE_NODE *Node) |
387 | { |
388 | ACPI_STATUS Status; |
389 | ACPI_PNP_DEVICE_ID *Hid; |
390 | ACPI_PNP_DEVICE_ID_LIST *Cid; |
391 | UINT32 i; |
392 | BOOLEAN Match; |
393 | |
394 | |
395 | /* Get the _HID and check for a PCI Root Bridge */ |
396 | |
397 | Status = AcpiUtExecute_HID (Node, &Hid); |
398 | if (ACPI_FAILURE (Status)) |
399 | { |
400 | return (FALSE); |
401 | } |
402 | |
403 | Match = AcpiUtIsPciRootBridge (Hid->String); |
404 | ACPI_FREE (Hid); |
405 | |
406 | if (Match) |
407 | { |
408 | return (TRUE); |
409 | } |
410 | |
411 | /* The _HID did not match. Get the _CID and check for a PCI Root Bridge */ |
412 | |
413 | Status = AcpiUtExecute_CID (Node, &Cid); |
414 | if (ACPI_FAILURE (Status)) |
415 | { |
416 | return (FALSE); |
417 | } |
418 | |
419 | /* Check all _CIDs in the returned list */ |
420 | |
421 | for (i = 0; i < Cid->Count; i++) |
422 | { |
423 | if (AcpiUtIsPciRootBridge (Cid->Ids[i].String)) |
424 | { |
425 | ACPI_FREE (Cid); |
426 | return (TRUE); |
427 | } |
428 | } |
429 | |
430 | ACPI_FREE (Cid); |
431 | return (FALSE); |
432 | } |
433 | |
434 | |
435 | /******************************************************************************* |
436 | * |
437 | * FUNCTION: AcpiEvPciBarRegionSetup |
438 | * |
439 | * PARAMETERS: Handle - Region we are interested in |
440 | * Function - Start or stop |
441 | * HandlerContext - Address space handler context |
442 | * RegionContext - Region specific context |
443 | * |
444 | * RETURN: Status |
445 | * |
446 | * DESCRIPTION: Setup a PciBAR operation region |
447 | * |
448 | * MUTEX: Assumes namespace is not locked |
449 | * |
450 | ******************************************************************************/ |
451 | |
452 | ACPI_STATUS |
453 | AcpiEvPciBarRegionSetup ( |
454 | ACPI_HANDLE Handle, |
455 | UINT32 Function, |
456 | void *HandlerContext, |
457 | void **RegionContext) |
458 | { |
459 | ACPI_FUNCTION_TRACE (EvPciBarRegionSetup); |
460 | |
461 | |
462 | return_ACPI_STATUS (AE_OK); |
463 | } |
464 | |
465 | |
466 | /******************************************************************************* |
467 | * |
468 | * FUNCTION: AcpiEvCmosRegionSetup |
469 | * |
470 | * PARAMETERS: Handle - Region we are interested in |
471 | * Function - Start or stop |
472 | * HandlerContext - Address space handler context |
473 | * RegionContext - Region specific context |
474 | * |
475 | * RETURN: Status |
476 | * |
477 | * DESCRIPTION: Setup a CMOS operation region |
478 | * |
479 | * MUTEX: Assumes namespace is not locked |
480 | * |
481 | ******************************************************************************/ |
482 | |
483 | ACPI_STATUS |
484 | AcpiEvCmosRegionSetup ( |
485 | ACPI_HANDLE Handle, |
486 | UINT32 Function, |
487 | void *HandlerContext, |
488 | void **RegionContext) |
489 | { |
490 | ACPI_FUNCTION_TRACE (EvCmosRegionSetup); |
491 | |
492 | |
493 | return_ACPI_STATUS (AE_OK); |
494 | } |
495 | |
496 | |
497 | /******************************************************************************* |
498 | * |
499 | * FUNCTION: AcpiEvDefaultRegionSetup |
500 | * |
501 | * PARAMETERS: Handle - Region we are interested in |
502 | * Function - Start or stop |
503 | * HandlerContext - Address space handler context |
504 | * RegionContext - Region specific context |
505 | * |
506 | * RETURN: Status |
507 | * |
508 | * DESCRIPTION: Default region initialization |
509 | * |
510 | ******************************************************************************/ |
511 | |
512 | ACPI_STATUS |
513 | AcpiEvDefaultRegionSetup ( |
514 | ACPI_HANDLE Handle, |
515 | UINT32 Function, |
516 | void *HandlerContext, |
517 | void **RegionContext) |
518 | { |
519 | ACPI_FUNCTION_TRACE (EvDefaultRegionSetup); |
520 | |
521 | |
522 | if (Function == ACPI_REGION_DEACTIVATE) |
523 | { |
524 | *RegionContext = NULL; |
525 | } |
526 | else |
527 | { |
528 | *RegionContext = HandlerContext; |
529 | } |
530 | |
531 | return_ACPI_STATUS (AE_OK); |
532 | } |
533 | |
534 | |
535 | /******************************************************************************* |
536 | * |
537 | * FUNCTION: AcpiEvInitializeRegion |
538 | * |
539 | * PARAMETERS: RegionObj - Region we are initializing |
540 | * AcpiNsLocked - Is namespace locked? |
541 | * |
542 | * RETURN: Status |
543 | * |
544 | * DESCRIPTION: Initializes the region, finds any _REG methods and saves them |
545 | * for execution at a later time |
546 | * |
547 | * Get the appropriate address space handler for a newly |
548 | * created region. |
549 | * |
550 | * This also performs address space specific initialization. For |
551 | * example, PCI regions must have an _ADR object that contains |
552 | * a PCI address in the scope of the definition. This address is |
553 | * required to perform an access to PCI config space. |
554 | * |
555 | * MUTEX: Interpreter should be unlocked, because we may run the _REG |
556 | * method for this region. |
557 | * |
558 | ******************************************************************************/ |
559 | |
560 | ACPI_STATUS |
561 | AcpiEvInitializeRegion ( |
562 | ACPI_OPERAND_OBJECT *RegionObj, |
563 | BOOLEAN AcpiNsLocked) |
564 | { |
565 | ACPI_OPERAND_OBJECT *HandlerObj; |
566 | ACPI_OPERAND_OBJECT *ObjDesc; |
567 | ACPI_ADR_SPACE_TYPE SpaceId; |
568 | ACPI_NAMESPACE_NODE *Node; |
569 | ACPI_STATUS Status; |
570 | |
571 | |
572 | ACPI_FUNCTION_TRACE_U32 (EvInitializeRegion, AcpiNsLocked); |
573 | |
574 | |
575 | if (!RegionObj) |
576 | { |
577 | return_ACPI_STATUS (AE_BAD_PARAMETER); |
578 | } |
579 | |
580 | if (RegionObj->Common.Flags & AOPOBJ_OBJECT_INITIALIZED) |
581 | { |
582 | return_ACPI_STATUS (AE_OK); |
583 | } |
584 | |
585 | RegionObj->Common.Flags |= AOPOBJ_OBJECT_INITIALIZED; |
586 | |
587 | Node = RegionObj->Region.Node->Parent; |
588 | SpaceId = RegionObj->Region.SpaceId; |
589 | |
590 | /* |
591 | * The following loop depends upon the root Node having no parent |
592 | * ie: AcpiGbl_RootNode->Parent being set to NULL |
593 | */ |
594 | while (Node) |
595 | { |
596 | /* Check to see if a handler exists */ |
597 | |
598 | HandlerObj = NULL; |
599 | ObjDesc = AcpiNsGetAttachedObject (Node); |
600 | if (ObjDesc) |
601 | { |
602 | /* Can only be a handler if the object exists */ |
603 | |
604 | switch (Node->Type) |
605 | { |
606 | case ACPI_TYPE_DEVICE: |
607 | case ACPI_TYPE_PROCESSOR: |
608 | case ACPI_TYPE_THERMAL: |
609 | |
610 | HandlerObj = ObjDesc->CommonNotify.Handler; |
611 | break; |
612 | |
613 | case ACPI_TYPE_METHOD: |
614 | /* |
615 | * If we are executing module level code, the original |
616 | * Node's object was replaced by this Method object and we |
617 | * saved the handler in the method object. |
618 | * |
619 | * See AcpiNsExecModuleCode |
620 | */ |
621 | if (!AcpiGbl_ParseTableAsTermList && |
622 | ObjDesc->Method.InfoFlags & ACPI_METHOD_MODULE_LEVEL) |
623 | { |
624 | HandlerObj = ObjDesc->Method.Dispatch.Handler; |
625 | } |
626 | break; |
627 | |
628 | default: |
629 | |
630 | /* Ignore other objects */ |
631 | |
632 | break; |
633 | } |
634 | |
635 | HandlerObj = AcpiEvFindRegionHandler (SpaceId, HandlerObj); |
636 | if (HandlerObj) |
637 | { |
638 | /* Found correct handler */ |
639 | |
640 | ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION, |
641 | "Found handler %p for region %p in obj %p\n" , |
642 | HandlerObj, RegionObj, ObjDesc)); |
643 | |
644 | Status = AcpiEvAttachRegion (HandlerObj, RegionObj, |
645 | AcpiNsLocked); |
646 | |
647 | /* |
648 | * Tell all users that this region is usable by |
649 | * running the _REG method |
650 | */ |
651 | if (AcpiNsLocked) |
652 | { |
653 | Status = AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); |
654 | if (ACPI_FAILURE (Status)) |
655 | { |
656 | return_ACPI_STATUS (Status); |
657 | } |
658 | } |
659 | |
660 | Status = AcpiEvExecuteRegMethod (RegionObj, ACPI_REG_CONNECT); |
661 | |
662 | if (AcpiNsLocked) |
663 | { |
664 | Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); |
665 | if (ACPI_FAILURE (Status)) |
666 | { |
667 | return_ACPI_STATUS (Status); |
668 | } |
669 | } |
670 | |
671 | return_ACPI_STATUS (AE_OK); |
672 | } |
673 | } |
674 | |
675 | /* This node does not have the handler we need; Pop up one level */ |
676 | |
677 | Node = Node->Parent; |
678 | } |
679 | |
680 | /* If we get here, there is no handler for this region */ |
681 | |
682 | ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION, |
683 | "No handler for RegionType %s(%X) (RegionObj %p)\n" , |
684 | AcpiUtGetRegionName (SpaceId), SpaceId, RegionObj)); |
685 | |
686 | return_ACPI_STATUS (AE_NOT_EXIST); |
687 | } |
688 | |