Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
0002 /******************************************************************************
0003  *
0004  * Module Name: evxface - External interfaces for ACPI events
0005  *
0006  * Copyright (C) 2000 - 2022, Intel Corp.
0007  *
0008  *****************************************************************************/
0009 
0010 #define EXPORT_ACPI_INTERFACES
0011 
0012 #include <acpi/acpi.h>
0013 #include "accommon.h"
0014 #include "acnamesp.h"
0015 #include "acevents.h"
0016 #include "acinterp.h"
0017 
0018 #define _COMPONENT          ACPI_EVENTS
0019 ACPI_MODULE_NAME("evxface")
0020 #if (!ACPI_REDUCED_HARDWARE)
0021 /* Local prototypes */
0022 static acpi_status
0023 acpi_ev_install_gpe_handler(acpi_handle gpe_device,
0024                 u32 gpe_number,
0025                 u32 type,
0026                 u8 is_raw_handler,
0027                 acpi_gpe_handler address, void *context);
0028 
0029 #endif
0030 
0031 
0032 /*******************************************************************************
0033  *
0034  * FUNCTION:    acpi_install_notify_handler
0035  *
0036  * PARAMETERS:  device          - The device for which notifies will be handled
0037  *              handler_type    - The type of handler:
0038  *                                  ACPI_SYSTEM_NOTIFY: System Handler (00-7F)
0039  *                                  ACPI_DEVICE_NOTIFY: Device Handler (80-FF)
0040  *                                  ACPI_ALL_NOTIFY:    Both System and Device
0041  *              handler         - Address of the handler
0042  *              context         - Value passed to the handler on each GPE
0043  *
0044  * RETURN:      Status
0045  *
0046  * DESCRIPTION: Install a handler for notifications on an ACPI Device,
0047  *              thermal_zone, or Processor object.
0048  *
0049  * NOTES:       The Root namespace object may have only one handler for each
0050  *              type of notify (System/Device). Device/Thermal/Processor objects
0051  *              may have one device notify handler, and multiple system notify
0052  *              handlers.
0053  *
0054  ******************************************************************************/
0055 
0056 acpi_status
0057 acpi_install_notify_handler(acpi_handle device,
0058                 u32 handler_type,
0059                 acpi_notify_handler handler, void *context)
0060 {
0061     struct acpi_namespace_node *node =
0062         ACPI_CAST_PTR(struct acpi_namespace_node, device);
0063     union acpi_operand_object *obj_desc;
0064     union acpi_operand_object *handler_obj;
0065     acpi_status status;
0066     u32 i;
0067 
0068     ACPI_FUNCTION_TRACE(acpi_install_notify_handler);
0069 
0070     /* Parameter validation */
0071 
0072     if ((!device) || (!handler) || (!handler_type) ||
0073         (handler_type > ACPI_MAX_NOTIFY_HANDLER_TYPE)) {
0074         return_ACPI_STATUS(AE_BAD_PARAMETER);
0075     }
0076 
0077     status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
0078     if (ACPI_FAILURE(status)) {
0079         return_ACPI_STATUS(status);
0080     }
0081 
0082     /*
0083      * Root Object:
0084      * Registering a notify handler on the root object indicates that the
0085      * caller wishes to receive notifications for all objects. Note that
0086      * only one global handler can be registered per notify type.
0087      * Ensure that a handler is not already installed.
0088      */
0089     if (device == ACPI_ROOT_OBJECT) {
0090         for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++) {
0091             if (handler_type & (i + 1)) {
0092                 if (acpi_gbl_global_notify[i].handler) {
0093                     status = AE_ALREADY_EXISTS;
0094                     goto unlock_and_exit;
0095                 }
0096 
0097                 acpi_gbl_global_notify[i].handler = handler;
0098                 acpi_gbl_global_notify[i].context = context;
0099             }
0100         }
0101 
0102         goto unlock_and_exit;   /* Global notify handler installed, all done */
0103     }
0104 
0105     /*
0106      * All Other Objects:
0107      * Caller will only receive notifications specific to the target
0108      * object. Note that only certain object types are allowed to
0109      * receive notifications.
0110      */
0111 
0112     /* Are Notifies allowed on this object? */
0113 
0114     if (!acpi_ev_is_notify_object(node)) {
0115         status = AE_TYPE;
0116         goto unlock_and_exit;
0117     }
0118 
0119     /* Check for an existing internal object, might not exist */
0120 
0121     obj_desc = acpi_ns_get_attached_object(node);
0122     if (!obj_desc) {
0123 
0124         /* Create a new object */
0125 
0126         obj_desc = acpi_ut_create_internal_object(node->type);
0127         if (!obj_desc) {
0128             status = AE_NO_MEMORY;
0129             goto unlock_and_exit;
0130         }
0131 
0132         /* Attach new object to the Node, remove local reference */
0133 
0134         status = acpi_ns_attach_object(device, obj_desc, node->type);
0135         acpi_ut_remove_reference(obj_desc);
0136         if (ACPI_FAILURE(status)) {
0137             goto unlock_and_exit;
0138         }
0139     }
0140 
0141     /* Ensure that the handler is not already installed in the lists */
0142 
0143     for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++) {
0144         if (handler_type & (i + 1)) {
0145             handler_obj = obj_desc->common_notify.notify_list[i];
0146             while (handler_obj) {
0147                 if (handler_obj->notify.handler == handler) {
0148                     status = AE_ALREADY_EXISTS;
0149                     goto unlock_and_exit;
0150                 }
0151 
0152                 handler_obj = handler_obj->notify.next[i];
0153             }
0154         }
0155     }
0156 
0157     /* Create and populate a new notify handler object */
0158 
0159     handler_obj = acpi_ut_create_internal_object(ACPI_TYPE_LOCAL_NOTIFY);
0160     if (!handler_obj) {
0161         status = AE_NO_MEMORY;
0162         goto unlock_and_exit;
0163     }
0164 
0165     handler_obj->notify.node = node;
0166     handler_obj->notify.handler_type = handler_type;
0167     handler_obj->notify.handler = handler;
0168     handler_obj->notify.context = context;
0169 
0170     /* Install the handler at the list head(s) */
0171 
0172     for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++) {
0173         if (handler_type & (i + 1)) {
0174             handler_obj->notify.next[i] =
0175                 obj_desc->common_notify.notify_list[i];
0176 
0177             obj_desc->common_notify.notify_list[i] = handler_obj;
0178         }
0179     }
0180 
0181     /* Add an extra reference if handler was installed in both lists */
0182 
0183     if (handler_type == ACPI_ALL_NOTIFY) {
0184         acpi_ut_add_reference(handler_obj);
0185     }
0186 
0187 unlock_and_exit:
0188     (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
0189     return_ACPI_STATUS(status);
0190 }
0191 
0192 ACPI_EXPORT_SYMBOL(acpi_install_notify_handler)
0193 
0194 /*******************************************************************************
0195  *
0196  * FUNCTION:    acpi_remove_notify_handler
0197  *
0198  * PARAMETERS:  device          - The device for which the handler is installed
0199  *              handler_type    - The type of handler:
0200  *                                  ACPI_SYSTEM_NOTIFY: System Handler (00-7F)
0201  *                                  ACPI_DEVICE_NOTIFY: Device Handler (80-FF)
0202  *                                  ACPI_ALL_NOTIFY:    Both System and Device
0203  *              handler         - Address of the handler
0204  *
0205  * RETURN:      Status
0206  *
0207  * DESCRIPTION: Remove a handler for notifies on an ACPI device
0208  *
0209  ******************************************************************************/
0210 acpi_status
0211 acpi_remove_notify_handler(acpi_handle device,
0212                u32 handler_type, acpi_notify_handler handler)
0213 {
0214     struct acpi_namespace_node *node =
0215         ACPI_CAST_PTR(struct acpi_namespace_node, device);
0216     union acpi_operand_object *obj_desc;
0217     union acpi_operand_object *handler_obj;
0218     union acpi_operand_object *previous_handler_obj;
0219     acpi_status status = AE_OK;
0220     u32 i;
0221 
0222     ACPI_FUNCTION_TRACE(acpi_remove_notify_handler);
0223 
0224     /* Parameter validation */
0225 
0226     if ((!device) || (!handler) || (!handler_type) ||
0227         (handler_type > ACPI_MAX_NOTIFY_HANDLER_TYPE)) {
0228         return_ACPI_STATUS(AE_BAD_PARAMETER);
0229     }
0230 
0231     /* Root Object. Global handlers are removed here */
0232 
0233     if (device == ACPI_ROOT_OBJECT) {
0234         for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++) {
0235             if (handler_type & (i + 1)) {
0236                 status =
0237                     acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
0238                 if (ACPI_FAILURE(status)) {
0239                     return_ACPI_STATUS(status);
0240                 }
0241 
0242                 if (!acpi_gbl_global_notify[i].handler ||
0243                     (acpi_gbl_global_notify[i].handler !=
0244                      handler)) {
0245                     status = AE_NOT_EXIST;
0246                     goto unlock_and_exit;
0247                 }
0248 
0249                 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
0250                           "Removing global notify handler\n"));
0251 
0252                 acpi_gbl_global_notify[i].handler = NULL;
0253                 acpi_gbl_global_notify[i].context = NULL;
0254 
0255                 (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
0256 
0257                 /* Make sure all deferred notify tasks are completed */
0258 
0259                 acpi_os_wait_events_complete();
0260             }
0261         }
0262 
0263         return_ACPI_STATUS(AE_OK);
0264     }
0265 
0266     /* All other objects: Are Notifies allowed on this object? */
0267 
0268     if (!acpi_ev_is_notify_object(node)) {
0269         return_ACPI_STATUS(AE_TYPE);
0270     }
0271 
0272     /* Must have an existing internal object */
0273 
0274     obj_desc = acpi_ns_get_attached_object(node);
0275     if (!obj_desc) {
0276         return_ACPI_STATUS(AE_NOT_EXIST);
0277     }
0278 
0279     /* Internal object exists. Find the handler and remove it */
0280 
0281     for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++) {
0282         if (handler_type & (i + 1)) {
0283             status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
0284             if (ACPI_FAILURE(status)) {
0285                 return_ACPI_STATUS(status);
0286             }
0287 
0288             handler_obj = obj_desc->common_notify.notify_list[i];
0289             previous_handler_obj = NULL;
0290 
0291             /* Attempt to find the handler in the handler list */
0292 
0293             while (handler_obj &&
0294                    (handler_obj->notify.handler != handler)) {
0295                 previous_handler_obj = handler_obj;
0296                 handler_obj = handler_obj->notify.next[i];
0297             }
0298 
0299             if (!handler_obj) {
0300                 status = AE_NOT_EXIST;
0301                 goto unlock_and_exit;
0302             }
0303 
0304             /* Remove the handler object from the list */
0305 
0306             if (previous_handler_obj) { /* Handler is not at the list head */
0307                 previous_handler_obj->notify.next[i] =
0308                     handler_obj->notify.next[i];
0309             } else {    /* Handler is at the list head */
0310 
0311                 obj_desc->common_notify.notify_list[i] =
0312                     handler_obj->notify.next[i];
0313             }
0314 
0315             (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
0316 
0317             /* Make sure all deferred notify tasks are completed */
0318 
0319             acpi_os_wait_events_complete();
0320             acpi_ut_remove_reference(handler_obj);
0321         }
0322     }
0323 
0324     return_ACPI_STATUS(status);
0325 
0326 unlock_and_exit:
0327     (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
0328     return_ACPI_STATUS(status);
0329 }
0330 
0331 ACPI_EXPORT_SYMBOL(acpi_remove_notify_handler)
0332 
0333 /*******************************************************************************
0334  *
0335  * FUNCTION:    acpi_install_exception_handler
0336  *
0337  * PARAMETERS:  handler         - Pointer to the handler function for the
0338  *                                event
0339  *
0340  * RETURN:      Status
0341  *
0342  * DESCRIPTION: Saves the pointer to the handler function
0343  *
0344  ******************************************************************************/
0345 #ifdef ACPI_FUTURE_USAGE
0346 acpi_status acpi_install_exception_handler(acpi_exception_handler handler)
0347 {
0348     acpi_status status;
0349 
0350     ACPI_FUNCTION_TRACE(acpi_install_exception_handler);
0351 
0352     status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
0353     if (ACPI_FAILURE(status)) {
0354         return_ACPI_STATUS(status);
0355     }
0356 
0357     /* Don't allow two handlers. */
0358 
0359     if (acpi_gbl_exception_handler) {
0360         status = AE_ALREADY_EXISTS;
0361         goto cleanup;
0362     }
0363 
0364     /* Install the handler */
0365 
0366     acpi_gbl_exception_handler = handler;
0367 
0368 cleanup:
0369     (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
0370     return_ACPI_STATUS(status);
0371 }
0372 
0373 ACPI_EXPORT_SYMBOL(acpi_install_exception_handler)
0374 #endif
0375 
0376 #if (!ACPI_REDUCED_HARDWARE)
0377 /*******************************************************************************
0378  *
0379  * FUNCTION:    acpi_install_sci_handler
0380  *
0381  * PARAMETERS:  address             - Address of the handler
0382  *              context             - Value passed to the handler on each SCI
0383  *
0384  * RETURN:      Status
0385  *
0386  * DESCRIPTION: Install a handler for a System Control Interrupt.
0387  *
0388  ******************************************************************************/
0389 acpi_status acpi_install_sci_handler(acpi_sci_handler address, void *context)
0390 {
0391     struct acpi_sci_handler_info *new_sci_handler;
0392     struct acpi_sci_handler_info *sci_handler;
0393     acpi_cpu_flags flags;
0394     acpi_status status;
0395 
0396     ACPI_FUNCTION_TRACE(acpi_install_sci_handler);
0397 
0398     if (!address) {
0399         return_ACPI_STATUS(AE_BAD_PARAMETER);
0400     }
0401 
0402     /* Allocate and init a handler object */
0403 
0404     new_sci_handler = ACPI_ALLOCATE(sizeof(struct acpi_sci_handler_info));
0405     if (!new_sci_handler) {
0406         return_ACPI_STATUS(AE_NO_MEMORY);
0407     }
0408 
0409     new_sci_handler->address = address;
0410     new_sci_handler->context = context;
0411 
0412     status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
0413     if (ACPI_FAILURE(status)) {
0414         goto exit;
0415     }
0416 
0417     /* Lock list during installation */
0418 
0419     flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
0420     sci_handler = acpi_gbl_sci_handler_list;
0421 
0422     /* Ensure handler does not already exist */
0423 
0424     while (sci_handler) {
0425         if (address == sci_handler->address) {
0426             status = AE_ALREADY_EXISTS;
0427             goto unlock_and_exit;
0428         }
0429 
0430         sci_handler = sci_handler->next;
0431     }
0432 
0433     /* Install the new handler into the global list (at head) */
0434 
0435     new_sci_handler->next = acpi_gbl_sci_handler_list;
0436     acpi_gbl_sci_handler_list = new_sci_handler;
0437 
0438 unlock_and_exit:
0439 
0440     acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
0441     (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
0442 
0443 exit:
0444     if (ACPI_FAILURE(status)) {
0445         ACPI_FREE(new_sci_handler);
0446     }
0447     return_ACPI_STATUS(status);
0448 }
0449 
0450 ACPI_EXPORT_SYMBOL(acpi_install_sci_handler)
0451 
0452 /*******************************************************************************
0453  *
0454  * FUNCTION:    acpi_remove_sci_handler
0455  *
0456  * PARAMETERS:  address             - Address of the handler
0457  *
0458  * RETURN:      Status
0459  *
0460  * DESCRIPTION: Remove a handler for a System Control Interrupt.
0461  *
0462  ******************************************************************************/
0463 acpi_status acpi_remove_sci_handler(acpi_sci_handler address)
0464 {
0465     struct acpi_sci_handler_info *prev_sci_handler;
0466     struct acpi_sci_handler_info *next_sci_handler;
0467     acpi_cpu_flags flags;
0468     acpi_status status;
0469 
0470     ACPI_FUNCTION_TRACE(acpi_remove_sci_handler);
0471 
0472     if (!address) {
0473         return_ACPI_STATUS(AE_BAD_PARAMETER);
0474     }
0475 
0476     status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
0477     if (ACPI_FAILURE(status)) {
0478         return_ACPI_STATUS(status);
0479     }
0480 
0481     /* Remove the SCI handler with lock */
0482 
0483     flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
0484 
0485     prev_sci_handler = NULL;
0486     next_sci_handler = acpi_gbl_sci_handler_list;
0487     while (next_sci_handler) {
0488         if (next_sci_handler->address == address) {
0489 
0490             /* Unlink and free the SCI handler info block */
0491 
0492             if (prev_sci_handler) {
0493                 prev_sci_handler->next = next_sci_handler->next;
0494             } else {
0495                 acpi_gbl_sci_handler_list =
0496                     next_sci_handler->next;
0497             }
0498 
0499             acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
0500             ACPI_FREE(next_sci_handler);
0501             goto unlock_and_exit;
0502         }
0503 
0504         prev_sci_handler = next_sci_handler;
0505         next_sci_handler = next_sci_handler->next;
0506     }
0507 
0508     acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
0509     status = AE_NOT_EXIST;
0510 
0511 unlock_and_exit:
0512     (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
0513     return_ACPI_STATUS(status);
0514 }
0515 
0516 ACPI_EXPORT_SYMBOL(acpi_remove_sci_handler)
0517 
0518 /*******************************************************************************
0519  *
0520  * FUNCTION:    acpi_install_global_event_handler
0521  *
0522  * PARAMETERS:  handler         - Pointer to the global event handler function
0523  *              context         - Value passed to the handler on each event
0524  *
0525  * RETURN:      Status
0526  *
0527  * DESCRIPTION: Saves the pointer to the handler function. The global handler
0528  *              is invoked upon each incoming GPE and Fixed Event. It is
0529  *              invoked at interrupt level at the time of the event dispatch.
0530  *              Can be used to update event counters, etc.
0531  *
0532  ******************************************************************************/
0533 acpi_status
0534 acpi_install_global_event_handler(acpi_gbl_event_handler handler, void *context)
0535 {
0536     acpi_status status;
0537 
0538     ACPI_FUNCTION_TRACE(acpi_install_global_event_handler);
0539 
0540     /* Parameter validation */
0541 
0542     if (!handler) {
0543         return_ACPI_STATUS(AE_BAD_PARAMETER);
0544     }
0545 
0546     status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
0547     if (ACPI_FAILURE(status)) {
0548         return_ACPI_STATUS(status);
0549     }
0550 
0551     /* Don't allow two handlers. */
0552 
0553     if (acpi_gbl_global_event_handler) {
0554         status = AE_ALREADY_EXISTS;
0555         goto cleanup;
0556     }
0557 
0558     acpi_gbl_global_event_handler = handler;
0559     acpi_gbl_global_event_handler_context = context;
0560 
0561 cleanup:
0562     (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
0563     return_ACPI_STATUS(status);
0564 }
0565 
0566 ACPI_EXPORT_SYMBOL(acpi_install_global_event_handler)
0567 
0568 /*******************************************************************************
0569  *
0570  * FUNCTION:    acpi_install_fixed_event_handler
0571  *
0572  * PARAMETERS:  event           - Event type to enable.
0573  *              handler         - Pointer to the handler function for the
0574  *                                event
0575  *              context         - Value passed to the handler on each GPE
0576  *
0577  * RETURN:      Status
0578  *
0579  * DESCRIPTION: Saves the pointer to the handler function and then enables the
0580  *              event.
0581  *
0582  ******************************************************************************/
0583 acpi_status
0584 acpi_install_fixed_event_handler(u32 event,
0585                  acpi_event_handler handler, void *context)
0586 {
0587     acpi_status status;
0588 
0589     ACPI_FUNCTION_TRACE(acpi_install_fixed_event_handler);
0590 
0591     /* Parameter validation */
0592 
0593     if (event > ACPI_EVENT_MAX) {
0594         return_ACPI_STATUS(AE_BAD_PARAMETER);
0595     }
0596 
0597     status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
0598     if (ACPI_FAILURE(status)) {
0599         return_ACPI_STATUS(status);
0600     }
0601 
0602     /* Do not allow multiple handlers */
0603 
0604     if (acpi_gbl_fixed_event_handlers[event].handler) {
0605         status = AE_ALREADY_EXISTS;
0606         goto cleanup;
0607     }
0608 
0609     /* Install the handler before enabling the event */
0610 
0611     acpi_gbl_fixed_event_handlers[event].handler = handler;
0612     acpi_gbl_fixed_event_handlers[event].context = context;
0613 
0614     status = acpi_clear_event(event);
0615     if (ACPI_SUCCESS(status))
0616         status = acpi_enable_event(event, 0);
0617     if (ACPI_FAILURE(status)) {
0618         ACPI_WARNING((AE_INFO,
0619                   "Could not enable fixed event - %s (%u)",
0620                   acpi_ut_get_event_name(event), event));
0621 
0622         /* Remove the handler */
0623 
0624         acpi_gbl_fixed_event_handlers[event].handler = NULL;
0625         acpi_gbl_fixed_event_handlers[event].context = NULL;
0626     } else {
0627         ACPI_DEBUG_PRINT((ACPI_DB_INFO,
0628                   "Enabled fixed event %s (%X), Handler=%p\n",
0629                   acpi_ut_get_event_name(event), event,
0630                   handler));
0631     }
0632 
0633 cleanup:
0634     (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
0635     return_ACPI_STATUS(status);
0636 }
0637 
0638 ACPI_EXPORT_SYMBOL(acpi_install_fixed_event_handler)
0639 
0640 /*******************************************************************************
0641  *
0642  * FUNCTION:    acpi_remove_fixed_event_handler
0643  *
0644  * PARAMETERS:  event           - Event type to disable.
0645  *              handler         - Address of the handler
0646  *
0647  * RETURN:      Status
0648  *
0649  * DESCRIPTION: Disables the event and unregisters the event handler.
0650  *
0651  ******************************************************************************/
0652 acpi_status
0653 acpi_remove_fixed_event_handler(u32 event, acpi_event_handler handler)
0654 {
0655     acpi_status status = AE_OK;
0656 
0657     ACPI_FUNCTION_TRACE(acpi_remove_fixed_event_handler);
0658 
0659     /* Parameter validation */
0660 
0661     if (event > ACPI_EVENT_MAX) {
0662         return_ACPI_STATUS(AE_BAD_PARAMETER);
0663     }
0664 
0665     status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
0666     if (ACPI_FAILURE(status)) {
0667         return_ACPI_STATUS(status);
0668     }
0669 
0670     /* Disable the event before removing the handler */
0671 
0672     status = acpi_disable_event(event, 0);
0673 
0674     /* Always Remove the handler */
0675 
0676     acpi_gbl_fixed_event_handlers[event].handler = NULL;
0677     acpi_gbl_fixed_event_handlers[event].context = NULL;
0678 
0679     if (ACPI_FAILURE(status)) {
0680         ACPI_WARNING((AE_INFO,
0681                   "Could not disable fixed event - %s (%u)",
0682                   acpi_ut_get_event_name(event), event));
0683     } else {
0684         ACPI_DEBUG_PRINT((ACPI_DB_INFO,
0685                   "Disabled fixed event - %s (%X)\n",
0686                   acpi_ut_get_event_name(event), event));
0687     }
0688 
0689     (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
0690     return_ACPI_STATUS(status);
0691 }
0692 
0693 ACPI_EXPORT_SYMBOL(acpi_remove_fixed_event_handler)
0694 
0695 /*******************************************************************************
0696  *
0697  * FUNCTION:    acpi_ev_install_gpe_handler
0698  *
0699  * PARAMETERS:  gpe_device      - Namespace node for the GPE (NULL for FADT
0700  *                                defined GPEs)
0701  *              gpe_number      - The GPE number within the GPE block
0702  *              type            - Whether this GPE should be treated as an
0703  *                                edge- or level-triggered interrupt.
0704  *              is_raw_handler  - Whether this GPE should be handled using
0705  *                                the special GPE handler mode.
0706  *              address         - Address of the handler
0707  *              context         - Value passed to the handler on each GPE
0708  *
0709  * RETURN:      Status
0710  *
0711  * DESCRIPTION: Internal function to install a handler for a General Purpose
0712  *              Event.
0713  *
0714  ******************************************************************************/
0715 static acpi_status
0716 acpi_ev_install_gpe_handler(acpi_handle gpe_device,
0717                 u32 gpe_number,
0718                 u32 type,
0719                 u8 is_raw_handler,
0720                 acpi_gpe_handler address, void *context)
0721 {
0722     struct acpi_gpe_event_info *gpe_event_info;
0723     struct acpi_gpe_handler_info *handler;
0724     acpi_status status;
0725     acpi_cpu_flags flags;
0726 
0727     ACPI_FUNCTION_TRACE(ev_install_gpe_handler);
0728 
0729     /* Parameter validation */
0730 
0731     if ((!address) || (type & ~ACPI_GPE_XRUPT_TYPE_MASK)) {
0732         return_ACPI_STATUS(AE_BAD_PARAMETER);
0733     }
0734 
0735     status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
0736     if (ACPI_FAILURE(status)) {
0737         return_ACPI_STATUS(status);
0738     }
0739 
0740     /* Allocate and init handler object (before lock) */
0741 
0742     handler = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_gpe_handler_info));
0743     if (!handler) {
0744         status = AE_NO_MEMORY;
0745         goto unlock_and_exit;
0746     }
0747 
0748     flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
0749 
0750     /* Ensure that we have a valid GPE number */
0751 
0752     gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
0753     if (!gpe_event_info) {
0754         status = AE_BAD_PARAMETER;
0755         goto free_and_exit;
0756     }
0757 
0758     /* Make sure that there isn't a handler there already */
0759 
0760     if ((ACPI_GPE_DISPATCH_TYPE(gpe_event_info->flags) ==
0761          ACPI_GPE_DISPATCH_HANDLER) ||
0762         (ACPI_GPE_DISPATCH_TYPE(gpe_event_info->flags) ==
0763          ACPI_GPE_DISPATCH_RAW_HANDLER)) {
0764         status = AE_ALREADY_EXISTS;
0765         goto free_and_exit;
0766     }
0767 
0768     handler->address = address;
0769     handler->context = context;
0770     handler->method_node = gpe_event_info->dispatch.method_node;
0771     handler->original_flags = (u8)(gpe_event_info->flags &
0772                        (ACPI_GPE_XRUPT_TYPE_MASK |
0773                     ACPI_GPE_DISPATCH_MASK));
0774 
0775     /*
0776      * If the GPE is associated with a method, it may have been enabled
0777      * automatically during initialization, in which case it has to be
0778      * disabled now to avoid spurious execution of the handler.
0779      */
0780     if (((ACPI_GPE_DISPATCH_TYPE(handler->original_flags) ==
0781           ACPI_GPE_DISPATCH_METHOD) ||
0782          (ACPI_GPE_DISPATCH_TYPE(handler->original_flags) ==
0783           ACPI_GPE_DISPATCH_NOTIFY)) && gpe_event_info->runtime_count) {
0784         handler->originally_enabled = TRUE;
0785         (void)acpi_ev_remove_gpe_reference(gpe_event_info);
0786 
0787         /* Sanity check of original type against new type */
0788 
0789         if (type !=
0790             (u32)(gpe_event_info->flags & ACPI_GPE_XRUPT_TYPE_MASK)) {
0791             ACPI_WARNING((AE_INFO,
0792                       "GPE type mismatch (level/edge)"));
0793         }
0794     }
0795 
0796     /* Install the handler */
0797 
0798     gpe_event_info->dispatch.handler = handler;
0799 
0800     /* Setup up dispatch flags to indicate handler (vs. method/notify) */
0801 
0802     gpe_event_info->flags &=
0803         ~(ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK);
0804     gpe_event_info->flags |=
0805         (u8)(type |
0806          (is_raw_handler ? ACPI_GPE_DISPATCH_RAW_HANDLER :
0807           ACPI_GPE_DISPATCH_HANDLER));
0808 
0809     acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
0810 
0811 unlock_and_exit:
0812     (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
0813     return_ACPI_STATUS(status);
0814 
0815 free_and_exit:
0816     acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
0817     ACPI_FREE(handler);
0818     goto unlock_and_exit;
0819 }
0820 
0821 /*******************************************************************************
0822  *
0823  * FUNCTION:    acpi_install_gpe_handler
0824  *
0825  * PARAMETERS:  gpe_device      - Namespace node for the GPE (NULL for FADT
0826  *                                defined GPEs)
0827  *              gpe_number      - The GPE number within the GPE block
0828  *              type            - Whether this GPE should be treated as an
0829  *                                edge- or level-triggered interrupt.
0830  *              address         - Address of the handler
0831  *              context         - Value passed to the handler on each GPE
0832  *
0833  * RETURN:      Status
0834  *
0835  * DESCRIPTION: Install a handler for a General Purpose Event.
0836  *
0837  ******************************************************************************/
0838 
0839 acpi_status
0840 acpi_install_gpe_handler(acpi_handle gpe_device,
0841              u32 gpe_number,
0842              u32 type, acpi_gpe_handler address, void *context)
0843 {
0844     acpi_status status;
0845 
0846     ACPI_FUNCTION_TRACE(acpi_install_gpe_handler);
0847 
0848     status = acpi_ev_install_gpe_handler(gpe_device, gpe_number, type,
0849                          FALSE, address, context);
0850 
0851     return_ACPI_STATUS(status);
0852 }
0853 
0854 ACPI_EXPORT_SYMBOL(acpi_install_gpe_handler)
0855 
0856 /*******************************************************************************
0857  *
0858  * FUNCTION:    acpi_install_gpe_raw_handler
0859  *
0860  * PARAMETERS:  gpe_device      - Namespace node for the GPE (NULL for FADT
0861  *                                defined GPEs)
0862  *              gpe_number      - The GPE number within the GPE block
0863  *              type            - Whether this GPE should be treated as an
0864  *                                edge- or level-triggered interrupt.
0865  *              address         - Address of the handler
0866  *              context         - Value passed to the handler on each GPE
0867  *
0868  * RETURN:      Status
0869  *
0870  * DESCRIPTION: Install a handler for a General Purpose Event.
0871  *
0872  ******************************************************************************/
0873 acpi_status
0874 acpi_install_gpe_raw_handler(acpi_handle gpe_device,
0875                  u32 gpe_number,
0876                  u32 type, acpi_gpe_handler address, void *context)
0877 {
0878     acpi_status status;
0879 
0880     ACPI_FUNCTION_TRACE(acpi_install_gpe_raw_handler);
0881 
0882     status = acpi_ev_install_gpe_handler(gpe_device, gpe_number, type,
0883                          TRUE, address, context);
0884 
0885     return_ACPI_STATUS(status);
0886 }
0887 
0888 ACPI_EXPORT_SYMBOL(acpi_install_gpe_raw_handler)
0889 
0890 /*******************************************************************************
0891  *
0892  * FUNCTION:    acpi_remove_gpe_handler
0893  *
0894  * PARAMETERS:  gpe_device      - Namespace node for the GPE (NULL for FADT
0895  *                                defined GPEs)
0896  *              gpe_number      - The event to remove a handler
0897  *              address         - Address of the handler
0898  *
0899  * RETURN:      Status
0900  *
0901  * DESCRIPTION: Remove a handler for a General Purpose acpi_event.
0902  *
0903  ******************************************************************************/
0904 acpi_status
0905 acpi_remove_gpe_handler(acpi_handle gpe_device,
0906             u32 gpe_number, acpi_gpe_handler address)
0907 {
0908     struct acpi_gpe_event_info *gpe_event_info;
0909     struct acpi_gpe_handler_info *handler;
0910     acpi_status status;
0911     acpi_cpu_flags flags;
0912 
0913     ACPI_FUNCTION_TRACE(acpi_remove_gpe_handler);
0914 
0915     /* Parameter validation */
0916 
0917     if (!address) {
0918         return_ACPI_STATUS(AE_BAD_PARAMETER);
0919     }
0920 
0921     status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
0922     if (ACPI_FAILURE(status)) {
0923         return_ACPI_STATUS(status);
0924     }
0925 
0926     flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
0927 
0928     /* Ensure that we have a valid GPE number */
0929 
0930     gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
0931     if (!gpe_event_info) {
0932         status = AE_BAD_PARAMETER;
0933         goto unlock_and_exit;
0934     }
0935 
0936     /* Make sure that a handler is indeed installed */
0937 
0938     if ((ACPI_GPE_DISPATCH_TYPE(gpe_event_info->flags) !=
0939          ACPI_GPE_DISPATCH_HANDLER) &&
0940         (ACPI_GPE_DISPATCH_TYPE(gpe_event_info->flags) !=
0941          ACPI_GPE_DISPATCH_RAW_HANDLER)) {
0942         status = AE_NOT_EXIST;
0943         goto unlock_and_exit;
0944     }
0945 
0946     /* Make sure that the installed handler is the same */
0947 
0948     if (gpe_event_info->dispatch.handler->address != address) {
0949         status = AE_BAD_PARAMETER;
0950         goto unlock_and_exit;
0951     }
0952 
0953     /* Remove the handler */
0954 
0955     handler = gpe_event_info->dispatch.handler;
0956     gpe_event_info->dispatch.handler = NULL;
0957 
0958     /* Restore Method node (if any), set dispatch flags */
0959 
0960     gpe_event_info->dispatch.method_node = handler->method_node;
0961     gpe_event_info->flags &=
0962         ~(ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK);
0963     gpe_event_info->flags |= handler->original_flags;
0964 
0965     /*
0966      * If the GPE was previously associated with a method and it was
0967      * enabled, it should be enabled at this point to restore the
0968      * post-initialization configuration.
0969      */
0970     if (((ACPI_GPE_DISPATCH_TYPE(handler->original_flags) ==
0971           ACPI_GPE_DISPATCH_METHOD) ||
0972          (ACPI_GPE_DISPATCH_TYPE(handler->original_flags) ==
0973           ACPI_GPE_DISPATCH_NOTIFY)) && handler->originally_enabled) {
0974         (void)acpi_ev_add_gpe_reference(gpe_event_info, FALSE);
0975         if (ACPI_GPE_IS_POLLING_NEEDED(gpe_event_info)) {
0976 
0977             /* Poll edge triggered GPEs to handle existing events */
0978 
0979             acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
0980             (void)acpi_ev_detect_gpe(gpe_device, gpe_event_info,
0981                          gpe_number);
0982             flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
0983         }
0984     }
0985 
0986     acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
0987     (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
0988 
0989     /* Make sure all deferred GPE tasks are completed */
0990 
0991     acpi_os_wait_events_complete();
0992 
0993     /* Now we can free the handler object */
0994 
0995     ACPI_FREE(handler);
0996     return_ACPI_STATUS(status);
0997 
0998 unlock_and_exit:
0999     acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
1000 
1001     (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
1002     return_ACPI_STATUS(status);
1003 }
1004 
1005 ACPI_EXPORT_SYMBOL(acpi_remove_gpe_handler)
1006 
1007 /*******************************************************************************
1008  *
1009  * FUNCTION:    acpi_acquire_global_lock
1010  *
1011  * PARAMETERS:  timeout         - How long the caller is willing to wait
1012  *              handle          - Where the handle to the lock is returned
1013  *                                (if acquired)
1014  *
1015  * RETURN:      Status
1016  *
1017  * DESCRIPTION: Acquire the ACPI Global Lock
1018  *
1019  * Note: Allows callers with the same thread ID to acquire the global lock
1020  * multiple times. In other words, externally, the behavior of the global lock
1021  * is identical to an AML mutex. On the first acquire, a new handle is
1022  * returned. On any subsequent calls to acquire by the same thread, the same
1023  * handle is returned.
1024  *
1025  ******************************************************************************/
1026 acpi_status acpi_acquire_global_lock(u16 timeout, u32 *handle)
1027 {
1028     acpi_status status;
1029 
1030     if (!handle) {
1031         return (AE_BAD_PARAMETER);
1032     }
1033 
1034     /* Must lock interpreter to prevent race conditions */
1035 
1036     acpi_ex_enter_interpreter();
1037 
1038     status = acpi_ex_acquire_mutex_object(timeout,
1039                           acpi_gbl_global_lock_mutex,
1040                           acpi_os_get_thread_id());
1041 
1042     if (ACPI_SUCCESS(status)) {
1043 
1044         /* Return the global lock handle (updated in acpi_ev_acquire_global_lock) */
1045 
1046         *handle = acpi_gbl_global_lock_handle;
1047     }
1048 
1049     acpi_ex_exit_interpreter();
1050     return (status);
1051 }
1052 
1053 ACPI_EXPORT_SYMBOL(acpi_acquire_global_lock)
1054 
1055 /*******************************************************************************
1056  *
1057  * FUNCTION:    acpi_release_global_lock
1058  *
1059  * PARAMETERS:  handle      - Returned from acpi_acquire_global_lock
1060  *
1061  * RETURN:      Status
1062  *
1063  * DESCRIPTION: Release the ACPI Global Lock. The handle must be valid.
1064  *
1065  ******************************************************************************/
1066 acpi_status acpi_release_global_lock(u32 handle)
1067 {
1068     acpi_status status;
1069 
1070     if (!handle || (handle != acpi_gbl_global_lock_handle)) {
1071         return (AE_NOT_ACQUIRED);
1072     }
1073 
1074     status = acpi_ex_release_mutex_object(acpi_gbl_global_lock_mutex);
1075     return (status);
1076 }
1077 
1078 ACPI_EXPORT_SYMBOL(acpi_release_global_lock)
1079 #endif              /* !ACPI_REDUCED_HARDWARE */