/******************************************************************************1*2* Module Name: evxface - External interfaces for ACPI events3*4*****************************************************************************/56/*7* Copyright (C) 2000 - 2011, Intel Corp.8* All rights reserved.9*10* Redistribution and use in source and binary forms, with or without11* modification, are permitted provided that the following conditions12* are met:13* 1. Redistributions of source code must retain the above copyright14* notice, this list of conditions, and the following disclaimer,15* without modification.16* 2. Redistributions in binary form must reproduce at minimum a disclaimer17* substantially similar to the "NO WARRANTY" disclaimer below18* ("Disclaimer") and any redistribution must be conditioned upon19* including a substantially similar Disclaimer requirement for further20* binary redistribution.21* 3. Neither the names of the above-listed copyright holders nor the names22* of any contributors may be used to endorse or promote products derived23* from this software without specific prior written permission.24*25* Alternatively, this software may be distributed under the terms of the26* GNU General Public License ("GPL") version 2 as published by the Free27* Software Foundation.28*29* NO WARRANTY30* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS31* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT32* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR33* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT34* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL35* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS36* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)37* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,38* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING39* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE40* POSSIBILITY OF SUCH DAMAGES.41*/4243#include <acpi/acpi.h>44#include "accommon.h"45#include "acnamesp.h"46#include "acevents.h"47#include "acinterp.h"4849#define _COMPONENT ACPI_EVENTS50ACPI_MODULE_NAME("evxface")5152/*******************************************************************************53*54* FUNCTION: acpi_install_exception_handler55*56* PARAMETERS: Handler - Pointer to the handler function for the57* event58*59* RETURN: Status60*61* DESCRIPTION: Saves the pointer to the handler function62*63******************************************************************************/64#ifdef ACPI_FUTURE_USAGE65acpi_status acpi_install_exception_handler(acpi_exception_handler handler)66{67acpi_status status;6869ACPI_FUNCTION_TRACE(acpi_install_exception_handler);7071status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);72if (ACPI_FAILURE(status)) {73return_ACPI_STATUS(status);74}7576/* Don't allow two handlers. */7778if (acpi_gbl_exception_handler) {79status = AE_ALREADY_EXISTS;80goto cleanup;81}8283/* Install the handler */8485acpi_gbl_exception_handler = handler;8687cleanup:88(void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);89return_ACPI_STATUS(status);90}9192ACPI_EXPORT_SYMBOL(acpi_install_exception_handler)93#endif /* ACPI_FUTURE_USAGE */9495/*******************************************************************************96*97* FUNCTION: acpi_install_global_event_handler98*99* PARAMETERS: Handler - Pointer to the global event handler function100* Context - Value passed to the handler on each event101*102* RETURN: Status103*104* DESCRIPTION: Saves the pointer to the handler function. The global handler105* is invoked upon each incoming GPE and Fixed Event. It is106* invoked at interrupt level at the time of the event dispatch.107* Can be used to update event counters, etc.108*109******************************************************************************/110acpi_status111acpi_install_global_event_handler(ACPI_GBL_EVENT_HANDLER handler, void *context)112{113acpi_status status;114115ACPI_FUNCTION_TRACE(acpi_install_global_event_handler);116117/* Parameter validation */118119if (!handler) {120return_ACPI_STATUS(AE_BAD_PARAMETER);121}122123status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);124if (ACPI_FAILURE(status)) {125return_ACPI_STATUS(status);126}127128/* Don't allow two handlers. */129130if (acpi_gbl_global_event_handler) {131status = AE_ALREADY_EXISTS;132goto cleanup;133}134135acpi_gbl_global_event_handler = handler;136acpi_gbl_global_event_handler_context = context;137138cleanup:139(void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);140return_ACPI_STATUS(status);141}142143ACPI_EXPORT_SYMBOL(acpi_install_global_event_handler)144145/*******************************************************************************146*147* FUNCTION: acpi_install_fixed_event_handler148*149* PARAMETERS: Event - Event type to enable.150* Handler - Pointer to the handler function for the151* event152* Context - Value passed to the handler on each GPE153*154* RETURN: Status155*156* DESCRIPTION: Saves the pointer to the handler function and then enables the157* event.158*159******************************************************************************/160acpi_status161acpi_install_fixed_event_handler(u32 event,162acpi_event_handler handler, void *context)163{164acpi_status status;165166ACPI_FUNCTION_TRACE(acpi_install_fixed_event_handler);167168/* Parameter validation */169170if (event > ACPI_EVENT_MAX) {171return_ACPI_STATUS(AE_BAD_PARAMETER);172}173174status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);175if (ACPI_FAILURE(status)) {176return_ACPI_STATUS(status);177}178179/* Don't allow two handlers. */180181if (NULL != acpi_gbl_fixed_event_handlers[event].handler) {182status = AE_ALREADY_EXISTS;183goto cleanup;184}185186/* Install the handler before enabling the event */187188acpi_gbl_fixed_event_handlers[event].handler = handler;189acpi_gbl_fixed_event_handlers[event].context = context;190191status = acpi_clear_event(event);192if (ACPI_SUCCESS(status))193status = acpi_enable_event(event, 0);194if (ACPI_FAILURE(status)) {195ACPI_WARNING((AE_INFO, "Could not enable fixed event 0x%X",196event));197198/* Remove the handler */199200acpi_gbl_fixed_event_handlers[event].handler = NULL;201acpi_gbl_fixed_event_handlers[event].context = NULL;202} else {203ACPI_DEBUG_PRINT((ACPI_DB_INFO,204"Enabled fixed event %X, Handler=%p\n", event,205handler));206}207208cleanup:209(void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);210return_ACPI_STATUS(status);211}212213ACPI_EXPORT_SYMBOL(acpi_install_fixed_event_handler)214215/*******************************************************************************216*217* FUNCTION: acpi_remove_fixed_event_handler218*219* PARAMETERS: Event - Event type to disable.220* Handler - Address of the handler221*222* RETURN: Status223*224* DESCRIPTION: Disables the event and unregisters the event handler.225*226******************************************************************************/227acpi_status228acpi_remove_fixed_event_handler(u32 event, acpi_event_handler handler)229{230acpi_status status = AE_OK;231232ACPI_FUNCTION_TRACE(acpi_remove_fixed_event_handler);233234/* Parameter validation */235236if (event > ACPI_EVENT_MAX) {237return_ACPI_STATUS(AE_BAD_PARAMETER);238}239240status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);241if (ACPI_FAILURE(status)) {242return_ACPI_STATUS(status);243}244245/* Disable the event before removing the handler */246247status = acpi_disable_event(event, 0);248249/* Always Remove the handler */250251acpi_gbl_fixed_event_handlers[event].handler = NULL;252acpi_gbl_fixed_event_handlers[event].context = NULL;253254if (ACPI_FAILURE(status)) {255ACPI_WARNING((AE_INFO,256"Could not write to fixed event enable register 0x%X",257event));258} else {259ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Disabled fixed event %X\n",260event));261}262263(void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);264return_ACPI_STATUS(status);265}266267ACPI_EXPORT_SYMBOL(acpi_remove_fixed_event_handler)268269/*******************************************************************************270*271* FUNCTION: acpi_populate_handler_object272*273* PARAMETERS: handler_obj - Handler object to populate274* handler_type - The type of handler:275* ACPI_SYSTEM_NOTIFY: system_handler (00-7f)276* ACPI_DEVICE_NOTIFY: driver_handler (80-ff)277* ACPI_ALL_NOTIFY: both system and device278* handler - Address of the handler279* context - Value passed to the handler on each GPE280* next - Address of a handler object to link to281*282* RETURN: None283*284* DESCRIPTION: Populate a handler object.285*286******************************************************************************/287static void288acpi_populate_handler_object(struct acpi_object_notify_handler *handler_obj,289u32 handler_type,290acpi_notify_handler handler, void *context,291struct acpi_object_notify_handler *next)292{293handler_obj->handler_type = handler_type;294handler_obj->handler = handler;295handler_obj->context = context;296handler_obj->next = next;297}298299/*******************************************************************************300*301* FUNCTION: acpi_add_handler_object302*303* PARAMETERS: parent_obj - Parent of the new object304* handler - Address of the handler305* context - Value passed to the handler on each GPE306*307* RETURN: Status308*309* DESCRIPTION: Create a new handler object and populate it.310*311******************************************************************************/312static acpi_status313acpi_add_handler_object(struct acpi_object_notify_handler *parent_obj,314acpi_notify_handler handler, void *context)315{316struct acpi_object_notify_handler *handler_obj;317318/* The parent must not be a defice notify handler object. */319if (parent_obj->handler_type & ACPI_DEVICE_NOTIFY)320return AE_BAD_PARAMETER;321322handler_obj = ACPI_ALLOCATE_ZEROED(sizeof(*handler_obj));323if (!handler_obj)324return AE_NO_MEMORY;325326acpi_populate_handler_object(handler_obj,327ACPI_SYSTEM_NOTIFY,328handler, context,329parent_obj->next);330parent_obj->next = handler_obj;331332return AE_OK;333}334335/*******************************************************************************336*337* FUNCTION: acpi_install_notify_handler338*339* PARAMETERS: Device - The device for which notifies will be handled340* handler_type - The type of handler:341* ACPI_SYSTEM_NOTIFY: system_handler (00-7f)342* ACPI_DEVICE_NOTIFY: driver_handler (80-ff)343* ACPI_ALL_NOTIFY: both system and device344* Handler - Address of the handler345* Context - Value passed to the handler on each GPE346*347* RETURN: Status348*349* DESCRIPTION: Install a handler for notifies on an ACPI device350*351******************************************************************************/352acpi_status353acpi_install_notify_handler(acpi_handle device,354u32 handler_type,355acpi_notify_handler handler, void *context)356{357union acpi_operand_object *obj_desc;358union acpi_operand_object *notify_obj;359struct acpi_namespace_node *node;360acpi_status status;361362ACPI_FUNCTION_TRACE(acpi_install_notify_handler);363364/* Parameter validation */365366if ((!device) ||367(!handler) || (handler_type > ACPI_MAX_NOTIFY_HANDLER_TYPE)) {368return_ACPI_STATUS(AE_BAD_PARAMETER);369}370371status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);372if (ACPI_FAILURE(status)) {373return_ACPI_STATUS(status);374}375376/* Convert and validate the device handle */377378node = acpi_ns_validate_handle(device);379if (!node) {380status = AE_BAD_PARAMETER;381goto unlock_and_exit;382}383384/*385* Root Object:386* Registering a notify handler on the root object indicates that the387* caller wishes to receive notifications for all objects. Note that388* only one <external> global handler can be regsitered (per notify type).389*/390if (device == ACPI_ROOT_OBJECT) {391392/* Make sure the handler is not already installed */393394if (((handler_type & ACPI_SYSTEM_NOTIFY) &&395acpi_gbl_system_notify.handler) ||396((handler_type & ACPI_DEVICE_NOTIFY) &&397acpi_gbl_device_notify.handler)) {398status = AE_ALREADY_EXISTS;399goto unlock_and_exit;400}401402if (handler_type & ACPI_SYSTEM_NOTIFY) {403acpi_gbl_system_notify.node = node;404acpi_gbl_system_notify.handler = handler;405acpi_gbl_system_notify.context = context;406}407408if (handler_type & ACPI_DEVICE_NOTIFY) {409acpi_gbl_device_notify.node = node;410acpi_gbl_device_notify.handler = handler;411acpi_gbl_device_notify.context = context;412}413414/* Global notify handler installed */415}416417/*418* All Other Objects:419* Caller will only receive notifications specific to the target object.420* Note that only certain object types can receive notifications.421*/422else {423/* Notifies allowed on this object? */424425if (!acpi_ev_is_notify_object(node)) {426status = AE_TYPE;427goto unlock_and_exit;428}429430/* Check for an existing internal object */431432obj_desc = acpi_ns_get_attached_object(node);433if (obj_desc) {434435/* Object exists. */436437/* For a device notify, make sure there's no handler. */438if ((handler_type & ACPI_DEVICE_NOTIFY) &&439obj_desc->common_notify.device_notify) {440status = AE_ALREADY_EXISTS;441goto unlock_and_exit;442}443444/* System notifies may have more handlers installed. */445notify_obj = obj_desc->common_notify.system_notify;446447if ((handler_type & ACPI_SYSTEM_NOTIFY) && notify_obj) {448struct acpi_object_notify_handler *parent_obj;449450if (handler_type & ACPI_DEVICE_NOTIFY) {451status = AE_ALREADY_EXISTS;452goto unlock_and_exit;453}454455parent_obj = ¬ify_obj->notify;456status = acpi_add_handler_object(parent_obj,457handler,458context);459goto unlock_and_exit;460}461} else {462/* Create a new object */463464obj_desc = acpi_ut_create_internal_object(node->type);465if (!obj_desc) {466status = AE_NO_MEMORY;467goto unlock_and_exit;468}469470/* Attach new object to the Node */471472status =473acpi_ns_attach_object(device, obj_desc, node->type);474475/* Remove local reference to the object */476477acpi_ut_remove_reference(obj_desc);478if (ACPI_FAILURE(status)) {479goto unlock_and_exit;480}481}482483/* Install the handler */484485notify_obj =486acpi_ut_create_internal_object(ACPI_TYPE_LOCAL_NOTIFY);487if (!notify_obj) {488status = AE_NO_MEMORY;489goto unlock_and_exit;490}491492acpi_populate_handler_object(¬ify_obj->notify,493handler_type,494handler, context,495NULL);496497if (handler_type & ACPI_SYSTEM_NOTIFY) {498obj_desc->common_notify.system_notify = notify_obj;499}500501if (handler_type & ACPI_DEVICE_NOTIFY) {502obj_desc->common_notify.device_notify = notify_obj;503}504505if (handler_type == ACPI_ALL_NOTIFY) {506507/* Extra ref if installed in both */508509acpi_ut_add_reference(notify_obj);510}511}512513unlock_and_exit:514(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);515return_ACPI_STATUS(status);516}517518ACPI_EXPORT_SYMBOL(acpi_install_notify_handler)519520/*******************************************************************************521*522* FUNCTION: acpi_remove_notify_handler523*524* PARAMETERS: Device - The device for which notifies will be handled525* handler_type - The type of handler:526* ACPI_SYSTEM_NOTIFY: system_handler (00-7f)527* ACPI_DEVICE_NOTIFY: driver_handler (80-ff)528* ACPI_ALL_NOTIFY: both system and device529* Handler - Address of the handler530*531* RETURN: Status532*533* DESCRIPTION: Remove a handler for notifies on an ACPI device534*535******************************************************************************/536acpi_status537acpi_remove_notify_handler(acpi_handle device,538u32 handler_type, acpi_notify_handler handler)539{540union acpi_operand_object *notify_obj;541union acpi_operand_object *obj_desc;542struct acpi_namespace_node *node;543acpi_status status;544545ACPI_FUNCTION_TRACE(acpi_remove_notify_handler);546547/* Parameter validation */548549if ((!device) ||550(!handler) || (handler_type > ACPI_MAX_NOTIFY_HANDLER_TYPE)) {551status = AE_BAD_PARAMETER;552goto exit;553}554555556/* Make sure all deferred tasks are completed */557acpi_os_wait_events_complete(NULL);558559status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);560if (ACPI_FAILURE(status)) {561goto exit;562}563564/* Convert and validate the device handle */565566node = acpi_ns_validate_handle(device);567if (!node) {568status = AE_BAD_PARAMETER;569goto unlock_and_exit;570}571572/* Root Object */573574if (device == ACPI_ROOT_OBJECT) {575ACPI_DEBUG_PRINT((ACPI_DB_INFO,576"Removing notify handler for namespace root object\n"));577578if (((handler_type & ACPI_SYSTEM_NOTIFY) &&579!acpi_gbl_system_notify.handler) ||580((handler_type & ACPI_DEVICE_NOTIFY) &&581!acpi_gbl_device_notify.handler)) {582status = AE_NOT_EXIST;583goto unlock_and_exit;584}585586if (handler_type & ACPI_SYSTEM_NOTIFY) {587acpi_gbl_system_notify.node = NULL;588acpi_gbl_system_notify.handler = NULL;589acpi_gbl_system_notify.context = NULL;590}591592if (handler_type & ACPI_DEVICE_NOTIFY) {593acpi_gbl_device_notify.node = NULL;594acpi_gbl_device_notify.handler = NULL;595acpi_gbl_device_notify.context = NULL;596}597}598599/* All Other Objects */600601else {602/* Notifies allowed on this object? */603604if (!acpi_ev_is_notify_object(node)) {605status = AE_TYPE;606goto unlock_and_exit;607}608609/* Check for an existing internal object */610611obj_desc = acpi_ns_get_attached_object(node);612if (!obj_desc) {613status = AE_NOT_EXIST;614goto unlock_and_exit;615}616617/* Object exists - make sure there's an existing handler */618619if (handler_type & ACPI_SYSTEM_NOTIFY) {620struct acpi_object_notify_handler *handler_obj;621struct acpi_object_notify_handler *parent_obj;622623notify_obj = obj_desc->common_notify.system_notify;624if (!notify_obj) {625status = AE_NOT_EXIST;626goto unlock_and_exit;627}628629handler_obj = ¬ify_obj->notify;630parent_obj = NULL;631while (handler_obj->handler != handler) {632if (handler_obj->next) {633parent_obj = handler_obj;634handler_obj = handler_obj->next;635} else {636break;637}638}639640if (handler_obj->handler != handler) {641status = AE_BAD_PARAMETER;642goto unlock_and_exit;643}644645/*646* Remove the handler. There are three possible cases.647* First, we may need to remove a non-embedded object.648* Second, we may need to remove the embedded object's649* handler data, while non-embedded objects exist.650* Finally, we may need to remove the embedded object651* entirely along with its container.652*/653if (parent_obj) {654/* Non-embedded object is being removed. */655parent_obj->next = handler_obj->next;656ACPI_FREE(handler_obj);657} else if (notify_obj->notify.next) {658/*659* The handler matches the embedded object, but660* there are more handler objects in the list.661* Replace the embedded object's data with the662* first next object's data and remove that663* object.664*/665parent_obj = ¬ify_obj->notify;666handler_obj = notify_obj->notify.next;667*parent_obj = *handler_obj;668ACPI_FREE(handler_obj);669} else {670/* No more handler objects in the list. */671obj_desc->common_notify.system_notify = NULL;672acpi_ut_remove_reference(notify_obj);673}674}675676if (handler_type & ACPI_DEVICE_NOTIFY) {677notify_obj = obj_desc->common_notify.device_notify;678if (!notify_obj) {679status = AE_NOT_EXIST;680goto unlock_and_exit;681}682683if (notify_obj->notify.handler != handler) {684status = AE_BAD_PARAMETER;685goto unlock_and_exit;686}687688/* Remove the handler */689obj_desc->common_notify.device_notify = NULL;690acpi_ut_remove_reference(notify_obj);691}692}693694unlock_and_exit:695(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);696exit:697if (ACPI_FAILURE(status))698ACPI_EXCEPTION((AE_INFO, status, "Removing notify handler"));699return_ACPI_STATUS(status);700}701702ACPI_EXPORT_SYMBOL(acpi_remove_notify_handler)703704/*******************************************************************************705*706* FUNCTION: acpi_install_gpe_handler707*708* PARAMETERS: gpe_device - Namespace node for the GPE (NULL for FADT709* defined GPEs)710* gpe_number - The GPE number within the GPE block711* Type - Whether this GPE should be treated as an712* edge- or level-triggered interrupt.713* Address - Address of the handler714* Context - Value passed to the handler on each GPE715*716* RETURN: Status717*718* DESCRIPTION: Install a handler for a General Purpose Event.719*720******************************************************************************/721acpi_status722acpi_install_gpe_handler(acpi_handle gpe_device,723u32 gpe_number,724u32 type, acpi_gpe_handler address, void *context)725{726struct acpi_gpe_event_info *gpe_event_info;727struct acpi_gpe_handler_info *handler;728acpi_status status;729acpi_cpu_flags flags;730731ACPI_FUNCTION_TRACE(acpi_install_gpe_handler);732733/* Parameter validation */734735if ((!address) || (type & ~ACPI_GPE_XRUPT_TYPE_MASK)) {736return_ACPI_STATUS(AE_BAD_PARAMETER);737}738739status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);740if (ACPI_FAILURE(status)) {741return_ACPI_STATUS(status);742}743744/* Allocate memory for the handler object */745746handler = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_gpe_handler_info));747if (!handler) {748status = AE_NO_MEMORY;749goto unlock_and_exit;750}751752flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);753754/* Ensure that we have a valid GPE number */755756gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);757if (!gpe_event_info) {758status = AE_BAD_PARAMETER;759goto free_and_exit;760}761762/* Make sure that there isn't a handler there already */763764if ((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) ==765ACPI_GPE_DISPATCH_HANDLER) {766status = AE_ALREADY_EXISTS;767goto free_and_exit;768}769770/* Allocate and init handler object */771772handler->address = address;773handler->context = context;774handler->method_node = gpe_event_info->dispatch.method_node;775handler->original_flags = gpe_event_info->flags &776(ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK);777778/*779* If the GPE is associated with a method, it might have been enabled780* automatically during initialization, in which case it has to be781* disabled now to avoid spurious execution of the handler.782*/783784if ((handler->original_flags & ACPI_GPE_DISPATCH_METHOD)785&& gpe_event_info->runtime_count) {786handler->originally_enabled = 1;787(void)acpi_ev_remove_gpe_reference(gpe_event_info);788}789790/* Install the handler */791792gpe_event_info->dispatch.handler = handler;793794/* Setup up dispatch flags to indicate handler (vs. method) */795796gpe_event_info->flags &=797~(ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK);798gpe_event_info->flags |= (u8) (type | ACPI_GPE_DISPATCH_HANDLER);799800acpi_os_release_lock(acpi_gbl_gpe_lock, flags);801802unlock_and_exit:803(void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);804return_ACPI_STATUS(status);805806free_and_exit:807acpi_os_release_lock(acpi_gbl_gpe_lock, flags);808ACPI_FREE(handler);809goto unlock_and_exit;810}811812ACPI_EXPORT_SYMBOL(acpi_install_gpe_handler)813814/*******************************************************************************815*816* FUNCTION: acpi_remove_gpe_handler817*818* PARAMETERS: gpe_device - Namespace node for the GPE (NULL for FADT819* defined GPEs)820* gpe_number - The event to remove a handler821* Address - Address of the handler822*823* RETURN: Status824*825* DESCRIPTION: Remove a handler for a General Purpose acpi_event.826*827******************************************************************************/828acpi_status829acpi_remove_gpe_handler(acpi_handle gpe_device,830u32 gpe_number, acpi_gpe_handler address)831{832struct acpi_gpe_event_info *gpe_event_info;833struct acpi_gpe_handler_info *handler;834acpi_status status;835acpi_cpu_flags flags;836837ACPI_FUNCTION_TRACE(acpi_remove_gpe_handler);838839/* Parameter validation */840841if (!address) {842return_ACPI_STATUS(AE_BAD_PARAMETER);843}844845/* Make sure all deferred tasks are completed */846847acpi_os_wait_events_complete(NULL);848849status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);850if (ACPI_FAILURE(status)) {851return_ACPI_STATUS(status);852}853854flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);855856/* Ensure that we have a valid GPE number */857858gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);859if (!gpe_event_info) {860status = AE_BAD_PARAMETER;861goto unlock_and_exit;862}863864/* Make sure that a handler is indeed installed */865866if ((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) !=867ACPI_GPE_DISPATCH_HANDLER) {868status = AE_NOT_EXIST;869goto unlock_and_exit;870}871872/* Make sure that the installed handler is the same */873874if (gpe_event_info->dispatch.handler->address != address) {875status = AE_BAD_PARAMETER;876goto unlock_and_exit;877}878879/* Remove the handler */880881handler = gpe_event_info->dispatch.handler;882883/* Restore Method node (if any), set dispatch flags */884885gpe_event_info->dispatch.method_node = handler->method_node;886gpe_event_info->flags &=887~(ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK);888gpe_event_info->flags |= handler->original_flags;889890/*891* If the GPE was previously associated with a method and it was892* enabled, it should be enabled at this point to restore the893* post-initialization configuration.894*/895896if ((handler->original_flags & ACPI_GPE_DISPATCH_METHOD)897&& handler->originally_enabled)898(void)acpi_ev_add_gpe_reference(gpe_event_info);899900/* Now we can free the handler object */901902ACPI_FREE(handler);903904unlock_and_exit:905acpi_os_release_lock(acpi_gbl_gpe_lock, flags);906907(void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);908return_ACPI_STATUS(status);909}910911ACPI_EXPORT_SYMBOL(acpi_remove_gpe_handler)912913/*******************************************************************************914*915* FUNCTION: acpi_acquire_global_lock916*917* PARAMETERS: Timeout - How long the caller is willing to wait918* Handle - Where the handle to the lock is returned919* (if acquired)920*921* RETURN: Status922*923* DESCRIPTION: Acquire the ACPI Global Lock924*925* Note: Allows callers with the same thread ID to acquire the global lock926* multiple times. In other words, externally, the behavior of the global lock927* is identical to an AML mutex. On the first acquire, a new handle is928* returned. On any subsequent calls to acquire by the same thread, the same929* handle is returned.930*931******************************************************************************/932acpi_status acpi_acquire_global_lock(u16 timeout, u32 * handle)933{934acpi_status status;935936if (!handle) {937return (AE_BAD_PARAMETER);938}939940/* Must lock interpreter to prevent race conditions */941942acpi_ex_enter_interpreter();943944status = acpi_ex_acquire_mutex_object(timeout,945acpi_gbl_global_lock_mutex,946acpi_os_get_thread_id());947948if (ACPI_SUCCESS(status)) {949950/* Return the global lock handle (updated in acpi_ev_acquire_global_lock) */951952*handle = acpi_gbl_global_lock_handle;953}954955acpi_ex_exit_interpreter();956return (status);957}958959ACPI_EXPORT_SYMBOL(acpi_acquire_global_lock)960961/*******************************************************************************962*963* FUNCTION: acpi_release_global_lock964*965* PARAMETERS: Handle - Returned from acpi_acquire_global_lock966*967* RETURN: Status968*969* DESCRIPTION: Release the ACPI Global Lock. The handle must be valid.970*971******************************************************************************/972acpi_status acpi_release_global_lock(u32 handle)973{974acpi_status status;975976if (!handle || (handle != acpi_gbl_global_lock_handle)) {977return (AE_NOT_ACQUIRED);978}979980status = acpi_ex_release_mutex_object(acpi_gbl_global_lock_mutex);981return (status);982}983984ACPI_EXPORT_SYMBOL(acpi_release_global_lock)985986987