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