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