linux/drivers/acpi/acpica/evxfgpe.c
<<
>>
Prefs
   1/******************************************************************************
   2 *
   3 * Module Name: evxfgpe - External Interfaces for General Purpose Events (GPEs)
   4 *
   5 *****************************************************************************/
   6
   7/*
   8 * Copyright (C) 2000 - 2011, 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
  49#define _COMPONENT          ACPI_EVENTS
  50ACPI_MODULE_NAME("evxfgpe")
  51
  52/******************************************************************************
  53 *
  54 * FUNCTION:    acpi_update_all_gpes
  55 *
  56 * PARAMETERS:  None
  57 *
  58 * RETURN:      Status
  59 *
  60 * DESCRIPTION: Complete GPE initialization and enable all GPEs that have
  61 *              associated _Lxx or _Exx methods and are not pointed to by any
  62 *              device _PRW methods (this indicates that these GPEs are
  63 *              generally intended for system or device wakeup. Such GPEs
  64 *              have to be enabled directly when the devices whose _PRW
  65 *              methods point to them are set up for wakeup signaling.)
  66 *
  67 * NOTE: Should be called after any GPEs are added to the system. Primarily,
  68 * after the system _PRW methods have been run, but also after a GPE Block
  69 * Device has been added or if any new GPE methods have been added via a
  70 * dynamic table load.
  71 *
  72 ******************************************************************************/
  73
  74acpi_status acpi_update_all_gpes(void)
  75{
  76        acpi_status status;
  77
  78        ACPI_FUNCTION_TRACE(acpi_update_all_gpes);
  79
  80        status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
  81        if (ACPI_FAILURE(status)) {
  82                return_ACPI_STATUS(status);
  83        }
  84
  85        if (acpi_gbl_all_gpes_initialized) {
  86                goto unlock_and_exit;
  87        }
  88
  89        status = acpi_ev_walk_gpe_list(acpi_ev_initialize_gpe_block, NULL);
  90        if (ACPI_SUCCESS(status)) {
  91                acpi_gbl_all_gpes_initialized = TRUE;
  92        }
  93
  94unlock_and_exit:
  95        (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
  96
  97        return_ACPI_STATUS(status);
  98}
  99
 100ACPI_EXPORT_SYMBOL(acpi_update_all_gpes)
 101
 102/*******************************************************************************
 103 *
 104 * FUNCTION:    acpi_enable_gpe
 105 *
 106 * PARAMETERS:  gpe_device      - Parent GPE Device. NULL for GPE0/GPE1
 107 *              gpe_number      - GPE level within the GPE block
 108 *
 109 * RETURN:      Status
 110 *
 111 * DESCRIPTION: Add a reference to a GPE. On the first reference, the GPE is
 112 *              hardware-enabled.
 113 *
 114 ******************************************************************************/
 115
 116acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number)
 117{
 118        acpi_status status = AE_BAD_PARAMETER;
 119        struct acpi_gpe_event_info *gpe_event_info;
 120        acpi_cpu_flags flags;
 121
 122        ACPI_FUNCTION_TRACE(acpi_enable_gpe);
 123
 124        flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
 125
 126        /* Ensure that we have a valid GPE number */
 127
 128        gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
 129        if (gpe_event_info) {
 130                status = acpi_ev_add_gpe_reference(gpe_event_info);
 131        }
 132
 133        acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
 134        return_ACPI_STATUS(status);
 135}
 136ACPI_EXPORT_SYMBOL(acpi_enable_gpe)
 137
 138/*******************************************************************************
 139 *
 140 * FUNCTION:    acpi_disable_gpe
 141 *
 142 * PARAMETERS:  gpe_device      - Parent GPE Device. NULL for GPE0/GPE1
 143 *              gpe_number      - GPE level within the GPE block
 144 *
 145 * RETURN:      Status
 146 *
 147 * DESCRIPTION: Remove a reference to a GPE. When the last reference is
 148 *              removed, only then is the GPE disabled (for runtime GPEs), or
 149 *              the GPE mask bit disabled (for wake GPEs)
 150 *
 151 ******************************************************************************/
 152
 153acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number)
 154{
 155        acpi_status status = AE_BAD_PARAMETER;
 156        struct acpi_gpe_event_info *gpe_event_info;
 157        acpi_cpu_flags flags;
 158
 159        ACPI_FUNCTION_TRACE(acpi_disable_gpe);
 160
 161        flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
 162
 163        /* Ensure that we have a valid GPE number */
 164
 165        gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
 166        if (gpe_event_info) {
 167                status = acpi_ev_remove_gpe_reference(gpe_event_info) ;
 168        }
 169
 170        acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
 171        return_ACPI_STATUS(status);
 172}
 173ACPI_EXPORT_SYMBOL(acpi_disable_gpe)
 174
 175
 176/*******************************************************************************
 177 *
 178 * FUNCTION:    acpi_setup_gpe_for_wake
 179 *
 180 * PARAMETERS:  wake_device         - Device associated with the GPE (via _PRW)
 181 *              gpe_device          - Parent GPE Device. NULL for GPE0/GPE1
 182 *              gpe_number          - GPE level within the GPE block
 183 *
 184 * RETURN:      Status
 185 *
 186 * DESCRIPTION: Mark a GPE as having the ability to wake the system. This
 187 *              interface is intended to be used as the host executes the
 188 *              _PRW methods (Power Resources for Wake) in the system tables.
 189 *              Each _PRW appears under a Device Object (The wake_device), and
 190 *              contains the info for the wake GPE associated with the
 191 *              wake_device.
 192 *
 193 ******************************************************************************/
 194acpi_status
 195acpi_setup_gpe_for_wake(acpi_handle wake_device,
 196                        acpi_handle gpe_device, u32 gpe_number)
 197{
 198        acpi_status status = AE_BAD_PARAMETER;
 199        struct acpi_gpe_event_info *gpe_event_info;
 200        struct acpi_namespace_node *device_node;
 201        struct acpi_gpe_notify_object *notify_object;
 202        acpi_cpu_flags flags;
 203        u8 gpe_dispatch_mask;
 204
 205        ACPI_FUNCTION_TRACE(acpi_setup_gpe_for_wake);
 206
 207        /* Parameter Validation */
 208
 209        if (!wake_device) {
 210                /*
 211                 * By forcing wake_device to be valid, we automatically enable the
 212                 * implicit notify feature on all hosts.
 213                 */
 214                return_ACPI_STATUS(AE_BAD_PARAMETER);
 215        }
 216
 217        flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
 218
 219        /* Ensure that we have a valid GPE number */
 220
 221        gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
 222        if (!gpe_event_info) {
 223                goto unlock_and_exit;
 224        }
 225
 226        if (wake_device == ACPI_ROOT_OBJECT) {
 227                goto out;
 228        }
 229
 230        /*
 231         * If there is no method or handler for this GPE, then the
 232         * wake_device will be notified whenever this GPE fires (aka
 233         * "implicit notify") Note: The GPE is assumed to be
 234         * level-triggered (for windows compatibility).
 235         */
 236        gpe_dispatch_mask = gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK;
 237        if (gpe_dispatch_mask != ACPI_GPE_DISPATCH_NONE
 238            && gpe_dispatch_mask != ACPI_GPE_DISPATCH_NOTIFY) {
 239                goto out;
 240        }
 241
 242        /* Validate wake_device is of type Device */
 243
 244        device_node = ACPI_CAST_PTR(struct acpi_namespace_node, wake_device);
 245        if (device_node->type != ACPI_TYPE_DEVICE) {
 246                goto unlock_and_exit;
 247        }
 248
 249        if (gpe_dispatch_mask == ACPI_GPE_DISPATCH_NONE) {
 250                gpe_event_info->flags = (ACPI_GPE_DISPATCH_NOTIFY |
 251                                         ACPI_GPE_LEVEL_TRIGGERED);
 252                gpe_event_info->dispatch.device.node = device_node;
 253                gpe_event_info->dispatch.device.next = NULL;
 254        } else {
 255                /* There are multiple devices to notify implicitly. */
 256
 257                notify_object = ACPI_ALLOCATE_ZEROED(sizeof(*notify_object));
 258                if (!notify_object) {
 259                        status = AE_NO_MEMORY;
 260                        goto unlock_and_exit;
 261                }
 262
 263                notify_object->node = device_node;
 264                notify_object->next = gpe_event_info->dispatch.device.next;
 265                gpe_event_info->dispatch.device.next = notify_object;
 266        }
 267
 268 out:
 269        gpe_event_info->flags |= ACPI_GPE_CAN_WAKE;
 270        status = AE_OK;
 271
 272 unlock_and_exit:
 273        acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
 274        return_ACPI_STATUS(status);
 275}
 276ACPI_EXPORT_SYMBOL(acpi_setup_gpe_for_wake)
 277
 278/*******************************************************************************
 279 *
 280 * FUNCTION:    acpi_set_gpe_wake_mask
 281 *
 282 * PARAMETERS:  gpe_device      - Parent GPE Device. NULL for GPE0/GPE1
 283 *              gpe_number      - GPE level within the GPE block
 284 *              Action          - Enable or Disable
 285 *
 286 * RETURN:      Status
 287 *
 288 * DESCRIPTION: Set or clear the GPE's wakeup enable mask bit. The GPE must
 289 *              already be marked as a WAKE GPE.
 290 *
 291 ******************************************************************************/
 292
 293acpi_status acpi_set_gpe_wake_mask(acpi_handle gpe_device, u32 gpe_number, u8 action)
 294{
 295        acpi_status status = AE_OK;
 296        struct acpi_gpe_event_info *gpe_event_info;
 297        struct acpi_gpe_register_info *gpe_register_info;
 298        acpi_cpu_flags flags;
 299        u32 register_bit;
 300
 301        ACPI_FUNCTION_TRACE(acpi_set_gpe_wake_mask);
 302
 303        flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
 304
 305        /*
 306         * Ensure that we have a valid GPE number and that this GPE is in
 307         * fact a wake GPE
 308         */
 309        gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
 310        if (!gpe_event_info) {
 311                status = AE_BAD_PARAMETER;
 312                goto unlock_and_exit;
 313        }
 314
 315        if (!(gpe_event_info->flags & ACPI_GPE_CAN_WAKE)) {
 316                status = AE_TYPE;
 317                goto unlock_and_exit;
 318        }
 319
 320        gpe_register_info = gpe_event_info->register_info;
 321        if (!gpe_register_info) {
 322                status = AE_NOT_EXIST;
 323                goto unlock_and_exit;
 324        }
 325
 326        register_bit =
 327            acpi_hw_get_gpe_register_bit(gpe_event_info, gpe_register_info);
 328
 329        /* Perform the action */
 330
 331        switch (action) {
 332        case ACPI_GPE_ENABLE:
 333                ACPI_SET_BIT(gpe_register_info->enable_for_wake,
 334                             (u8)register_bit);
 335                break;
 336
 337        case ACPI_GPE_DISABLE:
 338                ACPI_CLEAR_BIT(gpe_register_info->enable_for_wake,
 339                               (u8)register_bit);
 340                break;
 341
 342        default:
 343                ACPI_ERROR((AE_INFO, "%u, Invalid action", action));
 344                status = AE_BAD_PARAMETER;
 345                break;
 346        }
 347
 348unlock_and_exit:
 349        acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
 350        return_ACPI_STATUS(status);
 351}
 352
 353ACPI_EXPORT_SYMBOL(acpi_set_gpe_wake_mask)
 354
 355/*******************************************************************************
 356 *
 357 * FUNCTION:    acpi_clear_gpe
 358 *
 359 * PARAMETERS:  gpe_device      - Parent GPE Device. NULL for GPE0/GPE1
 360 *              gpe_number      - GPE level within the GPE block
 361 *
 362 * RETURN:      Status
 363 *
 364 * DESCRIPTION: Clear an ACPI event (general purpose)
 365 *
 366 ******************************************************************************/
 367acpi_status acpi_clear_gpe(acpi_handle gpe_device, u32 gpe_number)
 368{
 369        acpi_status status = AE_OK;
 370        struct acpi_gpe_event_info *gpe_event_info;
 371        acpi_cpu_flags flags;
 372
 373        ACPI_FUNCTION_TRACE(acpi_clear_gpe);
 374
 375        flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
 376
 377        /* Ensure that we have a valid GPE number */
 378
 379        gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
 380        if (!gpe_event_info) {
 381                status = AE_BAD_PARAMETER;
 382                goto unlock_and_exit;
 383        }
 384
 385        status = acpi_hw_clear_gpe(gpe_event_info);
 386
 387      unlock_and_exit:
 388        acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
 389        return_ACPI_STATUS(status);
 390}
 391
 392ACPI_EXPORT_SYMBOL(acpi_clear_gpe)
 393
 394/*******************************************************************************
 395 *
 396 * FUNCTION:    acpi_get_gpe_status
 397 *
 398 * PARAMETERS:  gpe_device      - Parent GPE Device. NULL for GPE0/GPE1
 399 *              gpe_number      - GPE level within the GPE block
 400 *              event_status    - Where the current status of the event will
 401 *                                be returned
 402 *
 403 * RETURN:      Status
 404 *
 405 * DESCRIPTION: Get the current status of a GPE (signalled/not_signalled)
 406 *
 407 ******************************************************************************/
 408acpi_status
 409acpi_get_gpe_status(acpi_handle gpe_device,
 410                    u32 gpe_number, acpi_event_status *event_status)
 411{
 412        acpi_status status = AE_OK;
 413        struct acpi_gpe_event_info *gpe_event_info;
 414        acpi_cpu_flags flags;
 415
 416        ACPI_FUNCTION_TRACE(acpi_get_gpe_status);
 417
 418        flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
 419
 420        /* Ensure that we have a valid GPE number */
 421
 422        gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
 423        if (!gpe_event_info) {
 424                status = AE_BAD_PARAMETER;
 425                goto unlock_and_exit;
 426        }
 427
 428        /* Obtain status on the requested GPE number */
 429
 430        status = acpi_hw_get_gpe_status(gpe_event_info, event_status);
 431
 432        if (gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK)
 433                *event_status |= ACPI_EVENT_FLAG_HANDLE;
 434
 435      unlock_and_exit:
 436        acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
 437        return_ACPI_STATUS(status);
 438}
 439
 440ACPI_EXPORT_SYMBOL(acpi_get_gpe_status)
 441
 442/******************************************************************************
 443 *
 444 * FUNCTION:    acpi_disable_all_gpes
 445 *
 446 * PARAMETERS:  None
 447 *
 448 * RETURN:      Status
 449 *
 450 * DESCRIPTION: Disable and clear all GPEs in all GPE blocks
 451 *
 452 ******************************************************************************/
 453
 454acpi_status acpi_disable_all_gpes(void)
 455{
 456        acpi_status status;
 457
 458        ACPI_FUNCTION_TRACE(acpi_disable_all_gpes);
 459
 460        status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
 461        if (ACPI_FAILURE(status)) {
 462                return_ACPI_STATUS(status);
 463        }
 464
 465        status = acpi_hw_disable_all_gpes();
 466        (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
 467
 468        return_ACPI_STATUS(status);
 469}
 470
 471ACPI_EXPORT_SYMBOL(acpi_disable_all_gpes)
 472
 473/******************************************************************************
 474 *
 475 * FUNCTION:    acpi_enable_all_runtime_gpes
 476 *
 477 * PARAMETERS:  None
 478 *
 479 * RETURN:      Status
 480 *
 481 * DESCRIPTION: Enable all "runtime" GPEs, in all GPE blocks
 482 *
 483 ******************************************************************************/
 484
 485acpi_status acpi_enable_all_runtime_gpes(void)
 486{
 487        acpi_status status;
 488
 489        ACPI_FUNCTION_TRACE(acpi_enable_all_runtime_gpes);
 490
 491        status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
 492        if (ACPI_FAILURE(status)) {
 493                return_ACPI_STATUS(status);
 494        }
 495
 496        status = acpi_hw_enable_all_runtime_gpes();
 497        (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
 498
 499        return_ACPI_STATUS(status);
 500}
 501
 502ACPI_EXPORT_SYMBOL(acpi_enable_all_runtime_gpes)
 503
 504/*******************************************************************************
 505 *
 506 * FUNCTION:    acpi_install_gpe_block
 507 *
 508 * PARAMETERS:  gpe_device          - Handle to the parent GPE Block Device
 509 *              gpe_block_address   - Address and space_iD
 510 *              register_count      - Number of GPE register pairs in the block
 511 *              interrupt_number    - H/W interrupt for the block
 512 *
 513 * RETURN:      Status
 514 *
 515 * DESCRIPTION: Create and Install a block of GPE registers. The GPEs are not
 516 *              enabled here.
 517 *
 518 ******************************************************************************/
 519acpi_status
 520acpi_install_gpe_block(acpi_handle gpe_device,
 521                       struct acpi_generic_address *gpe_block_address,
 522                       u32 register_count, u32 interrupt_number)
 523{
 524        acpi_status status;
 525        union acpi_operand_object *obj_desc;
 526        struct acpi_namespace_node *node;
 527        struct acpi_gpe_block_info *gpe_block;
 528
 529        ACPI_FUNCTION_TRACE(acpi_install_gpe_block);
 530
 531        if ((!gpe_device) || (!gpe_block_address) || (!register_count)) {
 532                return_ACPI_STATUS(AE_BAD_PARAMETER);
 533        }
 534
 535        status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
 536        if (ACPI_FAILURE(status)) {
 537                return (status);
 538        }
 539
 540        node = acpi_ns_validate_handle(gpe_device);
 541        if (!node) {
 542                status = AE_BAD_PARAMETER;
 543                goto unlock_and_exit;
 544        }
 545
 546        /*
 547         * For user-installed GPE Block Devices, the gpe_block_base_number
 548         * is always zero
 549         */
 550        status =
 551            acpi_ev_create_gpe_block(node, gpe_block_address, register_count, 0,
 552                                     interrupt_number, &gpe_block);
 553        if (ACPI_FAILURE(status)) {
 554                goto unlock_and_exit;
 555        }
 556
 557        /* Install block in the device_object attached to the node */
 558
 559        obj_desc = acpi_ns_get_attached_object(node);
 560        if (!obj_desc) {
 561
 562                /*
 563                 * No object, create a new one (Device nodes do not always have
 564                 * an attached object)
 565                 */
 566                obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_DEVICE);
 567                if (!obj_desc) {
 568                        status = AE_NO_MEMORY;
 569                        goto unlock_and_exit;
 570                }
 571
 572                status =
 573                    acpi_ns_attach_object(node, obj_desc, ACPI_TYPE_DEVICE);
 574
 575                /* Remove local reference to the object */
 576
 577                acpi_ut_remove_reference(obj_desc);
 578
 579                if (ACPI_FAILURE(status)) {
 580                        goto unlock_and_exit;
 581                }
 582        }
 583
 584        /* Now install the GPE block in the device_object */
 585
 586        obj_desc->device.gpe_block = gpe_block;
 587
 588      unlock_and_exit:
 589        (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
 590        return_ACPI_STATUS(status);
 591}
 592
 593ACPI_EXPORT_SYMBOL(acpi_install_gpe_block)
 594
 595/*******************************************************************************
 596 *
 597 * FUNCTION:    acpi_remove_gpe_block
 598 *
 599 * PARAMETERS:  gpe_device          - Handle to the parent GPE Block Device
 600 *
 601 * RETURN:      Status
 602 *
 603 * DESCRIPTION: Remove a previously installed block of GPE registers
 604 *
 605 ******************************************************************************/
 606acpi_status acpi_remove_gpe_block(acpi_handle gpe_device)
 607{
 608        union acpi_operand_object *obj_desc;
 609        acpi_status status;
 610        struct acpi_namespace_node *node;
 611
 612        ACPI_FUNCTION_TRACE(acpi_remove_gpe_block);
 613
 614        if (!gpe_device) {
 615                return_ACPI_STATUS(AE_BAD_PARAMETER);
 616        }
 617
 618        status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
 619        if (ACPI_FAILURE(status)) {
 620                return (status);
 621        }
 622
 623        node = acpi_ns_validate_handle(gpe_device);
 624        if (!node) {
 625                status = AE_BAD_PARAMETER;
 626                goto unlock_and_exit;
 627        }
 628
 629        /* Get the device_object attached to the node */
 630
 631        obj_desc = acpi_ns_get_attached_object(node);
 632        if (!obj_desc || !obj_desc->device.gpe_block) {
 633                return_ACPI_STATUS(AE_NULL_OBJECT);
 634        }
 635
 636        /* Delete the GPE block (but not the device_object) */
 637
 638        status = acpi_ev_delete_gpe_block(obj_desc->device.gpe_block);
 639        if (ACPI_SUCCESS(status)) {
 640                obj_desc->device.gpe_block = NULL;
 641        }
 642
 643      unlock_and_exit:
 644        (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
 645        return_ACPI_STATUS(status);
 646}
 647
 648ACPI_EXPORT_SYMBOL(acpi_remove_gpe_block)
 649
 650/*******************************************************************************
 651 *
 652 * FUNCTION:    acpi_get_gpe_device
 653 *
 654 * PARAMETERS:  Index               - System GPE index (0-current_gpe_count)
 655 *              gpe_device          - Where the parent GPE Device is returned
 656 *
 657 * RETURN:      Status
 658 *
 659 * DESCRIPTION: Obtain the GPE device associated with the input index. A NULL
 660 *              gpe device indicates that the gpe number is contained in one of
 661 *              the FADT-defined gpe blocks. Otherwise, the GPE block device.
 662 *
 663 ******************************************************************************/
 664acpi_status
 665acpi_get_gpe_device(u32 index, acpi_handle *gpe_device)
 666{
 667        struct acpi_gpe_device_info info;
 668        acpi_status status;
 669
 670        ACPI_FUNCTION_TRACE(acpi_get_gpe_device);
 671
 672        if (!gpe_device) {
 673                return_ACPI_STATUS(AE_BAD_PARAMETER);
 674        }
 675
 676        if (index >= acpi_current_gpe_count) {
 677                return_ACPI_STATUS(AE_NOT_EXIST);
 678        }
 679
 680        /* Setup and walk the GPE list */
 681
 682        info.index = index;
 683        info.status = AE_NOT_EXIST;
 684        info.gpe_device = NULL;
 685        info.next_block_base_index = 0;
 686
 687        status = acpi_ev_walk_gpe_list(acpi_ev_get_gpe_device, &info);
 688        if (ACPI_FAILURE(status)) {
 689                return_ACPI_STATUS(status);
 690        }
 691
 692        *gpe_device = ACPI_CAST_PTR(acpi_handle, info.gpe_device);
 693        return_ACPI_STATUS(info.status);
 694}
 695
 696ACPI_EXPORT_SYMBOL(acpi_get_gpe_device)
 697