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