brintos

brintos / linux-shallow public Read only

0
0
Text · 29.9 KiB · 24fa643 Raw
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