]> Pileus Git - ~andy/linux/blob - drivers/acpi/acpica/evxface.c
tools/power: turbostat: fix large c1% issue
[~andy/linux] / drivers / acpi / acpica / evxface.c
1 /******************************************************************************
2  *
3  * Module Name: evxface - External interfaces for ACPI events
4  *
5  *****************************************************************************/
6
7 /*
8  * Copyright (C) 2000 - 2012, 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 <linux/export.h>
45 #include <acpi/acpi.h>
46 #include "accommon.h"
47 #include "acnamesp.h"
48 #include "acevents.h"
49 #include "acinterp.h"
50
51 #define _COMPONENT          ACPI_EVENTS
52 ACPI_MODULE_NAME("evxface")
53
54
55 /*******************************************************************************
56  *
57  * FUNCTION:    acpi_populate_handler_object
58  *
59  * PARAMETERS:  handler_obj        - Handler object to populate
60  *              handler_type       - The type of handler:
61  *                                  ACPI_SYSTEM_NOTIFY: system_handler (00-7f)
62  *                                  ACPI_DEVICE_NOTIFY: driver_handler (80-ff)
63  *                                  ACPI_ALL_NOTIFY:  both system and device
64  *              handler            - Address of the handler
65  *              context            - Value passed to the handler on each GPE
66  *              next               - Address of a handler object to link to
67  *
68  * RETURN:      None
69  *
70  * DESCRIPTION: Populate a handler object.
71  *
72  ******************************************************************************/
73 static void
74 acpi_populate_handler_object(struct acpi_object_notify_handler *handler_obj,
75                              u32 handler_type,
76                              acpi_notify_handler handler, void *context,
77                              struct acpi_object_notify_handler *next)
78 {
79         handler_obj->handler_type = handler_type;
80         handler_obj->handler = handler;
81         handler_obj->context = context;
82         handler_obj->next = next;
83 }
84
85 /*******************************************************************************
86  *
87  * FUNCTION:    acpi_add_handler_object
88  *
89  * PARAMETERS:  parent_obj         - Parent of the new object
90  *              handler            - Address of the handler
91  *              context            - Value passed to the handler on each GPE
92  *
93  * RETURN:      Status
94  *
95  * DESCRIPTION: Create a new handler object and populate it.
96  *
97  ******************************************************************************/
98 static acpi_status
99 acpi_add_handler_object(struct acpi_object_notify_handler *parent_obj,
100                         acpi_notify_handler handler, void *context)
101 {
102         struct acpi_object_notify_handler *handler_obj;
103
104         /* The parent must not be a defice notify handler object. */
105         if (parent_obj->handler_type & ACPI_DEVICE_NOTIFY)
106                 return AE_BAD_PARAMETER;
107
108         handler_obj = ACPI_ALLOCATE_ZEROED(sizeof(*handler_obj));
109         if (!handler_obj)
110                 return AE_NO_MEMORY;
111
112         acpi_populate_handler_object(handler_obj,
113                                         ACPI_SYSTEM_NOTIFY,
114                                         handler, context,
115                                         parent_obj->next);
116         parent_obj->next = handler_obj;
117
118         return AE_OK;
119 }
120
121
122 /*******************************************************************************
123  *
124  * FUNCTION:    acpi_install_notify_handler
125  *
126  * PARAMETERS:  Device          - The device for which notifies will be handled
127  *              handler_type    - The type of handler:
128  *                                  ACPI_SYSTEM_NOTIFY: system_handler (00-7f)
129  *                                  ACPI_DEVICE_NOTIFY: driver_handler (80-ff)
130  *                                  ACPI_ALL_NOTIFY:  both system and device
131  *              Handler         - Address of the handler
132  *              Context         - Value passed to the handler on each GPE
133  *
134  * RETURN:      Status
135  *
136  * DESCRIPTION: Install a handler for notifies on an ACPI device
137  *
138  ******************************************************************************/
139 acpi_status
140 acpi_install_notify_handler(acpi_handle device,
141                             u32 handler_type,
142                             acpi_notify_handler handler, void *context)
143 {
144         union acpi_operand_object *obj_desc;
145         union acpi_operand_object *notify_obj;
146         struct acpi_namespace_node *node;
147         acpi_status status;
148
149         ACPI_FUNCTION_TRACE(acpi_install_notify_handler);
150
151         /* Parameter validation */
152
153         if ((!device) ||
154             (!handler) || (handler_type > ACPI_MAX_NOTIFY_HANDLER_TYPE)) {
155                 return_ACPI_STATUS(AE_BAD_PARAMETER);
156         }
157
158         status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
159         if (ACPI_FAILURE(status)) {
160                 return_ACPI_STATUS(status);
161         }
162
163         /* Convert and validate the device handle */
164
165         node = acpi_ns_validate_handle(device);
166         if (!node) {
167                 status = AE_BAD_PARAMETER;
168                 goto unlock_and_exit;
169         }
170
171         /*
172          * Root Object:
173          * Registering a notify handler on the root object indicates that the
174          * caller wishes to receive notifications for all objects. Note that
175          * only one <external> global handler can be regsitered (per notify type).
176          */
177         if (device == ACPI_ROOT_OBJECT) {
178
179                 /* Make sure the handler is not already installed */
180
181                 if (((handler_type & ACPI_SYSTEM_NOTIFY) &&
182                      acpi_gbl_system_notify.handler) ||
183                     ((handler_type & ACPI_DEVICE_NOTIFY) &&
184                      acpi_gbl_device_notify.handler)) {
185                         status = AE_ALREADY_EXISTS;
186                         goto unlock_and_exit;
187                 }
188
189                 if (handler_type & ACPI_SYSTEM_NOTIFY) {
190                         acpi_gbl_system_notify.node = node;
191                         acpi_gbl_system_notify.handler = handler;
192                         acpi_gbl_system_notify.context = context;
193                 }
194
195                 if (handler_type & ACPI_DEVICE_NOTIFY) {
196                         acpi_gbl_device_notify.node = node;
197                         acpi_gbl_device_notify.handler = handler;
198                         acpi_gbl_device_notify.context = context;
199                 }
200
201                 /* Global notify handler installed */
202         }
203
204         /*
205          * All Other Objects:
206          * Caller will only receive notifications specific to the target object.
207          * Note that only certain object types can receive notifications.
208          */
209         else {
210                 /* Notifies allowed on this object? */
211
212                 if (!acpi_ev_is_notify_object(node)) {
213                         status = AE_TYPE;
214                         goto unlock_and_exit;
215                 }
216
217                 /* Check for an existing internal object */
218
219                 obj_desc = acpi_ns_get_attached_object(node);
220                 if (obj_desc) {
221
222                         /* Object exists. */
223
224                         /* For a device notify, make sure there's no handler. */
225                         if ((handler_type & ACPI_DEVICE_NOTIFY) &&
226                              obj_desc->common_notify.device_notify) {
227                                 status = AE_ALREADY_EXISTS;
228                                 goto unlock_and_exit;
229                         }
230
231                         /* System notifies may have more handlers installed. */
232                         notify_obj = obj_desc->common_notify.system_notify;
233
234                         if ((handler_type & ACPI_SYSTEM_NOTIFY) && notify_obj) {
235                                 struct acpi_object_notify_handler *parent_obj;
236
237                                 if (handler_type & ACPI_DEVICE_NOTIFY) {
238                                         status = AE_ALREADY_EXISTS;
239                                         goto unlock_and_exit;
240                                 }
241
242                                 parent_obj = &notify_obj->notify;
243                                 status = acpi_add_handler_object(parent_obj,
244                                                                  handler,
245                                                                  context);
246                                 goto unlock_and_exit;
247                         }
248                 } else {
249                         /* Create a new object */
250
251                         obj_desc = acpi_ut_create_internal_object(node->type);
252                         if (!obj_desc) {
253                                 status = AE_NO_MEMORY;
254                                 goto unlock_and_exit;
255                         }
256
257                         /* Attach new object to the Node */
258
259                         status =
260                             acpi_ns_attach_object(device, obj_desc, node->type);
261
262                         /* Remove local reference to the object */
263
264                         acpi_ut_remove_reference(obj_desc);
265                         if (ACPI_FAILURE(status)) {
266                                 goto unlock_and_exit;
267                         }
268                 }
269
270                 /* Install the handler */
271
272                 notify_obj =
273                     acpi_ut_create_internal_object(ACPI_TYPE_LOCAL_NOTIFY);
274                 if (!notify_obj) {
275                         status = AE_NO_MEMORY;
276                         goto unlock_and_exit;
277                 }
278
279                 acpi_populate_handler_object(&notify_obj->notify,
280                                                 handler_type,
281                                                 handler, context,
282                                                 NULL);
283
284                 if (handler_type & ACPI_SYSTEM_NOTIFY) {
285                         obj_desc->common_notify.system_notify = notify_obj;
286                 }
287
288                 if (handler_type & ACPI_DEVICE_NOTIFY) {
289                         obj_desc->common_notify.device_notify = notify_obj;
290                 }
291
292                 if (handler_type == ACPI_ALL_NOTIFY) {
293
294                         /* Extra ref if installed in both */
295
296                         acpi_ut_add_reference(notify_obj);
297                 }
298         }
299
300       unlock_and_exit:
301         (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
302         return_ACPI_STATUS(status);
303 }
304
305 ACPI_EXPORT_SYMBOL(acpi_install_notify_handler)
306
307 /*******************************************************************************
308  *
309  * FUNCTION:    acpi_remove_notify_handler
310  *
311  * PARAMETERS:  Device          - The device for which notifies will be handled
312  *              handler_type    - The type of handler:
313  *                                  ACPI_SYSTEM_NOTIFY: system_handler (00-7f)
314  *                                  ACPI_DEVICE_NOTIFY: driver_handler (80-ff)
315  *                                  ACPI_ALL_NOTIFY:  both system and device
316  *              Handler         - Address of the handler
317  *
318  * RETURN:      Status
319  *
320  * DESCRIPTION: Remove a handler for notifies on an ACPI device
321  *
322  ******************************************************************************/
323 acpi_status
324 acpi_remove_notify_handler(acpi_handle device,
325                            u32 handler_type, acpi_notify_handler handler)
326 {
327         union acpi_operand_object *notify_obj;
328         union acpi_operand_object *obj_desc;
329         struct acpi_namespace_node *node;
330         acpi_status status;
331
332         ACPI_FUNCTION_TRACE(acpi_remove_notify_handler);
333
334         /* Parameter validation */
335
336         if ((!device) ||
337             (!handler) || (handler_type > ACPI_MAX_NOTIFY_HANDLER_TYPE)) {
338                 status = AE_BAD_PARAMETER;
339                 goto exit;
340         }
341
342
343         /* Make sure all deferred tasks are completed */
344         acpi_os_wait_events_complete(NULL);
345
346         status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
347         if (ACPI_FAILURE(status)) {
348                 goto exit;
349         }
350
351         /* Convert and validate the device handle */
352
353         node = acpi_ns_validate_handle(device);
354         if (!node) {
355                 status = AE_BAD_PARAMETER;
356                 goto unlock_and_exit;
357         }
358
359         /* Root Object */
360
361         if (device == ACPI_ROOT_OBJECT) {
362                 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
363                                   "Removing notify handler for namespace root object\n"));
364
365                 if (((handler_type & ACPI_SYSTEM_NOTIFY) &&
366                      !acpi_gbl_system_notify.handler) ||
367                     ((handler_type & ACPI_DEVICE_NOTIFY) &&
368                      !acpi_gbl_device_notify.handler)) {
369                         status = AE_NOT_EXIST;
370                         goto unlock_and_exit;
371                 }
372
373                 if (handler_type & ACPI_SYSTEM_NOTIFY) {
374                         acpi_gbl_system_notify.node = NULL;
375                         acpi_gbl_system_notify.handler = NULL;
376                         acpi_gbl_system_notify.context = NULL;
377                 }
378
379                 if (handler_type & ACPI_DEVICE_NOTIFY) {
380                         acpi_gbl_device_notify.node = NULL;
381                         acpi_gbl_device_notify.handler = NULL;
382                         acpi_gbl_device_notify.context = NULL;
383                 }
384         }
385
386         /* All Other Objects */
387
388         else {
389                 /* Notifies allowed on this object? */
390
391                 if (!acpi_ev_is_notify_object(node)) {
392                         status = AE_TYPE;
393                         goto unlock_and_exit;
394                 }
395
396                 /* Check for an existing internal object */
397
398                 obj_desc = acpi_ns_get_attached_object(node);
399                 if (!obj_desc) {
400                         status = AE_NOT_EXIST;
401                         goto unlock_and_exit;
402                 }
403
404                 /* Object exists - make sure there's an existing handler */
405
406                 if (handler_type & ACPI_SYSTEM_NOTIFY) {
407                         struct acpi_object_notify_handler *handler_obj;
408                         struct acpi_object_notify_handler *parent_obj;
409
410                         notify_obj = obj_desc->common_notify.system_notify;
411                         if (!notify_obj) {
412                                 status = AE_NOT_EXIST;
413                                 goto unlock_and_exit;
414                         }
415
416                         handler_obj = &notify_obj->notify;
417                         parent_obj = NULL;
418                         while (handler_obj->handler != handler) {
419                                 if (handler_obj->next) {
420                                         parent_obj = handler_obj;
421                                         handler_obj = handler_obj->next;
422                                 } else {
423                                         break;
424                                 }
425                         }
426
427                         if (handler_obj->handler != handler) {
428                                 status = AE_BAD_PARAMETER;
429                                 goto unlock_and_exit;
430                         }
431
432                         /*
433                          * Remove the handler.  There are three possible cases.
434                          * First, we may need to remove a non-embedded object.
435                          * Second, we may need to remove the embedded object's
436                          * handler data, while non-embedded objects exist.
437                          * Finally, we may need to remove the embedded object
438                          * entirely along with its container.
439                          */
440                         if (parent_obj) {
441                                 /* Non-embedded object is being removed. */
442                                 parent_obj->next = handler_obj->next;
443                                 ACPI_FREE(handler_obj);
444                         } else if (notify_obj->notify.next) {
445                                 /*
446                                  * The handler matches the embedded object, but
447                                  * there are more handler objects in the list.
448                                  * Replace the embedded object's data with the
449                                  * first next object's data and remove that
450                                  * object.
451                                  */
452                                 parent_obj = &notify_obj->notify;
453                                 handler_obj = notify_obj->notify.next;
454                                 *parent_obj = *handler_obj;
455                                 ACPI_FREE(handler_obj);
456                         } else {
457                                 /* No more handler objects in the list. */
458                                 obj_desc->common_notify.system_notify = NULL;
459                                 acpi_ut_remove_reference(notify_obj);
460                         }
461                 }
462
463                 if (handler_type & ACPI_DEVICE_NOTIFY) {
464                         notify_obj = obj_desc->common_notify.device_notify;
465                         if (!notify_obj) {
466                                 status = AE_NOT_EXIST;
467                                 goto unlock_and_exit;
468                         }
469
470                         if (notify_obj->notify.handler != handler) {
471                                 status = AE_BAD_PARAMETER;
472                                 goto unlock_and_exit;
473                         }
474
475                         /* Remove the handler */
476                         obj_desc->common_notify.device_notify = NULL;
477                         acpi_ut_remove_reference(notify_obj);
478                 }
479         }
480
481       unlock_and_exit:
482         (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
483       exit:
484         if (ACPI_FAILURE(status))
485                 ACPI_EXCEPTION((AE_INFO, status, "Removing notify handler"));
486         return_ACPI_STATUS(status);
487 }
488
489 ACPI_EXPORT_SYMBOL(acpi_remove_notify_handler)
490
491 /*******************************************************************************
492  *
493  * FUNCTION:    acpi_install_exception_handler
494  *
495  * PARAMETERS:  Handler         - Pointer to the handler function for the
496  *                                event
497  *
498  * RETURN:      Status
499  *
500  * DESCRIPTION: Saves the pointer to the handler function
501  *
502  ******************************************************************************/
503 #ifdef ACPI_FUTURE_USAGE
504 acpi_status acpi_install_exception_handler(acpi_exception_handler handler)
505 {
506         acpi_status status;
507
508         ACPI_FUNCTION_TRACE(acpi_install_exception_handler);
509
510         status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
511         if (ACPI_FAILURE(status)) {
512                 return_ACPI_STATUS(status);
513         }
514
515         /* Don't allow two handlers. */
516
517         if (acpi_gbl_exception_handler) {
518                 status = AE_ALREADY_EXISTS;
519                 goto cleanup;
520         }
521
522         /* Install the handler */
523
524         acpi_gbl_exception_handler = handler;
525
526       cleanup:
527         (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
528         return_ACPI_STATUS(status);
529 }
530
531 ACPI_EXPORT_SYMBOL(acpi_install_exception_handler)
532 #endif                          /*  ACPI_FUTURE_USAGE  */
533
534 #if (!ACPI_REDUCED_HARDWARE)
535 /*******************************************************************************
536  *
537  * FUNCTION:    acpi_install_global_event_handler
538  *
539  * PARAMETERS:  Handler         - Pointer to the global event handler function
540  *              Context         - Value passed to the handler on each event
541  *
542  * RETURN:      Status
543  *
544  * DESCRIPTION: Saves the pointer to the handler function. The global handler
545  *              is invoked upon each incoming GPE and Fixed Event. It is
546  *              invoked at interrupt level at the time of the event dispatch.
547  *              Can be used to update event counters, etc.
548  *
549  ******************************************************************************/
550 acpi_status
551 acpi_install_global_event_handler(ACPI_GBL_EVENT_HANDLER handler, void *context)
552 {
553         acpi_status status;
554
555         ACPI_FUNCTION_TRACE(acpi_install_global_event_handler);
556
557         /* Parameter validation */
558
559         if (!handler) {
560                 return_ACPI_STATUS(AE_BAD_PARAMETER);
561         }
562
563         status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
564         if (ACPI_FAILURE(status)) {
565                 return_ACPI_STATUS(status);
566         }
567
568         /* Don't allow two handlers. */
569
570         if (acpi_gbl_global_event_handler) {
571                 status = AE_ALREADY_EXISTS;
572                 goto cleanup;
573         }
574
575         acpi_gbl_global_event_handler = handler;
576         acpi_gbl_global_event_handler_context = context;
577
578       cleanup:
579         (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
580         return_ACPI_STATUS(status);
581 }
582
583 ACPI_EXPORT_SYMBOL(acpi_install_global_event_handler)
584
585 /*******************************************************************************
586  *
587  * FUNCTION:    acpi_install_fixed_event_handler
588  *
589  * PARAMETERS:  Event           - Event type to enable.
590  *              Handler         - Pointer to the handler function for the
591  *                                event
592  *              Context         - Value passed to the handler on each GPE
593  *
594  * RETURN:      Status
595  *
596  * DESCRIPTION: Saves the pointer to the handler function and then enables the
597  *              event.
598  *
599  ******************************************************************************/
600 acpi_status
601 acpi_install_fixed_event_handler(u32 event,
602                                  acpi_event_handler handler, void *context)
603 {
604         acpi_status status;
605
606         ACPI_FUNCTION_TRACE(acpi_install_fixed_event_handler);
607
608         /* Parameter validation */
609
610         if (event > ACPI_EVENT_MAX) {
611                 return_ACPI_STATUS(AE_BAD_PARAMETER);
612         }
613
614         status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
615         if (ACPI_FAILURE(status)) {
616                 return_ACPI_STATUS(status);
617         }
618
619         /* Don't allow two handlers. */
620
621         if (NULL != acpi_gbl_fixed_event_handlers[event].handler) {
622                 status = AE_ALREADY_EXISTS;
623                 goto cleanup;
624         }
625
626         /* Install the handler before enabling the event */
627
628         acpi_gbl_fixed_event_handlers[event].handler = handler;
629         acpi_gbl_fixed_event_handlers[event].context = context;
630
631         status = acpi_clear_event(event);
632         if (ACPI_SUCCESS(status))
633                 status = acpi_enable_event(event, 0);
634         if (ACPI_FAILURE(status)) {
635                 ACPI_WARNING((AE_INFO, "Could not enable fixed event 0x%X",
636                               event));
637
638                 /* Remove the handler */
639
640                 acpi_gbl_fixed_event_handlers[event].handler = NULL;
641                 acpi_gbl_fixed_event_handlers[event].context = NULL;
642         } else {
643                 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
644                                   "Enabled fixed event %X, Handler=%p\n", event,
645                                   handler));
646         }
647
648       cleanup:
649         (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
650         return_ACPI_STATUS(status);
651 }
652
653 ACPI_EXPORT_SYMBOL(acpi_install_fixed_event_handler)
654
655 /*******************************************************************************
656  *
657  * FUNCTION:    acpi_remove_fixed_event_handler
658  *
659  * PARAMETERS:  Event           - Event type to disable.
660  *              Handler         - Address of the handler
661  *
662  * RETURN:      Status
663  *
664  * DESCRIPTION: Disables the event and unregisters the event handler.
665  *
666  ******************************************************************************/
667 acpi_status
668 acpi_remove_fixed_event_handler(u32 event, acpi_event_handler handler)
669 {
670         acpi_status status = AE_OK;
671
672         ACPI_FUNCTION_TRACE(acpi_remove_fixed_event_handler);
673
674         /* Parameter validation */
675
676         if (event > ACPI_EVENT_MAX) {
677                 return_ACPI_STATUS(AE_BAD_PARAMETER);
678         }
679
680         status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
681         if (ACPI_FAILURE(status)) {
682                 return_ACPI_STATUS(status);
683         }
684
685         /* Disable the event before removing the handler */
686
687         status = acpi_disable_event(event, 0);
688
689         /* Always Remove the handler */
690
691         acpi_gbl_fixed_event_handlers[event].handler = NULL;
692         acpi_gbl_fixed_event_handlers[event].context = NULL;
693
694         if (ACPI_FAILURE(status)) {
695                 ACPI_WARNING((AE_INFO,
696                               "Could not write to fixed event enable register 0x%X",
697                               event));
698         } else {
699                 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Disabled fixed event %X\n",
700                                   event));
701         }
702
703         (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
704         return_ACPI_STATUS(status);
705 }
706
707 ACPI_EXPORT_SYMBOL(acpi_remove_fixed_event_handler)
708
709 /*******************************************************************************
710  *
711  * FUNCTION:    acpi_install_gpe_handler
712  *
713  * PARAMETERS:  gpe_device      - Namespace node for the GPE (NULL for FADT
714  *                                defined GPEs)
715  *              gpe_number      - The GPE number within the GPE block
716  *              Type            - Whether this GPE should be treated as an
717  *                                edge- or level-triggered interrupt.
718  *              Address         - Address of the handler
719  *              Context         - Value passed to the handler on each GPE
720  *
721  * RETURN:      Status
722  *
723  * DESCRIPTION: Install a handler for a General Purpose Event.
724  *
725  ******************************************************************************/
726 acpi_status
727 acpi_install_gpe_handler(acpi_handle gpe_device,
728                          u32 gpe_number,
729                          u32 type, acpi_gpe_handler address, void *context)
730 {
731         struct acpi_gpe_event_info *gpe_event_info;
732         struct acpi_gpe_handler_info *handler;
733         acpi_status status;
734         acpi_cpu_flags flags;
735
736         ACPI_FUNCTION_TRACE(acpi_install_gpe_handler);
737
738         /* Parameter validation */
739
740         if ((!address) || (type & ~ACPI_GPE_XRUPT_TYPE_MASK)) {
741                 return_ACPI_STATUS(AE_BAD_PARAMETER);
742         }
743
744         status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
745         if (ACPI_FAILURE(status)) {
746                 return_ACPI_STATUS(status);
747         }
748
749         /* Allocate memory for the handler object */
750
751         handler = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_gpe_handler_info));
752         if (!handler) {
753                 status = AE_NO_MEMORY;
754                 goto unlock_and_exit;
755         }
756
757         flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
758
759         /* Ensure that we have a valid GPE number */
760
761         gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
762         if (!gpe_event_info) {
763                 status = AE_BAD_PARAMETER;
764                 goto free_and_exit;
765         }
766
767         /* Make sure that there isn't a handler there already */
768
769         if ((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) ==
770             ACPI_GPE_DISPATCH_HANDLER) {
771                 status = AE_ALREADY_EXISTS;
772                 goto free_and_exit;
773         }
774
775         /* Allocate and init handler object */
776
777         handler->address = address;
778         handler->context = context;
779         handler->method_node = gpe_event_info->dispatch.method_node;
780         handler->original_flags = gpe_event_info->flags &
781                         (ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK);
782
783         /*
784          * If the GPE is associated with a method, it might have been enabled
785          * automatically during initialization, in which case it has to be
786          * disabled now to avoid spurious execution of the handler.
787          */
788
789         if ((handler->original_flags & ACPI_GPE_DISPATCH_METHOD)
790             && gpe_event_info->runtime_count) {
791                 handler->originally_enabled = 1;
792                 (void)acpi_ev_remove_gpe_reference(gpe_event_info);
793         }
794
795         /* Install the handler */
796
797         gpe_event_info->dispatch.handler = handler;
798
799         /* Setup up dispatch flags to indicate handler (vs. method) */
800
801         gpe_event_info->flags &=
802             ~(ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK);
803         gpe_event_info->flags |= (u8) (type | ACPI_GPE_DISPATCH_HANDLER);
804
805         acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
806
807 unlock_and_exit:
808         (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
809         return_ACPI_STATUS(status);
810
811 free_and_exit:
812         acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
813         ACPI_FREE(handler);
814         goto unlock_and_exit;
815 }
816
817 ACPI_EXPORT_SYMBOL(acpi_install_gpe_handler)
818
819 /*******************************************************************************
820  *
821  * FUNCTION:    acpi_remove_gpe_handler
822  *
823  * PARAMETERS:  gpe_device      - Namespace node for the GPE (NULL for FADT
824  *                                defined GPEs)
825  *              gpe_number      - The event to remove a handler
826  *              Address         - Address of the handler
827  *
828  * RETURN:      Status
829  *
830  * DESCRIPTION: Remove a handler for a General Purpose acpi_event.
831  *
832  ******************************************************************************/
833 acpi_status
834 acpi_remove_gpe_handler(acpi_handle gpe_device,
835                         u32 gpe_number, acpi_gpe_handler address)
836 {
837         struct acpi_gpe_event_info *gpe_event_info;
838         struct acpi_gpe_handler_info *handler;
839         acpi_status status;
840         acpi_cpu_flags flags;
841
842         ACPI_FUNCTION_TRACE(acpi_remove_gpe_handler);
843
844         /* Parameter validation */
845
846         if (!address) {
847                 return_ACPI_STATUS(AE_BAD_PARAMETER);
848         }
849
850         /* Make sure all deferred tasks are completed */
851
852         acpi_os_wait_events_complete(NULL);
853
854         status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
855         if (ACPI_FAILURE(status)) {
856                 return_ACPI_STATUS(status);
857         }
858
859         flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
860
861         /* Ensure that we have a valid GPE number */
862
863         gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
864         if (!gpe_event_info) {
865                 status = AE_BAD_PARAMETER;
866                 goto unlock_and_exit;
867         }
868
869         /* Make sure that a handler is indeed installed */
870
871         if ((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) !=
872             ACPI_GPE_DISPATCH_HANDLER) {
873                 status = AE_NOT_EXIST;
874                 goto unlock_and_exit;
875         }
876
877         /* Make sure that the installed handler is the same */
878
879         if (gpe_event_info->dispatch.handler->address != address) {
880                 status = AE_BAD_PARAMETER;
881                 goto unlock_and_exit;
882         }
883
884         /* Remove the handler */
885
886         handler = gpe_event_info->dispatch.handler;
887
888         /* Restore Method node (if any), set dispatch flags */
889
890         gpe_event_info->dispatch.method_node = handler->method_node;
891         gpe_event_info->flags &=
892                 ~(ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK);
893         gpe_event_info->flags |= handler->original_flags;
894
895         /*
896          * If the GPE was previously associated with a method and it was
897          * enabled, it should be enabled at this point to restore the
898          * post-initialization configuration.
899          */
900
901         if ((handler->original_flags & ACPI_GPE_DISPATCH_METHOD)
902             && handler->originally_enabled)
903                 (void)acpi_ev_add_gpe_reference(gpe_event_info);
904
905         /* Now we can free the handler object */
906
907         ACPI_FREE(handler);
908
909 unlock_and_exit:
910         acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
911
912         (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
913         return_ACPI_STATUS(status);
914 }
915
916 ACPI_EXPORT_SYMBOL(acpi_remove_gpe_handler)
917
918 /*******************************************************************************
919  *
920  * FUNCTION:    acpi_acquire_global_lock
921  *
922  * PARAMETERS:  Timeout         - How long the caller is willing to wait
923  *              Handle          - Where the handle to the lock is returned
924  *                                (if acquired)
925  *
926  * RETURN:      Status
927  *
928  * DESCRIPTION: Acquire the ACPI Global Lock
929  *
930  * Note: Allows callers with the same thread ID to acquire the global lock
931  * multiple times. In other words, externally, the behavior of the global lock
932  * is identical to an AML mutex. On the first acquire, a new handle is
933  * returned. On any subsequent calls to acquire by the same thread, the same
934  * handle is returned.
935  *
936  ******************************************************************************/
937 acpi_status acpi_acquire_global_lock(u16 timeout, u32 * handle)
938 {
939         acpi_status status;
940
941         if (!handle) {
942                 return (AE_BAD_PARAMETER);
943         }
944
945         /* Must lock interpreter to prevent race conditions */
946
947         acpi_ex_enter_interpreter();
948
949         status = acpi_ex_acquire_mutex_object(timeout,
950                                               acpi_gbl_global_lock_mutex,
951                                               acpi_os_get_thread_id());
952
953         if (ACPI_SUCCESS(status)) {
954
955                 /* Return the global lock handle (updated in acpi_ev_acquire_global_lock) */
956
957                 *handle = acpi_gbl_global_lock_handle;
958         }
959
960         acpi_ex_exit_interpreter();
961         return (status);
962 }
963
964 ACPI_EXPORT_SYMBOL(acpi_acquire_global_lock)
965
966 /*******************************************************************************
967  *
968  * FUNCTION:    acpi_release_global_lock
969  *
970  * PARAMETERS:  Handle      - Returned from acpi_acquire_global_lock
971  *
972  * RETURN:      Status
973  *
974  * DESCRIPTION: Release the ACPI Global Lock. The handle must be valid.
975  *
976  ******************************************************************************/
977 acpi_status acpi_release_global_lock(u32 handle)
978 {
979         acpi_status status;
980
981         if (!handle || (handle != acpi_gbl_global_lock_handle)) {
982                 return (AE_NOT_ACQUIRED);
983         }
984
985         status = acpi_ex_release_mutex_object(acpi_gbl_global_lock_mutex);
986         return (status);
987 }
988
989 ACPI_EXPORT_SYMBOL(acpi_release_global_lock)
990 #endif                          /* !ACPI_REDUCED_HARDWARE */