1 | /****************************************************************************** |
2 | * |
3 | * Module Name: evxface - External interfaces for ACPI events |
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 | #define EXPORT_ACPI_INTERFACES |
45 | |
46 | #include "acpi.h" |
47 | #include "accommon.h" |
48 | #include "acnamesp.h" |
49 | #include "acevents.h" |
50 | #include "acinterp.h" |
51 | |
52 | #define _COMPONENT ACPI_EVENTS |
53 | ACPI_MODULE_NAME ("evxface" ) |
54 | |
55 | #if (!ACPI_REDUCED_HARDWARE) |
56 | |
57 | /* Local prototypes */ |
58 | |
59 | static ACPI_STATUS |
60 | AcpiEvInstallGpeHandler ( |
61 | ACPI_HANDLE GpeDevice, |
62 | UINT32 GpeNumber, |
63 | UINT32 Type, |
64 | BOOLEAN IsRawHandler, |
65 | ACPI_GPE_HANDLER Address, |
66 | void *Context); |
67 | |
68 | #endif |
69 | |
70 | |
71 | /******************************************************************************* |
72 | * |
73 | * FUNCTION: AcpiInstallNotifyHandler |
74 | * |
75 | * PARAMETERS: Device - The device for which notifies will be handled |
76 | * HandlerType - The type of handler: |
77 | * ACPI_SYSTEM_NOTIFY: System Handler (00-7F) |
78 | * ACPI_DEVICE_NOTIFY: Device Handler (80-FF) |
79 | * ACPI_ALL_NOTIFY: Both System and Device |
80 | * Handler - Address of the handler |
81 | * Context - Value passed to the handler on each GPE |
82 | * |
83 | * RETURN: Status |
84 | * |
85 | * DESCRIPTION: Install a handler for notifications on an ACPI Device, |
86 | * ThermalZone, or Processor object. |
87 | * |
88 | * NOTES: The Root namespace object may have only one handler for each |
89 | * type of notify (System/Device). Device/Thermal/Processor objects |
90 | * may have one device notify handler, and multiple system notify |
91 | * handlers. |
92 | * |
93 | ******************************************************************************/ |
94 | |
95 | ACPI_STATUS |
96 | AcpiInstallNotifyHandler ( |
97 | ACPI_HANDLE Device, |
98 | UINT32 HandlerType, |
99 | ACPI_NOTIFY_HANDLER Handler, |
100 | void *Context) |
101 | { |
102 | ACPI_NAMESPACE_NODE *Node = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, Device); |
103 | ACPI_OPERAND_OBJECT *ObjDesc; |
104 | ACPI_OPERAND_OBJECT *HandlerObj; |
105 | ACPI_STATUS Status; |
106 | UINT32 i; |
107 | |
108 | |
109 | ACPI_FUNCTION_TRACE (AcpiInstallNotifyHandler); |
110 | |
111 | |
112 | /* Parameter validation */ |
113 | |
114 | if ((!Device) || (!Handler) || (!HandlerType) || |
115 | (HandlerType > ACPI_MAX_NOTIFY_HANDLER_TYPE)) |
116 | { |
117 | return_ACPI_STATUS (AE_BAD_PARAMETER); |
118 | } |
119 | |
120 | Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); |
121 | if (ACPI_FAILURE (Status)) |
122 | { |
123 | return_ACPI_STATUS (Status); |
124 | } |
125 | |
126 | /* |
127 | * Root Object: |
128 | * Registering a notify handler on the root object indicates that the |
129 | * caller wishes to receive notifications for all objects. Note that |
130 | * only one global handler can be registered per notify type. |
131 | * Ensure that a handler is not already installed. |
132 | */ |
133 | if (Device == ACPI_ROOT_OBJECT) |
134 | { |
135 | for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++) |
136 | { |
137 | if (HandlerType & (i+1)) |
138 | { |
139 | if (AcpiGbl_GlobalNotify[i].Handler) |
140 | { |
141 | Status = AE_ALREADY_EXISTS; |
142 | goto UnlockAndExit; |
143 | } |
144 | |
145 | AcpiGbl_GlobalNotify[i].Handler = Handler; |
146 | AcpiGbl_GlobalNotify[i].Context = Context; |
147 | } |
148 | } |
149 | |
150 | goto UnlockAndExit; /* Global notify handler installed, all done */ |
151 | } |
152 | |
153 | /* |
154 | * All Other Objects: |
155 | * Caller will only receive notifications specific to the target |
156 | * object. Note that only certain object types are allowed to |
157 | * receive notifications. |
158 | */ |
159 | |
160 | /* Are Notifies allowed on this object? */ |
161 | |
162 | if (!AcpiEvIsNotifyObject (Node)) |
163 | { |
164 | Status = AE_TYPE; |
165 | goto UnlockAndExit; |
166 | } |
167 | |
168 | /* Check for an existing internal object, might not exist */ |
169 | |
170 | ObjDesc = AcpiNsGetAttachedObject (Node); |
171 | if (!ObjDesc) |
172 | { |
173 | /* Create a new object */ |
174 | |
175 | ObjDesc = AcpiUtCreateInternalObject (Node->Type); |
176 | if (!ObjDesc) |
177 | { |
178 | Status = AE_NO_MEMORY; |
179 | goto UnlockAndExit; |
180 | } |
181 | |
182 | /* Attach new object to the Node, remove local reference */ |
183 | |
184 | Status = AcpiNsAttachObject (Device, ObjDesc, Node->Type); |
185 | AcpiUtRemoveReference (ObjDesc); |
186 | if (ACPI_FAILURE (Status)) |
187 | { |
188 | goto UnlockAndExit; |
189 | } |
190 | } |
191 | |
192 | /* Ensure that the handler is not already installed in the lists */ |
193 | |
194 | for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++) |
195 | { |
196 | if (HandlerType & (i+1)) |
197 | { |
198 | HandlerObj = ObjDesc->CommonNotify.NotifyList[i]; |
199 | while (HandlerObj) |
200 | { |
201 | if (HandlerObj->Notify.Handler == Handler) |
202 | { |
203 | Status = AE_ALREADY_EXISTS; |
204 | goto UnlockAndExit; |
205 | } |
206 | |
207 | HandlerObj = HandlerObj->Notify.Next[i]; |
208 | } |
209 | } |
210 | } |
211 | |
212 | /* Create and populate a new notify handler object */ |
213 | |
214 | HandlerObj = AcpiUtCreateInternalObject (ACPI_TYPE_LOCAL_NOTIFY); |
215 | if (!HandlerObj) |
216 | { |
217 | Status = AE_NO_MEMORY; |
218 | goto UnlockAndExit; |
219 | } |
220 | |
221 | HandlerObj->Notify.Node = Node; |
222 | HandlerObj->Notify.HandlerType = HandlerType; |
223 | HandlerObj->Notify.Handler = Handler; |
224 | HandlerObj->Notify.Context = Context; |
225 | |
226 | /* Install the handler at the list head(s) */ |
227 | |
228 | for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++) |
229 | { |
230 | if (HandlerType & (i+1)) |
231 | { |
232 | HandlerObj->Notify.Next[i] = |
233 | ObjDesc->CommonNotify.NotifyList[i]; |
234 | |
235 | ObjDesc->CommonNotify.NotifyList[i] = HandlerObj; |
236 | } |
237 | } |
238 | |
239 | /* Add an extra reference if handler was installed in both lists */ |
240 | |
241 | if (HandlerType == ACPI_ALL_NOTIFY) |
242 | { |
243 | AcpiUtAddReference (HandlerObj); |
244 | } |
245 | |
246 | |
247 | UnlockAndExit: |
248 | (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); |
249 | return_ACPI_STATUS (Status); |
250 | } |
251 | |
252 | ACPI_EXPORT_SYMBOL (AcpiInstallNotifyHandler) |
253 | |
254 | |
255 | /******************************************************************************* |
256 | * |
257 | * FUNCTION: AcpiRemoveNotifyHandler |
258 | * |
259 | * PARAMETERS: Device - The device for which the handler is installed |
260 | * HandlerType - The type of handler: |
261 | * ACPI_SYSTEM_NOTIFY: System Handler (00-7F) |
262 | * ACPI_DEVICE_NOTIFY: Device Handler (80-FF) |
263 | * ACPI_ALL_NOTIFY: Both System and Device |
264 | * Handler - Address of the handler |
265 | * |
266 | * RETURN: Status |
267 | * |
268 | * DESCRIPTION: Remove a handler for notifies on an ACPI device |
269 | * |
270 | ******************************************************************************/ |
271 | |
272 | ACPI_STATUS |
273 | AcpiRemoveNotifyHandler ( |
274 | ACPI_HANDLE Device, |
275 | UINT32 HandlerType, |
276 | ACPI_NOTIFY_HANDLER Handler) |
277 | { |
278 | ACPI_NAMESPACE_NODE *Node = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, Device); |
279 | ACPI_OPERAND_OBJECT *ObjDesc; |
280 | ACPI_OPERAND_OBJECT *HandlerObj; |
281 | ACPI_OPERAND_OBJECT *PreviousHandlerObj; |
282 | ACPI_STATUS Status = AE_OK; |
283 | UINT32 i; |
284 | |
285 | |
286 | ACPI_FUNCTION_TRACE (AcpiRemoveNotifyHandler); |
287 | |
288 | |
289 | /* Parameter validation */ |
290 | |
291 | if ((!Device) || (!Handler) || (!HandlerType) || |
292 | (HandlerType > ACPI_MAX_NOTIFY_HANDLER_TYPE)) |
293 | { |
294 | return_ACPI_STATUS (AE_BAD_PARAMETER); |
295 | } |
296 | |
297 | /* Root Object. Global handlers are removed here */ |
298 | |
299 | if (Device == ACPI_ROOT_OBJECT) |
300 | { |
301 | for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++) |
302 | { |
303 | if (HandlerType & (i+1)) |
304 | { |
305 | Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); |
306 | if (ACPI_FAILURE (Status)) |
307 | { |
308 | return_ACPI_STATUS (Status); |
309 | } |
310 | |
311 | if (!AcpiGbl_GlobalNotify[i].Handler || |
312 | (AcpiGbl_GlobalNotify[i].Handler != Handler)) |
313 | { |
314 | Status = AE_NOT_EXIST; |
315 | goto UnlockAndExit; |
316 | } |
317 | |
318 | ACPI_DEBUG_PRINT ((ACPI_DB_INFO, |
319 | "Removing global notify handler\n" )); |
320 | |
321 | AcpiGbl_GlobalNotify[i].Handler = NULL; |
322 | AcpiGbl_GlobalNotify[i].Context = NULL; |
323 | |
324 | (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); |
325 | |
326 | /* Make sure all deferred notify tasks are completed */ |
327 | |
328 | AcpiOsWaitEventsComplete (); |
329 | } |
330 | } |
331 | |
332 | return_ACPI_STATUS (AE_OK); |
333 | } |
334 | |
335 | /* All other objects: Are Notifies allowed on this object? */ |
336 | |
337 | if (!AcpiEvIsNotifyObject (Node)) |
338 | { |
339 | return_ACPI_STATUS (AE_TYPE); |
340 | } |
341 | |
342 | /* Must have an existing internal object */ |
343 | |
344 | ObjDesc = AcpiNsGetAttachedObject (Node); |
345 | if (!ObjDesc) |
346 | { |
347 | return_ACPI_STATUS (AE_NOT_EXIST); |
348 | } |
349 | |
350 | /* Internal object exists. Find the handler and remove it */ |
351 | |
352 | for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++) |
353 | { |
354 | if (HandlerType & (i+1)) |
355 | { |
356 | Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); |
357 | if (ACPI_FAILURE (Status)) |
358 | { |
359 | return_ACPI_STATUS (Status); |
360 | } |
361 | |
362 | HandlerObj = ObjDesc->CommonNotify.NotifyList[i]; |
363 | PreviousHandlerObj = NULL; |
364 | |
365 | /* Attempt to find the handler in the handler list */ |
366 | |
367 | while (HandlerObj && |
368 | (HandlerObj->Notify.Handler != Handler)) |
369 | { |
370 | PreviousHandlerObj = HandlerObj; |
371 | HandlerObj = HandlerObj->Notify.Next[i]; |
372 | } |
373 | |
374 | if (!HandlerObj) |
375 | { |
376 | Status = AE_NOT_EXIST; |
377 | goto UnlockAndExit; |
378 | } |
379 | |
380 | /* Remove the handler object from the list */ |
381 | |
382 | if (PreviousHandlerObj) /* Handler is not at the list head */ |
383 | { |
384 | PreviousHandlerObj->Notify.Next[i] = |
385 | HandlerObj->Notify.Next[i]; |
386 | } |
387 | else /* Handler is at the list head */ |
388 | { |
389 | ObjDesc->CommonNotify.NotifyList[i] = |
390 | HandlerObj->Notify.Next[i]; |
391 | } |
392 | |
393 | (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); |
394 | |
395 | /* Make sure all deferred notify tasks are completed */ |
396 | |
397 | AcpiOsWaitEventsComplete (); |
398 | AcpiUtRemoveReference (HandlerObj); |
399 | } |
400 | } |
401 | |
402 | return_ACPI_STATUS (Status); |
403 | |
404 | |
405 | UnlockAndExit: |
406 | (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); |
407 | return_ACPI_STATUS (Status); |
408 | } |
409 | |
410 | ACPI_EXPORT_SYMBOL (AcpiRemoveNotifyHandler) |
411 | |
412 | |
413 | /******************************************************************************* |
414 | * |
415 | * FUNCTION: AcpiInstallExceptionHandler |
416 | * |
417 | * PARAMETERS: Handler - Pointer to the handler function for the |
418 | * event |
419 | * |
420 | * RETURN: Status |
421 | * |
422 | * DESCRIPTION: Saves the pointer to the handler function |
423 | * |
424 | ******************************************************************************/ |
425 | |
426 | ACPI_STATUS |
427 | AcpiInstallExceptionHandler ( |
428 | ACPI_EXCEPTION_HANDLER Handler) |
429 | { |
430 | ACPI_STATUS Status; |
431 | |
432 | |
433 | ACPI_FUNCTION_TRACE (AcpiInstallExceptionHandler); |
434 | |
435 | |
436 | Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS); |
437 | if (ACPI_FAILURE (Status)) |
438 | { |
439 | return_ACPI_STATUS (Status); |
440 | } |
441 | |
442 | /* Don't allow two handlers. */ |
443 | |
444 | if (AcpiGbl_ExceptionHandler) |
445 | { |
446 | Status = AE_ALREADY_EXISTS; |
447 | goto Cleanup; |
448 | } |
449 | |
450 | /* Install the handler */ |
451 | |
452 | AcpiGbl_ExceptionHandler = Handler; |
453 | |
454 | Cleanup: |
455 | (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS); |
456 | return_ACPI_STATUS (Status); |
457 | } |
458 | |
459 | ACPI_EXPORT_SYMBOL (AcpiInstallExceptionHandler) |
460 | |
461 | |
462 | #if (!ACPI_REDUCED_HARDWARE) |
463 | /******************************************************************************* |
464 | * |
465 | * FUNCTION: AcpiInstallSciHandler |
466 | * |
467 | * PARAMETERS: Address - Address of the handler |
468 | * Context - Value passed to the handler on each SCI |
469 | * |
470 | * RETURN: Status |
471 | * |
472 | * DESCRIPTION: Install a handler for a System Control Interrupt. |
473 | * |
474 | ******************************************************************************/ |
475 | |
476 | ACPI_STATUS |
477 | AcpiInstallSciHandler ( |
478 | ACPI_SCI_HANDLER Address, |
479 | void *Context) |
480 | { |
481 | ACPI_SCI_HANDLER_INFO *NewSciHandler; |
482 | ACPI_SCI_HANDLER_INFO *SciHandler; |
483 | ACPI_CPU_FLAGS Flags; |
484 | ACPI_STATUS Status; |
485 | |
486 | |
487 | ACPI_FUNCTION_TRACE (AcpiInstallSciHandler); |
488 | |
489 | |
490 | if (!Address) |
491 | { |
492 | return_ACPI_STATUS (AE_BAD_PARAMETER); |
493 | } |
494 | |
495 | /* Allocate and init a handler object */ |
496 | |
497 | NewSciHandler = ACPI_ALLOCATE (sizeof (ACPI_SCI_HANDLER_INFO)); |
498 | if (!NewSciHandler) |
499 | { |
500 | return_ACPI_STATUS (AE_NO_MEMORY); |
501 | } |
502 | |
503 | NewSciHandler->Address = Address; |
504 | NewSciHandler->Context = Context; |
505 | |
506 | Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS); |
507 | if (ACPI_FAILURE (Status)) |
508 | { |
509 | goto Exit; |
510 | } |
511 | |
512 | /* Lock list during installation */ |
513 | |
514 | Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); |
515 | SciHandler = AcpiGbl_SciHandlerList; |
516 | |
517 | /* Ensure handler does not already exist */ |
518 | |
519 | while (SciHandler) |
520 | { |
521 | if (Address == SciHandler->Address) |
522 | { |
523 | Status = AE_ALREADY_EXISTS; |
524 | goto UnlockAndExit; |
525 | } |
526 | |
527 | SciHandler = SciHandler->Next; |
528 | } |
529 | |
530 | /* Install the new handler into the global list (at head) */ |
531 | |
532 | NewSciHandler->Next = AcpiGbl_SciHandlerList; |
533 | AcpiGbl_SciHandlerList = NewSciHandler; |
534 | |
535 | |
536 | UnlockAndExit: |
537 | |
538 | AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); |
539 | (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS); |
540 | |
541 | Exit: |
542 | if (ACPI_FAILURE (Status)) |
543 | { |
544 | ACPI_FREE (NewSciHandler); |
545 | } |
546 | return_ACPI_STATUS (Status); |
547 | } |
548 | |
549 | ACPI_EXPORT_SYMBOL (AcpiInstallSciHandler) |
550 | |
551 | |
552 | /******************************************************************************* |
553 | * |
554 | * FUNCTION: AcpiRemoveSciHandler |
555 | * |
556 | * PARAMETERS: Address - Address of the handler |
557 | * |
558 | * RETURN: Status |
559 | * |
560 | * DESCRIPTION: Remove a handler for a System Control Interrupt. |
561 | * |
562 | ******************************************************************************/ |
563 | |
564 | ACPI_STATUS |
565 | AcpiRemoveSciHandler ( |
566 | ACPI_SCI_HANDLER Address) |
567 | { |
568 | ACPI_SCI_HANDLER_INFO *PrevSciHandler; |
569 | ACPI_SCI_HANDLER_INFO *NextSciHandler; |
570 | ACPI_CPU_FLAGS Flags; |
571 | ACPI_STATUS Status; |
572 | |
573 | |
574 | ACPI_FUNCTION_TRACE (AcpiRemoveSciHandler); |
575 | |
576 | |
577 | if (!Address) |
578 | { |
579 | return_ACPI_STATUS (AE_BAD_PARAMETER); |
580 | } |
581 | |
582 | Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS); |
583 | if (ACPI_FAILURE (Status)) |
584 | { |
585 | return_ACPI_STATUS (Status); |
586 | } |
587 | |
588 | /* Remove the SCI handler with lock */ |
589 | |
590 | Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); |
591 | |
592 | PrevSciHandler = NULL; |
593 | NextSciHandler = AcpiGbl_SciHandlerList; |
594 | while (NextSciHandler) |
595 | { |
596 | if (NextSciHandler->Address == Address) |
597 | { |
598 | /* Unlink and free the SCI handler info block */ |
599 | |
600 | if (PrevSciHandler) |
601 | { |
602 | PrevSciHandler->Next = NextSciHandler->Next; |
603 | } |
604 | else |
605 | { |
606 | AcpiGbl_SciHandlerList = NextSciHandler->Next; |
607 | } |
608 | |
609 | AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); |
610 | ACPI_FREE (NextSciHandler); |
611 | goto UnlockAndExit; |
612 | } |
613 | |
614 | PrevSciHandler = NextSciHandler; |
615 | NextSciHandler = NextSciHandler->Next; |
616 | } |
617 | |
618 | AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); |
619 | Status = AE_NOT_EXIST; |
620 | |
621 | |
622 | UnlockAndExit: |
623 | (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS); |
624 | return_ACPI_STATUS (Status); |
625 | } |
626 | |
627 | ACPI_EXPORT_SYMBOL (AcpiRemoveSciHandler) |
628 | |
629 | |
630 | /******************************************************************************* |
631 | * |
632 | * FUNCTION: AcpiInstallGlobalEventHandler |
633 | * |
634 | * PARAMETERS: Handler - Pointer to the global event handler function |
635 | * Context - Value passed to the handler on each event |
636 | * |
637 | * RETURN: Status |
638 | * |
639 | * DESCRIPTION: Saves the pointer to the handler function. The global handler |
640 | * is invoked upon each incoming GPE and Fixed Event. It is |
641 | * invoked at interrupt level at the time of the event dispatch. |
642 | * Can be used to update event counters, etc. |
643 | * |
644 | ******************************************************************************/ |
645 | |
646 | ACPI_STATUS |
647 | AcpiInstallGlobalEventHandler ( |
648 | ACPI_GBL_EVENT_HANDLER Handler, |
649 | void *Context) |
650 | { |
651 | ACPI_STATUS Status; |
652 | |
653 | |
654 | ACPI_FUNCTION_TRACE (AcpiInstallGlobalEventHandler); |
655 | |
656 | |
657 | /* Parameter validation */ |
658 | |
659 | if (!Handler) |
660 | { |
661 | return_ACPI_STATUS (AE_BAD_PARAMETER); |
662 | } |
663 | |
664 | Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS); |
665 | if (ACPI_FAILURE (Status)) |
666 | { |
667 | return_ACPI_STATUS (Status); |
668 | } |
669 | |
670 | /* Don't allow two handlers. */ |
671 | |
672 | if (AcpiGbl_GlobalEventHandler) |
673 | { |
674 | Status = AE_ALREADY_EXISTS; |
675 | goto Cleanup; |
676 | } |
677 | |
678 | AcpiGbl_GlobalEventHandler = Handler; |
679 | AcpiGbl_GlobalEventHandlerContext = Context; |
680 | |
681 | |
682 | Cleanup: |
683 | (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS); |
684 | return_ACPI_STATUS (Status); |
685 | } |
686 | |
687 | ACPI_EXPORT_SYMBOL (AcpiInstallGlobalEventHandler) |
688 | |
689 | |
690 | /******************************************************************************* |
691 | * |
692 | * FUNCTION: AcpiInstallFixedEventHandler |
693 | * |
694 | * PARAMETERS: Event - Event type to enable. |
695 | * Handler - Pointer to the handler function for the |
696 | * event |
697 | * Context - Value passed to the handler on each GPE |
698 | * |
699 | * RETURN: Status |
700 | * |
701 | * DESCRIPTION: Saves the pointer to the handler function and then enables the |
702 | * event. |
703 | * |
704 | ******************************************************************************/ |
705 | |
706 | ACPI_STATUS |
707 | AcpiInstallFixedEventHandler ( |
708 | UINT32 Event, |
709 | ACPI_EVENT_HANDLER Handler, |
710 | void *Context) |
711 | { |
712 | ACPI_STATUS Status; |
713 | |
714 | |
715 | ACPI_FUNCTION_TRACE (AcpiInstallFixedEventHandler); |
716 | |
717 | |
718 | /* Parameter validation */ |
719 | |
720 | if (Event > ACPI_EVENT_MAX) |
721 | { |
722 | return_ACPI_STATUS (AE_BAD_PARAMETER); |
723 | } |
724 | |
725 | Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS); |
726 | if (ACPI_FAILURE (Status)) |
727 | { |
728 | return_ACPI_STATUS (Status); |
729 | } |
730 | |
731 | /* Do not allow multiple handlers */ |
732 | |
733 | if (AcpiGbl_FixedEventHandlers[Event].Handler) |
734 | { |
735 | Status = AE_ALREADY_EXISTS; |
736 | goto Cleanup; |
737 | } |
738 | |
739 | /* Install the handler before enabling the event */ |
740 | |
741 | AcpiGbl_FixedEventHandlers[Event].Handler = Handler; |
742 | AcpiGbl_FixedEventHandlers[Event].Context = Context; |
743 | |
744 | Status = AcpiEnableEvent (Event, 0); |
745 | if (ACPI_FAILURE (Status)) |
746 | { |
747 | ACPI_WARNING ((AE_INFO, |
748 | "Could not enable fixed event - %s (%u)" , |
749 | AcpiUtGetEventName (Event), Event)); |
750 | |
751 | /* Remove the handler */ |
752 | |
753 | AcpiGbl_FixedEventHandlers[Event].Handler = NULL; |
754 | AcpiGbl_FixedEventHandlers[Event].Context = NULL; |
755 | } |
756 | else |
757 | { |
758 | ACPI_DEBUG_PRINT ((ACPI_DB_INFO, |
759 | "Enabled fixed event %s (%X), Handler=%p\n" , |
760 | AcpiUtGetEventName (Event), Event, Handler)); |
761 | } |
762 | |
763 | |
764 | Cleanup: |
765 | (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS); |
766 | return_ACPI_STATUS (Status); |
767 | } |
768 | |
769 | ACPI_EXPORT_SYMBOL (AcpiInstallFixedEventHandler) |
770 | |
771 | |
772 | /******************************************************************************* |
773 | * |
774 | * FUNCTION: AcpiRemoveFixedEventHandler |
775 | * |
776 | * PARAMETERS: Event - Event type to disable. |
777 | * Handler - Address of the handler |
778 | * |
779 | * RETURN: Status |
780 | * |
781 | * DESCRIPTION: Disables the event and unregisters the event handler. |
782 | * |
783 | ******************************************************************************/ |
784 | |
785 | ACPI_STATUS |
786 | AcpiRemoveFixedEventHandler ( |
787 | UINT32 Event, |
788 | ACPI_EVENT_HANDLER Handler) |
789 | { |
790 | ACPI_STATUS Status = AE_OK; |
791 | |
792 | |
793 | ACPI_FUNCTION_TRACE (AcpiRemoveFixedEventHandler); |
794 | |
795 | |
796 | /* Parameter validation */ |
797 | |
798 | if (Event > ACPI_EVENT_MAX) |
799 | { |
800 | return_ACPI_STATUS (AE_BAD_PARAMETER); |
801 | } |
802 | |
803 | Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS); |
804 | if (ACPI_FAILURE (Status)) |
805 | { |
806 | return_ACPI_STATUS (Status); |
807 | } |
808 | |
809 | /* Disable the event before removing the handler */ |
810 | |
811 | Status = AcpiDisableEvent (Event, 0); |
812 | |
813 | /* Always Remove the handler */ |
814 | |
815 | AcpiGbl_FixedEventHandlers[Event].Handler = NULL; |
816 | AcpiGbl_FixedEventHandlers[Event].Context = NULL; |
817 | |
818 | if (ACPI_FAILURE (Status)) |
819 | { |
820 | ACPI_WARNING ((AE_INFO, |
821 | "Could not disable fixed event - %s (%u)" , |
822 | AcpiUtGetEventName (Event), Event)); |
823 | } |
824 | else |
825 | { |
826 | ACPI_DEBUG_PRINT ((ACPI_DB_INFO, |
827 | "Disabled fixed event - %s (%X)\n" , |
828 | AcpiUtGetEventName (Event), Event)); |
829 | } |
830 | |
831 | (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS); |
832 | return_ACPI_STATUS (Status); |
833 | } |
834 | |
835 | ACPI_EXPORT_SYMBOL (AcpiRemoveFixedEventHandler) |
836 | |
837 | |
838 | /******************************************************************************* |
839 | * |
840 | * FUNCTION: AcpiEvInstallGpeHandler |
841 | * |
842 | * PARAMETERS: GpeDevice - Namespace node for the GPE (NULL for FADT |
843 | * defined GPEs) |
844 | * GpeNumber - The GPE number within the GPE block |
845 | * Type - Whether this GPE should be treated as an |
846 | * edge- or level-triggered interrupt. |
847 | * IsRawHandler - Whether this GPE should be handled using |
848 | * the special GPE handler mode. |
849 | * Address - Address of the handler |
850 | * Context - Value passed to the handler on each GPE |
851 | * |
852 | * RETURN: Status |
853 | * |
854 | * DESCRIPTION: Internal function to install a handler for a General Purpose |
855 | * Event. |
856 | * |
857 | ******************************************************************************/ |
858 | |
859 | static ACPI_STATUS |
860 | AcpiEvInstallGpeHandler ( |
861 | ACPI_HANDLE GpeDevice, |
862 | UINT32 GpeNumber, |
863 | UINT32 Type, |
864 | BOOLEAN IsRawHandler, |
865 | ACPI_GPE_HANDLER Address, |
866 | void *Context) |
867 | { |
868 | ACPI_GPE_EVENT_INFO *GpeEventInfo; |
869 | ACPI_GPE_HANDLER_INFO *Handler; |
870 | ACPI_STATUS Status; |
871 | ACPI_CPU_FLAGS Flags; |
872 | |
873 | |
874 | ACPI_FUNCTION_TRACE (EvInstallGpeHandler); |
875 | |
876 | |
877 | /* Parameter validation */ |
878 | |
879 | if ((!Address) || (Type & ~ACPI_GPE_XRUPT_TYPE_MASK)) |
880 | { |
881 | return_ACPI_STATUS (AE_BAD_PARAMETER); |
882 | } |
883 | |
884 | Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS); |
885 | if (ACPI_FAILURE (Status)) |
886 | { |
887 | return_ACPI_STATUS (Status); |
888 | } |
889 | |
890 | /* Allocate and init handler object (before lock) */ |
891 | |
892 | Handler = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_GPE_HANDLER_INFO)); |
893 | if (!Handler) |
894 | { |
895 | Status = AE_NO_MEMORY; |
896 | goto UnlockAndExit; |
897 | } |
898 | |
899 | Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); |
900 | |
901 | /* Ensure that we have a valid GPE number */ |
902 | |
903 | GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber); |
904 | if (!GpeEventInfo) |
905 | { |
906 | Status = AE_BAD_PARAMETER; |
907 | goto FreeAndExit; |
908 | } |
909 | |
910 | /* Make sure that there isn't a handler there already */ |
911 | |
912 | if ((ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags) == |
913 | ACPI_GPE_DISPATCH_HANDLER) || |
914 | (ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags) == |
915 | ACPI_GPE_DISPATCH_RAW_HANDLER)) |
916 | { |
917 | Status = AE_ALREADY_EXISTS; |
918 | goto FreeAndExit; |
919 | } |
920 | |
921 | Handler->Address = Address; |
922 | Handler->Context = Context; |
923 | Handler->MethodNode = GpeEventInfo->Dispatch.MethodNode; |
924 | Handler->OriginalFlags = (UINT8) (GpeEventInfo->Flags & |
925 | (ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK)); |
926 | |
927 | /* |
928 | * If the GPE is associated with a method, it may have been enabled |
929 | * automatically during initialization, in which case it has to be |
930 | * disabled now to avoid spurious execution of the handler. |
931 | */ |
932 | if (((ACPI_GPE_DISPATCH_TYPE (Handler->OriginalFlags) == |
933 | ACPI_GPE_DISPATCH_METHOD) || |
934 | (ACPI_GPE_DISPATCH_TYPE (Handler->OriginalFlags) == |
935 | ACPI_GPE_DISPATCH_NOTIFY)) && |
936 | GpeEventInfo->RuntimeCount) |
937 | { |
938 | Handler->OriginallyEnabled = TRUE; |
939 | (void) AcpiEvRemoveGpeReference (GpeEventInfo); |
940 | |
941 | /* Sanity check of original type against new type */ |
942 | |
943 | if (Type != (UINT32) (GpeEventInfo->Flags & ACPI_GPE_XRUPT_TYPE_MASK)) |
944 | { |
945 | ACPI_WARNING ((AE_INFO, "GPE type mismatch (level/edge)" )); |
946 | } |
947 | } |
948 | |
949 | /* Install the handler */ |
950 | |
951 | GpeEventInfo->Dispatch.Handler = Handler; |
952 | |
953 | /* Setup up dispatch flags to indicate handler (vs. method/notify) */ |
954 | |
955 | GpeEventInfo->Flags &= ~(ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK); |
956 | GpeEventInfo->Flags |= (UINT8) (Type | (IsRawHandler ? |
957 | ACPI_GPE_DISPATCH_RAW_HANDLER : ACPI_GPE_DISPATCH_HANDLER)); |
958 | |
959 | AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); |
960 | |
961 | |
962 | UnlockAndExit: |
963 | (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS); |
964 | return_ACPI_STATUS (Status); |
965 | |
966 | FreeAndExit: |
967 | AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); |
968 | ACPI_FREE (Handler); |
969 | goto UnlockAndExit; |
970 | } |
971 | |
972 | |
973 | /******************************************************************************* |
974 | * |
975 | * FUNCTION: AcpiInstallGpeHandler |
976 | * |
977 | * PARAMETERS: GpeDevice - Namespace node for the GPE (NULL for FADT |
978 | * defined GPEs) |
979 | * GpeNumber - The GPE number within the GPE block |
980 | * Type - Whether this GPE should be treated as an |
981 | * edge- or level-triggered interrupt. |
982 | * Address - Address of the handler |
983 | * Context - Value passed to the handler on each GPE |
984 | * |
985 | * RETURN: Status |
986 | * |
987 | * DESCRIPTION: Install a handler for a General Purpose Event. |
988 | * |
989 | ******************************************************************************/ |
990 | |
991 | ACPI_STATUS |
992 | AcpiInstallGpeHandler ( |
993 | ACPI_HANDLE GpeDevice, |
994 | UINT32 GpeNumber, |
995 | UINT32 Type, |
996 | ACPI_GPE_HANDLER Address, |
997 | void *Context) |
998 | { |
999 | ACPI_STATUS Status; |
1000 | |
1001 | |
1002 | ACPI_FUNCTION_TRACE (AcpiInstallGpeHandler); |
1003 | |
1004 | |
1005 | Status = AcpiEvInstallGpeHandler (GpeDevice, GpeNumber, Type, |
1006 | FALSE, Address, Context); |
1007 | |
1008 | return_ACPI_STATUS (Status); |
1009 | } |
1010 | |
1011 | ACPI_EXPORT_SYMBOL (AcpiInstallGpeHandler) |
1012 | |
1013 | |
1014 | /******************************************************************************* |
1015 | * |
1016 | * FUNCTION: AcpiInstallGpeRawHandler |
1017 | * |
1018 | * PARAMETERS: GpeDevice - Namespace node for the GPE (NULL for FADT |
1019 | * defined GPEs) |
1020 | * GpeNumber - The GPE number within the GPE block |
1021 | * Type - Whether this GPE should be treated as an |
1022 | * edge- or level-triggered interrupt. |
1023 | * Address - Address of the handler |
1024 | * Context - Value passed to the handler on each GPE |
1025 | * |
1026 | * RETURN: Status |
1027 | * |
1028 | * DESCRIPTION: Install a handler for a General Purpose Event. |
1029 | * |
1030 | ******************************************************************************/ |
1031 | |
1032 | ACPI_STATUS |
1033 | AcpiInstallGpeRawHandler ( |
1034 | ACPI_HANDLE GpeDevice, |
1035 | UINT32 GpeNumber, |
1036 | UINT32 Type, |
1037 | ACPI_GPE_HANDLER Address, |
1038 | void *Context) |
1039 | { |
1040 | ACPI_STATUS Status; |
1041 | |
1042 | |
1043 | ACPI_FUNCTION_TRACE (AcpiInstallGpeRawHandler); |
1044 | |
1045 | |
1046 | Status = AcpiEvInstallGpeHandler (GpeDevice, GpeNumber, Type, |
1047 | TRUE, Address, Context); |
1048 | |
1049 | return_ACPI_STATUS (Status); |
1050 | } |
1051 | |
1052 | ACPI_EXPORT_SYMBOL (AcpiInstallGpeRawHandler) |
1053 | |
1054 | |
1055 | /******************************************************************************* |
1056 | * |
1057 | * FUNCTION: AcpiRemoveGpeHandler |
1058 | * |
1059 | * PARAMETERS: GpeDevice - Namespace node for the GPE (NULL for FADT |
1060 | * defined GPEs) |
1061 | * GpeNumber - The event to remove a handler |
1062 | * Address - Address of the handler |
1063 | * |
1064 | * RETURN: Status |
1065 | * |
1066 | * DESCRIPTION: Remove a handler for a General Purpose AcpiEvent. |
1067 | * |
1068 | ******************************************************************************/ |
1069 | |
1070 | ACPI_STATUS |
1071 | AcpiRemoveGpeHandler ( |
1072 | ACPI_HANDLE GpeDevice, |
1073 | UINT32 GpeNumber, |
1074 | ACPI_GPE_HANDLER Address) |
1075 | { |
1076 | ACPI_GPE_EVENT_INFO *GpeEventInfo; |
1077 | ACPI_GPE_HANDLER_INFO *Handler; |
1078 | ACPI_STATUS Status; |
1079 | ACPI_CPU_FLAGS Flags; |
1080 | |
1081 | |
1082 | ACPI_FUNCTION_TRACE (AcpiRemoveGpeHandler); |
1083 | |
1084 | |
1085 | /* Parameter validation */ |
1086 | |
1087 | if (!Address) |
1088 | { |
1089 | return_ACPI_STATUS (AE_BAD_PARAMETER); |
1090 | } |
1091 | |
1092 | Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS); |
1093 | if (ACPI_FAILURE (Status)) |
1094 | { |
1095 | return_ACPI_STATUS (Status); |
1096 | } |
1097 | |
1098 | Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); |
1099 | |
1100 | /* Ensure that we have a valid GPE number */ |
1101 | |
1102 | GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber); |
1103 | if (!GpeEventInfo) |
1104 | { |
1105 | Status = AE_BAD_PARAMETER; |
1106 | goto UnlockAndExit; |
1107 | } |
1108 | |
1109 | /* Make sure that a handler is indeed installed */ |
1110 | |
1111 | if ((ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags) != |
1112 | ACPI_GPE_DISPATCH_HANDLER) && |
1113 | (ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags) != |
1114 | ACPI_GPE_DISPATCH_RAW_HANDLER)) |
1115 | { |
1116 | Status = AE_NOT_EXIST; |
1117 | goto UnlockAndExit; |
1118 | } |
1119 | |
1120 | /* Make sure that the installed handler is the same */ |
1121 | |
1122 | if (GpeEventInfo->Dispatch.Handler->Address != Address) |
1123 | { |
1124 | Status = AE_BAD_PARAMETER; |
1125 | goto UnlockAndExit; |
1126 | } |
1127 | |
1128 | /* Remove the handler */ |
1129 | |
1130 | Handler = GpeEventInfo->Dispatch.Handler; |
1131 | GpeEventInfo->Dispatch.Handler = NULL; |
1132 | |
1133 | /* Restore Method node (if any), set dispatch flags */ |
1134 | |
1135 | GpeEventInfo->Dispatch.MethodNode = Handler->MethodNode; |
1136 | GpeEventInfo->Flags &= |
1137 | ~(ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK); |
1138 | GpeEventInfo->Flags |= Handler->OriginalFlags; |
1139 | |
1140 | /* |
1141 | * If the GPE was previously associated with a method and it was |
1142 | * enabled, it should be enabled at this point to restore the |
1143 | * post-initialization configuration. |
1144 | */ |
1145 | if (((ACPI_GPE_DISPATCH_TYPE (Handler->OriginalFlags) == |
1146 | ACPI_GPE_DISPATCH_METHOD) || |
1147 | (ACPI_GPE_DISPATCH_TYPE (Handler->OriginalFlags) == |
1148 | ACPI_GPE_DISPATCH_NOTIFY)) && |
1149 | Handler->OriginallyEnabled) |
1150 | { |
1151 | (void) AcpiEvAddGpeReference (GpeEventInfo); |
1152 | } |
1153 | |
1154 | AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); |
1155 | (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS); |
1156 | |
1157 | /* Make sure all deferred GPE tasks are completed */ |
1158 | |
1159 | AcpiOsWaitEventsComplete (); |
1160 | |
1161 | /* Now we can free the handler object */ |
1162 | |
1163 | ACPI_FREE (Handler); |
1164 | return_ACPI_STATUS (Status); |
1165 | |
1166 | UnlockAndExit: |
1167 | AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); |
1168 | (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS); |
1169 | return_ACPI_STATUS (Status); |
1170 | } |
1171 | |
1172 | ACPI_EXPORT_SYMBOL (AcpiRemoveGpeHandler) |
1173 | |
1174 | |
1175 | /******************************************************************************* |
1176 | * |
1177 | * FUNCTION: AcpiAcquireGlobalLock |
1178 | * |
1179 | * PARAMETERS: Timeout - How long the caller is willing to wait |
1180 | * Handle - Where the handle to the lock is returned |
1181 | * (if acquired) |
1182 | * |
1183 | * RETURN: Status |
1184 | * |
1185 | * DESCRIPTION: Acquire the ACPI Global Lock |
1186 | * |
1187 | * Note: Allows callers with the same thread ID to acquire the global lock |
1188 | * multiple times. In other words, externally, the behavior of the global lock |
1189 | * is identical to an AML mutex. On the first acquire, a new handle is |
1190 | * returned. On any subsequent calls to acquire by the same thread, the same |
1191 | * handle is returned. |
1192 | * |
1193 | ******************************************************************************/ |
1194 | |
1195 | ACPI_STATUS |
1196 | AcpiAcquireGlobalLock ( |
1197 | UINT16 Timeout, |
1198 | UINT32 *Handle) |
1199 | { |
1200 | ACPI_STATUS Status; |
1201 | |
1202 | |
1203 | if (!Handle) |
1204 | { |
1205 | return (AE_BAD_PARAMETER); |
1206 | } |
1207 | |
1208 | /* Must lock interpreter to prevent race conditions */ |
1209 | |
1210 | AcpiExEnterInterpreter (); |
1211 | |
1212 | Status = AcpiExAcquireMutexObject (Timeout, |
1213 | AcpiGbl_GlobalLockMutex, AcpiOsGetThreadId ()); |
1214 | |
1215 | if (ACPI_SUCCESS (Status)) |
1216 | { |
1217 | /* Return the global lock handle (updated in AcpiEvAcquireGlobalLock) */ |
1218 | |
1219 | *Handle = AcpiGbl_GlobalLockHandle; |
1220 | } |
1221 | |
1222 | AcpiExExitInterpreter (); |
1223 | return (Status); |
1224 | } |
1225 | |
1226 | ACPI_EXPORT_SYMBOL (AcpiAcquireGlobalLock) |
1227 | |
1228 | |
1229 | /******************************************************************************* |
1230 | * |
1231 | * FUNCTION: AcpiReleaseGlobalLock |
1232 | * |
1233 | * PARAMETERS: Handle - Returned from AcpiAcquireGlobalLock |
1234 | * |
1235 | * RETURN: Status |
1236 | * |
1237 | * DESCRIPTION: Release the ACPI Global Lock. The handle must be valid. |
1238 | * |
1239 | ******************************************************************************/ |
1240 | |
1241 | ACPI_STATUS |
1242 | AcpiReleaseGlobalLock ( |
1243 | UINT32 Handle) |
1244 | { |
1245 | ACPI_STATUS Status; |
1246 | |
1247 | |
1248 | if (!Handle || (Handle != AcpiGbl_GlobalLockHandle)) |
1249 | { |
1250 | return (AE_NOT_ACQUIRED); |
1251 | } |
1252 | |
1253 | Status = AcpiExReleaseMutexObject (AcpiGbl_GlobalLockMutex); |
1254 | return (Status); |
1255 | } |
1256 | |
1257 | ACPI_EXPORT_SYMBOL (AcpiReleaseGlobalLock) |
1258 | |
1259 | #endif /* !ACPI_REDUCED_HARDWARE */ |
1260 | |