1 /****************************************************************************** 2 * 3 * Module Name: evxface - External interfaces for ACPI events 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 "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 /* Make sure all deferred tasks are completed */ 253 254 acpi_os_wait_events_complete(); 255 256 status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); 257 if (ACPI_FAILURE(status)) { 258 return_ACPI_STATUS(status); 259 } 260 261 /* Root Object. Global handlers are removed here */ 262 263 if (device == ACPI_ROOT_OBJECT) { 264 for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++) { 265 if (handler_type & (i + 1)) { 266 if (!acpi_gbl_global_notify[i].handler || 267 (acpi_gbl_global_notify[i].handler != 268 handler)) { 269 status = AE_NOT_EXIST; 270 goto unlock_and_exit; 271 } 272 273 ACPI_DEBUG_PRINT((ACPI_DB_INFO, 274 "Removing global notify handler\n")); 275 276 acpi_gbl_global_notify[i].handler = NULL; 277 acpi_gbl_global_notify[i].context = NULL; 278 } 279 } 280 281 goto unlock_and_exit; 282 } 283 284 /* All other objects: Are Notifies allowed on this object? */ 285 286 if (!acpi_ev_is_notify_object(node)) { 287 status = AE_TYPE; 288 goto unlock_and_exit; 289 } 290 291 /* Must have an existing internal object */ 292 293 obj_desc = acpi_ns_get_attached_object(node); 294 if (!obj_desc) { 295 status = AE_NOT_EXIST; 296 goto unlock_and_exit; 297 } 298 299 /* Internal object exists. Find the handler and remove it */ 300 301 for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++) { 302 if (handler_type & (i + 1)) { 303 handler_obj = obj_desc->common_notify.notify_list[i]; 304 previous_handler_obj = NULL; 305 306 /* Attempt to find the handler in the handler list */ 307 308 while (handler_obj && 309 (handler_obj->notify.handler != handler)) { 310 previous_handler_obj = handler_obj; 311 handler_obj = handler_obj->notify.next[i]; 312 } 313 314 if (!handler_obj) { 315 status = AE_NOT_EXIST; 316 goto unlock_and_exit; 317 } 318 319 /* Remove the handler object from the list */ 320 321 if (previous_handler_obj) { /* Handler is not at the list head */ 322 previous_handler_obj->notify.next[i] = 323 handler_obj->notify.next[i]; 324 } else { /* Handler is at the list head */ 325 326 obj_desc->common_notify.notify_list[i] = 327 handler_obj->notify.next[i]; 328 } 329 330 acpi_ut_remove_reference(handler_obj); 331 } 332 } 333 334 unlock_and_exit: 335 (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); 336 return_ACPI_STATUS(status); 337 } 338 339 ACPI_EXPORT_SYMBOL(acpi_remove_notify_handler) 340 341 /******************************************************************************* 342 * 343 * FUNCTION: acpi_install_exception_handler 344 * 345 * PARAMETERS: handler - Pointer to the handler function for the 346 * event 347 * 348 * RETURN: Status 349 * 350 * DESCRIPTION: Saves the pointer to the handler function 351 * 352 ******************************************************************************/ 353 #ifdef ACPI_FUTURE_USAGE 354 acpi_status acpi_install_exception_handler(acpi_exception_handler handler) 355 { 356 acpi_status status; 357 358 ACPI_FUNCTION_TRACE(acpi_install_exception_handler); 359 360 status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS); 361 if (ACPI_FAILURE(status)) { 362 return_ACPI_STATUS(status); 363 } 364 365 /* Don't allow two handlers. */ 366 367 if (acpi_gbl_exception_handler) { 368 status = AE_ALREADY_EXISTS; 369 goto cleanup; 370 } 371 372 /* Install the handler */ 373 374 acpi_gbl_exception_handler = handler; 375 376 cleanup: 377 (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); 378 return_ACPI_STATUS(status); 379 } 380 381 ACPI_EXPORT_SYMBOL(acpi_install_exception_handler) 382 #endif /* ACPI_FUTURE_USAGE */ 383 384 #if (!ACPI_REDUCED_HARDWARE) 385 /******************************************************************************* 386 * 387 * FUNCTION: acpi_install_global_event_handler 388 * 389 * PARAMETERS: handler - Pointer to the global event handler function 390 * context - Value passed to the handler on each event 391 * 392 * RETURN: Status 393 * 394 * DESCRIPTION: Saves the pointer to the handler function. The global handler 395 * is invoked upon each incoming GPE and Fixed Event. It is 396 * invoked at interrupt level at the time of the event dispatch. 397 * Can be used to update event counters, etc. 398 * 399 ******************************************************************************/ 400 acpi_status 401 acpi_install_global_event_handler(ACPI_GBL_EVENT_HANDLER handler, void *context) 402 { 403 acpi_status status; 404 405 ACPI_FUNCTION_TRACE(acpi_install_global_event_handler); 406 407 /* Parameter validation */ 408 409 if (!handler) { 410 return_ACPI_STATUS(AE_BAD_PARAMETER); 411 } 412 413 status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS); 414 if (ACPI_FAILURE(status)) { 415 return_ACPI_STATUS(status); 416 } 417 418 /* Don't allow two handlers. */ 419 420 if (acpi_gbl_global_event_handler) { 421 status = AE_ALREADY_EXISTS; 422 goto cleanup; 423 } 424 425 acpi_gbl_global_event_handler = handler; 426 acpi_gbl_global_event_handler_context = context; 427 428 cleanup: 429 (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); 430 return_ACPI_STATUS(status); 431 } 432 433 ACPI_EXPORT_SYMBOL(acpi_install_global_event_handler) 434 435 /******************************************************************************* 436 * 437 * FUNCTION: acpi_install_fixed_event_handler 438 * 439 * PARAMETERS: event - Event type to enable. 440 * handler - Pointer to the handler function for the 441 * event 442 * context - Value passed to the handler on each GPE 443 * 444 * RETURN: Status 445 * 446 * DESCRIPTION: Saves the pointer to the handler function and then enables the 447 * event. 448 * 449 ******************************************************************************/ 450 acpi_status 451 acpi_install_fixed_event_handler(u32 event, 452 acpi_event_handler handler, void *context) 453 { 454 acpi_status status; 455 456 ACPI_FUNCTION_TRACE(acpi_install_fixed_event_handler); 457 458 /* Parameter validation */ 459 460 if (event > ACPI_EVENT_MAX) { 461 return_ACPI_STATUS(AE_BAD_PARAMETER); 462 } 463 464 status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS); 465 if (ACPI_FAILURE(status)) { 466 return_ACPI_STATUS(status); 467 } 468 469 /* Don't allow two handlers. */ 470 471 if (NULL != acpi_gbl_fixed_event_handlers[event].handler) { 472 status = AE_ALREADY_EXISTS; 473 goto cleanup; 474 } 475 476 /* Install the handler before enabling the event */ 477 478 acpi_gbl_fixed_event_handlers[event].handler = handler; 479 acpi_gbl_fixed_event_handlers[event].context = context; 480 481 status = acpi_clear_event(event); 482 if (ACPI_SUCCESS(status)) 483 status = acpi_enable_event(event, 0); 484 if (ACPI_FAILURE(status)) { 485 ACPI_WARNING((AE_INFO, "Could not enable fixed event 0x%X", 486 event)); 487 488 /* Remove the handler */ 489 490 acpi_gbl_fixed_event_handlers[event].handler = NULL; 491 acpi_gbl_fixed_event_handlers[event].context = NULL; 492 } else { 493 ACPI_DEBUG_PRINT((ACPI_DB_INFO, 494 "Enabled fixed event %X, Handler=%p\n", event, 495 handler)); 496 } 497 498 cleanup: 499 (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); 500 return_ACPI_STATUS(status); 501 } 502 503 ACPI_EXPORT_SYMBOL(acpi_install_fixed_event_handler) 504 505 /******************************************************************************* 506 * 507 * FUNCTION: acpi_remove_fixed_event_handler 508 * 509 * PARAMETERS: event - Event type to disable. 510 * handler - Address of the handler 511 * 512 * RETURN: Status 513 * 514 * DESCRIPTION: Disables the event and unregisters the event handler. 515 * 516 ******************************************************************************/ 517 acpi_status 518 acpi_remove_fixed_event_handler(u32 event, acpi_event_handler handler) 519 { 520 acpi_status status = AE_OK; 521 522 ACPI_FUNCTION_TRACE(acpi_remove_fixed_event_handler); 523 524 /* Parameter validation */ 525 526 if (event > ACPI_EVENT_MAX) { 527 return_ACPI_STATUS(AE_BAD_PARAMETER); 528 } 529 530 status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS); 531 if (ACPI_FAILURE(status)) { 532 return_ACPI_STATUS(status); 533 } 534 535 /* Disable the event before removing the handler */ 536 537 status = acpi_disable_event(event, 0); 538 539 /* Always Remove the handler */ 540 541 acpi_gbl_fixed_event_handlers[event].handler = NULL; 542 acpi_gbl_fixed_event_handlers[event].context = NULL; 543 544 if (ACPI_FAILURE(status)) { 545 ACPI_WARNING((AE_INFO, 546 "Could not write to fixed event enable register 0x%X", 547 event)); 548 } else { 549 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Disabled fixed event %X\n", 550 event)); 551 } 552 553 (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); 554 return_ACPI_STATUS(status); 555 } 556 557 ACPI_EXPORT_SYMBOL(acpi_remove_fixed_event_handler) 558 559 /******************************************************************************* 560 * 561 * FUNCTION: acpi_install_gpe_handler 562 * 563 * PARAMETERS: gpe_device - Namespace node for the GPE (NULL for FADT 564 * defined GPEs) 565 * gpe_number - The GPE number within the GPE block 566 * type - Whether this GPE should be treated as an 567 * edge- or level-triggered interrupt. 568 * address - Address of the handler 569 * context - Value passed to the handler on each GPE 570 * 571 * RETURN: Status 572 * 573 * DESCRIPTION: Install a handler for a General Purpose Event. 574 * 575 ******************************************************************************/ 576 acpi_status 577 acpi_install_gpe_handler(acpi_handle gpe_device, 578 u32 gpe_number, 579 u32 type, acpi_gpe_handler address, void *context) 580 { 581 struct acpi_gpe_event_info *gpe_event_info; 582 struct acpi_gpe_handler_info *handler; 583 acpi_status status; 584 acpi_cpu_flags flags; 585 586 ACPI_FUNCTION_TRACE(acpi_install_gpe_handler); 587 588 /* Parameter validation */ 589 590 if ((!address) || (type & ~ACPI_GPE_XRUPT_TYPE_MASK)) { 591 return_ACPI_STATUS(AE_BAD_PARAMETER); 592 } 593 594 status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS); 595 if (ACPI_FAILURE(status)) { 596 return_ACPI_STATUS(status); 597 } 598 599 /* Allocate memory for the handler object */ 600 601 handler = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_gpe_handler_info)); 602 if (!handler) { 603 status = AE_NO_MEMORY; 604 goto unlock_and_exit; 605 } 606 607 flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); 608 609 /* Ensure that we have a valid GPE number */ 610 611 gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number); 612 if (!gpe_event_info) { 613 status = AE_BAD_PARAMETER; 614 goto free_and_exit; 615 } 616 617 /* Make sure that there isn't a handler there already */ 618 619 if ((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) == 620 ACPI_GPE_DISPATCH_HANDLER) { 621 status = AE_ALREADY_EXISTS; 622 goto free_and_exit; 623 } 624 625 /* Allocate and init handler object */ 626 627 handler->address = address; 628 handler->context = context; 629 handler->method_node = gpe_event_info->dispatch.method_node; 630 handler->original_flags = gpe_event_info->flags & 631 (ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK); 632 633 /* 634 * If the GPE is associated with a method, it might have been enabled 635 * automatically during initialization, in which case it has to be 636 * disabled now to avoid spurious execution of the handler. 637 */ 638 639 if ((handler->original_flags & ACPI_GPE_DISPATCH_METHOD) 640 && gpe_event_info->runtime_count) { 641 handler->originally_enabled = 1; 642 (void)acpi_ev_remove_gpe_reference(gpe_event_info); 643 } 644 645 /* Install the handler */ 646 647 gpe_event_info->dispatch.handler = handler; 648 649 /* Setup up dispatch flags to indicate handler (vs. method) */ 650 651 gpe_event_info->flags &= 652 ~(ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK); 653 gpe_event_info->flags |= (u8) (type | ACPI_GPE_DISPATCH_HANDLER); 654 655 acpi_os_release_lock(acpi_gbl_gpe_lock, flags); 656 657 unlock_and_exit: 658 (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); 659 return_ACPI_STATUS(status); 660 661 free_and_exit: 662 acpi_os_release_lock(acpi_gbl_gpe_lock, flags); 663 ACPI_FREE(handler); 664 goto unlock_and_exit; 665 } 666 667 ACPI_EXPORT_SYMBOL(acpi_install_gpe_handler) 668 669 /******************************************************************************* 670 * 671 * FUNCTION: acpi_remove_gpe_handler 672 * 673 * PARAMETERS: gpe_device - Namespace node for the GPE (NULL for FADT 674 * defined GPEs) 675 * gpe_number - The event to remove a handler 676 * address - Address of the handler 677 * 678 * RETURN: Status 679 * 680 * DESCRIPTION: Remove a handler for a General Purpose acpi_event. 681 * 682 ******************************************************************************/ 683 acpi_status 684 acpi_remove_gpe_handler(acpi_handle gpe_device, 685 u32 gpe_number, acpi_gpe_handler address) 686 { 687 struct acpi_gpe_event_info *gpe_event_info; 688 struct acpi_gpe_handler_info *handler; 689 acpi_status status; 690 acpi_cpu_flags flags; 691 692 ACPI_FUNCTION_TRACE(acpi_remove_gpe_handler); 693 694 /* Parameter validation */ 695 696 if (!address) { 697 return_ACPI_STATUS(AE_BAD_PARAMETER); 698 } 699 700 /* Make sure all deferred tasks are completed */ 701 702 acpi_os_wait_events_complete(); 703 704 status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS); 705 if (ACPI_FAILURE(status)) { 706 return_ACPI_STATUS(status); 707 } 708 709 flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); 710 711 /* Ensure that we have a valid GPE number */ 712 713 gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number); 714 if (!gpe_event_info) { 715 status = AE_BAD_PARAMETER; 716 goto unlock_and_exit; 717 } 718 719 /* Make sure that a handler is indeed installed */ 720 721 if ((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) != 722 ACPI_GPE_DISPATCH_HANDLER) { 723 status = AE_NOT_EXIST; 724 goto unlock_and_exit; 725 } 726 727 /* Make sure that the installed handler is the same */ 728 729 if (gpe_event_info->dispatch.handler->address != address) { 730 status = AE_BAD_PARAMETER; 731 goto unlock_and_exit; 732 } 733 734 /* Remove the handler */ 735 736 handler = gpe_event_info->dispatch.handler; 737 738 /* Restore Method node (if any), set dispatch flags */ 739 740 gpe_event_info->dispatch.method_node = handler->method_node; 741 gpe_event_info->flags &= 742 ~(ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK); 743 gpe_event_info->flags |= handler->original_flags; 744 745 /* 746 * If the GPE was previously associated with a method and it was 747 * enabled, it should be enabled at this point to restore the 748 * post-initialization configuration. 749 */ 750 751 if ((handler->original_flags & ACPI_GPE_DISPATCH_METHOD) 752 && handler->originally_enabled) 753 (void)acpi_ev_add_gpe_reference(gpe_event_info); 754 755 /* Now we can free the handler object */ 756 757 ACPI_FREE(handler); 758 759 unlock_and_exit: 760 acpi_os_release_lock(acpi_gbl_gpe_lock, flags); 761 762 (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); 763 return_ACPI_STATUS(status); 764 } 765 766 ACPI_EXPORT_SYMBOL(acpi_remove_gpe_handler) 767 768 /******************************************************************************* 769 * 770 * FUNCTION: acpi_acquire_global_lock 771 * 772 * PARAMETERS: timeout - How long the caller is willing to wait 773 * handle - Where the handle to the lock is returned 774 * (if acquired) 775 * 776 * RETURN: Status 777 * 778 * DESCRIPTION: Acquire the ACPI Global Lock 779 * 780 * Note: Allows callers with the same thread ID to acquire the global lock 781 * multiple times. In other words, externally, the behavior of the global lock 782 * is identical to an AML mutex. On the first acquire, a new handle is 783 * returned. On any subsequent calls to acquire by the same thread, the same 784 * handle is returned. 785 * 786 ******************************************************************************/ 787 acpi_status acpi_acquire_global_lock(u16 timeout, u32 * handle) 788 { 789 acpi_status status; 790 791 if (!handle) { 792 return (AE_BAD_PARAMETER); 793 } 794 795 /* Must lock interpreter to prevent race conditions */ 796 797 acpi_ex_enter_interpreter(); 798 799 status = acpi_ex_acquire_mutex_object(timeout, 800 acpi_gbl_global_lock_mutex, 801 acpi_os_get_thread_id()); 802 803 if (ACPI_SUCCESS(status)) { 804 805 /* Return the global lock handle (updated in acpi_ev_acquire_global_lock) */ 806 807 *handle = acpi_gbl_global_lock_handle; 808 } 809 810 acpi_ex_exit_interpreter(); 811 return (status); 812 } 813 814 ACPI_EXPORT_SYMBOL(acpi_acquire_global_lock) 815 816 /******************************************************************************* 817 * 818 * FUNCTION: acpi_release_global_lock 819 * 820 * PARAMETERS: handle - Returned from acpi_acquire_global_lock 821 * 822 * RETURN: Status 823 * 824 * DESCRIPTION: Release the ACPI Global Lock. The handle must be valid. 825 * 826 ******************************************************************************/ 827 acpi_status acpi_release_global_lock(u32 handle) 828 { 829 acpi_status status; 830 831 if (!handle || (handle != acpi_gbl_global_lock_handle)) { 832 return (AE_NOT_ACQUIRED); 833 } 834 835 status = acpi_ex_release_mutex_object(acpi_gbl_global_lock_mutex); 836 return (status); 837 } 838 839 ACPI_EXPORT_SYMBOL(acpi_release_global_lock) 840 #endif /* !ACPI_REDUCED_HARDWARE */ 841