1080 lines · c
1// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.02/******************************************************************************3 *4 * Module Name: evxface - External interfaces for ACPI events5 *6 * Copyright (C) 2000 - 2023, Intel Corp.7 *8 *****************************************************************************/9 10#define EXPORT_ACPI_INTERFACES11 12#include <acpi/acpi.h>13#include "accommon.h"14#include "acnamesp.h"15#include "acevents.h"16#include "acinterp.h"17 18#define _COMPONENT ACPI_EVENTS19ACPI_MODULE_NAME("evxface")20#if (!ACPI_REDUCED_HARDWARE)21/* Local prototypes */22static acpi_status23acpi_ev_install_gpe_handler(acpi_handle gpe_device,24 u32 gpe_number,25 u32 type,26 u8 is_raw_handler,27 acpi_gpe_handler address, void *context);28 29#endif30 31 32/*******************************************************************************33 *34 * FUNCTION: acpi_install_notify_handler35 *36 * PARAMETERS: device - The device for which notifies will be handled37 * handler_type - The type of handler:38 * ACPI_SYSTEM_NOTIFY: System Handler (00-7F)39 * ACPI_DEVICE_NOTIFY: Device Handler (80-FF)40 * ACPI_ALL_NOTIFY: Both System and Device41 * handler - Address of the handler42 * context - Value passed to the handler on each GPE43 *44 * RETURN: Status45 *46 * DESCRIPTION: Install a handler for notifications on an ACPI Device,47 * thermal_zone, or Processor object.48 *49 * NOTES: The Root namespace object may have only one handler for each50 * type of notify (System/Device). Device/Thermal/Processor objects51 * may have one device notify handler, and multiple system notify52 * handlers.53 *54 ******************************************************************************/55 56acpi_status57acpi_install_notify_handler(acpi_handle device,58 u32 handler_type,59 acpi_notify_handler handler, void *context)60{61 struct acpi_namespace_node *node =62 ACPI_CAST_PTR(struct acpi_namespace_node, device);63 union acpi_operand_object *obj_desc;64 union acpi_operand_object *handler_obj;65 acpi_status status;66 u32 i;67 68 ACPI_FUNCTION_TRACE(acpi_install_notify_handler);69 70 /* Parameter validation */71 72 if ((!device) || (!handler) || (!handler_type) ||73 (handler_type > ACPI_MAX_NOTIFY_HANDLER_TYPE)) {74 return_ACPI_STATUS(AE_BAD_PARAMETER);75 }76 77 status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);78 if (ACPI_FAILURE(status)) {79 return_ACPI_STATUS(status);80 }81 82 /*83 * Root Object:84 * Registering a notify handler on the root object indicates that the85 * caller wishes to receive notifications for all objects. Note that86 * only one global handler can be registered per notify type.87 * Ensure that a handler is not already installed.88 */89 if (device == ACPI_ROOT_OBJECT) {90 for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++) {91 if (handler_type & (i + 1)) {92 if (acpi_gbl_global_notify[i].handler) {93 status = AE_ALREADY_EXISTS;94 goto unlock_and_exit;95 }96 97 acpi_gbl_global_notify[i].handler = handler;98 acpi_gbl_global_notify[i].context = context;99 }100 }101 102 goto unlock_and_exit; /* Global notify handler installed, all done */103 }104 105 /*106 * All Other Objects:107 * Caller will only receive notifications specific to the target108 * object. Note that only certain object types are allowed to109 * receive notifications.110 */111 112 /* Are Notifies allowed on this object? */113 114 if (!acpi_ev_is_notify_object(node)) {115 status = AE_TYPE;116 goto unlock_and_exit;117 }118 119 /* Check for an existing internal object, might not exist */120 121 obj_desc = acpi_ns_get_attached_object(node);122 if (!obj_desc) {123 124 /* Create a new object */125 126 obj_desc = acpi_ut_create_internal_object(node->type);127 if (!obj_desc) {128 status = AE_NO_MEMORY;129 goto unlock_and_exit;130 }131 132 /* Attach new object to the Node, remove local reference */133 134 status = acpi_ns_attach_object(device, obj_desc, node->type);135 acpi_ut_remove_reference(obj_desc);136 if (ACPI_FAILURE(status)) {137 goto unlock_and_exit;138 }139 }140 141 /* Ensure that the handler is not already installed in the lists */142 143 for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++) {144 if (handler_type & (i + 1)) {145 handler_obj = obj_desc->common_notify.notify_list[i];146 while (handler_obj) {147 if (handler_obj->notify.handler == handler) {148 status = AE_ALREADY_EXISTS;149 goto unlock_and_exit;150 }151 152 handler_obj = handler_obj->notify.next[i];153 }154 }155 }156 157 /* Create and populate a new notify handler object */158 159 handler_obj = acpi_ut_create_internal_object(ACPI_TYPE_LOCAL_NOTIFY);160 if (!handler_obj) {161 status = AE_NO_MEMORY;162 goto unlock_and_exit;163 }164 165 handler_obj->notify.node = node;166 handler_obj->notify.handler_type = handler_type;167 handler_obj->notify.handler = handler;168 handler_obj->notify.context = context;169 170 /* Install the handler at the list head(s) */171 172 for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++) {173 if (handler_type & (i + 1)) {174 handler_obj->notify.next[i] =175 obj_desc->common_notify.notify_list[i];176 177 obj_desc->common_notify.notify_list[i] = handler_obj;178 }179 }180 181 /* Add an extra reference if handler was installed in both lists */182 183 if (handler_type == ACPI_ALL_NOTIFY) {184 acpi_ut_add_reference(handler_obj);185 }186 187unlock_and_exit:188 (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);189 return_ACPI_STATUS(status);190}191 192ACPI_EXPORT_SYMBOL(acpi_install_notify_handler)193 194/*******************************************************************************195 *196 * FUNCTION: acpi_remove_notify_handler197 *198 * PARAMETERS: device - The device for which the handler is installed199 * handler_type - The type of handler:200 * ACPI_SYSTEM_NOTIFY: System Handler (00-7F)201 * ACPI_DEVICE_NOTIFY: Device Handler (80-FF)202 * ACPI_ALL_NOTIFY: Both System and Device203 * handler - Address of the handler204 *205 * RETURN: Status206 *207 * DESCRIPTION: Remove a handler for notifies on an ACPI device208 *209 ******************************************************************************/210acpi_status211acpi_remove_notify_handler(acpi_handle device,212 u32 handler_type, acpi_notify_handler handler)213{214 struct acpi_namespace_node *node =215 ACPI_CAST_PTR(struct acpi_namespace_node, device);216 union acpi_operand_object *obj_desc;217 union acpi_operand_object *handler_obj;218 union acpi_operand_object *previous_handler_obj;219 acpi_status status = AE_OK;220 u32 i;221 222 ACPI_FUNCTION_TRACE(acpi_remove_notify_handler);223 224 /* Parameter validation */225 226 if ((!device) || (!handler) || (!handler_type) ||227 (handler_type > ACPI_MAX_NOTIFY_HANDLER_TYPE)) {228 return_ACPI_STATUS(AE_BAD_PARAMETER);229 }230 231 /* Root Object. Global handlers are removed here */232 233 if (device == ACPI_ROOT_OBJECT) {234 for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++) {235 if (handler_type & (i + 1)) {236 status =237 acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);238 if (ACPI_FAILURE(status)) {239 return_ACPI_STATUS(status);240 }241 242 if (!acpi_gbl_global_notify[i].handler ||243 (acpi_gbl_global_notify[i].handler !=244 handler)) {245 status = AE_NOT_EXIST;246 goto unlock_and_exit;247 }248 249 ACPI_DEBUG_PRINT((ACPI_DB_INFO,250 "Removing global notify handler\n"));251 252 acpi_gbl_global_notify[i].handler = NULL;253 acpi_gbl_global_notify[i].context = NULL;254 255 (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);256 257 /* Make sure all deferred notify tasks are completed */258 259 acpi_os_wait_events_complete();260 }261 }262 263 return_ACPI_STATUS(AE_OK);264 }265 266 /* All other objects: Are Notifies allowed on this object? */267 268 if (!acpi_ev_is_notify_object(node)) {269 return_ACPI_STATUS(AE_TYPE);270 }271 272 /* Must have an existing internal object */273 274 obj_desc = acpi_ns_get_attached_object(node);275 if (!obj_desc) {276 return_ACPI_STATUS(AE_NOT_EXIST);277 }278 279 /* Internal object exists. Find the handler and remove it */280 281 for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++) {282 if (handler_type & (i + 1)) {283 status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);284 if (ACPI_FAILURE(status)) {285 return_ACPI_STATUS(status);286 }287 288 handler_obj = obj_desc->common_notify.notify_list[i];289 previous_handler_obj = NULL;290 291 /* Attempt to find the handler in the handler list */292 293 while (handler_obj &&294 (handler_obj->notify.handler != handler)) {295 previous_handler_obj = handler_obj;296 handler_obj = handler_obj->notify.next[i];297 }298 299 if (!handler_obj) {300 status = AE_NOT_EXIST;301 goto unlock_and_exit;302 }303 304 /* Remove the handler object from the list */305 306 if (previous_handler_obj) { /* Handler is not at the list head */307 previous_handler_obj->notify.next[i] =308 handler_obj->notify.next[i];309 } else { /* Handler is at the list head */310 311 obj_desc->common_notify.notify_list[i] =312 handler_obj->notify.next[i];313 }314 315 (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);316 317 /* Make sure all deferred notify tasks are completed */318 319 acpi_os_wait_events_complete();320 acpi_ut_remove_reference(handler_obj);321 }322 }323 324 return_ACPI_STATUS(status);325 326unlock_and_exit:327 (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);328 return_ACPI_STATUS(status);329}330 331ACPI_EXPORT_SYMBOL(acpi_remove_notify_handler)332 333/*******************************************************************************334 *335 * FUNCTION: acpi_install_exception_handler336 *337 * PARAMETERS: handler - Pointer to the handler function for the338 * event339 *340 * RETURN: Status341 *342 * DESCRIPTION: Saves the pointer to the handler function343 *344 ******************************************************************************/345#ifdef ACPI_FUTURE_USAGE346acpi_status acpi_install_exception_handler(acpi_exception_handler handler)347{348 acpi_status status;349 350 ACPI_FUNCTION_TRACE(acpi_install_exception_handler);351 352 status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);353 if (ACPI_FAILURE(status)) {354 return_ACPI_STATUS(status);355 }356 357 /* Don't allow two handlers. */358 359 if (acpi_gbl_exception_handler) {360 status = AE_ALREADY_EXISTS;361 goto cleanup;362 }363 364 /* Install the handler */365 366 acpi_gbl_exception_handler = handler;367 368cleanup:369 (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);370 return_ACPI_STATUS(status);371}372 373ACPI_EXPORT_SYMBOL(acpi_install_exception_handler)374#endif375 376#if (!ACPI_REDUCED_HARDWARE)377/*******************************************************************************378 *379 * FUNCTION: acpi_install_sci_handler380 *381 * PARAMETERS: address - Address of the handler382 * context - Value passed to the handler on each SCI383 *384 * RETURN: Status385 *386 * DESCRIPTION: Install a handler for a System Control Interrupt.387 *388 ******************************************************************************/389acpi_status acpi_install_sci_handler(acpi_sci_handler address, void *context)390{391 struct acpi_sci_handler_info *new_sci_handler;392 struct acpi_sci_handler_info *sci_handler;393 acpi_cpu_flags flags;394 acpi_status status;395 396 ACPI_FUNCTION_TRACE(acpi_install_sci_handler);397 398 if (!address) {399 return_ACPI_STATUS(AE_BAD_PARAMETER);400 }401 402 /* Allocate and init a handler object */403 404 new_sci_handler = ACPI_ALLOCATE(sizeof(struct acpi_sci_handler_info));405 if (!new_sci_handler) {406 return_ACPI_STATUS(AE_NO_MEMORY);407 }408 409 new_sci_handler->address = address;410 new_sci_handler->context = context;411 412 status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);413 if (ACPI_FAILURE(status)) {414 goto exit;415 }416 417 /* Lock list during installation */418 419 flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);420 sci_handler = acpi_gbl_sci_handler_list;421 422 /* Ensure handler does not already exist */423 424 while (sci_handler) {425 if (address == sci_handler->address) {426 status = AE_ALREADY_EXISTS;427 goto unlock_and_exit;428 }429 430 sci_handler = sci_handler->next;431 }432 433 /* Install the new handler into the global list (at head) */434 435 new_sci_handler->next = acpi_gbl_sci_handler_list;436 acpi_gbl_sci_handler_list = new_sci_handler;437 438unlock_and_exit:439 440 acpi_os_release_lock(acpi_gbl_gpe_lock, flags);441 (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);442 443exit:444 if (ACPI_FAILURE(status)) {445 ACPI_FREE(new_sci_handler);446 }447 return_ACPI_STATUS(status);448}449 450ACPI_EXPORT_SYMBOL(acpi_install_sci_handler)451 452/*******************************************************************************453 *454 * FUNCTION: acpi_remove_sci_handler455 *456 * PARAMETERS: address - Address of the handler457 *458 * RETURN: Status459 *460 * DESCRIPTION: Remove a handler for a System Control Interrupt.461 *462 ******************************************************************************/463acpi_status acpi_remove_sci_handler(acpi_sci_handler address)464{465 struct acpi_sci_handler_info *prev_sci_handler;466 struct acpi_sci_handler_info *next_sci_handler;467 acpi_cpu_flags flags;468 acpi_status status;469 470 ACPI_FUNCTION_TRACE(acpi_remove_sci_handler);471 472 if (!address) {473 return_ACPI_STATUS(AE_BAD_PARAMETER);474 }475 476 status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);477 if (ACPI_FAILURE(status)) {478 return_ACPI_STATUS(status);479 }480 481 /* Remove the SCI handler with lock */482 483 flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);484 485 prev_sci_handler = NULL;486 next_sci_handler = acpi_gbl_sci_handler_list;487 while (next_sci_handler) {488 if (next_sci_handler->address == address) {489 490 /* Unlink and free the SCI handler info block */491 492 if (prev_sci_handler) {493 prev_sci_handler->next = next_sci_handler->next;494 } else {495 acpi_gbl_sci_handler_list =496 next_sci_handler->next;497 }498 499 acpi_os_release_lock(acpi_gbl_gpe_lock, flags);500 ACPI_FREE(next_sci_handler);501 goto unlock_and_exit;502 }503 504 prev_sci_handler = next_sci_handler;505 next_sci_handler = next_sci_handler->next;506 }507 508 acpi_os_release_lock(acpi_gbl_gpe_lock, flags);509 status = AE_NOT_EXIST;510 511unlock_and_exit:512 (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);513 return_ACPI_STATUS(status);514}515 516ACPI_EXPORT_SYMBOL(acpi_remove_sci_handler)517 518/*******************************************************************************519 *520 * FUNCTION: acpi_install_global_event_handler521 *522 * PARAMETERS: handler - Pointer to the global event handler function523 * context - Value passed to the handler on each event524 *525 * RETURN: Status526 *527 * DESCRIPTION: Saves the pointer to the handler function. The global handler528 * is invoked upon each incoming GPE and Fixed Event. It is529 * invoked at interrupt level at the time of the event dispatch.530 * Can be used to update event counters, etc.531 *532 ******************************************************************************/533acpi_status534acpi_install_global_event_handler(acpi_gbl_event_handler handler, void *context)535{536 acpi_status status;537 538 ACPI_FUNCTION_TRACE(acpi_install_global_event_handler);539 540 /* Parameter validation */541 542 if (!handler) {543 return_ACPI_STATUS(AE_BAD_PARAMETER);544 }545 546 status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);547 if (ACPI_FAILURE(status)) {548 return_ACPI_STATUS(status);549 }550 551 /* Don't allow two handlers. */552 553 if (acpi_gbl_global_event_handler) {554 status = AE_ALREADY_EXISTS;555 goto cleanup;556 }557 558 acpi_gbl_global_event_handler = handler;559 acpi_gbl_global_event_handler_context = context;560 561cleanup:562 (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);563 return_ACPI_STATUS(status);564}565 566ACPI_EXPORT_SYMBOL(acpi_install_global_event_handler)567 568/*******************************************************************************569 *570 * FUNCTION: acpi_install_fixed_event_handler571 *572 * PARAMETERS: event - Event type to enable.573 * handler - Pointer to the handler function for the574 * event575 * context - Value passed to the handler on each GPE576 *577 * RETURN: Status578 *579 * DESCRIPTION: Saves the pointer to the handler function and then enables the580 * event.581 *582 ******************************************************************************/583acpi_status584acpi_install_fixed_event_handler(u32 event,585 acpi_event_handler handler, void *context)586{587 acpi_status status;588 589 ACPI_FUNCTION_TRACE(acpi_install_fixed_event_handler);590 591 /* Parameter validation */592 593 if (event > ACPI_EVENT_MAX) {594 return_ACPI_STATUS(AE_BAD_PARAMETER);595 }596 597 status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);598 if (ACPI_FAILURE(status)) {599 return_ACPI_STATUS(status);600 }601 602 /* Do not allow multiple handlers */603 604 if (acpi_gbl_fixed_event_handlers[event].handler) {605 status = AE_ALREADY_EXISTS;606 goto cleanup;607 }608 609 /* Install the handler before enabling the event */610 611 acpi_gbl_fixed_event_handlers[event].handler = handler;612 acpi_gbl_fixed_event_handlers[event].context = context;613 614 status = acpi_clear_event(event);615 if (ACPI_SUCCESS(status))616 status = acpi_enable_event(event, 0);617 if (ACPI_FAILURE(status)) {618 ACPI_WARNING((AE_INFO,619 "Could not enable fixed event - %s (%u)",620 acpi_ut_get_event_name(event), event));621 622 /* Remove the handler */623 624 acpi_gbl_fixed_event_handlers[event].handler = NULL;625 acpi_gbl_fixed_event_handlers[event].context = NULL;626 } else {627 ACPI_DEBUG_PRINT((ACPI_DB_INFO,628 "Enabled fixed event %s (%X), Handler=%p\n",629 acpi_ut_get_event_name(event), event,630 handler));631 }632 633cleanup:634 (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);635 return_ACPI_STATUS(status);636}637 638ACPI_EXPORT_SYMBOL(acpi_install_fixed_event_handler)639 640/*******************************************************************************641 *642 * FUNCTION: acpi_remove_fixed_event_handler643 *644 * PARAMETERS: event - Event type to disable.645 * handler - Address of the handler646 *647 * RETURN: Status648 *649 * DESCRIPTION: Disables the event and unregisters the event handler.650 *651 ******************************************************************************/652acpi_status653acpi_remove_fixed_event_handler(u32 event, acpi_event_handler handler)654{655 acpi_status status = AE_OK;656 657 ACPI_FUNCTION_TRACE(acpi_remove_fixed_event_handler);658 659 /* Parameter validation */660 661 if (event > ACPI_EVENT_MAX) {662 return_ACPI_STATUS(AE_BAD_PARAMETER);663 }664 665 status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);666 if (ACPI_FAILURE(status)) {667 return_ACPI_STATUS(status);668 }669 670 /* Disable the event before removing the handler */671 672 status = acpi_disable_event(event, 0);673 674 /* Always Remove the handler */675 676 acpi_gbl_fixed_event_handlers[event].handler = NULL;677 acpi_gbl_fixed_event_handlers[event].context = NULL;678 679 if (ACPI_FAILURE(status)) {680 ACPI_WARNING((AE_INFO,681 "Could not disable fixed event - %s (%u)",682 acpi_ut_get_event_name(event), event));683 } else {684 ACPI_DEBUG_PRINT((ACPI_DB_INFO,685 "Disabled fixed event - %s (%X)\n",686 acpi_ut_get_event_name(event), event));687 }688 689 (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);690 return_ACPI_STATUS(status);691}692 693ACPI_EXPORT_SYMBOL(acpi_remove_fixed_event_handler)694 695/*******************************************************************************696 *697 * FUNCTION: acpi_ev_install_gpe_handler698 *699 * PARAMETERS: gpe_device - Namespace node for the GPE (NULL for FADT700 * defined GPEs)701 * gpe_number - The GPE number within the GPE block702 * type - Whether this GPE should be treated as an703 * edge- or level-triggered interrupt.704 * is_raw_handler - Whether this GPE should be handled using705 * the special GPE handler mode.706 * address - Address of the handler707 * context - Value passed to the handler on each GPE708 *709 * RETURN: Status710 *711 * DESCRIPTION: Internal function to install a handler for a General Purpose712 * Event.713 *714 ******************************************************************************/715static acpi_status716acpi_ev_install_gpe_handler(acpi_handle gpe_device,717 u32 gpe_number,718 u32 type,719 u8 is_raw_handler,720 acpi_gpe_handler address, void *context)721{722 struct acpi_gpe_event_info *gpe_event_info;723 struct acpi_gpe_handler_info *handler;724 acpi_status status;725 acpi_cpu_flags flags;726 727 ACPI_FUNCTION_TRACE(ev_install_gpe_handler);728 729 /* Parameter validation */730 731 if ((!address) || (type & ~ACPI_GPE_XRUPT_TYPE_MASK)) {732 return_ACPI_STATUS(AE_BAD_PARAMETER);733 }734 735 status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);736 if (ACPI_FAILURE(status)) {737 return_ACPI_STATUS(status);738 }739 740 /* Allocate and init handler object (before lock) */741 742 handler = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_gpe_handler_info));743 if (!handler) {744 status = AE_NO_MEMORY;745 goto unlock_and_exit;746 }747 748 flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);749 750 /* Ensure that we have a valid GPE number */751 752 gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);753 if (!gpe_event_info) {754 status = AE_BAD_PARAMETER;755 goto free_and_exit;756 }757 758 /* Make sure that there isn't a handler there already */759 760 if ((ACPI_GPE_DISPATCH_TYPE(gpe_event_info->flags) ==761 ACPI_GPE_DISPATCH_HANDLER) ||762 (ACPI_GPE_DISPATCH_TYPE(gpe_event_info->flags) ==763 ACPI_GPE_DISPATCH_RAW_HANDLER)) {764 status = AE_ALREADY_EXISTS;765 goto free_and_exit;766 }767 768 handler->address = address;769 handler->context = context;770 handler->method_node = gpe_event_info->dispatch.method_node;771 handler->original_flags = (u8)(gpe_event_info->flags &772 (ACPI_GPE_XRUPT_TYPE_MASK |773 ACPI_GPE_DISPATCH_MASK));774 775 /*776 * If the GPE is associated with a method, it may have been enabled777 * automatically during initialization, in which case it has to be778 * disabled now to avoid spurious execution of the handler.779 */780 if (((ACPI_GPE_DISPATCH_TYPE(handler->original_flags) ==781 ACPI_GPE_DISPATCH_METHOD) ||782 (ACPI_GPE_DISPATCH_TYPE(handler->original_flags) ==783 ACPI_GPE_DISPATCH_NOTIFY)) && gpe_event_info->runtime_count) {784 handler->originally_enabled = TRUE;785 (void)acpi_ev_remove_gpe_reference(gpe_event_info);786 787 /* Sanity check of original type against new type */788 789 if (type !=790 (u32)(gpe_event_info->flags & ACPI_GPE_XRUPT_TYPE_MASK)) {791 ACPI_WARNING((AE_INFO,792 "GPE type mismatch (level/edge)"));793 }794 }795 796 /* Install the handler */797 798 gpe_event_info->dispatch.handler = handler;799 800 /* Setup up dispatch flags to indicate handler (vs. method/notify) */801 802 gpe_event_info->flags &=803 ~(ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK);804 gpe_event_info->flags |=805 (u8)(type |806 (is_raw_handler ? ACPI_GPE_DISPATCH_RAW_HANDLER :807 ACPI_GPE_DISPATCH_HANDLER));808 809 acpi_os_release_lock(acpi_gbl_gpe_lock, flags);810 811unlock_and_exit:812 (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);813 return_ACPI_STATUS(status);814 815free_and_exit:816 acpi_os_release_lock(acpi_gbl_gpe_lock, flags);817 ACPI_FREE(handler);818 goto unlock_and_exit;819}820 821/*******************************************************************************822 *823 * FUNCTION: acpi_install_gpe_handler824 *825 * PARAMETERS: gpe_device - Namespace node for the GPE (NULL for FADT826 * defined GPEs)827 * gpe_number - The GPE number within the GPE block828 * type - Whether this GPE should be treated as an829 * edge- or level-triggered interrupt.830 * address - Address of the handler831 * context - Value passed to the handler on each GPE832 *833 * RETURN: Status834 *835 * DESCRIPTION: Install a handler for a General Purpose Event.836 *837 ******************************************************************************/838 839acpi_status840acpi_install_gpe_handler(acpi_handle gpe_device,841 u32 gpe_number,842 u32 type, acpi_gpe_handler address, void *context)843{844 acpi_status status;845 846 ACPI_FUNCTION_TRACE(acpi_install_gpe_handler);847 848 status = acpi_ev_install_gpe_handler(gpe_device, gpe_number, type,849 FALSE, address, context);850 851 return_ACPI_STATUS(status);852}853 854ACPI_EXPORT_SYMBOL(acpi_install_gpe_handler)855 856/*******************************************************************************857 *858 * FUNCTION: acpi_install_gpe_raw_handler859 *860 * PARAMETERS: gpe_device - Namespace node for the GPE (NULL for FADT861 * defined GPEs)862 * gpe_number - The GPE number within the GPE block863 * type - Whether this GPE should be treated as an864 * edge- or level-triggered interrupt.865 * address - Address of the handler866 * context - Value passed to the handler on each GPE867 *868 * RETURN: Status869 *870 * DESCRIPTION: Install a handler for a General Purpose Event.871 *872 ******************************************************************************/873acpi_status874acpi_install_gpe_raw_handler(acpi_handle gpe_device,875 u32 gpe_number,876 u32 type, acpi_gpe_handler address, void *context)877{878 acpi_status status;879 880 ACPI_FUNCTION_TRACE(acpi_install_gpe_raw_handler);881 882 status = acpi_ev_install_gpe_handler(gpe_device, gpe_number, type,883 TRUE, address, context);884 885 return_ACPI_STATUS(status);886}887 888ACPI_EXPORT_SYMBOL(acpi_install_gpe_raw_handler)889 890/*******************************************************************************891 *892 * FUNCTION: acpi_remove_gpe_handler893 *894 * PARAMETERS: gpe_device - Namespace node for the GPE (NULL for FADT895 * defined GPEs)896 * gpe_number - The event to remove a handler897 * address - Address of the handler898 *899 * RETURN: Status900 *901 * DESCRIPTION: Remove a handler for a General Purpose acpi_event.902 *903 ******************************************************************************/904acpi_status905acpi_remove_gpe_handler(acpi_handle gpe_device,906 u32 gpe_number, acpi_gpe_handler address)907{908 struct acpi_gpe_event_info *gpe_event_info;909 struct acpi_gpe_handler_info *handler;910 acpi_status status;911 acpi_cpu_flags flags;912 913 ACPI_FUNCTION_TRACE(acpi_remove_gpe_handler);914 915 /* Parameter validation */916 917 if (!address) {918 return_ACPI_STATUS(AE_BAD_PARAMETER);919 }920 921 status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);922 if (ACPI_FAILURE(status)) {923 return_ACPI_STATUS(status);924 }925 926 flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);927 928 /* Ensure that we have a valid GPE number */929 930 gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);931 if (!gpe_event_info) {932 status = AE_BAD_PARAMETER;933 goto unlock_and_exit;934 }935 936 /* Make sure that a handler is indeed installed */937 938 if ((ACPI_GPE_DISPATCH_TYPE(gpe_event_info->flags) !=939 ACPI_GPE_DISPATCH_HANDLER) &&940 (ACPI_GPE_DISPATCH_TYPE(gpe_event_info->flags) !=941 ACPI_GPE_DISPATCH_RAW_HANDLER)) {942 status = AE_NOT_EXIST;943 goto unlock_and_exit;944 }945 946 /* Make sure that the installed handler is the same */947 948 if (gpe_event_info->dispatch.handler->address != address) {949 status = AE_BAD_PARAMETER;950 goto unlock_and_exit;951 }952 953 /* Remove the handler */954 955 handler = gpe_event_info->dispatch.handler;956 gpe_event_info->dispatch.handler = NULL;957 958 /* Restore Method node (if any), set dispatch flags */959 960 gpe_event_info->dispatch.method_node = handler->method_node;961 gpe_event_info->flags &=962 ~(ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK);963 gpe_event_info->flags |= handler->original_flags;964 965 /*966 * If the GPE was previously associated with a method and it was967 * enabled, it should be enabled at this point to restore the968 * post-initialization configuration.969 */970 if (((ACPI_GPE_DISPATCH_TYPE(handler->original_flags) ==971 ACPI_GPE_DISPATCH_METHOD) ||972 (ACPI_GPE_DISPATCH_TYPE(handler->original_flags) ==973 ACPI_GPE_DISPATCH_NOTIFY)) && handler->originally_enabled) {974 (void)acpi_ev_add_gpe_reference(gpe_event_info, FALSE);975 if (ACPI_GPE_IS_POLLING_NEEDED(gpe_event_info)) {976 977 /* Poll edge triggered GPEs to handle existing events */978 979 acpi_os_release_lock(acpi_gbl_gpe_lock, flags);980 (void)acpi_ev_detect_gpe(gpe_device, gpe_event_info,981 gpe_number);982 flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);983 }984 }985 986 acpi_os_release_lock(acpi_gbl_gpe_lock, flags);987 (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);988 989 /* Make sure all deferred GPE tasks are completed */990 991 acpi_os_wait_events_complete();992 993 /* Now we can free the handler object */994 995 ACPI_FREE(handler);996 return_ACPI_STATUS(status);997 998unlock_and_exit:999 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 1005ACPI_EXPORT_SYMBOL(acpi_remove_gpe_handler)1006 1007/*******************************************************************************1008 *1009 * FUNCTION: acpi_acquire_global_lock1010 *1011 * PARAMETERS: timeout - How long the caller is willing to wait1012 * handle - Where the handle to the lock is returned1013 * (if acquired)1014 *1015 * RETURN: Status1016 *1017 * DESCRIPTION: Acquire the ACPI Global Lock1018 *1019 * Note: Allows callers with the same thread ID to acquire the global lock1020 * multiple times. In other words, externally, the behavior of the global lock1021 * is identical to an AML mutex. On the first acquire, a new handle is1022 * returned. On any subsequent calls to acquire by the same thread, the same1023 * handle is returned.1024 *1025 ******************************************************************************/1026acpi_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 1053ACPI_EXPORT_SYMBOL(acpi_acquire_global_lock)1054 1055/*******************************************************************************1056 *1057 * FUNCTION: acpi_release_global_lock1058 *1059 * PARAMETERS: handle - Returned from acpi_acquire_global_lock1060 *1061 * RETURN: Status1062 *1063 * DESCRIPTION: Release the ACPI Global Lock. The handle must be valid.1064 *1065 ******************************************************************************/1066acpi_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 1078ACPI_EXPORT_SYMBOL(acpi_release_global_lock)1079#endif /* !ACPI_REDUCED_HARDWARE */1080