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