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