1 /****************************************************************************** 2 * 3 * Module Name: evxfgpe - External Interfaces for General Purpose Events (GPEs) 4 * 5 *****************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2012, Intel Corp. 9 * All rights reserved. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions, and the following disclaimer, 16 * without modification. 17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer 18 * substantially similar to the "NO WARRANTY" disclaimer below 19 * ("Disclaimer") and any redistribution must be conditioned upon 20 * including a substantially similar Disclaimer requirement for further 21 * binary redistribution. 22 * 3. Neither the names of the above-listed copyright holders nor the names 23 * of any contributors may be used to endorse or promote products derived 24 * from this software without specific prior written permission. 25 * 26 * Alternatively, this software may be distributed under the terms of the 27 * GNU General Public License ("GPL") version 2 as published by the Free 28 * Software Foundation. 29 * 30 * NO WARRANTY 31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 41 * POSSIBILITY OF SUCH DAMAGES. 42 */ 43 44 #include <linux/export.h> 45 #include <acpi/acpi.h> 46 #include "accommon.h" 47 #include "acevents.h" 48 #include "acnamesp.h" 49 50 #define _COMPONENT ACPI_EVENTS 51 ACPI_MODULE_NAME("evxfgpe") 52 53 #if (!ACPI_REDUCED_HARDWARE) /* Entire module */ 54 /****************************************************************************** 55 * 56 * FUNCTION: acpi_update_all_gpes 57 * 58 * PARAMETERS: None 59 * 60 * RETURN: Status 61 * 62 * DESCRIPTION: Complete GPE initialization and enable all GPEs that have 63 * associated _Lxx or _Exx methods and are not pointed to by any 64 * device _PRW methods (this indicates that these GPEs are 65 * generally intended for system or device wakeup. Such GPEs 66 * have to be enabled directly when the devices whose _PRW 67 * methods point to them are set up for wakeup signaling.) 68 * 69 * NOTE: Should be called after any GPEs are added to the system. Primarily, 70 * after the system _PRW methods have been run, but also after a GPE Block 71 * Device has been added or if any new GPE methods have been added via a 72 * dynamic table load. 73 * 74 ******************************************************************************/ 75 76 acpi_status acpi_update_all_gpes(void) 77 { 78 acpi_status status; 79 80 ACPI_FUNCTION_TRACE(acpi_update_all_gpes); 81 82 status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS); 83 if (ACPI_FAILURE(status)) { 84 return_ACPI_STATUS(status); 85 } 86 87 if (acpi_gbl_all_gpes_initialized) { 88 goto unlock_and_exit; 89 } 90 91 status = acpi_ev_walk_gpe_list(acpi_ev_initialize_gpe_block, NULL); 92 if (ACPI_SUCCESS(status)) { 93 acpi_gbl_all_gpes_initialized = TRUE; 94 } 95 96 unlock_and_exit: 97 (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); 98 99 return_ACPI_STATUS(status); 100 } 101 102 ACPI_EXPORT_SYMBOL(acpi_update_all_gpes) 103 104 /******************************************************************************* 105 * 106 * FUNCTION: acpi_enable_gpe 107 * 108 * PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1 109 * gpe_number - GPE level within the GPE block 110 * 111 * RETURN: Status 112 * 113 * DESCRIPTION: Add a reference to a GPE. On the first reference, the GPE is 114 * hardware-enabled. 115 * 116 ******************************************************************************/ 117 118 acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number) 119 { 120 acpi_status status = AE_BAD_PARAMETER; 121 struct acpi_gpe_event_info *gpe_event_info; 122 acpi_cpu_flags flags; 123 124 ACPI_FUNCTION_TRACE(acpi_enable_gpe); 125 126 flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); 127 128 /* Ensure that we have a valid GPE number */ 129 130 gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number); 131 if (gpe_event_info) { 132 status = acpi_ev_add_gpe_reference(gpe_event_info); 133 } 134 135 acpi_os_release_lock(acpi_gbl_gpe_lock, flags); 136 return_ACPI_STATUS(status); 137 } 138 ACPI_EXPORT_SYMBOL(acpi_enable_gpe) 139 140 /******************************************************************************* 141 * 142 * FUNCTION: acpi_disable_gpe 143 * 144 * PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1 145 * gpe_number - GPE level within the GPE block 146 * 147 * RETURN: Status 148 * 149 * DESCRIPTION: Remove a reference to a GPE. When the last reference is 150 * removed, only then is the GPE disabled (for runtime GPEs), or 151 * the GPE mask bit disabled (for wake GPEs) 152 * 153 ******************************************************************************/ 154 155 acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number) 156 { 157 acpi_status status = AE_BAD_PARAMETER; 158 struct acpi_gpe_event_info *gpe_event_info; 159 acpi_cpu_flags flags; 160 161 ACPI_FUNCTION_TRACE(acpi_disable_gpe); 162 163 flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); 164 165 /* Ensure that we have a valid GPE number */ 166 167 gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number); 168 if (gpe_event_info) { 169 status = acpi_ev_remove_gpe_reference(gpe_event_info) ; 170 } 171 172 acpi_os_release_lock(acpi_gbl_gpe_lock, flags); 173 return_ACPI_STATUS(status); 174 } 175 ACPI_EXPORT_SYMBOL(acpi_disable_gpe) 176 177 178 /******************************************************************************* 179 * 180 * FUNCTION: acpi_setup_gpe_for_wake 181 * 182 * PARAMETERS: wake_device - Device associated with the GPE (via _PRW) 183 * gpe_device - Parent GPE Device. NULL for GPE0/GPE1 184 * gpe_number - GPE level within the GPE block 185 * 186 * RETURN: Status 187 * 188 * DESCRIPTION: Mark a GPE as having the ability to wake the system. This 189 * interface is intended to be used as the host executes the 190 * _PRW methods (Power Resources for Wake) in the system tables. 191 * Each _PRW appears under a Device Object (The wake_device), and 192 * contains the info for the wake GPE associated with the 193 * wake_device. 194 * 195 ******************************************************************************/ 196 acpi_status 197 acpi_setup_gpe_for_wake(acpi_handle wake_device, 198 acpi_handle gpe_device, u32 gpe_number) 199 { 200 acpi_status status; 201 struct acpi_gpe_event_info *gpe_event_info; 202 struct acpi_namespace_node *device_node; 203 struct acpi_gpe_notify_info *notify; 204 struct acpi_gpe_notify_info *new_notify; 205 acpi_cpu_flags flags; 206 207 ACPI_FUNCTION_TRACE(acpi_setup_gpe_for_wake); 208 209 /* Parameter Validation */ 210 211 if (!wake_device) { 212 /* 213 * By forcing wake_device to be valid, we automatically enable the 214 * implicit notify feature on all hosts. 215 */ 216 return_ACPI_STATUS(AE_BAD_PARAMETER); 217 } 218 219 /* Handle root object case */ 220 221 if (wake_device == ACPI_ROOT_OBJECT) { 222 device_node = acpi_gbl_root_node; 223 } else { 224 device_node = 225 ACPI_CAST_PTR(struct acpi_namespace_node, wake_device); 226 } 227 228 /* Validate WakeDevice is of type Device */ 229 230 if (device_node->type != ACPI_TYPE_DEVICE) { 231 return_ACPI_STATUS (AE_BAD_PARAMETER); 232 } 233 234 /* 235 * Allocate a new notify object up front, in case it is needed. 236 * Memory allocation while holding a spinlock is a big no-no 237 * on some hosts. 238 */ 239 new_notify = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_gpe_notify_info)); 240 if (!new_notify) { 241 return_ACPI_STATUS(AE_NO_MEMORY); 242 } 243 244 flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); 245 246 /* Ensure that we have a valid GPE number */ 247 248 gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number); 249 if (!gpe_event_info) { 250 status = AE_BAD_PARAMETER; 251 goto unlock_and_exit; 252 } 253 254 /* 255 * If there is no method or handler for this GPE, then the 256 * wake_device will be notified whenever this GPE fires. This is 257 * known as an "implicit notify". Note: The GPE is assumed to be 258 * level-triggered (for windows compatibility). 259 */ 260 if ((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) == 261 ACPI_GPE_DISPATCH_NONE) { 262 /* 263 * This is the first device for implicit notify on this GPE. 264 * Just set the flags here, and enter the NOTIFY block below. 265 */ 266 gpe_event_info->flags = 267 (ACPI_GPE_DISPATCH_NOTIFY | ACPI_GPE_LEVEL_TRIGGERED); 268 } 269 270 /* 271 * If we already have an implicit notify on this GPE, add 272 * this device to the notify list. 273 */ 274 if ((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) == 275 ACPI_GPE_DISPATCH_NOTIFY) { 276 277 /* Ensure that the device is not already in the list */ 278 279 notify = gpe_event_info->dispatch.notify_list; 280 while (notify) { 281 if (notify->device_node == device_node) { 282 status = AE_ALREADY_EXISTS; 283 goto unlock_and_exit; 284 } 285 notify = notify->next; 286 } 287 288 /* Add this device to the notify list for this GPE */ 289 290 new_notify->device_node = device_node; 291 new_notify->next = gpe_event_info->dispatch.notify_list; 292 gpe_event_info->dispatch.notify_list = new_notify; 293 new_notify = NULL; 294 } 295 296 /* Mark the GPE as a possible wake event */ 297 298 gpe_event_info->flags |= ACPI_GPE_CAN_WAKE; 299 status = AE_OK; 300 301 unlock_and_exit: 302 acpi_os_release_lock(acpi_gbl_gpe_lock, flags); 303 304 /* Delete the notify object if it was not used above */ 305 306 if (new_notify) { 307 ACPI_FREE(new_notify); 308 } 309 return_ACPI_STATUS(status); 310 } 311 ACPI_EXPORT_SYMBOL(acpi_setup_gpe_for_wake) 312 313 /******************************************************************************* 314 * 315 * FUNCTION: acpi_set_gpe_wake_mask 316 * 317 * PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1 318 * gpe_number - GPE level within the GPE block 319 * action - Enable or Disable 320 * 321 * RETURN: Status 322 * 323 * DESCRIPTION: Set or clear the GPE's wakeup enable mask bit. The GPE must 324 * already be marked as a WAKE GPE. 325 * 326 ******************************************************************************/ 327 328 acpi_status 329 acpi_set_gpe_wake_mask(acpi_handle gpe_device, u32 gpe_number, u8 action) 330 { 331 acpi_status status = AE_OK; 332 struct acpi_gpe_event_info *gpe_event_info; 333 struct acpi_gpe_register_info *gpe_register_info; 334 acpi_cpu_flags flags; 335 u32 register_bit; 336 337 ACPI_FUNCTION_TRACE(acpi_set_gpe_wake_mask); 338 339 flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); 340 341 /* 342 * Ensure that we have a valid GPE number and that this GPE is in 343 * fact a wake GPE 344 */ 345 gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number); 346 if (!gpe_event_info) { 347 status = AE_BAD_PARAMETER; 348 goto unlock_and_exit; 349 } 350 351 if (!(gpe_event_info->flags & ACPI_GPE_CAN_WAKE)) { 352 status = AE_TYPE; 353 goto unlock_and_exit; 354 } 355 356 gpe_register_info = gpe_event_info->register_info; 357 if (!gpe_register_info) { 358 status = AE_NOT_EXIST; 359 goto unlock_and_exit; 360 } 361 362 register_bit = acpi_hw_get_gpe_register_bit(gpe_event_info); 363 364 /* Perform the action */ 365 366 switch (action) { 367 case ACPI_GPE_ENABLE: 368 ACPI_SET_BIT(gpe_register_info->enable_for_wake, 369 (u8)register_bit); 370 break; 371 372 case ACPI_GPE_DISABLE: 373 ACPI_CLEAR_BIT(gpe_register_info->enable_for_wake, 374 (u8)register_bit); 375 break; 376 377 default: 378 ACPI_ERROR((AE_INFO, "%u, Invalid action", action)); 379 status = AE_BAD_PARAMETER; 380 break; 381 } 382 383 unlock_and_exit: 384 acpi_os_release_lock(acpi_gbl_gpe_lock, flags); 385 return_ACPI_STATUS(status); 386 } 387 388 ACPI_EXPORT_SYMBOL(acpi_set_gpe_wake_mask) 389 390 /******************************************************************************* 391 * 392 * FUNCTION: acpi_clear_gpe 393 * 394 * PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1 395 * gpe_number - GPE level within the GPE block 396 * 397 * RETURN: Status 398 * 399 * DESCRIPTION: Clear an ACPI event (general purpose) 400 * 401 ******************************************************************************/ 402 acpi_status acpi_clear_gpe(acpi_handle gpe_device, u32 gpe_number) 403 { 404 acpi_status status = AE_OK; 405 struct acpi_gpe_event_info *gpe_event_info; 406 acpi_cpu_flags flags; 407 408 ACPI_FUNCTION_TRACE(acpi_clear_gpe); 409 410 flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); 411 412 /* Ensure that we have a valid GPE number */ 413 414 gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number); 415 if (!gpe_event_info) { 416 status = AE_BAD_PARAMETER; 417 goto unlock_and_exit; 418 } 419 420 status = acpi_hw_clear_gpe(gpe_event_info); 421 422 unlock_and_exit: 423 acpi_os_release_lock(acpi_gbl_gpe_lock, flags); 424 return_ACPI_STATUS(status); 425 } 426 427 ACPI_EXPORT_SYMBOL(acpi_clear_gpe) 428 429 /******************************************************************************* 430 * 431 * FUNCTION: acpi_get_gpe_status 432 * 433 * PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1 434 * gpe_number - GPE level within the GPE block 435 * event_status - Where the current status of the event will 436 * be returned 437 * 438 * RETURN: Status 439 * 440 * DESCRIPTION: Get the current status of a GPE (signalled/not_signalled) 441 * 442 ******************************************************************************/ 443 acpi_status 444 acpi_get_gpe_status(acpi_handle gpe_device, 445 u32 gpe_number, acpi_event_status *event_status) 446 { 447 acpi_status status = AE_OK; 448 struct acpi_gpe_event_info *gpe_event_info; 449 acpi_cpu_flags flags; 450 451 ACPI_FUNCTION_TRACE(acpi_get_gpe_status); 452 453 flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); 454 455 /* Ensure that we have a valid GPE number */ 456 457 gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number); 458 if (!gpe_event_info) { 459 status = AE_BAD_PARAMETER; 460 goto unlock_and_exit; 461 } 462 463 /* Obtain status on the requested GPE number */ 464 465 status = acpi_hw_get_gpe_status(gpe_event_info, event_status); 466 467 if (gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) 468 *event_status |= ACPI_EVENT_FLAG_HANDLE; 469 470 unlock_and_exit: 471 acpi_os_release_lock(acpi_gbl_gpe_lock, flags); 472 return_ACPI_STATUS(status); 473 } 474 475 ACPI_EXPORT_SYMBOL(acpi_get_gpe_status) 476 477 /****************************************************************************** 478 * 479 * FUNCTION: acpi_disable_all_gpes 480 * 481 * PARAMETERS: None 482 * 483 * RETURN: Status 484 * 485 * DESCRIPTION: Disable and clear all GPEs in all GPE blocks 486 * 487 ******************************************************************************/ 488 489 acpi_status acpi_disable_all_gpes(void) 490 { 491 acpi_status status; 492 493 ACPI_FUNCTION_TRACE(acpi_disable_all_gpes); 494 495 status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS); 496 if (ACPI_FAILURE(status)) { 497 return_ACPI_STATUS(status); 498 } 499 500 status = acpi_hw_disable_all_gpes(); 501 (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); 502 503 return_ACPI_STATUS(status); 504 } 505 506 ACPI_EXPORT_SYMBOL(acpi_disable_all_gpes) 507 508 /****************************************************************************** 509 * 510 * FUNCTION: acpi_enable_all_runtime_gpes 511 * 512 * PARAMETERS: None 513 * 514 * RETURN: Status 515 * 516 * DESCRIPTION: Enable all "runtime" GPEs, in all GPE blocks 517 * 518 ******************************************************************************/ 519 520 acpi_status acpi_enable_all_runtime_gpes(void) 521 { 522 acpi_status status; 523 524 ACPI_FUNCTION_TRACE(acpi_enable_all_runtime_gpes); 525 526 status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS); 527 if (ACPI_FAILURE(status)) { 528 return_ACPI_STATUS(status); 529 } 530 531 status = acpi_hw_enable_all_runtime_gpes(); 532 (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); 533 534 return_ACPI_STATUS(status); 535 } 536 537 ACPI_EXPORT_SYMBOL(acpi_enable_all_runtime_gpes) 538 539 /******************************************************************************* 540 * 541 * FUNCTION: acpi_install_gpe_block 542 * 543 * PARAMETERS: gpe_device - Handle to the parent GPE Block Device 544 * gpe_block_address - Address and space_ID 545 * register_count - Number of GPE register pairs in the block 546 * interrupt_number - H/W interrupt for the block 547 * 548 * RETURN: Status 549 * 550 * DESCRIPTION: Create and Install a block of GPE registers. The GPEs are not 551 * enabled here. 552 * 553 ******************************************************************************/ 554 acpi_status 555 acpi_install_gpe_block(acpi_handle gpe_device, 556 struct acpi_generic_address *gpe_block_address, 557 u32 register_count, u32 interrupt_number) 558 { 559 acpi_status status; 560 union acpi_operand_object *obj_desc; 561 struct acpi_namespace_node *node; 562 struct acpi_gpe_block_info *gpe_block; 563 564 ACPI_FUNCTION_TRACE(acpi_install_gpe_block); 565 566 if ((!gpe_device) || (!gpe_block_address) || (!register_count)) { 567 return_ACPI_STATUS(AE_BAD_PARAMETER); 568 } 569 570 status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); 571 if (ACPI_FAILURE(status)) { 572 return_ACPI_STATUS(status); 573 } 574 575 node = acpi_ns_validate_handle(gpe_device); 576 if (!node) { 577 status = AE_BAD_PARAMETER; 578 goto unlock_and_exit; 579 } 580 581 /* 582 * For user-installed GPE Block Devices, the gpe_block_base_number 583 * is always zero 584 */ 585 status = 586 acpi_ev_create_gpe_block(node, gpe_block_address, register_count, 0, 587 interrupt_number, &gpe_block); 588 if (ACPI_FAILURE(status)) { 589 goto unlock_and_exit; 590 } 591 592 /* Install block in the device_object attached to the node */ 593 594 obj_desc = acpi_ns_get_attached_object(node); 595 if (!obj_desc) { 596 597 /* 598 * No object, create a new one (Device nodes do not always have 599 * an attached object) 600 */ 601 obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_DEVICE); 602 if (!obj_desc) { 603 status = AE_NO_MEMORY; 604 goto unlock_and_exit; 605 } 606 607 status = 608 acpi_ns_attach_object(node, obj_desc, ACPI_TYPE_DEVICE); 609 610 /* Remove local reference to the object */ 611 612 acpi_ut_remove_reference(obj_desc); 613 614 if (ACPI_FAILURE(status)) { 615 goto unlock_and_exit; 616 } 617 } 618 619 /* Now install the GPE block in the device_object */ 620 621 obj_desc->device.gpe_block = gpe_block; 622 623 unlock_and_exit: 624 (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); 625 return_ACPI_STATUS(status); 626 } 627 628 ACPI_EXPORT_SYMBOL(acpi_install_gpe_block) 629 630 /******************************************************************************* 631 * 632 * FUNCTION: acpi_remove_gpe_block 633 * 634 * PARAMETERS: gpe_device - Handle to the parent GPE Block Device 635 * 636 * RETURN: Status 637 * 638 * DESCRIPTION: Remove a previously installed block of GPE registers 639 * 640 ******************************************************************************/ 641 acpi_status acpi_remove_gpe_block(acpi_handle gpe_device) 642 { 643 union acpi_operand_object *obj_desc; 644 acpi_status status; 645 struct acpi_namespace_node *node; 646 647 ACPI_FUNCTION_TRACE(acpi_remove_gpe_block); 648 649 if (!gpe_device) { 650 return_ACPI_STATUS(AE_BAD_PARAMETER); 651 } 652 653 status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); 654 if (ACPI_FAILURE(status)) { 655 return_ACPI_STATUS(status); 656 } 657 658 node = acpi_ns_validate_handle(gpe_device); 659 if (!node) { 660 status = AE_BAD_PARAMETER; 661 goto unlock_and_exit; 662 } 663 664 /* Get the device_object attached to the node */ 665 666 obj_desc = acpi_ns_get_attached_object(node); 667 if (!obj_desc || !obj_desc->device.gpe_block) { 668 return_ACPI_STATUS(AE_NULL_OBJECT); 669 } 670 671 /* Delete the GPE block (but not the device_object) */ 672 673 status = acpi_ev_delete_gpe_block(obj_desc->device.gpe_block); 674 if (ACPI_SUCCESS(status)) { 675 obj_desc->device.gpe_block = NULL; 676 } 677 678 unlock_and_exit: 679 (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); 680 return_ACPI_STATUS(status); 681 } 682 683 ACPI_EXPORT_SYMBOL(acpi_remove_gpe_block) 684 685 /******************************************************************************* 686 * 687 * FUNCTION: acpi_get_gpe_device 688 * 689 * PARAMETERS: index - System GPE index (0-current_gpe_count) 690 * gpe_device - Where the parent GPE Device is returned 691 * 692 * RETURN: Status 693 * 694 * DESCRIPTION: Obtain the GPE device associated with the input index. A NULL 695 * gpe device indicates that the gpe number is contained in one of 696 * the FADT-defined gpe blocks. Otherwise, the GPE block device. 697 * 698 ******************************************************************************/ 699 acpi_status acpi_get_gpe_device(u32 index, acpi_handle * gpe_device) 700 { 701 struct acpi_gpe_device_info info; 702 acpi_status status; 703 704 ACPI_FUNCTION_TRACE(acpi_get_gpe_device); 705 706 if (!gpe_device) { 707 return_ACPI_STATUS(AE_BAD_PARAMETER); 708 } 709 710 if (index >= acpi_current_gpe_count) { 711 return_ACPI_STATUS(AE_NOT_EXIST); 712 } 713 714 /* Setup and walk the GPE list */ 715 716 info.index = index; 717 info.status = AE_NOT_EXIST; 718 info.gpe_device = NULL; 719 info.next_block_base_index = 0; 720 721 status = acpi_ev_walk_gpe_list(acpi_ev_get_gpe_device, &info); 722 if (ACPI_FAILURE(status)) { 723 return_ACPI_STATUS(status); 724 } 725 726 *gpe_device = ACPI_CAST_PTR(acpi_handle, info.gpe_device); 727 return_ACPI_STATUS(info.status); 728 } 729 730 ACPI_EXPORT_SYMBOL(acpi_get_gpe_device) 731 #endif /* !ACPI_REDUCED_HARDWARE */ 732