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