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