linux/drivers/acpi/acpica/evxfevnt.c
<<
>>
Prefs
   1/******************************************************************************
   2 *
   3 * Module Name: evxfevnt - External Interfaces, ACPI event disable/enable
   4 *
   5 *****************************************************************************/
   6
   7/*
   8 * Copyright (C) 2000 - 2008, Intel Corp.
   9 * All rights reserved.
  10 *
  11 * Redistribution and use in source and binary forms, with or without
  12 * modification, are permitted provided that the following conditions
  13 * are met:
  14 * 1. Redistributions of source code must retain the above copyright
  15 *    notice, this list of conditions, and the following disclaimer,
  16 *    without modification.
  17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
  18 *    substantially similar to the "NO WARRANTY" disclaimer below
  19 *    ("Disclaimer") and any redistribution must be conditioned upon
  20 *    including a substantially similar Disclaimer requirement for further
  21 *    binary redistribution.
  22 * 3. Neither the names of the above-listed copyright holders nor the names
  23 *    of any contributors may be used to endorse or promote products derived
  24 *    from this software without specific prior written permission.
  25 *
  26 * Alternatively, this software may be distributed under the terms of the
  27 * GNU General Public License ("GPL") version 2 as published by the Free
  28 * Software Foundation.
  29 *
  30 * NO WARRANTY
  31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
  34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
  40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  41 * POSSIBILITY OF SUCH DAMAGES.
  42 */
  43
  44#include <acpi/acpi.h>
  45#include "accommon.h"
  46#include "acevents.h"
  47#include "acnamesp.h"
  48#include "actables.h"
  49
  50#define _COMPONENT          ACPI_EVENTS
  51ACPI_MODULE_NAME("evxfevnt")
  52
  53/* Local prototypes */
  54static acpi_status
  55acpi_ev_get_gpe_device(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
  56                       struct acpi_gpe_block_info *gpe_block, void *context);
  57
  58/*******************************************************************************
  59 *
  60 * FUNCTION:    acpi_enable
  61 *
  62 * PARAMETERS:  None
  63 *
  64 * RETURN:      Status
  65 *
  66 * DESCRIPTION: Transfers the system into ACPI mode.
  67 *
  68 ******************************************************************************/
  69
  70acpi_status acpi_enable(void)
  71{
  72        acpi_status status = AE_OK;
  73
  74        ACPI_FUNCTION_TRACE(acpi_enable);
  75
  76        /* ACPI tables must be present */
  77
  78        if (!acpi_tb_tables_loaded()) {
  79                return_ACPI_STATUS(AE_NO_ACPI_TABLES);
  80        }
  81
  82        /* Check current mode */
  83
  84        if (acpi_hw_get_mode() == ACPI_SYS_MODE_ACPI) {
  85                ACPI_DEBUG_PRINT((ACPI_DB_INIT,
  86                                  "System is already in ACPI mode\n"));
  87        } else {
  88                /* Transition to ACPI mode */
  89
  90                status = acpi_hw_set_mode(ACPI_SYS_MODE_ACPI);
  91                if (ACPI_FAILURE(status)) {
  92                        ACPI_ERROR((AE_INFO,
  93                                    "Could not transition to ACPI mode"));
  94                        return_ACPI_STATUS(status);
  95                }
  96
  97                ACPI_DEBUG_PRINT((ACPI_DB_INIT,
  98                                  "Transition to ACPI mode successful\n"));
  99        }
 100
 101        return_ACPI_STATUS(status);
 102}
 103
 104ACPI_EXPORT_SYMBOL(acpi_enable)
 105
 106/*******************************************************************************
 107 *
 108 * FUNCTION:    acpi_disable
 109 *
 110 * PARAMETERS:  None
 111 *
 112 * RETURN:      Status
 113 *
 114 * DESCRIPTION: Transfers the system into LEGACY (non-ACPI) mode.
 115 *
 116 ******************************************************************************/
 117acpi_status acpi_disable(void)
 118{
 119        acpi_status status = AE_OK;
 120
 121        ACPI_FUNCTION_TRACE(acpi_disable);
 122
 123        if (acpi_hw_get_mode() == ACPI_SYS_MODE_LEGACY) {
 124                ACPI_DEBUG_PRINT((ACPI_DB_INIT,
 125                                  "System is already in legacy (non-ACPI) mode\n"));
 126        } else {
 127                /* Transition to LEGACY mode */
 128
 129                status = acpi_hw_set_mode(ACPI_SYS_MODE_LEGACY);
 130
 131                if (ACPI_FAILURE(status)) {
 132                        ACPI_ERROR((AE_INFO,
 133                                    "Could not exit ACPI mode to legacy mode"));
 134                        return_ACPI_STATUS(status);
 135                }
 136
 137                ACPI_DEBUG_PRINT((ACPI_DB_INIT, "ACPI mode disabled\n"));
 138        }
 139
 140        return_ACPI_STATUS(status);
 141}
 142
 143ACPI_EXPORT_SYMBOL(acpi_disable)
 144
 145/*******************************************************************************
 146 *
 147 * FUNCTION:    acpi_enable_event
 148 *
 149 * PARAMETERS:  Event           - The fixed eventto be enabled
 150 *              Flags           - Reserved
 151 *
 152 * RETURN:      Status
 153 *
 154 * DESCRIPTION: Enable an ACPI event (fixed)
 155 *
 156 ******************************************************************************/
 157acpi_status acpi_enable_event(u32 event, u32 flags)
 158{
 159        acpi_status status = AE_OK;
 160        u32 value;
 161
 162        ACPI_FUNCTION_TRACE(acpi_enable_event);
 163
 164        /* Decode the Fixed Event */
 165
 166        if (event > ACPI_EVENT_MAX) {
 167                return_ACPI_STATUS(AE_BAD_PARAMETER);
 168        }
 169
 170        /*
 171         * Enable the requested fixed event (by writing a one to the enable
 172         * register bit)
 173         */
 174        status =
 175            acpi_write_bit_register(acpi_gbl_fixed_event_info[event].
 176                                    enable_register_id, ACPI_ENABLE_EVENT);
 177        if (ACPI_FAILURE(status)) {
 178                return_ACPI_STATUS(status);
 179        }
 180
 181        /* Make sure that the hardware responded */
 182
 183        status =
 184            acpi_read_bit_register(acpi_gbl_fixed_event_info[event].
 185                                   enable_register_id, &value);
 186        if (ACPI_FAILURE(status)) {
 187                return_ACPI_STATUS(status);
 188        }
 189
 190        if (value != 1) {
 191                ACPI_ERROR((AE_INFO,
 192                            "Could not enable %s event",
 193                            acpi_ut_get_event_name(event)));
 194                return_ACPI_STATUS(AE_NO_HARDWARE_RESPONSE);
 195        }
 196
 197        return_ACPI_STATUS(status);
 198}
 199
 200ACPI_EXPORT_SYMBOL(acpi_enable_event)
 201
 202/*******************************************************************************
 203 *
 204 * FUNCTION:    acpi_set_gpe_type
 205 *
 206 * PARAMETERS:  gpe_device      - Parent GPE Device
 207 *              gpe_number      - GPE level within the GPE block
 208 *              Type            - New GPE type
 209 *
 210 * RETURN:      Status
 211 *
 212 * DESCRIPTION: Set the type of an individual GPE
 213 *
 214 ******************************************************************************/
 215acpi_status acpi_set_gpe_type(acpi_handle gpe_device, u32 gpe_number, u8 type)
 216{
 217        acpi_status status = AE_OK;
 218        struct acpi_gpe_event_info *gpe_event_info;
 219
 220        ACPI_FUNCTION_TRACE(acpi_set_gpe_type);
 221
 222        /* Ensure that we have a valid GPE number */
 223
 224        gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
 225        if (!gpe_event_info) {
 226                status = AE_BAD_PARAMETER;
 227                goto unlock_and_exit;
 228        }
 229
 230        if ((gpe_event_info->flags & ACPI_GPE_TYPE_MASK) == type) {
 231                return_ACPI_STATUS(AE_OK);
 232        }
 233
 234        /* Set the new type (will disable GPE if currently enabled) */
 235
 236        status = acpi_ev_set_gpe_type(gpe_event_info, type);
 237
 238      unlock_and_exit:
 239        return_ACPI_STATUS(status);
 240}
 241
 242ACPI_EXPORT_SYMBOL(acpi_set_gpe_type)
 243
 244/*******************************************************************************
 245 *
 246 * FUNCTION:    acpi_enable_gpe
 247 *
 248 * PARAMETERS:  gpe_device      - Parent GPE Device
 249 *              gpe_number      - GPE level within the GPE block
 250 *              Flags           - Just enable, or also wake enable?
 251 *                                Called from ISR or not
 252 *
 253 * RETURN:      Status
 254 *
 255 * DESCRIPTION: Enable an ACPI event (general purpose)
 256 *
 257 ******************************************************************************/
 258acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number)
 259{
 260        acpi_status status = AE_OK;
 261        acpi_cpu_flags flags;
 262        struct acpi_gpe_event_info *gpe_event_info;
 263
 264        ACPI_FUNCTION_TRACE(acpi_enable_gpe);
 265
 266        flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
 267
 268        /* Ensure that we have a valid GPE number */
 269
 270        gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
 271        if (!gpe_event_info) {
 272                status = AE_BAD_PARAMETER;
 273                goto unlock_and_exit;
 274        }
 275
 276        /* Perform the enable */
 277
 278        status = acpi_ev_enable_gpe(gpe_event_info, TRUE);
 279
 280      unlock_and_exit:
 281        acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
 282        return_ACPI_STATUS(status);
 283}
 284
 285ACPI_EXPORT_SYMBOL(acpi_enable_gpe)
 286
 287/*******************************************************************************
 288 *
 289 * FUNCTION:    acpi_disable_gpe
 290 *
 291 * PARAMETERS:  gpe_device      - Parent GPE Device
 292 *              gpe_number      - GPE level within the GPE block
 293 *              Flags           - Just disable, or also wake disable?
 294 *                                Called from ISR or not
 295 *
 296 * RETURN:      Status
 297 *
 298 * DESCRIPTION: Disable an ACPI event (general purpose)
 299 *
 300 ******************************************************************************/
 301acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number)
 302{
 303        acpi_status status = AE_OK;
 304        acpi_cpu_flags flags;
 305        struct acpi_gpe_event_info *gpe_event_info;
 306
 307        ACPI_FUNCTION_TRACE(acpi_disable_gpe);
 308
 309        flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
 310        /* Ensure that we have a valid GPE number */
 311
 312        gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
 313        if (!gpe_event_info) {
 314                status = AE_BAD_PARAMETER;
 315                goto unlock_and_exit;
 316        }
 317
 318        status = acpi_ev_disable_gpe(gpe_event_info);
 319
 320unlock_and_exit:
 321        acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
 322        return_ACPI_STATUS(status);
 323}
 324
 325ACPI_EXPORT_SYMBOL(acpi_disable_gpe)
 326
 327/*******************************************************************************
 328 *
 329 * FUNCTION:    acpi_disable_event
 330 *
 331 * PARAMETERS:  Event           - The fixed eventto be enabled
 332 *              Flags           - Reserved
 333 *
 334 * RETURN:      Status
 335 *
 336 * DESCRIPTION: Disable an ACPI event (fixed)
 337 *
 338 ******************************************************************************/
 339acpi_status acpi_disable_event(u32 event, u32 flags)
 340{
 341        acpi_status status = AE_OK;
 342        u32 value;
 343
 344        ACPI_FUNCTION_TRACE(acpi_disable_event);
 345
 346        /* Decode the Fixed Event */
 347
 348        if (event > ACPI_EVENT_MAX) {
 349                return_ACPI_STATUS(AE_BAD_PARAMETER);
 350        }
 351
 352        /*
 353         * Disable the requested fixed event (by writing a zero to the enable
 354         * register bit)
 355         */
 356        status =
 357            acpi_write_bit_register(acpi_gbl_fixed_event_info[event].
 358                                    enable_register_id, ACPI_DISABLE_EVENT);
 359        if (ACPI_FAILURE(status)) {
 360                return_ACPI_STATUS(status);
 361        }
 362
 363        status =
 364            acpi_read_bit_register(acpi_gbl_fixed_event_info[event].
 365                                   enable_register_id, &value);
 366        if (ACPI_FAILURE(status)) {
 367                return_ACPI_STATUS(status);
 368        }
 369
 370        if (value != 0) {
 371                ACPI_ERROR((AE_INFO,
 372                            "Could not disable %s events",
 373                            acpi_ut_get_event_name(event)));
 374                return_ACPI_STATUS(AE_NO_HARDWARE_RESPONSE);
 375        }
 376
 377        return_ACPI_STATUS(status);
 378}
 379
 380ACPI_EXPORT_SYMBOL(acpi_disable_event)
 381
 382/*******************************************************************************
 383 *
 384 * FUNCTION:    acpi_clear_event
 385 *
 386 * PARAMETERS:  Event           - The fixed event to be cleared
 387 *
 388 * RETURN:      Status
 389 *
 390 * DESCRIPTION: Clear an ACPI event (fixed)
 391 *
 392 ******************************************************************************/
 393acpi_status acpi_clear_event(u32 event)
 394{
 395        acpi_status status = AE_OK;
 396
 397        ACPI_FUNCTION_TRACE(acpi_clear_event);
 398
 399        /* Decode the Fixed Event */
 400
 401        if (event > ACPI_EVENT_MAX) {
 402                return_ACPI_STATUS(AE_BAD_PARAMETER);
 403        }
 404
 405        /*
 406         * Clear the requested fixed event (By writing a one to the status
 407         * register bit)
 408         */
 409        status =
 410            acpi_write_bit_register(acpi_gbl_fixed_event_info[event].
 411                                    status_register_id, ACPI_CLEAR_STATUS);
 412
 413        return_ACPI_STATUS(status);
 414}
 415
 416ACPI_EXPORT_SYMBOL(acpi_clear_event)
 417
 418/*******************************************************************************
 419 *
 420 * FUNCTION:    acpi_clear_gpe
 421 *
 422 * PARAMETERS:  gpe_device      - Parent GPE Device
 423 *              gpe_number      - GPE level within the GPE block
 424 *              Flags           - Called from an ISR or not
 425 *
 426 * RETURN:      Status
 427 *
 428 * DESCRIPTION: Clear an ACPI event (general purpose)
 429 *
 430 ******************************************************************************/
 431acpi_status acpi_clear_gpe(acpi_handle gpe_device, u32 gpe_number, u32 flags)
 432{
 433        acpi_status status = AE_OK;
 434        struct acpi_gpe_event_info *gpe_event_info;
 435
 436        ACPI_FUNCTION_TRACE(acpi_clear_gpe);
 437
 438        /* Use semaphore lock if not executing at interrupt level */
 439
 440        if (flags & ACPI_NOT_ISR) {
 441                status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
 442                if (ACPI_FAILURE(status)) {
 443                        return_ACPI_STATUS(status);
 444                }
 445        }
 446
 447        /* Ensure that we have a valid GPE number */
 448
 449        gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
 450        if (!gpe_event_info) {
 451                status = AE_BAD_PARAMETER;
 452                goto unlock_and_exit;
 453        }
 454
 455        status = acpi_hw_clear_gpe(gpe_event_info);
 456
 457      unlock_and_exit:
 458        if (flags & ACPI_NOT_ISR) {
 459                (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
 460        }
 461        return_ACPI_STATUS(status);
 462}
 463
 464ACPI_EXPORT_SYMBOL(acpi_clear_gpe)
 465/*******************************************************************************
 466 *
 467 * FUNCTION:    acpi_get_event_status
 468 *
 469 * PARAMETERS:  Event           - The fixed event
 470 *              event_status    - Where the current status of the event will
 471 *                                be returned
 472 *
 473 * RETURN:      Status
 474 *
 475 * DESCRIPTION: Obtains and returns the current status of the event
 476 *
 477 ******************************************************************************/
 478acpi_status acpi_get_event_status(u32 event, acpi_event_status * event_status)
 479{
 480        acpi_status status = AE_OK;
 481        u32 value;
 482
 483        ACPI_FUNCTION_TRACE(acpi_get_event_status);
 484
 485        if (!event_status) {
 486                return_ACPI_STATUS(AE_BAD_PARAMETER);
 487        }
 488
 489        /* Decode the Fixed Event */
 490
 491        if (event > ACPI_EVENT_MAX) {
 492                return_ACPI_STATUS(AE_BAD_PARAMETER);
 493        }
 494
 495        /* Get the status of the requested fixed event */
 496
 497        status =
 498            acpi_read_bit_register(acpi_gbl_fixed_event_info[event].
 499                              enable_register_id, &value);
 500        if (ACPI_FAILURE(status))
 501                return_ACPI_STATUS(status);
 502
 503        *event_status = value;
 504
 505        status =
 506            acpi_read_bit_register(acpi_gbl_fixed_event_info[event].
 507                              status_register_id, &value);
 508        if (ACPI_FAILURE(status))
 509                return_ACPI_STATUS(status);
 510
 511        if (value)
 512                *event_status |= ACPI_EVENT_FLAG_SET;
 513
 514        if (acpi_gbl_fixed_event_handlers[event].handler)
 515                *event_status |= ACPI_EVENT_FLAG_HANDLE;
 516
 517        return_ACPI_STATUS(status);
 518}
 519
 520ACPI_EXPORT_SYMBOL(acpi_get_event_status)
 521
 522/*******************************************************************************
 523 *
 524 * FUNCTION:    acpi_get_gpe_status
 525 *
 526 * PARAMETERS:  gpe_device      - Parent GPE Device
 527 *              gpe_number      - GPE level within the GPE block
 528 *              Flags           - Called from an ISR or not
 529 *              event_status    - Where the current status of the event will
 530 *                                be returned
 531 *
 532 * RETURN:      Status
 533 *
 534 * DESCRIPTION: Get status of an event (general purpose)
 535 *
 536 ******************************************************************************/
 537acpi_status
 538acpi_get_gpe_status(acpi_handle gpe_device,
 539                    u32 gpe_number, u32 flags, acpi_event_status * event_status)
 540{
 541        acpi_status status = AE_OK;
 542        struct acpi_gpe_event_info *gpe_event_info;
 543
 544        ACPI_FUNCTION_TRACE(acpi_get_gpe_status);
 545
 546        /* Use semaphore lock if not executing at interrupt level */
 547
 548        if (flags & ACPI_NOT_ISR) {
 549                status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
 550                if (ACPI_FAILURE(status)) {
 551                        return_ACPI_STATUS(status);
 552                }
 553        }
 554
 555        /* Ensure that we have a valid GPE number */
 556
 557        gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
 558        if (!gpe_event_info) {
 559                status = AE_BAD_PARAMETER;
 560                goto unlock_and_exit;
 561        }
 562
 563        /* Obtain status on the requested GPE number */
 564
 565        status = acpi_hw_get_gpe_status(gpe_event_info, event_status);
 566
 567        if (gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK)
 568                *event_status |= ACPI_EVENT_FLAG_HANDLE;
 569
 570      unlock_and_exit:
 571        if (flags & ACPI_NOT_ISR) {
 572                (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
 573        }
 574        return_ACPI_STATUS(status);
 575}
 576
 577ACPI_EXPORT_SYMBOL(acpi_get_gpe_status)
 578/*******************************************************************************
 579 *
 580 * FUNCTION:    acpi_install_gpe_block
 581 *
 582 * PARAMETERS:  gpe_device          - Handle to the parent GPE Block Device
 583 *              gpe_block_address   - Address and space_iD
 584 *              register_count      - Number of GPE register pairs in the block
 585 *              interrupt_number    - H/W interrupt for the block
 586 *
 587 * RETURN:      Status
 588 *
 589 * DESCRIPTION: Create and Install a block of GPE registers
 590 *
 591 ******************************************************************************/
 592acpi_status
 593acpi_install_gpe_block(acpi_handle gpe_device,
 594                       struct acpi_generic_address *gpe_block_address,
 595                       u32 register_count, u32 interrupt_number)
 596{
 597        acpi_status status;
 598        union acpi_operand_object *obj_desc;
 599        struct acpi_namespace_node *node;
 600        struct acpi_gpe_block_info *gpe_block;
 601
 602        ACPI_FUNCTION_TRACE(acpi_install_gpe_block);
 603
 604        if ((!gpe_device) || (!gpe_block_address) || (!register_count)) {
 605                return_ACPI_STATUS(AE_BAD_PARAMETER);
 606        }
 607
 608        status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
 609        if (ACPI_FAILURE(status)) {
 610                return (status);
 611        }
 612
 613        node = acpi_ns_map_handle_to_node(gpe_device);
 614        if (!node) {
 615                status = AE_BAD_PARAMETER;
 616                goto unlock_and_exit;
 617        }
 618
 619        /*
 620         * For user-installed GPE Block Devices, the gpe_block_base_number
 621         * is always zero
 622         */
 623        status =
 624            acpi_ev_create_gpe_block(node, gpe_block_address, register_count, 0,
 625                                     interrupt_number, &gpe_block);
 626        if (ACPI_FAILURE(status)) {
 627                goto unlock_and_exit;
 628        }
 629
 630        /* Run the _PRW methods and enable the GPEs */
 631
 632        status = acpi_ev_initialize_gpe_block(node, gpe_block);
 633        if (ACPI_FAILURE(status)) {
 634                goto unlock_and_exit;
 635        }
 636
 637        /* Get the device_object attached to the node */
 638
 639        obj_desc = acpi_ns_get_attached_object(node);
 640        if (!obj_desc) {
 641
 642                /* No object, create a new one */
 643
 644                obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_DEVICE);
 645                if (!obj_desc) {
 646                        status = AE_NO_MEMORY;
 647                        goto unlock_and_exit;
 648                }
 649
 650                status =
 651                    acpi_ns_attach_object(node, obj_desc, ACPI_TYPE_DEVICE);
 652
 653                /* Remove local reference to the object */
 654
 655                acpi_ut_remove_reference(obj_desc);
 656
 657                if (ACPI_FAILURE(status)) {
 658                        goto unlock_and_exit;
 659                }
 660        }
 661
 662        /* Install the GPE block in the device_object */
 663
 664        obj_desc->device.gpe_block = gpe_block;
 665
 666      unlock_and_exit:
 667        (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
 668        return_ACPI_STATUS(status);
 669}
 670
 671ACPI_EXPORT_SYMBOL(acpi_install_gpe_block)
 672
 673/*******************************************************************************
 674 *
 675 * FUNCTION:    acpi_remove_gpe_block
 676 *
 677 * PARAMETERS:  gpe_device          - Handle to the parent GPE Block Device
 678 *
 679 * RETURN:      Status
 680 *
 681 * DESCRIPTION: Remove a previously installed block of GPE registers
 682 *
 683 ******************************************************************************/
 684acpi_status acpi_remove_gpe_block(acpi_handle gpe_device)
 685{
 686        union acpi_operand_object *obj_desc;
 687        acpi_status status;
 688        struct acpi_namespace_node *node;
 689
 690        ACPI_FUNCTION_TRACE(acpi_remove_gpe_block);
 691
 692        if (!gpe_device) {
 693                return_ACPI_STATUS(AE_BAD_PARAMETER);
 694        }
 695
 696        status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
 697        if (ACPI_FAILURE(status)) {
 698                return (status);
 699        }
 700
 701        node = acpi_ns_map_handle_to_node(gpe_device);
 702        if (!node) {
 703                status = AE_BAD_PARAMETER;
 704                goto unlock_and_exit;
 705        }
 706
 707        /* Get the device_object attached to the node */
 708
 709        obj_desc = acpi_ns_get_attached_object(node);
 710        if (!obj_desc || !obj_desc->device.gpe_block) {
 711                return_ACPI_STATUS(AE_NULL_OBJECT);
 712        }
 713
 714        /* Delete the GPE block (but not the device_object) */
 715
 716        status = acpi_ev_delete_gpe_block(obj_desc->device.gpe_block);
 717        if (ACPI_SUCCESS(status)) {
 718                obj_desc->device.gpe_block = NULL;
 719        }
 720
 721      unlock_and_exit:
 722        (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
 723        return_ACPI_STATUS(status);
 724}
 725
 726ACPI_EXPORT_SYMBOL(acpi_remove_gpe_block)
 727
 728/*******************************************************************************
 729 *
 730 * FUNCTION:    acpi_get_gpe_device
 731 *
 732 * PARAMETERS:  Index               - System GPE index (0-current_gpe_count)
 733 *              gpe_device          - Where the parent GPE Device is returned
 734 *
 735 * RETURN:      Status
 736 *
 737 * DESCRIPTION: Obtain the GPE device associated with the input index. A NULL
 738 *              gpe device indicates that the gpe number is contained in one of
 739 *              the FADT-defined gpe blocks. Otherwise, the GPE block device.
 740 *
 741 ******************************************************************************/
 742acpi_status
 743acpi_get_gpe_device(u32 index, acpi_handle *gpe_device)
 744{
 745        struct acpi_gpe_device_info info;
 746        acpi_status status;
 747
 748        ACPI_FUNCTION_TRACE(acpi_get_gpe_device);
 749
 750        if (!gpe_device) {
 751                return_ACPI_STATUS(AE_BAD_PARAMETER);
 752        }
 753
 754        if (index >= acpi_current_gpe_count) {
 755                return_ACPI_STATUS(AE_NOT_EXIST);
 756        }
 757
 758        /* Setup and walk the GPE list */
 759
 760        info.index = index;
 761        info.status = AE_NOT_EXIST;
 762        info.gpe_device = NULL;
 763        info.next_block_base_index = 0;
 764
 765        status = acpi_ev_walk_gpe_list(acpi_ev_get_gpe_device, &info);
 766        if (ACPI_FAILURE(status)) {
 767                return_ACPI_STATUS(status);
 768        }
 769
 770        *gpe_device = info.gpe_device;
 771        return_ACPI_STATUS(info.status);
 772}
 773
 774ACPI_EXPORT_SYMBOL(acpi_get_gpe_device)
 775
 776/*******************************************************************************
 777 *
 778 * FUNCTION:    acpi_ev_get_gpe_device
 779 *
 780 * PARAMETERS:  GPE_WALK_CALLBACK
 781 *
 782 * RETURN:      Status
 783 *
 784 * DESCRIPTION: Matches the input GPE index (0-current_gpe_count) with a GPE
 785 *              block device. NULL if the GPE is one of the FADT-defined GPEs.
 786 *
 787 ******************************************************************************/
 788static acpi_status
 789acpi_ev_get_gpe_device(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
 790                       struct acpi_gpe_block_info *gpe_block, void *context)
 791{
 792        struct acpi_gpe_device_info *info = context;
 793
 794        /* Increment Index by the number of GPEs in this block */
 795
 796        info->next_block_base_index +=
 797            (gpe_block->register_count * ACPI_GPE_REGISTER_WIDTH);
 798
 799        if (info->index < info->next_block_base_index) {
 800                /*
 801                 * The GPE index is within this block, get the node. Leave the node
 802                 * NULL for the FADT-defined GPEs
 803                 */
 804                if ((gpe_block->node)->type == ACPI_TYPE_DEVICE) {
 805                        info->gpe_device = gpe_block->node;
 806                }
 807
 808                info->status = AE_OK;
 809                return (AE_CTRL_END);
 810        }
 811
 812        return (AE_OK);
 813}
 814
 815/******************************************************************************
 816 *
 817 * FUNCTION:    acpi_disable_all_gpes
 818 *
 819 * PARAMETERS:  None
 820 *
 821 * RETURN:      Status
 822 *
 823 * DESCRIPTION: Disable and clear all GPEs in all GPE blocks
 824 *
 825 ******************************************************************************/
 826
 827acpi_status acpi_disable_all_gpes(void)
 828{
 829        acpi_status status;
 830
 831        ACPI_FUNCTION_TRACE(acpi_disable_all_gpes);
 832
 833        status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
 834        if (ACPI_FAILURE(status)) {
 835                return_ACPI_STATUS(status);
 836        }
 837
 838        status = acpi_hw_disable_all_gpes();
 839        (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
 840
 841        return_ACPI_STATUS(status);
 842}
 843
 844/******************************************************************************
 845 *
 846 * FUNCTION:    acpi_enable_all_runtime_gpes
 847 *
 848 * PARAMETERS:  None
 849 *
 850 * RETURN:      Status
 851 *
 852 * DESCRIPTION: Enable all "runtime" GPEs, in all GPE blocks
 853 *
 854 ******************************************************************************/
 855
 856acpi_status acpi_enable_all_runtime_gpes(void)
 857{
 858        acpi_status status;
 859
 860        ACPI_FUNCTION_TRACE(acpi_enable_all_runtime_gpes);
 861
 862        status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
 863        if (ACPI_FAILURE(status)) {
 864                return_ACPI_STATUS(status);
 865        }
 866
 867        status = acpi_hw_enable_all_runtime_gpes();
 868        (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
 869
 870        return_ACPI_STATUS(status);
 871}
 872