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