cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

evxface.c (30630B)


      1// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
      2/******************************************************************************
      3 *
      4 * Module Name: evxface - External interfaces for ACPI events
      5 *
      6 * Copyright (C) 2000 - 2022, Intel Corp.
      7 *
      8 *****************************************************************************/
      9
     10#define EXPORT_ACPI_INTERFACES
     11
     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_EVENTS
     19ACPI_MODULE_NAME("evxface")
     20#if (!ACPI_REDUCED_HARDWARE)
     21/* Local prototypes */
     22static acpi_status
     23acpi_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#endif
     30
     31
     32/*******************************************************************************
     33 *
     34 * FUNCTION:    acpi_install_notify_handler
     35 *
     36 * PARAMETERS:  device          - The device for which notifies will be handled
     37 *              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 Device
     41 *              handler         - Address of the handler
     42 *              context         - Value passed to the handler on each GPE
     43 *
     44 * RETURN:      Status
     45 *
     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 each
     50 *              type of notify (System/Device). Device/Thermal/Processor objects
     51 *              may have one device notify handler, and multiple system notify
     52 *              handlers.
     53 *
     54 ******************************************************************************/
     55
     56acpi_status
     57acpi_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 the
     85	 * caller wishes to receive notifications for all objects. Note that
     86	 * 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 target
    108	 * object. Note that only certain object types are allowed to
    109	 * 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_handler
    197 *
    198 * PARAMETERS:  device          - The device for which the handler is installed
    199 *              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 Device
    203 *              handler         - Address of the handler
    204 *
    205 * RETURN:      Status
    206 *
    207 * DESCRIPTION: Remove a handler for notifies on an ACPI device
    208 *
    209 ******************************************************************************/
    210acpi_status
    211acpi_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_handler
    336 *
    337 * PARAMETERS:  handler         - Pointer to the handler function for the
    338 *                                event
    339 *
    340 * RETURN:      Status
    341 *
    342 * DESCRIPTION: Saves the pointer to the handler function
    343 *
    344 ******************************************************************************/
    345#ifdef ACPI_FUTURE_USAGE
    346acpi_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#endif
    375
    376#if (!ACPI_REDUCED_HARDWARE)
    377/*******************************************************************************
    378 *
    379 * FUNCTION:    acpi_install_sci_handler
    380 *
    381 * PARAMETERS:  address             - Address of the handler
    382 *              context             - Value passed to the handler on each SCI
    383 *
    384 * RETURN:      Status
    385 *
    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_handler
    455 *
    456 * PARAMETERS:  address             - Address of the handler
    457 *
    458 * RETURN:      Status
    459 *
    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_handler
    521 *
    522 * PARAMETERS:  handler         - Pointer to the global event handler function
    523 *              context         - Value passed to the handler on each event
    524 *
    525 * RETURN:      Status
    526 *
    527 * DESCRIPTION: Saves the pointer to the handler function. The global handler
    528 *              is invoked upon each incoming GPE and Fixed Event. It is
    529 *              invoked at interrupt level at the time of the event dispatch.
    530 *              Can be used to update event counters, etc.
    531 *
    532 ******************************************************************************/
    533acpi_status
    534acpi_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_handler
    571 *
    572 * PARAMETERS:  event           - Event type to enable.
    573 *              handler         - Pointer to the handler function for the
    574 *                                event
    575 *              context         - Value passed to the handler on each GPE
    576 *
    577 * RETURN:      Status
    578 *
    579 * DESCRIPTION: Saves the pointer to the handler function and then enables the
    580 *              event.
    581 *
    582 ******************************************************************************/
    583acpi_status
    584acpi_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_handler
    643 *
    644 * PARAMETERS:  event           - Event type to disable.
    645 *              handler         - Address of the handler
    646 *
    647 * RETURN:      Status
    648 *
    649 * DESCRIPTION: Disables the event and unregisters the event handler.
    650 *
    651 ******************************************************************************/
    652acpi_status
    653acpi_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_handler
    698 *
    699 * PARAMETERS:  gpe_device      - Namespace node for the GPE (NULL for FADT
    700 *                                defined GPEs)
    701 *              gpe_number      - The GPE number within the GPE block
    702 *              type            - Whether this GPE should be treated as an
    703 *                                edge- or level-triggered interrupt.
    704 *              is_raw_handler  - Whether this GPE should be handled using
    705 *                                the special GPE handler mode.
    706 *              address         - Address of the handler
    707 *              context         - Value passed to the handler on each GPE
    708 *
    709 * RETURN:      Status
    710 *
    711 * DESCRIPTION: Internal function to install a handler for a General Purpose
    712 *              Event.
    713 *
    714 ******************************************************************************/
    715static acpi_status
    716acpi_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 enabled
    777	 * automatically during initialization, in which case it has to be
    778	 * 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_handler
    824 *
    825 * PARAMETERS:  gpe_device      - Namespace node for the GPE (NULL for FADT
    826 *                                defined GPEs)
    827 *              gpe_number      - The GPE number within the GPE block
    828 *              type            - Whether this GPE should be treated as an
    829 *                                edge- or level-triggered interrupt.
    830 *              address         - Address of the handler
    831 *              context         - Value passed to the handler on each GPE
    832 *
    833 * RETURN:      Status
    834 *
    835 * DESCRIPTION: Install a handler for a General Purpose Event.
    836 *
    837 ******************************************************************************/
    838
    839acpi_status
    840acpi_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_handler
    859 *
    860 * PARAMETERS:  gpe_device      - Namespace node for the GPE (NULL for FADT
    861 *                                defined GPEs)
    862 *              gpe_number      - The GPE number within the GPE block
    863 *              type            - Whether this GPE should be treated as an
    864 *                                edge- or level-triggered interrupt.
    865 *              address         - Address of the handler
    866 *              context         - Value passed to the handler on each GPE
    867 *
    868 * RETURN:      Status
    869 *
    870 * DESCRIPTION: Install a handler for a General Purpose Event.
    871 *
    872 ******************************************************************************/
    873acpi_status
    874acpi_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_handler
    893 *
    894 * PARAMETERS:  gpe_device      - Namespace node for the GPE (NULL for FADT
    895 *                                defined GPEs)
    896 *              gpe_number      - The event to remove a handler
    897 *              address         - Address of the handler
    898 *
    899 * RETURN:      Status
    900 *
    901 * DESCRIPTION: Remove a handler for a General Purpose acpi_event.
    902 *
    903 ******************************************************************************/
    904acpi_status
    905acpi_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 was
    967	 * enabled, it should be enabled at this point to restore the
    968	 * 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_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 ******************************************************************************/
   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_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 ******************************************************************************/
   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 */