1 /****************************************************************************** 2 * 3 * Module Name: evxfgpe - External Interfaces for General Purpose Events (GPEs) 4 * 5 *****************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2013, 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 176 ACPI_EXPORT_SYMBOL(acpi_disable_gpe) 177 178 179 /******************************************************************************* 180 * 181 * FUNCTION: acpi_setup_gpe_for_wake 182 * 183 * PARAMETERS: wake_device - Device associated with the GPE (via _PRW) 184 * gpe_device - Parent GPE Device. NULL for GPE0/GPE1 185 * gpe_number - GPE level within the GPE block 186 * 187 * RETURN: Status 188 * 189 * DESCRIPTION: Mark a GPE as having the ability to wake the system. This 190 * interface is intended to be used as the host executes the 191 * _PRW methods (Power Resources for Wake) in the system tables. 192 * Each _PRW appears under a Device Object (The wake_device), and 193 * contains the info for the wake GPE associated with the 194 * wake_device. 195 * 196 ******************************************************************************/ 197 acpi_status 198 acpi_setup_gpe_for_wake(acpi_handle wake_device, 199 acpi_handle gpe_device, u32 gpe_number) 200 { 201 acpi_status status; 202 struct acpi_gpe_event_info *gpe_event_info; 203 struct acpi_namespace_node *device_node; 204 struct acpi_gpe_notify_info *notify; 205 struct acpi_gpe_notify_info *new_notify; 206 acpi_cpu_flags flags; 207 208 ACPI_FUNCTION_TRACE(acpi_setup_gpe_for_wake); 209 210 /* Parameter Validation */ 211 212 if (!wake_device) { 213 /* 214 * By forcing wake_device to be valid, we automatically enable the 215 * implicit notify feature on all hosts. 216 */ 217 return_ACPI_STATUS(AE_BAD_PARAMETER); 218 } 219 220 /* Handle root object case */ 221 222 if (wake_device == ACPI_ROOT_OBJECT) { 223 device_node = acpi_gbl_root_node; 224 } else { 225 device_node = 226 ACPI_CAST_PTR(struct acpi_namespace_node, wake_device); 227 } 228 229 /* Validate wake_device is of type Device */ 230 231 if (device_node->type != ACPI_TYPE_DEVICE) { 232 return_ACPI_STATUS (AE_BAD_PARAMETER); 233 } 234 235 /* 236 * Allocate a new notify object up front, in case it is needed. 237 * Memory allocation while holding a spinlock is a big no-no 238 * on some hosts. 239 */ 240 new_notify = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_gpe_notify_info)); 241 if (!new_notify) { 242 return_ACPI_STATUS(AE_NO_MEMORY); 243 } 244 245 flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); 246 247 /* Ensure that we have a valid GPE number */ 248 249 gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number); 250 if (!gpe_event_info) { 251 status = AE_BAD_PARAMETER; 252 goto unlock_and_exit; 253 } 254 255 /* 256 * If there is no method or handler for this GPE, then the 257 * wake_device will be notified whenever this GPE fires. This is 258 * known as an "implicit notify". Note: The GPE is assumed to be 259 * level-triggered (for windows compatibility). 260 */ 261 if ((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) == 262 ACPI_GPE_DISPATCH_NONE) { 263 /* 264 * This is the first device for implicit notify on this GPE. 265 * Just set the flags here, and enter the NOTIFY block below. 266 */ 267 gpe_event_info->flags = 268 (ACPI_GPE_DISPATCH_NOTIFY | ACPI_GPE_LEVEL_TRIGGERED); 269 } 270 271 /* 272 * If we already have an implicit notify on this GPE, add 273 * this device to the notify list. 274 */ 275 if ((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) == 276 ACPI_GPE_DISPATCH_NOTIFY) { 277 278 /* Ensure that the device is not already in the list */ 279 280 notify = gpe_event_info->dispatch.notify_list; 281 while (notify) { 282 if (notify->device_node == device_node) { 283 status = AE_ALREADY_EXISTS; 284 goto unlock_and_exit; 285 } 286 notify = notify->next; 287 } 288 289 /* Add this device to the notify list for this GPE */ 290 291 new_notify->device_node = device_node; 292 new_notify->next = gpe_event_info->dispatch.notify_list; 293 gpe_event_info->dispatch.notify_list = new_notify; 294 new_notify = NULL; 295 } 296 297 /* Mark the GPE as a possible wake event */ 298 299 gpe_event_info->flags |= ACPI_GPE_CAN_WAKE; 300 status = AE_OK; 301 302 unlock_and_exit: 303 acpi_os_release_lock(acpi_gbl_gpe_lock, flags); 304 305 /* Delete the notify object if it was not used above */ 306 307 if (new_notify) { 308 ACPI_FREE(new_notify); 309 } 310 return_ACPI_STATUS(status); 311 } 312 ACPI_EXPORT_SYMBOL(acpi_setup_gpe_for_wake) 313 314 /******************************************************************************* 315 * 316 * FUNCTION: acpi_set_gpe_wake_mask 317 * 318 * PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1 319 * gpe_number - GPE level within the GPE block 320 * action - Enable or Disable 321 * 322 * RETURN: Status 323 * 324 * DESCRIPTION: Set or clear the GPE's wakeup enable mask bit. The GPE must 325 * already be marked as a WAKE GPE. 326 * 327 ******************************************************************************/ 328 329 acpi_status 330 acpi_set_gpe_wake_mask(acpi_handle gpe_device, u32 gpe_number, u8 action) 331 { 332 acpi_status status = AE_OK; 333 struct acpi_gpe_event_info *gpe_event_info; 334 struct acpi_gpe_register_info *gpe_register_info; 335 acpi_cpu_flags flags; 336 u32 register_bit; 337 338 ACPI_FUNCTION_TRACE(acpi_set_gpe_wake_mask); 339 340 flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); 341 342 /* 343 * Ensure that we have a valid GPE number and that this GPE is in 344 * fact a wake GPE 345 */ 346 gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number); 347 if (!gpe_event_info) { 348 status = AE_BAD_PARAMETER; 349 goto unlock_and_exit; 350 } 351 352 if (!(gpe_event_info->flags & ACPI_GPE_CAN_WAKE)) { 353 status = AE_TYPE; 354 goto unlock_and_exit; 355 } 356 357 gpe_register_info = gpe_event_info->register_info; 358 if (!gpe_register_info) { 359 status = AE_NOT_EXIST; 360 goto unlock_and_exit; 361 } 362 363 register_bit = acpi_hw_get_gpe_register_bit(gpe_event_info); 364 365 /* Perform the action */ 366 367 switch (action) { 368 case ACPI_GPE_ENABLE: 369 ACPI_SET_BIT(gpe_register_info->enable_for_wake, 370 (u8)register_bit); 371 break; 372 373 case ACPI_GPE_DISABLE: 374 ACPI_CLEAR_BIT(gpe_register_info->enable_for_wake, 375 (u8)register_bit); 376 break; 377 378 default: 379 ACPI_ERROR((AE_INFO, "%u, Invalid action", action)); 380 status = AE_BAD_PARAMETER; 381 break; 382 } 383 384 unlock_and_exit: 385 acpi_os_release_lock(acpi_gbl_gpe_lock, flags); 386 return_ACPI_STATUS(status); 387 } 388 389 ACPI_EXPORT_SYMBOL(acpi_set_gpe_wake_mask) 390 391 /******************************************************************************* 392 * 393 * FUNCTION: acpi_clear_gpe 394 * 395 * PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1 396 * gpe_number - GPE level within the GPE block 397 * 398 * RETURN: Status 399 * 400 * DESCRIPTION: Clear an ACPI event (general purpose) 401 * 402 ******************************************************************************/ 403 acpi_status acpi_clear_gpe(acpi_handle gpe_device, u32 gpe_number) 404 { 405 acpi_status status = AE_OK; 406 struct acpi_gpe_event_info *gpe_event_info; 407 acpi_cpu_flags flags; 408 409 ACPI_FUNCTION_TRACE(acpi_clear_gpe); 410 411 flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); 412 413 /* Ensure that we have a valid GPE number */ 414 415 gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number); 416 if (!gpe_event_info) { 417 status = AE_BAD_PARAMETER; 418 goto unlock_and_exit; 419 } 420 421 status = acpi_hw_clear_gpe(gpe_event_info); 422 423 unlock_and_exit: 424 acpi_os_release_lock(acpi_gbl_gpe_lock, flags); 425 return_ACPI_STATUS(status); 426 } 427 428 ACPI_EXPORT_SYMBOL(acpi_clear_gpe) 429 430 /******************************************************************************* 431 * 432 * FUNCTION: acpi_get_gpe_status 433 * 434 * PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1 435 * gpe_number - GPE level within the GPE block 436 * event_status - Where the current status of the event 437 * will be returned 438 * 439 * RETURN: Status 440 * 441 * DESCRIPTION: Get the current status of a GPE (signalled/not_signalled) 442 * 443 ******************************************************************************/ 444 acpi_status 445 acpi_get_gpe_status(acpi_handle gpe_device, 446 u32 gpe_number, acpi_event_status *event_status) 447 { 448 acpi_status status = AE_OK; 449 struct acpi_gpe_event_info *gpe_event_info; 450 acpi_cpu_flags flags; 451 452 ACPI_FUNCTION_TRACE(acpi_get_gpe_status); 453 454 flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); 455 456 /* Ensure that we have a valid GPE number */ 457 458 gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number); 459 if (!gpe_event_info) { 460 status = AE_BAD_PARAMETER; 461 goto unlock_and_exit; 462 } 463 464 /* Obtain status on the requested GPE number */ 465 466 status = acpi_hw_get_gpe_status(gpe_event_info, event_status); 467 468 if (gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) 469 *event_status |= ACPI_EVENT_FLAG_HANDLE; 470 471 unlock_and_exit: 472 acpi_os_release_lock(acpi_gbl_gpe_lock, flags); 473 return_ACPI_STATUS(status); 474 } 475 476 ACPI_EXPORT_SYMBOL(acpi_get_gpe_status) 477 478 /****************************************************************************** 479 * 480 * FUNCTION: acpi_disable_all_gpes 481 * 482 * PARAMETERS: None 483 * 484 * RETURN: Status 485 * 486 * DESCRIPTION: Disable and clear all GPEs in all GPE blocks 487 * 488 ******************************************************************************/ 489 490 acpi_status acpi_disable_all_gpes(void) 491 { 492 acpi_status status; 493 494 ACPI_FUNCTION_TRACE(acpi_disable_all_gpes); 495 496 status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS); 497 if (ACPI_FAILURE(status)) { 498 return_ACPI_STATUS(status); 499 } 500 501 status = acpi_hw_disable_all_gpes(); 502 (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); 503 504 return_ACPI_STATUS(status); 505 } 506 507 ACPI_EXPORT_SYMBOL(acpi_disable_all_gpes) 508 509 /****************************************************************************** 510 * 511 * FUNCTION: acpi_enable_all_runtime_gpes 512 * 513 * PARAMETERS: None 514 * 515 * RETURN: Status 516 * 517 * DESCRIPTION: Enable all "runtime" GPEs, in all GPE blocks 518 * 519 ******************************************************************************/ 520 521 acpi_status acpi_enable_all_runtime_gpes(void) 522 { 523 acpi_status status; 524 525 ACPI_FUNCTION_TRACE(acpi_enable_all_runtime_gpes); 526 527 status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS); 528 if (ACPI_FAILURE(status)) { 529 return_ACPI_STATUS(status); 530 } 531 532 status = acpi_hw_enable_all_runtime_gpes(); 533 (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); 534 535 return_ACPI_STATUS(status); 536 } 537 538 ACPI_EXPORT_SYMBOL(acpi_enable_all_runtime_gpes) 539 540 /******************************************************************************* 541 * 542 * FUNCTION: acpi_install_gpe_block 543 * 544 * PARAMETERS: gpe_device - Handle to the parent GPE Block Device 545 * gpe_block_address - Address and space_ID 546 * register_count - Number of GPE register pairs in the block 547 * interrupt_number - H/W interrupt for the block 548 * 549 * RETURN: Status 550 * 551 * DESCRIPTION: Create and Install a block of GPE registers. The GPEs are not 552 * enabled here. 553 * 554 ******************************************************************************/ 555 acpi_status 556 acpi_install_gpe_block(acpi_handle gpe_device, 557 struct acpi_generic_address *gpe_block_address, 558 u32 register_count, u32 interrupt_number) 559 { 560 acpi_status status; 561 union acpi_operand_object *obj_desc; 562 struct acpi_namespace_node *node; 563 struct acpi_gpe_block_info *gpe_block; 564 565 ACPI_FUNCTION_TRACE(acpi_install_gpe_block); 566 567 if ((!gpe_device) || (!gpe_block_address) || (!register_count)) { 568 return_ACPI_STATUS(AE_BAD_PARAMETER); 569 } 570 571 status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); 572 if (ACPI_FAILURE(status)) { 573 return_ACPI_STATUS(status); 574 } 575 576 node = acpi_ns_validate_handle(gpe_device); 577 if (!node) { 578 status = AE_BAD_PARAMETER; 579 goto unlock_and_exit; 580 } 581 582 /* 583 * For user-installed GPE Block Devices, the gpe_block_base_number 584 * is always zero 585 */ 586 status = 587 acpi_ev_create_gpe_block(node, gpe_block_address, register_count, 0, 588 interrupt_number, &gpe_block); 589 if (ACPI_FAILURE(status)) { 590 goto unlock_and_exit; 591 } 592 593 /* Install block in the device_object attached to the node */ 594 595 obj_desc = acpi_ns_get_attached_object(node); 596 if (!obj_desc) { 597 598 /* 599 * No object, create a new one (Device nodes do not always have 600 * an attached object) 601 */ 602 obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_DEVICE); 603 if (!obj_desc) { 604 status = AE_NO_MEMORY; 605 goto unlock_and_exit; 606 } 607 608 status = 609 acpi_ns_attach_object(node, obj_desc, ACPI_TYPE_DEVICE); 610 611 /* Remove local reference to the object */ 612 613 acpi_ut_remove_reference(obj_desc); 614 615 if (ACPI_FAILURE(status)) { 616 goto unlock_and_exit; 617 } 618 } 619 620 /* Now install the GPE block in the device_object */ 621 622 obj_desc->device.gpe_block = gpe_block; 623 624 unlock_and_exit: 625 (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); 626 return_ACPI_STATUS(status); 627 } 628 629 ACPI_EXPORT_SYMBOL(acpi_install_gpe_block) 630 631 /******************************************************************************* 632 * 633 * FUNCTION: acpi_remove_gpe_block 634 * 635 * PARAMETERS: gpe_device - Handle to the parent GPE Block Device 636 * 637 * RETURN: Status 638 * 639 * DESCRIPTION: Remove a previously installed block of GPE registers 640 * 641 ******************************************************************************/ 642 acpi_status acpi_remove_gpe_block(acpi_handle gpe_device) 643 { 644 union acpi_operand_object *obj_desc; 645 acpi_status status; 646 struct acpi_namespace_node *node; 647 648 ACPI_FUNCTION_TRACE(acpi_remove_gpe_block); 649 650 if (!gpe_device) { 651 return_ACPI_STATUS(AE_BAD_PARAMETER); 652 } 653 654 status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); 655 if (ACPI_FAILURE(status)) { 656 return_ACPI_STATUS(status); 657 } 658 659 node = acpi_ns_validate_handle(gpe_device); 660 if (!node) { 661 status = AE_BAD_PARAMETER; 662 goto unlock_and_exit; 663 } 664 665 /* Get the device_object attached to the node */ 666 667 obj_desc = acpi_ns_get_attached_object(node); 668 if (!obj_desc || !obj_desc->device.gpe_block) { 669 return_ACPI_STATUS(AE_NULL_OBJECT); 670 } 671 672 /* Delete the GPE block (but not the device_object) */ 673 674 status = acpi_ev_delete_gpe_block(obj_desc->device.gpe_block); 675 if (ACPI_SUCCESS(status)) { 676 obj_desc->device.gpe_block = NULL; 677 } 678 679 unlock_and_exit: 680 (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); 681 return_ACPI_STATUS(status); 682 } 683 684 ACPI_EXPORT_SYMBOL(acpi_remove_gpe_block) 685 686 /******************************************************************************* 687 * 688 * FUNCTION: acpi_get_gpe_device 689 * 690 * PARAMETERS: index - System GPE index (0-current_gpe_count) 691 * gpe_device - Where the parent GPE Device is returned 692 * 693 * RETURN: Status 694 * 695 * DESCRIPTION: Obtain the GPE device associated with the input index. A NULL 696 * gpe device indicates that the gpe number is contained in one of 697 * the FADT-defined gpe blocks. Otherwise, the GPE block device. 698 * 699 ******************************************************************************/ 700 acpi_status acpi_get_gpe_device(u32 index, acpi_handle * gpe_device) 701 { 702 struct acpi_gpe_device_info info; 703 acpi_status status; 704 705 ACPI_FUNCTION_TRACE(acpi_get_gpe_device); 706 707 if (!gpe_device) { 708 return_ACPI_STATUS(AE_BAD_PARAMETER); 709 } 710 711 if (index >= acpi_current_gpe_count) { 712 return_ACPI_STATUS(AE_NOT_EXIST); 713 } 714 715 /* Setup and walk the GPE list */ 716 717 info.index = index; 718 info.status = AE_NOT_EXIST; 719 info.gpe_device = NULL; 720 info.next_block_base_index = 0; 721 722 status = acpi_ev_walk_gpe_list(acpi_ev_get_gpe_device, &info); 723 if (ACPI_FAILURE(status)) { 724 return_ACPI_STATUS(status); 725 } 726 727 *gpe_device = ACPI_CAST_PTR(acpi_handle, info.gpe_device); 728 return_ACPI_STATUS(info.status); 729 } 730 731 ACPI_EXPORT_SYMBOL(acpi_get_gpe_device) 732 #endif /* !ACPI_REDUCED_HARDWARE */ 733