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