1 /****************************************************************************** 2 * 3 * Module Name: evxface - External interfaces for ACPI events 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 "acnamesp.h" 48 #include "acevents.h" 49 #include "acinterp.h" 50 51 #define _COMPONENT ACPI_EVENTS 52 ACPI_MODULE_NAME("evxface") 53 54 55 /******************************************************************************* 56 * 57 * FUNCTION: acpi_install_notify_handler 58 * 59 * PARAMETERS: device - The device for which notifies will be handled 60 * handler_type - The type of handler: 61 * ACPI_SYSTEM_NOTIFY: System Handler (00-7F) 62 * ACPI_DEVICE_NOTIFY: Device Handler (80-FF) 63 * ACPI_ALL_NOTIFY: Both System and Device 64 * handler - Address of the handler 65 * context - Value passed to the handler on each GPE 66 * 67 * RETURN: Status 68 * 69 * DESCRIPTION: Install a handler for notifications on an ACPI Device, 70 * thermal_zone, or Processor object. 71 * 72 * NOTES: The Root namespace object may have only one handler for each 73 * type of notify (System/Device). Device/Thermal/Processor objects 74 * may have one device notify handler, and multiple system notify 75 * handlers. 76 * 77 ******************************************************************************/ 78 acpi_status 79 acpi_install_notify_handler(acpi_handle device, 80 u32 handler_type, 81 acpi_notify_handler handler, void *context) 82 { 83 struct acpi_namespace_node *node = 84 ACPI_CAST_PTR(struct acpi_namespace_node, device); 85 union acpi_operand_object *obj_desc; 86 union acpi_operand_object *handler_obj; 87 acpi_status status; 88 u32 i; 89 90 ACPI_FUNCTION_TRACE(acpi_install_notify_handler); 91 92 /* Parameter validation */ 93 94 if ((!device) || (!handler) || (!handler_type) || 95 (handler_type > ACPI_MAX_NOTIFY_HANDLER_TYPE)) { 96 return_ACPI_STATUS(AE_BAD_PARAMETER); 97 } 98 99 status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); 100 if (ACPI_FAILURE(status)) { 101 return_ACPI_STATUS(status); 102 } 103 104 /* 105 * Root Object: 106 * Registering a notify handler on the root object indicates that the 107 * caller wishes to receive notifications for all objects. Note that 108 * only one global handler can be registered per notify type. 109 * Ensure that a handler is not already installed. 110 */ 111 if (device == ACPI_ROOT_OBJECT) { 112 for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++) { 113 if (handler_type & (i + 1)) { 114 if (acpi_gbl_global_notify[i].handler) { 115 status = AE_ALREADY_EXISTS; 116 goto unlock_and_exit; 117 } 118 119 acpi_gbl_global_notify[i].handler = handler; 120 acpi_gbl_global_notify[i].context = context; 121 } 122 } 123 124 goto unlock_and_exit; /* Global notify handler installed, all done */ 125 } 126 127 /* 128 * All Other Objects: 129 * Caller will only receive notifications specific to the target 130 * object. Note that only certain object types are allowed to 131 * receive notifications. 132 */ 133 134 /* Are Notifies allowed on this object? */ 135 136 if (!acpi_ev_is_notify_object(node)) { 137 status = AE_TYPE; 138 goto unlock_and_exit; 139 } 140 141 /* Check for an existing internal object, might not exist */ 142 143 obj_desc = acpi_ns_get_attached_object(node); 144 if (!obj_desc) { 145 146 /* Create a new object */ 147 148 obj_desc = acpi_ut_create_internal_object(node->type); 149 if (!obj_desc) { 150 status = AE_NO_MEMORY; 151 goto unlock_and_exit; 152 } 153 154 /* Attach new object to the Node, remove local reference */ 155 156 status = acpi_ns_attach_object(device, obj_desc, node->type); 157 acpi_ut_remove_reference(obj_desc); 158 if (ACPI_FAILURE(status)) { 159 goto unlock_and_exit; 160 } 161 } 162 163 /* Ensure that the handler is not already installed in the lists */ 164 165 for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++) { 166 if (handler_type & (i + 1)) { 167 handler_obj = obj_desc->common_notify.notify_list[i]; 168 while (handler_obj) { 169 if (handler_obj->notify.handler == handler) { 170 status = AE_ALREADY_EXISTS; 171 goto unlock_and_exit; 172 } 173 174 handler_obj = handler_obj->notify.next[i]; 175 } 176 } 177 } 178 179 /* Create and populate a new notify handler object */ 180 181 handler_obj = acpi_ut_create_internal_object(ACPI_TYPE_LOCAL_NOTIFY); 182 if (!handler_obj) { 183 status = AE_NO_MEMORY; 184 goto unlock_and_exit; 185 } 186 187 handler_obj->notify.node = node; 188 handler_obj->notify.handler_type = handler_type; 189 handler_obj->notify.handler = handler; 190 handler_obj->notify.context = context; 191 192 /* Install the handler at the list head(s) */ 193 194 for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++) { 195 if (handler_type & (i + 1)) { 196 handler_obj->notify.next[i] = 197 obj_desc->common_notify.notify_list[i]; 198 199 obj_desc->common_notify.notify_list[i] = handler_obj; 200 } 201 } 202 203 /* Add an extra reference if handler was installed in both lists */ 204 205 if (handler_type == ACPI_ALL_NOTIFY) { 206 acpi_ut_add_reference(handler_obj); 207 } 208 209 unlock_and_exit: 210 (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); 211 return_ACPI_STATUS(status); 212 } 213 214 ACPI_EXPORT_SYMBOL(acpi_install_notify_handler) 215 216 /******************************************************************************* 217 * 218 * FUNCTION: acpi_remove_notify_handler 219 * 220 * PARAMETERS: device - The device for which the handler is installed 221 * handler_type - The type of handler: 222 * ACPI_SYSTEM_NOTIFY: System Handler (00-7F) 223 * ACPI_DEVICE_NOTIFY: Device Handler (80-FF) 224 * ACPI_ALL_NOTIFY: Both System and Device 225 * handler - Address of the handler 226 * 227 * RETURN: Status 228 * 229 * DESCRIPTION: Remove a handler for notifies on an ACPI device 230 * 231 ******************************************************************************/ 232 acpi_status 233 acpi_remove_notify_handler(acpi_handle device, 234 u32 handler_type, acpi_notify_handler handler) 235 { 236 struct acpi_namespace_node *node = 237 ACPI_CAST_PTR(struct acpi_namespace_node, device); 238 union acpi_operand_object *obj_desc; 239 union acpi_operand_object *handler_obj; 240 union acpi_operand_object *previous_handler_obj; 241 acpi_status status; 242 u32 i; 243 244 ACPI_FUNCTION_TRACE(acpi_remove_notify_handler); 245 246 /* Parameter validation */ 247 248 if ((!device) || (!handler) || (!handler_type) || 249 (handler_type > ACPI_MAX_NOTIFY_HANDLER_TYPE)) { 250 return_ACPI_STATUS(AE_BAD_PARAMETER); 251 } 252 253 /* Make sure all deferred notify tasks are completed */ 254 255 acpi_os_wait_events_complete(); 256 257 status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); 258 if (ACPI_FAILURE(status)) { 259 return_ACPI_STATUS(status); 260 } 261 262 /* Root Object. Global handlers are removed here */ 263 264 if (device == ACPI_ROOT_OBJECT) { 265 for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++) { 266 if (handler_type & (i + 1)) { 267 if (!acpi_gbl_global_notify[i].handler || 268 (acpi_gbl_global_notify[i].handler != 269 handler)) { 270 status = AE_NOT_EXIST; 271 goto unlock_and_exit; 272 } 273 274 ACPI_DEBUG_PRINT((ACPI_DB_INFO, 275 "Removing global notify handler\n")); 276 277 acpi_gbl_global_notify[i].handler = NULL; 278 acpi_gbl_global_notify[i].context = NULL; 279 } 280 } 281 282 goto unlock_and_exit; 283 } 284 285 /* All other objects: Are Notifies allowed on this object? */ 286 287 if (!acpi_ev_is_notify_object(node)) { 288 status = AE_TYPE; 289 goto unlock_and_exit; 290 } 291 292 /* Must have an existing internal object */ 293 294 obj_desc = acpi_ns_get_attached_object(node); 295 if (!obj_desc) { 296 status = AE_NOT_EXIST; 297 goto unlock_and_exit; 298 } 299 300 /* Internal object exists. Find the handler and remove it */ 301 302 for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++) { 303 if (handler_type & (i + 1)) { 304 handler_obj = obj_desc->common_notify.notify_list[i]; 305 previous_handler_obj = NULL; 306 307 /* Attempt to find the handler in the handler list */ 308 309 while (handler_obj && 310 (handler_obj->notify.handler != handler)) { 311 previous_handler_obj = handler_obj; 312 handler_obj = handler_obj->notify.next[i]; 313 } 314 315 if (!handler_obj) { 316 status = AE_NOT_EXIST; 317 goto unlock_and_exit; 318 } 319 320 /* Remove the handler object from the list */ 321 322 if (previous_handler_obj) { /* Handler is not at the list head */ 323 previous_handler_obj->notify.next[i] = 324 handler_obj->notify.next[i]; 325 } else { /* Handler is at the list head */ 326 327 obj_desc->common_notify.notify_list[i] = 328 handler_obj->notify.next[i]; 329 } 330 331 acpi_ut_remove_reference(handler_obj); 332 } 333 } 334 335 unlock_and_exit: 336 (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); 337 return_ACPI_STATUS(status); 338 } 339 340 ACPI_EXPORT_SYMBOL(acpi_remove_notify_handler) 341 342 /******************************************************************************* 343 * 344 * FUNCTION: acpi_install_exception_handler 345 * 346 * PARAMETERS: handler - Pointer to the handler function for the 347 * event 348 * 349 * RETURN: Status 350 * 351 * DESCRIPTION: Saves the pointer to the handler function 352 * 353 ******************************************************************************/ 354 #ifdef ACPI_FUTURE_USAGE 355 acpi_status acpi_install_exception_handler(acpi_exception_handler handler) 356 { 357 acpi_status status; 358 359 ACPI_FUNCTION_TRACE(acpi_install_exception_handler); 360 361 status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS); 362 if (ACPI_FAILURE(status)) { 363 return_ACPI_STATUS(status); 364 } 365 366 /* Don't allow two handlers. */ 367 368 if (acpi_gbl_exception_handler) { 369 status = AE_ALREADY_EXISTS; 370 goto cleanup; 371 } 372 373 /* Install the handler */ 374 375 acpi_gbl_exception_handler = handler; 376 377 cleanup: 378 (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); 379 return_ACPI_STATUS(status); 380 } 381 382 ACPI_EXPORT_SYMBOL(acpi_install_exception_handler) 383 #endif /* ACPI_FUTURE_USAGE */ 384 385 #if (!ACPI_REDUCED_HARDWARE) 386 /******************************************************************************* 387 * 388 * FUNCTION: acpi_install_global_event_handler 389 * 390 * PARAMETERS: handler - Pointer to the global event handler function 391 * context - Value passed to the handler on each event 392 * 393 * RETURN: Status 394 * 395 * DESCRIPTION: Saves the pointer to the handler function. The global handler 396 * is invoked upon each incoming GPE and Fixed Event. It is 397 * invoked at interrupt level at the time of the event dispatch. 398 * Can be used to update event counters, etc. 399 * 400 ******************************************************************************/ 401 acpi_status 402 acpi_install_global_event_handler(acpi_gbl_event_handler handler, void *context) 403 { 404 acpi_status status; 405 406 ACPI_FUNCTION_TRACE(acpi_install_global_event_handler); 407 408 /* Parameter validation */ 409 410 if (!handler) { 411 return_ACPI_STATUS(AE_BAD_PARAMETER); 412 } 413 414 status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS); 415 if (ACPI_FAILURE(status)) { 416 return_ACPI_STATUS(status); 417 } 418 419 /* Don't allow two handlers. */ 420 421 if (acpi_gbl_global_event_handler) { 422 status = AE_ALREADY_EXISTS; 423 goto cleanup; 424 } 425 426 acpi_gbl_global_event_handler = handler; 427 acpi_gbl_global_event_handler_context = context; 428 429 cleanup: 430 (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); 431 return_ACPI_STATUS(status); 432 } 433 434 ACPI_EXPORT_SYMBOL(acpi_install_global_event_handler) 435 436 /******************************************************************************* 437 * 438 * FUNCTION: acpi_install_fixed_event_handler 439 * 440 * PARAMETERS: event - Event type to enable. 441 * handler - Pointer to the handler function for the 442 * event 443 * context - Value passed to the handler on each GPE 444 * 445 * RETURN: Status 446 * 447 * DESCRIPTION: Saves the pointer to the handler function and then enables the 448 * event. 449 * 450 ******************************************************************************/ 451 acpi_status 452 acpi_install_fixed_event_handler(u32 event, 453 acpi_event_handler handler, void *context) 454 { 455 acpi_status status; 456 457 ACPI_FUNCTION_TRACE(acpi_install_fixed_event_handler); 458 459 /* Parameter validation */ 460 461 if (event > ACPI_EVENT_MAX) { 462 return_ACPI_STATUS(AE_BAD_PARAMETER); 463 } 464 465 status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS); 466 if (ACPI_FAILURE(status)) { 467 return_ACPI_STATUS(status); 468 } 469 470 /* Do not allow multiple handlers */ 471 472 if (acpi_gbl_fixed_event_handlers[event].handler) { 473 status = AE_ALREADY_EXISTS; 474 goto cleanup; 475 } 476 477 /* Install the handler before enabling the event */ 478 479 acpi_gbl_fixed_event_handlers[event].handler = handler; 480 acpi_gbl_fixed_event_handlers[event].context = context; 481 482 status = acpi_clear_event(event); 483 if (ACPI_SUCCESS(status)) 484 status = acpi_enable_event(event, 0); 485 if (ACPI_FAILURE(status)) { 486 ACPI_WARNING((AE_INFO, 487 "Could not enable fixed event - %s (%u)", 488 acpi_ut_get_event_name(event), event)); 489 490 /* Remove the handler */ 491 492 acpi_gbl_fixed_event_handlers[event].handler = NULL; 493 acpi_gbl_fixed_event_handlers[event].context = NULL; 494 } else { 495 ACPI_DEBUG_PRINT((ACPI_DB_INFO, 496 "Enabled fixed event %s (%X), Handler=%p\n", 497 acpi_ut_get_event_name(event), event, 498 handler)); 499 } 500 501 cleanup: 502 (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); 503 return_ACPI_STATUS(status); 504 } 505 506 ACPI_EXPORT_SYMBOL(acpi_install_fixed_event_handler) 507 508 /******************************************************************************* 509 * 510 * FUNCTION: acpi_remove_fixed_event_handler 511 * 512 * PARAMETERS: event - Event type to disable. 513 * handler - Address of the handler 514 * 515 * RETURN: Status 516 * 517 * DESCRIPTION: Disables the event and unregisters the event handler. 518 * 519 ******************************************************************************/ 520 acpi_status 521 acpi_remove_fixed_event_handler(u32 event, acpi_event_handler handler) 522 { 523 acpi_status status = AE_OK; 524 525 ACPI_FUNCTION_TRACE(acpi_remove_fixed_event_handler); 526 527 /* Parameter validation */ 528 529 if (event > ACPI_EVENT_MAX) { 530 return_ACPI_STATUS(AE_BAD_PARAMETER); 531 } 532 533 status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS); 534 if (ACPI_FAILURE(status)) { 535 return_ACPI_STATUS(status); 536 } 537 538 /* Disable the event before removing the handler */ 539 540 status = acpi_disable_event(event, 0); 541 542 /* Always Remove the handler */ 543 544 acpi_gbl_fixed_event_handlers[event].handler = NULL; 545 acpi_gbl_fixed_event_handlers[event].context = NULL; 546 547 if (ACPI_FAILURE(status)) { 548 ACPI_WARNING((AE_INFO, 549 "Could not disable fixed event - %s (%u)", 550 acpi_ut_get_event_name(event), event)); 551 } else { 552 ACPI_DEBUG_PRINT((ACPI_DB_INFO, 553 "Disabled fixed event - %s (%X)\n", 554 acpi_ut_get_event_name(event), event)); 555 } 556 557 (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); 558 return_ACPI_STATUS(status); 559 } 560 561 ACPI_EXPORT_SYMBOL(acpi_remove_fixed_event_handler) 562 563 /******************************************************************************* 564 * 565 * FUNCTION: acpi_install_gpe_handler 566 * 567 * PARAMETERS: gpe_device - Namespace node for the GPE (NULL for FADT 568 * defined GPEs) 569 * gpe_number - The GPE number within the GPE block 570 * type - Whether this GPE should be treated as an 571 * edge- or level-triggered interrupt. 572 * address - Address of the handler 573 * context - Value passed to the handler on each GPE 574 * 575 * RETURN: Status 576 * 577 * DESCRIPTION: Install a handler for a General Purpose Event. 578 * 579 ******************************************************************************/ 580 acpi_status 581 acpi_install_gpe_handler(acpi_handle gpe_device, 582 u32 gpe_number, 583 u32 type, acpi_gpe_handler address, void *context) 584 { 585 struct acpi_gpe_event_info *gpe_event_info; 586 struct acpi_gpe_handler_info *handler; 587 acpi_status status; 588 acpi_cpu_flags flags; 589 590 ACPI_FUNCTION_TRACE(acpi_install_gpe_handler); 591 592 /* Parameter validation */ 593 594 if ((!address) || (type & ~ACPI_GPE_XRUPT_TYPE_MASK)) { 595 return_ACPI_STATUS(AE_BAD_PARAMETER); 596 } 597 598 status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS); 599 if (ACPI_FAILURE(status)) { 600 return_ACPI_STATUS(status); 601 } 602 603 /* Allocate and init handler object (before lock) */ 604 605 handler = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_gpe_handler_info)); 606 if (!handler) { 607 status = AE_NO_MEMORY; 608 goto unlock_and_exit; 609 } 610 611 flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); 612 613 /* Ensure that we have a valid GPE number */ 614 615 gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number); 616 if (!gpe_event_info) { 617 status = AE_BAD_PARAMETER; 618 goto free_and_exit; 619 } 620 621 /* Make sure that there isn't a handler there already */ 622 623 if ((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) == 624 ACPI_GPE_DISPATCH_HANDLER) { 625 status = AE_ALREADY_EXISTS; 626 goto free_and_exit; 627 } 628 629 handler->address = address; 630 handler->context = context; 631 handler->method_node = gpe_event_info->dispatch.method_node; 632 handler->original_flags = (u8)(gpe_event_info->flags & 633 (ACPI_GPE_XRUPT_TYPE_MASK | 634 ACPI_GPE_DISPATCH_MASK)); 635 636 /* 637 * If the GPE is associated with a method, it may have been enabled 638 * automatically during initialization, in which case it has to be 639 * disabled now to avoid spurious execution of the handler. 640 */ 641 642 if ((handler->original_flags & ACPI_GPE_DISPATCH_METHOD) 643 && gpe_event_info->runtime_count) { 644 handler->originally_enabled = 1; 645 (void)acpi_ev_remove_gpe_reference(gpe_event_info); 646 } 647 648 /* Install the handler */ 649 650 gpe_event_info->dispatch.handler = handler; 651 652 /* Setup up dispatch flags to indicate handler (vs. method/notify) */ 653 654 gpe_event_info->flags &= 655 ~(ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK); 656 gpe_event_info->flags |= (u8) (type | ACPI_GPE_DISPATCH_HANDLER); 657 658 acpi_os_release_lock(acpi_gbl_gpe_lock, flags); 659 660 unlock_and_exit: 661 (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); 662 return_ACPI_STATUS(status); 663 664 free_and_exit: 665 acpi_os_release_lock(acpi_gbl_gpe_lock, flags); 666 ACPI_FREE(handler); 667 goto unlock_and_exit; 668 } 669 670 ACPI_EXPORT_SYMBOL(acpi_install_gpe_handler) 671 672 /******************************************************************************* 673 * 674 * FUNCTION: acpi_remove_gpe_handler 675 * 676 * PARAMETERS: gpe_device - Namespace node for the GPE (NULL for FADT 677 * defined GPEs) 678 * gpe_number - The event to remove a handler 679 * address - Address of the handler 680 * 681 * RETURN: Status 682 * 683 * DESCRIPTION: Remove a handler for a General Purpose acpi_event. 684 * 685 ******************************************************************************/ 686 acpi_status 687 acpi_remove_gpe_handler(acpi_handle gpe_device, 688 u32 gpe_number, acpi_gpe_handler address) 689 { 690 struct acpi_gpe_event_info *gpe_event_info; 691 struct acpi_gpe_handler_info *handler; 692 acpi_status status; 693 acpi_cpu_flags flags; 694 695 ACPI_FUNCTION_TRACE(acpi_remove_gpe_handler); 696 697 /* Parameter validation */ 698 699 if (!address) { 700 return_ACPI_STATUS(AE_BAD_PARAMETER); 701 } 702 703 /* Make sure all deferred GPE tasks are completed */ 704 705 acpi_os_wait_events_complete(); 706 707 status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS); 708 if (ACPI_FAILURE(status)) { 709 return_ACPI_STATUS(status); 710 } 711 712 flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); 713 714 /* Ensure that we have a valid GPE number */ 715 716 gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number); 717 if (!gpe_event_info) { 718 status = AE_BAD_PARAMETER; 719 goto unlock_and_exit; 720 } 721 722 /* Make sure that a handler is indeed installed */ 723 724 if ((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) != 725 ACPI_GPE_DISPATCH_HANDLER) { 726 status = AE_NOT_EXIST; 727 goto unlock_and_exit; 728 } 729 730 /* Make sure that the installed handler is the same */ 731 732 if (gpe_event_info->dispatch.handler->address != address) { 733 status = AE_BAD_PARAMETER; 734 goto unlock_and_exit; 735 } 736 737 /* Remove the handler */ 738 739 handler = gpe_event_info->dispatch.handler; 740 741 /* Restore Method node (if any), set dispatch flags */ 742 743 gpe_event_info->dispatch.method_node = handler->method_node; 744 gpe_event_info->flags &= 745 ~(ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK); 746 gpe_event_info->flags |= handler->original_flags; 747 748 /* 749 * If the GPE was previously associated with a method and it was 750 * enabled, it should be enabled at this point to restore the 751 * post-initialization configuration. 752 */ 753 if ((handler->original_flags & ACPI_GPE_DISPATCH_METHOD) && 754 handler->originally_enabled) { 755 (void)acpi_ev_add_gpe_reference(gpe_event_info); 756 } 757 758 /* Now we can free the handler object */ 759 760 ACPI_FREE(handler); 761 762 unlock_and_exit: 763 acpi_os_release_lock(acpi_gbl_gpe_lock, flags); 764 765 (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); 766 return_ACPI_STATUS(status); 767 } 768 769 ACPI_EXPORT_SYMBOL(acpi_remove_gpe_handler) 770 771 /******************************************************************************* 772 * 773 * FUNCTION: acpi_acquire_global_lock 774 * 775 * PARAMETERS: timeout - How long the caller is willing to wait 776 * handle - Where the handle to the lock is returned 777 * (if acquired) 778 * 779 * RETURN: Status 780 * 781 * DESCRIPTION: Acquire the ACPI Global Lock 782 * 783 * Note: Allows callers with the same thread ID to acquire the global lock 784 * multiple times. In other words, externally, the behavior of the global lock 785 * is identical to an AML mutex. On the first acquire, a new handle is 786 * returned. On any subsequent calls to acquire by the same thread, the same 787 * handle is returned. 788 * 789 ******************************************************************************/ 790 acpi_status acpi_acquire_global_lock(u16 timeout, u32 * handle) 791 { 792 acpi_status status; 793 794 if (!handle) { 795 return (AE_BAD_PARAMETER); 796 } 797 798 /* Must lock interpreter to prevent race conditions */ 799 800 acpi_ex_enter_interpreter(); 801 802 status = acpi_ex_acquire_mutex_object(timeout, 803 acpi_gbl_global_lock_mutex, 804 acpi_os_get_thread_id()); 805 806 if (ACPI_SUCCESS(status)) { 807 808 /* Return the global lock handle (updated in acpi_ev_acquire_global_lock) */ 809 810 *handle = acpi_gbl_global_lock_handle; 811 } 812 813 acpi_ex_exit_interpreter(); 814 return (status); 815 } 816 817 ACPI_EXPORT_SYMBOL(acpi_acquire_global_lock) 818 819 /******************************************************************************* 820 * 821 * FUNCTION: acpi_release_global_lock 822 * 823 * PARAMETERS: handle - Returned from acpi_acquire_global_lock 824 * 825 * RETURN: Status 826 * 827 * DESCRIPTION: Release the ACPI Global Lock. The handle must be valid. 828 * 829 ******************************************************************************/ 830 acpi_status acpi_release_global_lock(u32 handle) 831 { 832 acpi_status status; 833 834 if (!handle || (handle != acpi_gbl_global_lock_handle)) { 835 return (AE_NOT_ACQUIRED); 836 } 837 838 status = acpi_ex_release_mutex_object(acpi_gbl_global_lock_mutex); 839 return (status); 840 } 841 842 ACPI_EXPORT_SYMBOL(acpi_release_global_lock) 843 #endif /* !ACPI_REDUCED_HARDWARE */ 844