brintos

brintos / linux-shallow public Read only

0
0
Text · 29.6 KiB · 4eeeb3b Raw
1050 lines · c
1// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.02/******************************************************************************3 *4 * Module Name: evxfgpe - External Interfaces for General Purpose Events (GPEs)5 *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 "acevents.h"15#include "acnamesp.h"16 17#define _COMPONENT          ACPI_EVENTS18ACPI_MODULE_NAME("evxfgpe")19 20#if (!ACPI_REDUCED_HARDWARE)	/* Entire module */21/*******************************************************************************22 *23 * FUNCTION:    acpi_update_all_gpes24 *25 * PARAMETERS:  None26 *27 * RETURN:      Status28 *29 * DESCRIPTION: Complete GPE initialization and enable all GPEs that have30 *              associated _Lxx or _Exx methods and are not pointed to by any31 *              device _PRW methods (this indicates that these GPEs are32 *              generally intended for system or device wakeup. Such GPEs33 *              have to be enabled directly when the devices whose _PRW34 *              methods point to them are set up for wakeup signaling.)35 *36 * NOTE: Should be called after any GPEs are added to the system. Primarily,37 * after the system _PRW methods have been run, but also after a GPE Block38 * Device has been added or if any new GPE methods have been added via a39 * dynamic table load.40 *41 ******************************************************************************/42 43acpi_status acpi_update_all_gpes(void)44{45	acpi_status status;46	u8 is_polling_needed = FALSE;47 48	ACPI_FUNCTION_TRACE(acpi_update_all_gpes);49 50	status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);51	if (ACPI_FAILURE(status)) {52		return_ACPI_STATUS(status);53	}54 55	if (acpi_gbl_all_gpes_initialized) {56		goto unlock_and_exit;57	}58 59	status = acpi_ev_walk_gpe_list(acpi_ev_initialize_gpe_block,60				       &is_polling_needed);61	if (ACPI_SUCCESS(status)) {62		acpi_gbl_all_gpes_initialized = TRUE;63	}64 65unlock_and_exit:66	(void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);67 68	if (is_polling_needed && acpi_gbl_all_gpes_initialized) {69 70		/* Poll GPEs to handle already triggered events */71 72		acpi_ev_gpe_detect(acpi_gbl_gpe_xrupt_list_head);73	}74	return_ACPI_STATUS(status);75}76 77ACPI_EXPORT_SYMBOL(acpi_update_all_gpes)78 79/*******************************************************************************80 *81 * FUNCTION:    acpi_enable_gpe82 *83 * PARAMETERS:  gpe_device          - Parent GPE Device. NULL for GPE0/GPE184 *              gpe_number          - GPE level within the GPE block85 *86 * RETURN:      Status87 *88 * DESCRIPTION: Add a reference to a GPE. On the first reference, the GPE is89 *              hardware-enabled.90 *91 ******************************************************************************/92acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number)93{94	acpi_status status = AE_BAD_PARAMETER;95	struct acpi_gpe_event_info *gpe_event_info;96	acpi_cpu_flags flags;97 98	ACPI_FUNCTION_TRACE(acpi_enable_gpe);99 100	flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);101 102	/*103	 * Ensure that we have a valid GPE number and that there is some way104	 * of handling the GPE (handler or a GPE method). In other words, we105	 * won't allow a valid GPE to be enabled if there is no way to handle it.106	 */107	gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);108	if (gpe_event_info) {109		if (ACPI_GPE_DISPATCH_TYPE(gpe_event_info->flags) !=110		    ACPI_GPE_DISPATCH_NONE) {111			status = acpi_ev_add_gpe_reference(gpe_event_info, TRUE);112			if (ACPI_SUCCESS(status) &&113			    ACPI_GPE_IS_POLLING_NEEDED(gpe_event_info)) {114 115				/* Poll edge-triggered GPEs to handle existing events */116 117				acpi_os_release_lock(acpi_gbl_gpe_lock, flags);118				(void)acpi_ev_detect_gpe(gpe_device,119							 gpe_event_info,120							 gpe_number);121				flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);122			}123		} else {124			status = AE_NO_HANDLER;125		}126	}127 128	acpi_os_release_lock(acpi_gbl_gpe_lock, flags);129	return_ACPI_STATUS(status);130}131ACPI_EXPORT_SYMBOL(acpi_enable_gpe)132 133/*******************************************************************************134 *135 * FUNCTION:    acpi_disable_gpe136 *137 * PARAMETERS:  gpe_device      - Parent GPE Device. NULL for GPE0/GPE1138 *              gpe_number      - GPE level within the GPE block139 *140 * RETURN:      Status141 *142 * DESCRIPTION: Remove a reference to a GPE. When the last reference is143 *              removed, only then is the GPE disabled (for runtime GPEs), or144 *              the GPE mask bit disabled (for wake GPEs)145 *146 ******************************************************************************/147 148acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number)149{150	acpi_status status = AE_BAD_PARAMETER;151	struct acpi_gpe_event_info *gpe_event_info;152	acpi_cpu_flags flags;153 154	ACPI_FUNCTION_TRACE(acpi_disable_gpe);155 156	flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);157 158	/* Ensure that we have a valid GPE number */159 160	gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);161	if (gpe_event_info) {162		status = acpi_ev_remove_gpe_reference(gpe_event_info) ;163	}164 165	acpi_os_release_lock(acpi_gbl_gpe_lock, flags);166	return_ACPI_STATUS(status);167}168 169ACPI_EXPORT_SYMBOL(acpi_disable_gpe)170 171/*******************************************************************************172 *173 * FUNCTION:    acpi_set_gpe174 *175 * PARAMETERS:  gpe_device          - Parent GPE Device. NULL for GPE0/GPE1176 *              gpe_number          - GPE level within the GPE block177 *              action              - ACPI_GPE_ENABLE or ACPI_GPE_DISABLE178 *179 * RETURN:      Status180 *181 * DESCRIPTION: Enable or disable an individual GPE. This function bypasses182 *              the reference count mechanism used in the acpi_enable_gpe(),183 *              acpi_disable_gpe() interfaces.184 *              This API is typically used by the GPE raw handler mode driver185 *              to switch between the polling mode and the interrupt mode after186 *              the driver has enabled the GPE.187 *              The APIs should be invoked in this order:188 *               acpi_enable_gpe()            <- Ensure the reference count > 0189 *               acpi_set_gpe(ACPI_GPE_DISABLE) <- Enter polling mode190 *               acpi_set_gpe(ACPI_GPE_ENABLE) <- Leave polling mode191 *               acpi_disable_gpe()           <- Decrease the reference count192 *193 * Note: If a GPE is shared by 2 silicon components, then both the drivers194 *       should support GPE polling mode or disabling the GPE for long period195 *       for one driver may break the other. So use it with care since all196 *       firmware _Lxx/_Exx handlers currently rely on the GPE interrupt mode.197 *198 ******************************************************************************/199acpi_status acpi_set_gpe(acpi_handle gpe_device, u32 gpe_number, u8 action)200{201	struct acpi_gpe_event_info *gpe_event_info;202	acpi_status status;203	acpi_cpu_flags flags;204 205	ACPI_FUNCTION_TRACE(acpi_set_gpe);206 207	flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);208 209	/* Ensure that we have a valid GPE number */210 211	gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);212	if (!gpe_event_info) {213		status = AE_BAD_PARAMETER;214		goto unlock_and_exit;215	}216 217	/* Perform the action */218 219	switch (action) {220	case ACPI_GPE_ENABLE:221 222		status = acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_ENABLE);223		gpe_event_info->disable_for_dispatch = FALSE;224		break;225 226	case ACPI_GPE_DISABLE:227 228		status = acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_DISABLE);229		gpe_event_info->disable_for_dispatch = TRUE;230		break;231 232	default:233 234		status = AE_BAD_PARAMETER;235		break;236	}237 238unlock_and_exit:239	acpi_os_release_lock(acpi_gbl_gpe_lock, flags);240	return_ACPI_STATUS(status);241}242 243ACPI_EXPORT_SYMBOL(acpi_set_gpe)244 245/*******************************************************************************246 *247 * FUNCTION:    acpi_mask_gpe248 *249 * PARAMETERS:  gpe_device          - Parent GPE Device. NULL for GPE0/GPE1250 *              gpe_number          - GPE level within the GPE block251 *              is_masked           - Whether the GPE is masked or not252 *253 * RETURN:      Status254 *255 * DESCRIPTION: Unconditionally mask/unmask the an individual GPE, ex., to256 *              prevent a GPE flooding.257 *258 ******************************************************************************/259acpi_status acpi_mask_gpe(acpi_handle gpe_device, u32 gpe_number, u8 is_masked)260{261	struct acpi_gpe_event_info *gpe_event_info;262	acpi_status status;263	acpi_cpu_flags flags;264 265	ACPI_FUNCTION_TRACE(acpi_mask_gpe);266 267	flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);268 269	/* Ensure that we have a valid GPE number */270 271	gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);272	if (!gpe_event_info) {273		status = AE_BAD_PARAMETER;274		goto unlock_and_exit;275	}276 277	status = acpi_ev_mask_gpe(gpe_event_info, is_masked);278 279unlock_and_exit:280	acpi_os_release_lock(acpi_gbl_gpe_lock, flags);281	return_ACPI_STATUS(status);282}283 284ACPI_EXPORT_SYMBOL(acpi_mask_gpe)285 286/*******************************************************************************287 *288 * FUNCTION:    acpi_mark_gpe_for_wake289 *290 * PARAMETERS:  gpe_device          - Parent GPE Device. NULL for GPE0/GPE1291 *              gpe_number          - GPE level within the GPE block292 *293 * RETURN:      Status294 *295 * DESCRIPTION: Mark a GPE as having the ability to wake the system. Simply296 *              sets the ACPI_GPE_CAN_WAKE flag.297 *298 * Some potential callers of acpi_setup_gpe_for_wake may know in advance that299 * there won't be any notify handlers installed for device wake notifications300 * from the given GPE (one example is a button GPE in Linux). For these cases,301 * acpi_mark_gpe_for_wake should be used instead of acpi_setup_gpe_for_wake.302 * This will set the ACPI_GPE_CAN_WAKE flag for the GPE without trying to303 * setup implicit wake notification for it (since there's no handler method).304 *305 ******************************************************************************/306acpi_status acpi_mark_gpe_for_wake(acpi_handle gpe_device, u32 gpe_number)307{308	struct acpi_gpe_event_info *gpe_event_info;309	acpi_status status = AE_BAD_PARAMETER;310	acpi_cpu_flags flags;311 312	ACPI_FUNCTION_TRACE(acpi_mark_gpe_for_wake);313 314	flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);315 316	/* Ensure that we have a valid GPE number */317 318	gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);319	if (gpe_event_info) {320 321		/* Mark the GPE as a possible wake event */322 323		gpe_event_info->flags |= ACPI_GPE_CAN_WAKE;324		status = AE_OK;325	}326 327	acpi_os_release_lock(acpi_gbl_gpe_lock, flags);328	return_ACPI_STATUS(status);329}330 331ACPI_EXPORT_SYMBOL(acpi_mark_gpe_for_wake)332 333/*******************************************************************************334 *335 * FUNCTION:    acpi_setup_gpe_for_wake336 *337 * PARAMETERS:  wake_device         - Device associated with the GPE (via _PRW)338 *              gpe_device          - Parent GPE Device. NULL for GPE0/GPE1339 *              gpe_number          - GPE level within the GPE block340 *341 * RETURN:      Status342 *343 * DESCRIPTION: Mark a GPE as having the ability to wake the system. This344 *              interface is intended to be used as the host executes the345 *              _PRW methods (Power Resources for Wake) in the system tables.346 *              Each _PRW appears under a Device Object (The wake_device), and347 *              contains the info for the wake GPE associated with the348 *              wake_device.349 *350 ******************************************************************************/351acpi_status352acpi_setup_gpe_for_wake(acpi_handle wake_device,353			acpi_handle gpe_device, u32 gpe_number)354{355	acpi_status status;356	struct acpi_gpe_event_info *gpe_event_info;357	struct acpi_namespace_node *device_node;358	struct acpi_gpe_notify_info *notify;359	struct acpi_gpe_notify_info *new_notify;360	acpi_cpu_flags flags;361 362	ACPI_FUNCTION_TRACE(acpi_setup_gpe_for_wake);363 364	/* Parameter Validation */365 366	if (!wake_device) {367		/*368		 * By forcing wake_device to be valid, we automatically enable the369		 * implicit notify feature on all hosts.370		 */371		return_ACPI_STATUS(AE_BAD_PARAMETER);372	}373 374	/* Handle root object case */375 376	if (wake_device == ACPI_ROOT_OBJECT) {377		device_node = acpi_gbl_root_node;378	} else {379		device_node =380		    ACPI_CAST_PTR(struct acpi_namespace_node, wake_device);381	}382 383	/* Validate wake_device is of type Device */384 385	if (device_node->type != ACPI_TYPE_DEVICE) {386		return_ACPI_STATUS (AE_BAD_PARAMETER);387	}388 389	/*390	 * Allocate a new notify object up front, in case it is needed.391	 * Memory allocation while holding a spinlock is a big no-no392	 * on some hosts.393	 */394	new_notify = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_gpe_notify_info));395	if (!new_notify) {396		return_ACPI_STATUS(AE_NO_MEMORY);397	}398 399	flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);400 401	/* Ensure that we have a valid GPE number */402 403	gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);404	if (!gpe_event_info) {405		status = AE_BAD_PARAMETER;406		goto unlock_and_exit;407	}408 409	/*410	 * If there is no method or handler for this GPE, then the411	 * wake_device will be notified whenever this GPE fires. This is412	 * known as an "implicit notify". Note: The GPE is assumed to be413	 * level-triggered (for windows compatibility).414	 */415	if (ACPI_GPE_DISPATCH_TYPE(gpe_event_info->flags) ==416	    ACPI_GPE_DISPATCH_NONE) {417		/*418		 * This is the first device for implicit notify on this GPE.419		 * Just set the flags here, and enter the NOTIFY block below.420		 */421		gpe_event_info->flags =422		    (ACPI_GPE_DISPATCH_NOTIFY | ACPI_GPE_LEVEL_TRIGGERED);423	} else if (gpe_event_info->flags & ACPI_GPE_AUTO_ENABLED) {424		/*425		 * A reference to this GPE has been added during the GPE block426		 * initialization, so drop it now to prevent the GPE from being427		 * permanently enabled and clear its ACPI_GPE_AUTO_ENABLED flag.428		 */429		(void)acpi_ev_remove_gpe_reference(gpe_event_info);430		gpe_event_info->flags &= ~ACPI_GPE_AUTO_ENABLED;431	}432 433	/*434	 * If we already have an implicit notify on this GPE, add435	 * this device to the notify list.436	 */437	if (ACPI_GPE_DISPATCH_TYPE(gpe_event_info->flags) ==438	    ACPI_GPE_DISPATCH_NOTIFY) {439 440		/* Ensure that the device is not already in the list */441 442		notify = gpe_event_info->dispatch.notify_list;443		while (notify) {444			if (notify->device_node == device_node) {445				status = AE_ALREADY_EXISTS;446				goto unlock_and_exit;447			}448			notify = notify->next;449		}450 451		/* Add this device to the notify list for this GPE */452 453		new_notify->device_node = device_node;454		new_notify->next = gpe_event_info->dispatch.notify_list;455		gpe_event_info->dispatch.notify_list = new_notify;456		new_notify = NULL;457	}458 459	/* Mark the GPE as a possible wake event */460 461	gpe_event_info->flags |= ACPI_GPE_CAN_WAKE;462	status = AE_OK;463 464unlock_and_exit:465	acpi_os_release_lock(acpi_gbl_gpe_lock, flags);466 467	/* Delete the notify object if it was not used above */468 469	if (new_notify) {470		ACPI_FREE(new_notify);471	}472	return_ACPI_STATUS(status);473}474ACPI_EXPORT_SYMBOL(acpi_setup_gpe_for_wake)475 476/*******************************************************************************477 *478 * FUNCTION:    acpi_set_gpe_wake_mask479 *480 * PARAMETERS:  gpe_device      - Parent GPE Device. NULL for GPE0/GPE1481 *              gpe_number      - GPE level within the GPE block482 *              action              - Enable or Disable483 *484 * RETURN:      Status485 *486 * DESCRIPTION: Set or clear the GPE's wakeup enable mask bit. The GPE must487 *              already be marked as a WAKE GPE.488 *489 ******************************************************************************/490 491acpi_status492acpi_set_gpe_wake_mask(acpi_handle gpe_device, u32 gpe_number, u8 action)493{494	acpi_status status = AE_OK;495	struct acpi_gpe_event_info *gpe_event_info;496	struct acpi_gpe_register_info *gpe_register_info;497	acpi_cpu_flags flags;498	u32 register_bit;499 500	ACPI_FUNCTION_TRACE(acpi_set_gpe_wake_mask);501 502	flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);503 504	/*505	 * Ensure that we have a valid GPE number and that this GPE is in506	 * fact a wake GPE507	 */508	gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);509	if (!gpe_event_info) {510		status = AE_BAD_PARAMETER;511		goto unlock_and_exit;512	}513 514	if (!(gpe_event_info->flags & ACPI_GPE_CAN_WAKE)) {515		status = AE_TYPE;516		goto unlock_and_exit;517	}518 519	gpe_register_info = gpe_event_info->register_info;520	if (!gpe_register_info) {521		status = AE_NOT_EXIST;522		goto unlock_and_exit;523	}524 525	register_bit = acpi_hw_get_gpe_register_bit(gpe_event_info);526 527	/* Perform the action */528 529	switch (action) {530	case ACPI_GPE_ENABLE:531 532		ACPI_SET_BIT(gpe_register_info->enable_for_wake,533			     (u8)register_bit);534		break;535 536	case ACPI_GPE_DISABLE:537 538		ACPI_CLEAR_BIT(gpe_register_info->enable_for_wake,539			       (u8)register_bit);540		break;541 542	default:543 544		ACPI_ERROR((AE_INFO, "%u, Invalid action", action));545		status = AE_BAD_PARAMETER;546		break;547	}548 549unlock_and_exit:550	acpi_os_release_lock(acpi_gbl_gpe_lock, flags);551	return_ACPI_STATUS(status);552}553 554ACPI_EXPORT_SYMBOL(acpi_set_gpe_wake_mask)555 556/*******************************************************************************557 *558 * FUNCTION:    acpi_clear_gpe559 *560 * PARAMETERS:  gpe_device      - Parent GPE Device. NULL for GPE0/GPE1561 *              gpe_number      - GPE level within the GPE block562 *563 * RETURN:      Status564 *565 * DESCRIPTION: Clear an ACPI event (general purpose)566 *567 ******************************************************************************/568acpi_status acpi_clear_gpe(acpi_handle gpe_device, u32 gpe_number)569{570	acpi_status status = AE_OK;571	struct acpi_gpe_event_info *gpe_event_info;572	acpi_cpu_flags flags;573 574	ACPI_FUNCTION_TRACE(acpi_clear_gpe);575 576	flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);577 578	/* Ensure that we have a valid GPE number */579 580	gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);581	if (!gpe_event_info) {582		status = AE_BAD_PARAMETER;583		goto unlock_and_exit;584	}585 586	status = acpi_hw_clear_gpe(gpe_event_info);587 588      unlock_and_exit:589	acpi_os_release_lock(acpi_gbl_gpe_lock, flags);590	return_ACPI_STATUS(status);591}592 593ACPI_EXPORT_SYMBOL(acpi_clear_gpe)594 595/*******************************************************************************596 *597 * FUNCTION:    acpi_get_gpe_status598 *599 * PARAMETERS:  gpe_device          - Parent GPE Device. NULL for GPE0/GPE1600 *              gpe_number          - GPE level within the GPE block601 *              event_status        - Where the current status of the event602 *                                    will be returned603 *604 * RETURN:      Status605 *606 * DESCRIPTION: Get the current status of a GPE (signalled/not_signalled)607 *608 ******************************************************************************/609acpi_status610acpi_get_gpe_status(acpi_handle gpe_device,611		    u32 gpe_number, acpi_event_status *event_status)612{613	acpi_status status = AE_OK;614	struct acpi_gpe_event_info *gpe_event_info;615	acpi_cpu_flags flags;616 617	ACPI_FUNCTION_TRACE(acpi_get_gpe_status);618 619	flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);620 621	/* Ensure that we have a valid GPE number */622 623	gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);624	if (!gpe_event_info) {625		status = AE_BAD_PARAMETER;626		goto unlock_and_exit;627	}628 629	/* Obtain status on the requested GPE number */630 631	status = acpi_hw_get_gpe_status(gpe_event_info, event_status);632 633unlock_and_exit:634	acpi_os_release_lock(acpi_gbl_gpe_lock, flags);635	return_ACPI_STATUS(status);636}637 638ACPI_EXPORT_SYMBOL(acpi_get_gpe_status)639 640/*******************************************************************************641 *642 * FUNCTION:    acpi_gispatch_gpe643 *644 * PARAMETERS:  gpe_device          - Parent GPE Device. NULL for GPE0/GPE1645 *              gpe_number          - GPE level within the GPE block646 *647 * RETURN:      INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED648 *649 * DESCRIPTION: Detect and dispatch a General Purpose Event to either a function650 *              (e.g. EC) or method (e.g. _Lxx/_Exx) handler.651 *652 ******************************************************************************/653u32 acpi_dispatch_gpe(acpi_handle gpe_device, u32 gpe_number)654{655	ACPI_FUNCTION_TRACE(acpi_dispatch_gpe);656 657	return acpi_ev_detect_gpe(gpe_device, NULL, gpe_number);658}659 660ACPI_EXPORT_SYMBOL(acpi_dispatch_gpe)661 662/*******************************************************************************663 *664 * FUNCTION:    acpi_finish_gpe665 *666 * PARAMETERS:  gpe_device          - Namespace node for the GPE Block667 *                                    (NULL for FADT defined GPEs)668 *              gpe_number          - GPE level within the GPE block669 *670 * RETURN:      Status671 *672 * DESCRIPTION: Clear and conditionally re-enable a GPE. This completes the GPE673 *              processing. Intended for use by asynchronous host-installed674 *              GPE handlers. The GPE is only re-enabled if the enable_for_run bit675 *              is set in the GPE info.676 *677 ******************************************************************************/678acpi_status acpi_finish_gpe(acpi_handle gpe_device, u32 gpe_number)679{680	struct acpi_gpe_event_info *gpe_event_info;681	acpi_status status;682	acpi_cpu_flags flags;683 684	ACPI_FUNCTION_TRACE(acpi_finish_gpe);685 686	flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);687 688	/* Ensure that we have a valid GPE number */689 690	gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);691	if (!gpe_event_info) {692		status = AE_BAD_PARAMETER;693		goto unlock_and_exit;694	}695 696	status = acpi_ev_finish_gpe(gpe_event_info);697 698unlock_and_exit:699	acpi_os_release_lock(acpi_gbl_gpe_lock, flags);700	return_ACPI_STATUS(status);701}702 703ACPI_EXPORT_SYMBOL(acpi_finish_gpe)704 705/******************************************************************************706 *707 * FUNCTION:    acpi_disable_all_gpes708 *709 * PARAMETERS:  None710 *711 * RETURN:      Status712 *713 * DESCRIPTION: Disable and clear all GPEs in all GPE blocks714 *715 ******************************************************************************/716 717acpi_status acpi_disable_all_gpes(void)718{719	acpi_status status;720 721	ACPI_FUNCTION_TRACE(acpi_disable_all_gpes);722 723	status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);724	if (ACPI_FAILURE(status)) {725		return_ACPI_STATUS(status);726	}727 728	status = acpi_hw_disable_all_gpes();729	(void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);730 731	return_ACPI_STATUS(status);732}733 734ACPI_EXPORT_SYMBOL(acpi_disable_all_gpes)735 736/******************************************************************************737 *738 * FUNCTION:    acpi_enable_all_runtime_gpes739 *740 * PARAMETERS:  None741 *742 * RETURN:      Status743 *744 * DESCRIPTION: Enable all "runtime" GPEs, in all GPE blocks745 *746 ******************************************************************************/747 748acpi_status acpi_enable_all_runtime_gpes(void)749{750	acpi_status status;751 752	ACPI_FUNCTION_TRACE(acpi_enable_all_runtime_gpes);753 754	status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);755	if (ACPI_FAILURE(status)) {756		return_ACPI_STATUS(status);757	}758 759	status = acpi_hw_enable_all_runtime_gpes();760	(void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);761 762	return_ACPI_STATUS(status);763}764 765ACPI_EXPORT_SYMBOL(acpi_enable_all_runtime_gpes)766 767/******************************************************************************768 *769 * FUNCTION:    acpi_enable_all_wakeup_gpes770 *771 * PARAMETERS:  None772 *773 * RETURN:      Status774 *775 * DESCRIPTION: Enable all "wakeup" GPEs and disable all of the other GPEs, in776 *              all GPE blocks.777 *778 ******************************************************************************/779acpi_status acpi_enable_all_wakeup_gpes(void)780{781	acpi_status status;782 783	ACPI_FUNCTION_TRACE(acpi_enable_all_wakeup_gpes);784 785	status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);786	if (ACPI_FAILURE(status)) {787		return_ACPI_STATUS(status);788	}789 790	status = acpi_hw_enable_all_wakeup_gpes();791	(void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);792 793	return_ACPI_STATUS(status);794}795 796ACPI_EXPORT_SYMBOL(acpi_enable_all_wakeup_gpes)797 798/******************************************************************************799 *800 * FUNCTION:    acpi_any_gpe_status_set801 *802 * PARAMETERS:  gpe_skip_number      - Number of the GPE to skip803 *804 * RETURN:      Whether or not the status bit is set for any GPE805 *806 * DESCRIPTION: Check the status bits of all enabled GPEs, except for the one807 *              represented by the "skip" argument, and return TRUE if any of808 *              them is set or FALSE otherwise.809 *810 ******************************************************************************/811u32 acpi_any_gpe_status_set(u32 gpe_skip_number)812{813	acpi_status status;814	acpi_handle gpe_device;815	u8 ret;816 817	ACPI_FUNCTION_TRACE(acpi_any_gpe_status_set);818 819	status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);820	if (ACPI_FAILURE(status)) {821		return (FALSE);822	}823 824	status = acpi_get_gpe_device(gpe_skip_number, &gpe_device);825	if (ACPI_FAILURE(status)) {826		gpe_device = NULL;827	}828 829	ret = acpi_hw_check_all_gpes(gpe_device, gpe_skip_number);830	(void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);831 832	return (ret);833}834 835ACPI_EXPORT_SYMBOL(acpi_any_gpe_status_set)836 837/*******************************************************************************838 *839 * FUNCTION:    acpi_install_gpe_block840 *841 * PARAMETERS:  gpe_device          - Handle to the parent GPE Block Device842 *              gpe_block_address   - Address and space_ID843 *              register_count      - Number of GPE register pairs in the block844 *              interrupt_number    - H/W interrupt for the block845 *846 * RETURN:      Status847 *848 * DESCRIPTION: Create and Install a block of GPE registers. The GPEs are not849 *              enabled here.850 *851 ******************************************************************************/852acpi_status853acpi_install_gpe_block(acpi_handle gpe_device,854		       struct acpi_generic_address *gpe_block_address,855		       u32 register_count, u32 interrupt_number)856{857	acpi_status status;858	union acpi_operand_object *obj_desc;859	struct acpi_namespace_node *node;860	struct acpi_gpe_block_info *gpe_block;861 862	ACPI_FUNCTION_TRACE(acpi_install_gpe_block);863 864	if ((!gpe_device) || (!gpe_block_address) || (!register_count)) {865		return_ACPI_STATUS(AE_BAD_PARAMETER);866	}867 868	status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);869	if (ACPI_FAILURE(status)) {870		return_ACPI_STATUS(status);871	}872 873	node = acpi_ns_validate_handle(gpe_device);874	if (!node) {875		status = AE_BAD_PARAMETER;876		goto unlock_and_exit;877	}878 879	/* Validate the parent device */880 881	if (node->type != ACPI_TYPE_DEVICE) {882		status = AE_TYPE;883		goto unlock_and_exit;884	}885 886	if (node->object) {887		status = AE_ALREADY_EXISTS;888		goto unlock_and_exit;889	}890 891	/*892	 * For user-installed GPE Block Devices, the gpe_block_base_number893	 * is always zero894	 */895	status = acpi_ev_create_gpe_block(node, gpe_block_address->address,896					  gpe_block_address->space_id,897					  register_count, 0, interrupt_number,898					  &gpe_block);899	if (ACPI_FAILURE(status)) {900		goto unlock_and_exit;901	}902 903	/* Install block in the device_object attached to the node */904 905	obj_desc = acpi_ns_get_attached_object(node);906	if (!obj_desc) {907 908		/*909		 * No object, create a new one (Device nodes do not always have910		 * an attached object)911		 */912		obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_DEVICE);913		if (!obj_desc) {914			status = AE_NO_MEMORY;915			goto unlock_and_exit;916		}917 918		status =919		    acpi_ns_attach_object(node, obj_desc, ACPI_TYPE_DEVICE);920 921		/* Remove local reference to the object */922 923		acpi_ut_remove_reference(obj_desc);924 925		if (ACPI_FAILURE(status)) {926			goto unlock_and_exit;927		}928	}929 930	/* Now install the GPE block in the device_object */931 932	obj_desc->device.gpe_block = gpe_block;933 934unlock_and_exit:935	(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);936	return_ACPI_STATUS(status);937}938 939ACPI_EXPORT_SYMBOL(acpi_install_gpe_block)940 941/*******************************************************************************942 *943 * FUNCTION:    acpi_remove_gpe_block944 *945 * PARAMETERS:  gpe_device          - Handle to the parent GPE Block Device946 *947 * RETURN:      Status948 *949 * DESCRIPTION: Remove a previously installed block of GPE registers950 *951 ******************************************************************************/952acpi_status acpi_remove_gpe_block(acpi_handle gpe_device)953{954	union acpi_operand_object *obj_desc;955	acpi_status status;956	struct acpi_namespace_node *node;957 958	ACPI_FUNCTION_TRACE(acpi_remove_gpe_block);959 960	if (!gpe_device) {961		return_ACPI_STATUS(AE_BAD_PARAMETER);962	}963 964	status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);965	if (ACPI_FAILURE(status)) {966		return_ACPI_STATUS(status);967	}968 969	node = acpi_ns_validate_handle(gpe_device);970	if (!node) {971		status = AE_BAD_PARAMETER;972		goto unlock_and_exit;973	}974 975	/* Validate the parent device */976 977	if (node->type != ACPI_TYPE_DEVICE) {978		status = AE_TYPE;979		goto unlock_and_exit;980	}981 982	/* Get the device_object attached to the node */983 984	obj_desc = acpi_ns_get_attached_object(node);985	if (!obj_desc || !obj_desc->device.gpe_block) {986		return_ACPI_STATUS(AE_NULL_OBJECT);987	}988 989	/* Delete the GPE block (but not the device_object) */990 991	status = acpi_ev_delete_gpe_block(obj_desc->device.gpe_block);992	if (ACPI_SUCCESS(status)) {993		obj_desc->device.gpe_block = NULL;994	}995 996unlock_and_exit:997	(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);998	return_ACPI_STATUS(status);999}1000 1001ACPI_EXPORT_SYMBOL(acpi_remove_gpe_block)1002 1003/*******************************************************************************1004 *1005 * FUNCTION:    acpi_get_gpe_device1006 *1007 * PARAMETERS:  index               - System GPE index (0-current_gpe_count)1008 *              gpe_device          - Where the parent GPE Device is returned1009 *1010 * RETURN:      Status1011 *1012 * DESCRIPTION: Obtain the GPE device associated with the input index. A NULL1013 *              gpe device indicates that the gpe number is contained in one of1014 *              the FADT-defined gpe blocks. Otherwise, the GPE block device.1015 *1016 ******************************************************************************/1017acpi_status acpi_get_gpe_device(u32 index, acpi_handle *gpe_device)1018{1019	struct acpi_gpe_device_info info;1020	acpi_status status;1021 1022	ACPI_FUNCTION_TRACE(acpi_get_gpe_device);1023 1024	if (!gpe_device) {1025		return_ACPI_STATUS(AE_BAD_PARAMETER);1026	}1027 1028	if (index >= acpi_current_gpe_count) {1029		return_ACPI_STATUS(AE_NOT_EXIST);1030	}1031 1032	/* Setup and walk the GPE list */1033 1034	info.index = index;1035	info.status = AE_NOT_EXIST;1036	info.gpe_device = NULL;1037	info.next_block_base_index = 0;1038 1039	status = acpi_ev_walk_gpe_list(acpi_ev_get_gpe_device, &info);1040	if (ACPI_FAILURE(status)) {1041		return_ACPI_STATUS(status);1042	}1043 1044	*gpe_device = ACPI_CAST_PTR(acpi_handle, info.gpe_device);1045	return_ACPI_STATUS(info.status);1046}1047 1048ACPI_EXPORT_SYMBOL(acpi_get_gpe_device)1049#endif				/* !ACPI_REDUCED_HARDWARE */1050