linux-bk/drivers/acpi/events/evxface.c
<<
>>
Prefs
   1/******************************************************************************
   2 *
   3 * Module Name: evxface - External interfaces for ACPI events
   4 *
   5 *****************************************************************************/
   6
   7/*
   8 * Copyright (C) 2000 - 2005, R. Byron Moore
   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/module.h>
  45
  46#include <acpi/acpi.h>
  47#include <acpi/acnamesp.h>
  48#include <acpi/acevents.h>
  49#include <acpi/acinterp.h>
  50
  51#define _COMPONENT          ACPI_EVENTS
  52         ACPI_MODULE_NAME    ("evxface")
  53
  54
  55/*******************************************************************************
  56 *
  57 * FUNCTION:    acpi_install_exception_handler
  58 *
  59 * PARAMETERS:  Handler         - Pointer to the handler function for the
  60 *                                event
  61 *
  62 * RETURN:      Status
  63 *
  64 * DESCRIPTION: Saves the pointer to the handler function
  65 *
  66 ******************************************************************************/
  67#ifdef ACPI_FUTURE_USAGE
  68acpi_status
  69acpi_install_exception_handler (
  70        acpi_exception_handler          handler)
  71{
  72        acpi_status                     status;
  73
  74
  75        ACPI_FUNCTION_TRACE ("acpi_install_exception_handler");
  76
  77
  78        status = acpi_ut_acquire_mutex (ACPI_MTX_EVENTS);
  79        if (ACPI_FAILURE (status)) {
  80                return_ACPI_STATUS (status);
  81        }
  82
  83        /* Don't allow two handlers. */
  84
  85        if (acpi_gbl_exception_handler) {
  86                status = AE_ALREADY_EXISTS;
  87                goto cleanup;
  88        }
  89
  90        /* Install the handler */
  91
  92        acpi_gbl_exception_handler = handler;
  93
  94cleanup:
  95        (void) acpi_ut_release_mutex (ACPI_MTX_EVENTS);
  96        return_ACPI_STATUS (status);
  97}
  98#endif  /*  ACPI_FUTURE_USAGE  */
  99
 100
 101/*******************************************************************************
 102 *
 103 * FUNCTION:    acpi_install_fixed_event_handler
 104 *
 105 * PARAMETERS:  Event           - Event type to enable.
 106 *              Handler         - Pointer to the handler function for the
 107 *                                event
 108 *              Context         - Value passed to the handler on each GPE
 109 *
 110 * RETURN:      Status
 111 *
 112 * DESCRIPTION: Saves the pointer to the handler function and then enables the
 113 *              event.
 114 *
 115 ******************************************************************************/
 116
 117acpi_status
 118acpi_install_fixed_event_handler (
 119        u32                             event,
 120        acpi_event_handler              handler,
 121        void                            *context)
 122{
 123        acpi_status                     status;
 124
 125
 126        ACPI_FUNCTION_TRACE ("acpi_install_fixed_event_handler");
 127
 128
 129        /* Parameter validation */
 130
 131        if (event > ACPI_EVENT_MAX) {
 132                return_ACPI_STATUS (AE_BAD_PARAMETER);
 133        }
 134
 135        status = acpi_ut_acquire_mutex (ACPI_MTX_EVENTS);
 136        if (ACPI_FAILURE (status)) {
 137                return_ACPI_STATUS (status);
 138        }
 139
 140        /* Don't allow two handlers. */
 141
 142        if (NULL != acpi_gbl_fixed_event_handlers[event].handler) {
 143                status = AE_ALREADY_EXISTS;
 144                goto cleanup;
 145        }
 146
 147        /* Install the handler before enabling the event */
 148
 149        acpi_gbl_fixed_event_handlers[event].handler = handler;
 150        acpi_gbl_fixed_event_handlers[event].context = context;
 151
 152        status = acpi_enable_event (event, 0);
 153        if (ACPI_FAILURE (status)) {
 154                ACPI_DEBUG_PRINT ((ACPI_DB_WARN, "Could not enable fixed event.\n"));
 155
 156                /* Remove the handler */
 157
 158                acpi_gbl_fixed_event_handlers[event].handler = NULL;
 159                acpi_gbl_fixed_event_handlers[event].context = NULL;
 160        }
 161        else {
 162                ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
 163                        "Enabled fixed event %X, Handler=%p\n", event, handler));
 164        }
 165
 166
 167cleanup:
 168        (void) acpi_ut_release_mutex (ACPI_MTX_EVENTS);
 169        return_ACPI_STATUS (status);
 170}
 171EXPORT_SYMBOL(acpi_install_fixed_event_handler);
 172
 173
 174/*******************************************************************************
 175 *
 176 * FUNCTION:    acpi_remove_fixed_event_handler
 177 *
 178 * PARAMETERS:  Event           - Event type to disable.
 179 *              Handler         - Address of the handler
 180 *
 181 * RETURN:      Status
 182 *
 183 * DESCRIPTION: Disables the event and unregisters the event handler.
 184 *
 185 ******************************************************************************/
 186
 187acpi_status
 188acpi_remove_fixed_event_handler (
 189        u32                             event,
 190        acpi_event_handler              handler)
 191{
 192        acpi_status                     status = AE_OK;
 193
 194
 195        ACPI_FUNCTION_TRACE ("acpi_remove_fixed_event_handler");
 196
 197
 198        /* Parameter validation */
 199
 200        if (event > ACPI_EVENT_MAX) {
 201                return_ACPI_STATUS (AE_BAD_PARAMETER);
 202        }
 203
 204        status = acpi_ut_acquire_mutex (ACPI_MTX_EVENTS);
 205        if (ACPI_FAILURE (status)) {
 206                return_ACPI_STATUS (status);
 207        }
 208
 209        /* Disable the event before removing the handler */
 210
 211        status = acpi_disable_event (event, 0);
 212
 213        /* Always Remove the handler */
 214
 215        acpi_gbl_fixed_event_handlers[event].handler = NULL;
 216        acpi_gbl_fixed_event_handlers[event].context = NULL;
 217
 218        if (ACPI_FAILURE (status)) {
 219                ACPI_DEBUG_PRINT ((ACPI_DB_WARN,
 220                        "Could not write to fixed event enable register.\n"));
 221        }
 222        else {
 223                ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Disabled fixed event %X.\n", event));
 224        }
 225
 226        (void) acpi_ut_release_mutex (ACPI_MTX_EVENTS);
 227        return_ACPI_STATUS (status);
 228}
 229EXPORT_SYMBOL(acpi_remove_fixed_event_handler);
 230
 231
 232/*******************************************************************************
 233 *
 234 * FUNCTION:    acpi_install_notify_handler
 235 *
 236 * PARAMETERS:  Device          - The device for which notifies will be handled
 237 *              handler_type    - The type of handler:
 238 *                                  ACPI_SYSTEM_NOTIFY: system_handler (00-7f)
 239 *                                  ACPI_DEVICE_NOTIFY: driver_handler (80-ff)
 240 *                                  ACPI_ALL_NOTIFY:  both system and device
 241 *              Handler         - Address of the handler
 242 *              Context         - Value passed to the handler on each GPE
 243 *
 244 * RETURN:      Status
 245 *
 246 * DESCRIPTION: Install a handler for notifies on an ACPI device
 247 *
 248 ******************************************************************************/
 249
 250acpi_status
 251acpi_install_notify_handler (
 252        acpi_handle                     device,
 253        u32                             handler_type,
 254        acpi_notify_handler             handler,
 255        void                            *context)
 256{
 257        union acpi_operand_object       *obj_desc;
 258        union acpi_operand_object       *notify_obj;
 259        struct acpi_namespace_node      *node;
 260        acpi_status                     status;
 261
 262
 263        ACPI_FUNCTION_TRACE ("acpi_install_notify_handler");
 264
 265
 266        /* Parameter validation */
 267
 268        if ((!device)  ||
 269                (!handler) ||
 270                (handler_type > ACPI_MAX_NOTIFY_HANDLER_TYPE)) {
 271                return_ACPI_STATUS (AE_BAD_PARAMETER);
 272        }
 273
 274        status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
 275        if (ACPI_FAILURE (status)) {
 276                return_ACPI_STATUS (status);
 277        }
 278
 279        /* Convert and validate the device handle */
 280
 281        node = acpi_ns_map_handle_to_node (device);
 282        if (!node) {
 283                status = AE_BAD_PARAMETER;
 284                goto unlock_and_exit;
 285        }
 286
 287        /*
 288         * Root Object:
 289         * Registering a notify handler on the root object indicates that the
 290         * caller wishes to receive notifications for all objects.  Note that
 291         * only one <external> global handler can be regsitered (per notify type).
 292         */
 293        if (device == ACPI_ROOT_OBJECT) {
 294                /* Make sure the handler is not already installed */
 295
 296                if (((handler_type & ACPI_SYSTEM_NOTIFY) &&
 297                                acpi_gbl_system_notify.handler)     ||
 298                        ((handler_type & ACPI_DEVICE_NOTIFY) &&
 299                                acpi_gbl_device_notify.handler)) {
 300                        status = AE_ALREADY_EXISTS;
 301                        goto unlock_and_exit;
 302                }
 303
 304                if (handler_type & ACPI_SYSTEM_NOTIFY) {
 305                        acpi_gbl_system_notify.node  = node;
 306                        acpi_gbl_system_notify.handler = handler;
 307                        acpi_gbl_system_notify.context = context;
 308                }
 309
 310                if (handler_type & ACPI_DEVICE_NOTIFY) {
 311                        acpi_gbl_device_notify.node  = node;
 312                        acpi_gbl_device_notify.handler = handler;
 313                        acpi_gbl_device_notify.context = context;
 314                }
 315
 316                /* Global notify handler installed */
 317        }
 318
 319        /*
 320         * All Other Objects:
 321         * Caller will only receive notifications specific to the target object.
 322         * Note that only certain object types can receive notifications.
 323         */
 324        else {
 325                /* Notifies allowed on this object? */
 326
 327                if (!acpi_ev_is_notify_object (node)) {
 328                        status = AE_TYPE;
 329                        goto unlock_and_exit;
 330                }
 331
 332                /* Check for an existing internal object */
 333
 334                obj_desc = acpi_ns_get_attached_object (node);
 335                if (obj_desc) {
 336                        /* Object exists - make sure there's no handler */
 337
 338                        if (((handler_type & ACPI_SYSTEM_NOTIFY) &&
 339                                        obj_desc->common_notify.system_notify) ||
 340                                ((handler_type & ACPI_DEVICE_NOTIFY) &&
 341                                        obj_desc->common_notify.device_notify)) {
 342                                status = AE_ALREADY_EXISTS;
 343                                goto unlock_and_exit;
 344                        }
 345                }
 346                else {
 347                        /* Create a new object */
 348
 349                        obj_desc = acpi_ut_create_internal_object (node->type);
 350                        if (!obj_desc) {
 351                                status = AE_NO_MEMORY;
 352                                goto unlock_and_exit;
 353                        }
 354
 355                        /* Attach new object to the Node */
 356
 357                        status = acpi_ns_attach_object (device, obj_desc, node->type);
 358
 359                        /* Remove local reference to the object */
 360
 361                        acpi_ut_remove_reference (obj_desc);
 362                        if (ACPI_FAILURE (status)) {
 363                                goto unlock_and_exit;
 364                        }
 365                }
 366
 367                /* Install the handler */
 368
 369                notify_obj = acpi_ut_create_internal_object (ACPI_TYPE_LOCAL_NOTIFY);
 370                if (!notify_obj) {
 371                        status = AE_NO_MEMORY;
 372                        goto unlock_and_exit;
 373                }
 374
 375                notify_obj->notify.node   = node;
 376                notify_obj->notify.handler = handler;
 377                notify_obj->notify.context = context;
 378
 379                if (handler_type & ACPI_SYSTEM_NOTIFY) {
 380                        obj_desc->common_notify.system_notify = notify_obj;
 381                }
 382
 383                if (handler_type & ACPI_DEVICE_NOTIFY) {
 384                        obj_desc->common_notify.device_notify = notify_obj;
 385                }
 386
 387                if (handler_type == ACPI_ALL_NOTIFY) {
 388                        /* Extra ref if installed in both */
 389
 390                        acpi_ut_add_reference (notify_obj);
 391                }
 392        }
 393
 394
 395unlock_and_exit:
 396        (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
 397        return_ACPI_STATUS (status);
 398}
 399EXPORT_SYMBOL(acpi_install_notify_handler);
 400
 401
 402/*******************************************************************************
 403 *
 404 * FUNCTION:    acpi_remove_notify_handler
 405 *
 406 * PARAMETERS:  Device          - The device for which notifies will be handled
 407 *              handler_type    - The type of handler:
 408 *                                  ACPI_SYSTEM_NOTIFY: system_handler (00-7f)
 409 *                                  ACPI_DEVICE_NOTIFY: driver_handler (80-ff)
 410 *                                  ACPI_ALL_NOTIFY:  both system and device
 411 *              Handler         - Address of the handler
 412 *
 413 * RETURN:      Status
 414 *
 415 * DESCRIPTION: Remove a handler for notifies on an ACPI device
 416 *
 417 ******************************************************************************/
 418
 419acpi_status
 420acpi_remove_notify_handler (
 421        acpi_handle                     device,
 422        u32                             handler_type,
 423        acpi_notify_handler             handler)
 424{
 425        union acpi_operand_object       *notify_obj;
 426        union acpi_operand_object       *obj_desc;
 427        struct acpi_namespace_node      *node;
 428        acpi_status                     status;
 429
 430
 431        ACPI_FUNCTION_TRACE ("acpi_remove_notify_handler");
 432
 433
 434        /* Parameter validation */
 435
 436        if ((!device)  ||
 437                (!handler) ||
 438                (handler_type > ACPI_MAX_NOTIFY_HANDLER_TYPE)) {
 439                return_ACPI_STATUS (AE_BAD_PARAMETER);
 440        }
 441
 442        status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
 443        if (ACPI_FAILURE (status)) {
 444                return_ACPI_STATUS (status);
 445        }
 446
 447        /* Convert and validate the device handle */
 448
 449        node = acpi_ns_map_handle_to_node (device);
 450        if (!node) {
 451                status = AE_BAD_PARAMETER;
 452                goto unlock_and_exit;
 453        }
 454
 455        /* Root Object */
 456
 457        if (device == ACPI_ROOT_OBJECT) {
 458                ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Removing notify handler for ROOT object.\n"));
 459
 460                if (((handler_type & ACPI_SYSTEM_NOTIFY) &&
 461                          !acpi_gbl_system_notify.handler)      ||
 462                        ((handler_type & ACPI_DEVICE_NOTIFY) &&
 463                          !acpi_gbl_device_notify.handler)) {
 464                        status = AE_NOT_EXIST;
 465                        goto unlock_and_exit;
 466                }
 467
 468                /* Make sure all deferred tasks are completed */
 469
 470                (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
 471                acpi_os_wait_events_complete(NULL);
 472                status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
 473                if (ACPI_FAILURE (status)) {
 474                        return_ACPI_STATUS (status);
 475                }
 476
 477                if (handler_type & ACPI_SYSTEM_NOTIFY) {
 478                        acpi_gbl_system_notify.node  = NULL;
 479                        acpi_gbl_system_notify.handler = NULL;
 480                        acpi_gbl_system_notify.context = NULL;
 481                }
 482
 483                if (handler_type & ACPI_DEVICE_NOTIFY) {
 484                        acpi_gbl_device_notify.node  = NULL;
 485                        acpi_gbl_device_notify.handler = NULL;
 486                        acpi_gbl_device_notify.context = NULL;
 487                }
 488        }
 489
 490        /* All Other Objects */
 491
 492        else {
 493                /* Notifies allowed on this object? */
 494
 495                if (!acpi_ev_is_notify_object (node)) {
 496                        status = AE_TYPE;
 497                        goto unlock_and_exit;
 498                }
 499
 500                /* Check for an existing internal object */
 501
 502                obj_desc = acpi_ns_get_attached_object (node);
 503                if (!obj_desc) {
 504                        status = AE_NOT_EXIST;
 505                        goto unlock_and_exit;
 506                }
 507
 508                /* Object exists - make sure there's an existing handler */
 509
 510                if (handler_type & ACPI_SYSTEM_NOTIFY) {
 511                        notify_obj = obj_desc->common_notify.system_notify;
 512                        if ((!notify_obj) ||
 513                                 (notify_obj->notify.handler != handler)) {
 514                                status = AE_BAD_PARAMETER;
 515                                goto unlock_and_exit;
 516                        }
 517                        /* Make sure all deferred tasks are completed */
 518
 519                        (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
 520                        acpi_os_wait_events_complete(NULL);
 521                        status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
 522                        if (ACPI_FAILURE (status)) {
 523                                return_ACPI_STATUS (status);
 524                        }
 525
 526                        /* Remove the handler */
 527                        obj_desc->common_notify.system_notify = NULL;
 528                        acpi_ut_remove_reference (notify_obj);
 529                }
 530
 531                if (handler_type & ACPI_DEVICE_NOTIFY) {
 532                        notify_obj = obj_desc->common_notify.device_notify;
 533                        if ((!notify_obj) ||
 534                                 (notify_obj->notify.handler != handler)) {
 535                                status = AE_BAD_PARAMETER;
 536                                goto unlock_and_exit;
 537                        }
 538                        /* Make sure all deferred tasks are completed */
 539
 540                        (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
 541                        acpi_os_wait_events_complete(NULL);
 542                        status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
 543                        if (ACPI_FAILURE (status)) {
 544                                return_ACPI_STATUS (status);
 545                        }
 546
 547                        /* Remove the handler */
 548                        obj_desc->common_notify.device_notify = NULL;
 549                        acpi_ut_remove_reference (notify_obj);
 550                }
 551        }
 552
 553
 554unlock_and_exit:
 555        (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
 556        return_ACPI_STATUS (status);
 557}
 558EXPORT_SYMBOL(acpi_remove_notify_handler);
 559
 560
 561/*******************************************************************************
 562 *
 563 * FUNCTION:    acpi_install_gpe_handler
 564 *
 565 * PARAMETERS:  gpe_number      - The GPE number within the GPE block
 566 *              gpe_block       - GPE block (NULL == FADT GPEs)
 567 *              Type            - Whether this GPE should be treated as an
 568 *                                edge- or level-triggered interrupt.
 569 *              Address         - Address of the handler
 570 *              Context         - Value passed to the handler on each GPE
 571 *
 572 * RETURN:      Status
 573 *
 574 * DESCRIPTION: Install a handler for a General Purpose Event.
 575 *
 576 ******************************************************************************/
 577
 578acpi_status
 579acpi_install_gpe_handler (
 580        acpi_handle                     gpe_device,
 581        u32                             gpe_number,
 582        u32                             type,
 583        acpi_event_handler              address,
 584        void                            *context)
 585{
 586        struct acpi_gpe_event_info      *gpe_event_info;
 587        struct acpi_handler_info        *handler;
 588        acpi_status                     status;
 589
 590
 591        ACPI_FUNCTION_TRACE ("acpi_install_gpe_handler");
 592
 593
 594        /* Parameter validation */
 595
 596        if ((!address) || (type > ACPI_GPE_XRUPT_TYPE_MASK)) {
 597                return_ACPI_STATUS (AE_BAD_PARAMETER);
 598        }
 599
 600        status = acpi_ut_acquire_mutex (ACPI_MTX_EVENTS);
 601        if (ACPI_FAILURE (status)) {
 602                return_ACPI_STATUS (status);
 603        }
 604
 605        /* Ensure that we have a valid GPE number */
 606
 607        gpe_event_info = acpi_ev_get_gpe_event_info (gpe_device, gpe_number);
 608        if (!gpe_event_info) {
 609                status = AE_BAD_PARAMETER;
 610                goto unlock_and_exit;
 611        }
 612
 613        /* Make sure that there isn't a handler there already */
 614
 615        if ((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) == ACPI_GPE_DISPATCH_HANDLER) {
 616                status = AE_ALREADY_EXISTS;
 617                goto unlock_and_exit;
 618        }
 619
 620        /* Allocate and init handler object */
 621
 622        handler = ACPI_MEM_CALLOCATE (sizeof (struct acpi_handler_info));
 623        if (!handler) {
 624                status = AE_NO_MEMORY;
 625                goto unlock_and_exit;
 626        }
 627
 628        handler->address    = address;
 629        handler->context    = context;
 630        handler->method_node = gpe_event_info->dispatch.method_node;
 631
 632        /* Disable the GPE before installing the handler */
 633
 634        status = acpi_ev_disable_gpe (gpe_event_info);
 635        if (ACPI_FAILURE (status)) {
 636                goto unlock_and_exit;
 637        }
 638
 639        /* Install the handler */
 640
 641        acpi_os_acquire_lock (acpi_gbl_gpe_lock, ACPI_NOT_ISR);
 642        gpe_event_info->dispatch.handler = handler;
 643
 644        /* Setup up dispatch flags to indicate handler (vs. method) */
 645
 646        gpe_event_info->flags &= ~(ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK); /* Clear bits */
 647        gpe_event_info->flags |= (u8) (type | ACPI_GPE_DISPATCH_HANDLER);
 648
 649        acpi_os_release_lock (acpi_gbl_gpe_lock, ACPI_NOT_ISR);
 650
 651
 652unlock_and_exit:
 653        (void) acpi_ut_release_mutex (ACPI_MTX_EVENTS);
 654        return_ACPI_STATUS (status);
 655}
 656EXPORT_SYMBOL(acpi_install_gpe_handler);
 657
 658
 659/*******************************************************************************
 660 *
 661 * FUNCTION:    acpi_remove_gpe_handler
 662 *
 663 * PARAMETERS:  gpe_number      - The event to remove a handler
 664 *              gpe_block       - GPE block (NULL == FADT GPEs)
 665 *              Address         - Address of the handler
 666 *
 667 * RETURN:      Status
 668 *
 669 * DESCRIPTION: Remove a handler for a General Purpose acpi_event.
 670 *
 671 ******************************************************************************/
 672
 673acpi_status
 674acpi_remove_gpe_handler (
 675        acpi_handle                     gpe_device,
 676        u32                             gpe_number,
 677        acpi_event_handler              address)
 678{
 679        struct acpi_gpe_event_info      *gpe_event_info;
 680        struct acpi_handler_info        *handler;
 681        acpi_status                     status;
 682
 683
 684        ACPI_FUNCTION_TRACE ("acpi_remove_gpe_handler");
 685
 686
 687        /* Parameter validation */
 688
 689        if (!address) {
 690                return_ACPI_STATUS (AE_BAD_PARAMETER);
 691        }
 692
 693        status = acpi_ut_acquire_mutex (ACPI_MTX_EVENTS);
 694        if (ACPI_FAILURE (status)) {
 695                return_ACPI_STATUS (status);
 696        }
 697
 698        /* Ensure that we have a valid GPE number */
 699
 700        gpe_event_info = acpi_ev_get_gpe_event_info (gpe_device, gpe_number);
 701        if (!gpe_event_info) {
 702                status = AE_BAD_PARAMETER;
 703                goto unlock_and_exit;
 704        }
 705
 706        /* Make sure that a handler is indeed installed */
 707
 708        if ((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) != ACPI_GPE_DISPATCH_HANDLER) {
 709                status = AE_NOT_EXIST;
 710                goto unlock_and_exit;
 711        }
 712
 713        /* Make sure that the installed handler is the same */
 714
 715        if (gpe_event_info->dispatch.handler->address != address) {
 716                status = AE_BAD_PARAMETER;
 717                goto unlock_and_exit;
 718        }
 719
 720        /* Disable the GPE before removing the handler */
 721
 722        status = acpi_ev_disable_gpe (gpe_event_info);
 723        if (ACPI_FAILURE (status)) {
 724                goto unlock_and_exit;
 725        }
 726
 727        /* Make sure all deferred tasks are completed */
 728
 729        (void) acpi_ut_release_mutex (ACPI_MTX_EVENTS);
 730        acpi_os_wait_events_complete(NULL);
 731        status = acpi_ut_acquire_mutex (ACPI_MTX_EVENTS);
 732        if (ACPI_FAILURE (status)) {
 733                return_ACPI_STATUS (status);
 734        }
 735
 736        /* Remove the handler */
 737
 738        acpi_os_acquire_lock (acpi_gbl_gpe_lock, ACPI_NOT_ISR);
 739        handler = gpe_event_info->dispatch.handler;
 740
 741        /* Restore Method node (if any), set dispatch flags */
 742
 743        gpe_event_info->dispatch.method_node = handler->method_node;
 744        gpe_event_info->flags &= ~ACPI_GPE_DISPATCH_MASK; /* Clear bits */
 745        if (handler->method_node) {
 746                gpe_event_info->flags |= ACPI_GPE_DISPATCH_METHOD;
 747        }
 748        acpi_os_release_lock (acpi_gbl_gpe_lock, ACPI_NOT_ISR);
 749
 750        /* Now we can free the handler object */
 751
 752        ACPI_MEM_FREE (handler);
 753
 754
 755unlock_and_exit:
 756        (void) acpi_ut_release_mutex (ACPI_MTX_EVENTS);
 757        return_ACPI_STATUS (status);
 758}
 759EXPORT_SYMBOL(acpi_remove_gpe_handler);
 760
 761
 762/*******************************************************************************
 763 *
 764 * FUNCTION:    acpi_acquire_global_lock
 765 *
 766 * PARAMETERS:  Timeout         - How long the caller is willing to wait
 767 *              out_handle      - A handle to the lock if acquired
 768 *
 769 * RETURN:      Status
 770 *
 771 * DESCRIPTION: Acquire the ACPI Global Lock
 772 *
 773 ******************************************************************************/
 774
 775acpi_status
 776acpi_acquire_global_lock (
 777        u16                             timeout,
 778        u32                             *handle)
 779{
 780        acpi_status                     status;
 781
 782
 783        if (!handle) {
 784                return (AE_BAD_PARAMETER);
 785        }
 786
 787        status = acpi_ex_enter_interpreter ();
 788        if (ACPI_FAILURE (status)) {
 789                return (status);
 790        }
 791
 792        status = acpi_ev_acquire_global_lock (timeout);
 793        acpi_ex_exit_interpreter ();
 794
 795        if (ACPI_SUCCESS (status)) {
 796                acpi_gbl_global_lock_handle++;
 797                *handle = acpi_gbl_global_lock_handle;
 798        }
 799
 800        return (status);
 801}
 802EXPORT_SYMBOL(acpi_acquire_global_lock);
 803
 804
 805/*******************************************************************************
 806 *
 807 * FUNCTION:    acpi_release_global_lock
 808 *
 809 * PARAMETERS:  Handle      - Returned from acpi_acquire_global_lock
 810 *
 811 * RETURN:      Status
 812 *
 813 * DESCRIPTION: Release the ACPI Global Lock
 814 *
 815 ******************************************************************************/
 816
 817acpi_status
 818acpi_release_global_lock (
 819        u32                             handle)
 820{
 821        acpi_status                     status;
 822
 823
 824        if (handle != acpi_gbl_global_lock_handle) {
 825                return (AE_NOT_ACQUIRED);
 826        }
 827
 828        status = acpi_ev_release_global_lock ();
 829        return (status);
 830}
 831EXPORT_SYMBOL(acpi_release_global_lock);
 832
 833
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.