* evgpe - GPE handling and dispatch
  */
 acpi_status
-acpi_ev_update_gpe_enable_masks(struct acpi_gpe_event_info *gpe_event_info,
-                               u8 type);
+acpi_ev_update_gpe_enable_masks(struct acpi_gpe_event_info *gpe_event_info);
 
 acpi_status
 acpi_ev_enable_gpe(struct acpi_gpe_event_info *gpe_event_info,
 
 u32 acpi_ev_gpe_detect(struct acpi_gpe_xrupt_info *gpe_xrupt_list);
 
-acpi_status
-acpi_ev_set_gpe_type(struct acpi_gpe_event_info *gpe_event_info, u8 type);
-
 acpi_status
 acpi_ev_check_for_wake_only_gpe(struct acpi_gpe_event_info *gpe_event_info);
 
 
        struct acpi_gpe_register_info *register_info;   /* Backpointer to register info */
        u8 flags;               /* Misc info about this GPE */
        u8 gpe_number;          /* This GPE */
+       u8 runtime_count;
+       u8 wakeup_count;
 };
 
 /* Information about a GPE register pair, one per each status/enable pair in an array */
 
 /* Local prototypes */
 static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context);
 
-/*******************************************************************************
- *
- * FUNCTION:    acpi_ev_set_gpe_type
- *
- * PARAMETERS:  gpe_event_info          - GPE to set
- *              Type                    - New type
- *
- * RETURN:      Status
- *
- * DESCRIPTION: Sets the new type for the GPE (wake, run, or wake/run)
- *
- ******************************************************************************/
-
-acpi_status
-acpi_ev_set_gpe_type(struct acpi_gpe_event_info *gpe_event_info, u8 type)
-{
-       acpi_status status;
-
-       ACPI_FUNCTION_TRACE(ev_set_gpe_type);
-
-       /* Validate type and update register enable masks */
-
-       switch (type) {
-       case ACPI_GPE_TYPE_WAKE:
-       case ACPI_GPE_TYPE_RUNTIME:
-       case ACPI_GPE_TYPE_WAKE_RUN:
-               break;
-
-       default:
-               return_ACPI_STATUS(AE_BAD_PARAMETER);
-       }
-
-       /* Disable the GPE if currently enabled */
-
-       status = acpi_ev_disable_gpe(gpe_event_info);
-
-       /* Clear the type bits and insert the new Type */
-
-       gpe_event_info->flags &= ~ACPI_GPE_TYPE_MASK;
-       gpe_event_info->flags |= type;
-       return_ACPI_STATUS(status);
-}
-
 /*******************************************************************************
  *
  * FUNCTION:    acpi_ev_update_gpe_enable_masks
  *
  * PARAMETERS:  gpe_event_info          - GPE to update
- *              Type                    - What to do: ACPI_GPE_DISABLE or
- *                                        ACPI_GPE_ENABLE
  *
  * RETURN:      Status
  *
  ******************************************************************************/
 
 acpi_status
-acpi_ev_update_gpe_enable_masks(struct acpi_gpe_event_info *gpe_event_info,
-                               u8 type)
+acpi_ev_update_gpe_enable_masks(struct acpi_gpe_event_info *gpe_event_info)
 {
        struct acpi_gpe_register_info *gpe_register_info;
        u8 register_bit;
            (1 <<
             (gpe_event_info->gpe_number - gpe_register_info->base_gpe_number));
 
-       /* 1) Disable case. Simply clear all enable bits */
-
-       if (type == ACPI_GPE_DISABLE) {
-               ACPI_CLEAR_BIT(gpe_register_info->enable_for_wake,
-                              register_bit);
-               ACPI_CLEAR_BIT(gpe_register_info->enable_for_run, register_bit);
-               return_ACPI_STATUS(AE_OK);
-       }
-
-       /* 2) Enable case. Set/Clear the appropriate enable bits */
+       ACPI_CLEAR_BIT(gpe_register_info->enable_for_wake, register_bit);
+       ACPI_CLEAR_BIT(gpe_register_info->enable_for_run, register_bit);
 
-       switch (gpe_event_info->flags & ACPI_GPE_TYPE_MASK) {
-       case ACPI_GPE_TYPE_WAKE:
-               ACPI_SET_BIT(gpe_register_info->enable_for_wake, register_bit);
-               ACPI_CLEAR_BIT(gpe_register_info->enable_for_run, register_bit);
-               break;
-
-       case ACPI_GPE_TYPE_RUNTIME:
-               ACPI_CLEAR_BIT(gpe_register_info->enable_for_wake,
-                              register_bit);
+       if (gpe_event_info->runtime_count)
                ACPI_SET_BIT(gpe_register_info->enable_for_run, register_bit);
-               break;
 
-       case ACPI_GPE_TYPE_WAKE_RUN:
+       if (gpe_event_info->wakeup_count)
                ACPI_SET_BIT(gpe_register_info->enable_for_wake, register_bit);
-               ACPI_SET_BIT(gpe_register_info->enable_for_run, register_bit);
-               break;
-
-       default:
-               return_ACPI_STATUS(AE_BAD_PARAMETER);
-       }
 
        return_ACPI_STATUS(AE_OK);
 }
 
        /* Make sure HW enable masks are updated */
 
-       status =
-           acpi_ev_update_gpe_enable_masks(gpe_event_info, ACPI_GPE_ENABLE);
-       if (ACPI_FAILURE(status)) {
+       status = acpi_ev_update_gpe_enable_masks(gpe_event_info);
+       if (ACPI_FAILURE(status))
                return_ACPI_STATUS(status);
-       }
 
        /* Mark wake-enabled or HW enable, or both */
 
-       switch (gpe_event_info->flags & ACPI_GPE_TYPE_MASK) {
-       case ACPI_GPE_TYPE_WAKE:
-
-               ACPI_SET_BIT(gpe_event_info->flags, ACPI_GPE_WAKE_ENABLED);
-               break;
-
-       case ACPI_GPE_TYPE_WAKE_RUN:
-
-               ACPI_SET_BIT(gpe_event_info->flags, ACPI_GPE_WAKE_ENABLED);
-
-               /*lint -fallthrough */
-
-       case ACPI_GPE_TYPE_RUNTIME:
-
-               ACPI_SET_BIT(gpe_event_info->flags, ACPI_GPE_RUN_ENABLED);
-
-               if (write_to_hardware) {
-
-                       /* Clear the GPE (of stale events), then enable it */
-
-                       status = acpi_hw_clear_gpe(gpe_event_info);
-                       if (ACPI_FAILURE(status)) {
-                               return_ACPI_STATUS(status);
-                       }
-
-                       /* Enable the requested runtime GPE */
-
-                       status = acpi_hw_write_gpe_enable_reg(gpe_event_info);
-               }
-               break;
+       if (gpe_event_info->runtime_count && write_to_hardware) {
+               /* Clear the GPE (of stale events), then enable it */
+               status = acpi_hw_clear_gpe(gpe_event_info);
+               if (ACPI_FAILURE(status))
+                       return_ACPI_STATUS(status);
 
-       default:
-               return_ACPI_STATUS(AE_BAD_PARAMETER);
+               /* Enable the requested runtime GPE */
+               status = acpi_hw_write_gpe_enable_reg(gpe_event_info);
        }
 
        return_ACPI_STATUS(AE_OK);
 
        /* Make sure HW enable masks are updated */
 
-       status =
-           acpi_ev_update_gpe_enable_masks(gpe_event_info, ACPI_GPE_DISABLE);
-       if (ACPI_FAILURE(status)) {
+       status = acpi_ev_update_gpe_enable_masks(gpe_event_info);
+       if (ACPI_FAILURE(status))
                return_ACPI_STATUS(status);
-       }
-
-       /* Clear the appropriate enabled flags for this GPE */
-
-       switch (gpe_event_info->flags & ACPI_GPE_TYPE_MASK) {
-       case ACPI_GPE_TYPE_WAKE:
-               ACPI_CLEAR_BIT(gpe_event_info->flags, ACPI_GPE_WAKE_ENABLED);
-               break;
-
-       case ACPI_GPE_TYPE_WAKE_RUN:
-               ACPI_CLEAR_BIT(gpe_event_info->flags, ACPI_GPE_WAKE_ENABLED);
-
-               /* fallthrough */
-
-       case ACPI_GPE_TYPE_RUNTIME:
-
-               /* Disable the requested runtime GPE */
-
-               ACPI_CLEAR_BIT(gpe_event_info->flags, ACPI_GPE_RUN_ENABLED);
-               break;
-
-       default:
-               break;
-       }
 
        /*
         * Even if we don't know the GPE type, make sure that we always
 
        u32 gpe_number;
        char name[ACPI_NAME_SIZE + 1];
        u8 type;
-       acpi_status status;
 
        ACPI_FUNCTION_TRACE(ev_save_method_info);
 
 
        /*
         * Now we can add this information to the gpe_event_info block for use
-        * during dispatch of this GPE. Default type is RUNTIME, although this may
-        * change when the _PRW methods are executed later.
+        * during dispatch of this GPE.
         */
        gpe_event_info =
            &gpe_block->event_info[gpe_number - gpe_block->block_base_number];
 
-       gpe_event_info->flags = (u8)
-           (type | ACPI_GPE_DISPATCH_METHOD | ACPI_GPE_TYPE_RUNTIME);
+       gpe_event_info->flags = (u8) (type | ACPI_GPE_DISPATCH_METHOD);
 
        gpe_event_info->dispatch.method_node =
            (struct acpi_namespace_node *)obj_handle;
 
-       /* Update enable mask, but don't enable the HW GPE as of yet */
-
-       status = acpi_ev_enable_gpe(gpe_event_info, FALSE);
-
        ACPI_DEBUG_PRINT((ACPI_DB_LOAD,
                          "Registered GPE method %s as GPE number 0x%.2X\n",
                          name, gpe_number));
-       return_ACPI_STATUS(status);
+       return_ACPI_STATUS(AE_OK);
 }
 
 /*******************************************************************************
                                                        gpe_block->
                                                        block_base_number];
 
-               /* Mark GPE for WAKE-ONLY but WAKE_DISABLED */
-
-               gpe_event_info->flags &=
-                   ~(ACPI_GPE_WAKE_ENABLED | ACPI_GPE_RUN_ENABLED);
-
-               status =
-                   acpi_ev_set_gpe_type(gpe_event_info, ACPI_GPE_TYPE_WAKE);
-               if (ACPI_FAILURE(status)) {
-                       goto cleanup;
-               }
-
-               status =
-                   acpi_ev_update_gpe_enable_masks(gpe_event_info,
-                                                   ACPI_GPE_DISABLE);
+               gpe_event_info->flags |= ACPI_GPE_CAN_WAKE;
        }
 
       cleanup:
 acpi_ev_initialize_gpe_block(struct acpi_namespace_node *gpe_device,
                             struct acpi_gpe_block_info *gpe_block)
 {
-       acpi_status status;
        struct acpi_gpe_event_info *gpe_event_info;
        struct acpi_gpe_walk_info gpe_info;
        u32 wake_gpe_count;
                gpe_info.gpe_block = gpe_block;
                gpe_info.gpe_device = gpe_device;
 
-               status =
-                   acpi_ns_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
+               acpi_ns_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
                                           ACPI_UINT32_MAX, ACPI_NS_WALK_UNLOCK,
                                           acpi_ev_match_prw_and_gpe, NULL,
                                           &gpe_info, NULL);
        }
 
        /*
-        * Enable all GPEs in this block that have these attributes:
-        * 1) are "runtime" or "run/wake" GPEs, and
-        * 2) have a corresponding _Lxx or _Exx method
-        *
-        * Any other GPEs within this block must be enabled via the
-        * acpi_enable_gpe() external interface.
+        * Enable all GPEs that have a corresponding method and aren't
+        * capable of generating wakeups. Any other GPEs within this block
+        * must be enabled via the acpi_enable_gpe() interface.
         */
        wake_gpe_count = 0;
        gpe_enabled_count = 0;
+       if (gpe_device == acpi_gbl_fadt_gpe_device)
+               gpe_device = NULL;
 
        for (i = 0; i < gpe_block->register_count; i++) {
-               for (j = 0; j < 8; j++) {
+               for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++) {
+                       acpi_status status;
+                       acpi_size gpe_index;
+                       int gpe_number;
 
                        /* Get the info block for this particular GPE */
+                       gpe_index = (acpi_size)i * ACPI_GPE_REGISTER_WIDTH + j;
+                       gpe_event_info = &gpe_block->event_info[gpe_index];
 
-                       gpe_event_info = &gpe_block->event_info[((acpi_size) i *
-                                                                ACPI_GPE_REGISTER_WIDTH)
-                                                               + j];
-
-                       if (((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) ==
-                            ACPI_GPE_DISPATCH_METHOD) &&
-                           (gpe_event_info->flags & ACPI_GPE_TYPE_RUNTIME)) {
-                               gpe_enabled_count++;
-                       }
-
-                       if (gpe_event_info->flags & ACPI_GPE_TYPE_WAKE) {
+                       if (gpe_event_info->flags & ACPI_GPE_CAN_WAKE) {
                                wake_gpe_count++;
+                               if (acpi_gbl_leave_wake_gpes_disabled)
+                                       continue;
                        }
+
+                       if (!(gpe_event_info->flags & ACPI_GPE_DISPATCH_METHOD))
+                               continue;
+
+                       gpe_number = gpe_index + gpe_block->block_base_number;
+                       status = acpi_enable_gpe(gpe_device, gpe_number,
+                                               ACPI_GPE_TYPE_RUNTIME);
+                       if (ACPI_FAILURE(status))
+                               ACPI_ERROR((AE_INFO,
+                                               "Failed to enable GPE %02X\n",
+                                               gpe_number));
+                       else
+                               gpe_enabled_count++;
                }
        }
 
                          "Found %u Wake, Enabled %u Runtime GPEs in this block\n",
                          wake_gpe_count, gpe_enabled_count));
 
-       /* Enable all valid runtime GPEs found above */
-
-       status = acpi_hw_enable_runtime_gpe_block(NULL, gpe_block, NULL);
-       if (ACPI_FAILURE(status)) {
-               ACPI_ERROR((AE_INFO, "Could not enable GPEs in GpeBlock %p",
-                           gpe_block));
-       }
-
-       return_ACPI_STATUS(status);
+       return_ACPI_STATUS(AE_OK);
 }
 
 /*******************************************************************************
 
        handler->context = context;
        handler->method_node = gpe_event_info->dispatch.method_node;
 
-       /* Disable the GPE before installing the handler */
-
-       status = acpi_ev_disable_gpe(gpe_event_info);
-       if (ACPI_FAILURE(status)) {
-               goto unlock_and_exit;
-       }
-
        /* Install the handler */
 
        flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
                goto unlock_and_exit;
        }
 
-       /* Disable the GPE before removing the handler */
-
-       status = acpi_ev_disable_gpe(gpe_event_info);
-       if (ACPI_FAILURE(status)) {
-               goto unlock_and_exit;
-       }
-
        /* Make sure all deferred tasks are completed */
 
        (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
 
 
 /*******************************************************************************
  *
- * FUNCTION:    acpi_set_gpe_type
+ * FUNCTION:    acpi_set_gpe
  *
  * PARAMETERS:  gpe_device      - Parent GPE Device
  *              gpe_number      - GPE level within the GPE block
- *              Type            - New GPE type
+ *              action          - Enable or disable
+ *                                Called from ISR or not
  *
  * RETURN:      Status
  *
- * DESCRIPTION: Set the type of an individual GPE
+ * DESCRIPTION: Enable or disable an ACPI event (general purpose)
  *
  ******************************************************************************/
-acpi_status acpi_set_gpe_type(acpi_handle gpe_device, u32 gpe_number, u8 type)
+acpi_status acpi_set_gpe(acpi_handle gpe_device, u32 gpe_number, u8 action)
 {
        acpi_status status = AE_OK;
+       acpi_cpu_flags flags;
        struct acpi_gpe_event_info *gpe_event_info;
 
-       ACPI_FUNCTION_TRACE(acpi_set_gpe_type);
+       ACPI_FUNCTION_TRACE(acpi_set_gpe);
+
+       flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
 
        /* Ensure that we have a valid GPE number */
 
                goto unlock_and_exit;
        }
 
-       if ((gpe_event_info->flags & ACPI_GPE_TYPE_MASK) == type) {
-               return_ACPI_STATUS(AE_OK);
-       }
+       /* Perform the action */
+
+       switch (action) {
+       case ACPI_GPE_ENABLE:
+               status = acpi_ev_enable_gpe(gpe_event_info, TRUE);
+               break;
 
-       /* Set the new type (will disable GPE if currently enabled) */
+       case ACPI_GPE_DISABLE:
+               status = acpi_ev_disable_gpe(gpe_event_info);
+               break;
 
-       status = acpi_ev_set_gpe_type(gpe_event_info, type);
+       default:
+               ACPI_ERROR((AE_INFO, "Invalid action\n"));
+               status = AE_BAD_PARAMETER;
+               break;
+       }
 
       unlock_and_exit:
+       acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
        return_ACPI_STATUS(status);
 }
 
-ACPI_EXPORT_SYMBOL(acpi_set_gpe_type)
+ACPI_EXPORT_SYMBOL(acpi_set_gpe)
 
 /*******************************************************************************
  *
  *
  * PARAMETERS:  gpe_device      - Parent GPE Device
  *              gpe_number      - GPE level within the GPE block
- *              Flags           - Just enable, or also wake enable?
- *                                Called from ISR or not
+ *              type            - Purpose the GPE will be used for
  *
  * RETURN:      Status
  *
- * DESCRIPTION: Enable an ACPI event (general purpose)
+ * DESCRIPTION: Take a reference to a GPE and enable it if necessary
  *
  ******************************************************************************/
-acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number)
+acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number, u8 type)
 {
        acpi_status status = AE_OK;
        acpi_cpu_flags flags;
                goto unlock_and_exit;
        }
 
-       /* Perform the enable */
+       if (type & ACPI_GPE_TYPE_RUNTIME) {
+               if (++gpe_event_info->runtime_count == 1)
+                       status = acpi_ev_enable_gpe(gpe_event_info, TRUE);
 
-       status = acpi_ev_enable_gpe(gpe_event_info, TRUE);
+               if (ACPI_FAILURE(status))
+                       gpe_event_info->runtime_count--;
+       }
 
-      unlock_and_exit:
+       if (type & ACPI_GPE_TYPE_WAKE) {
+               if (!(gpe_event_info->flags & ACPI_GPE_CAN_WAKE)) {
+                       status = AE_BAD_PARAMETER;
+                       goto unlock_and_exit;
+               }
+
+               /*
+                * Wake-up GPEs are only enabled right prior to putting the
+                * system into a sleep state.
+                */
+               if (++gpe_event_info->wakeup_count == 1)
+                       acpi_ev_update_gpe_enable_masks(gpe_event_info);
+       }
+
+unlock_and_exit:
        acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
        return_ACPI_STATUS(status);
 }
-
 ACPI_EXPORT_SYMBOL(acpi_enable_gpe)
 
 /*******************************************************************************
  *
  * PARAMETERS:  gpe_device      - Parent GPE Device
  *              gpe_number      - GPE level within the GPE block
- *              Flags           - Just disable, or also wake disable?
- *                                Called from ISR or not
+ *              type            - Purpose the GPE won't be used for any more
  *
  * RETURN:      Status
  *
- * DESCRIPTION: Disable an ACPI event (general purpose)
+ * DESCRIPTION: Release a reference to a GPE and disable it if necessary
  *
  ******************************************************************************/
-acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number)
+acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number, u8 type)
 {
        acpi_status status = AE_OK;
        acpi_cpu_flags flags;
                goto unlock_and_exit;
        }
 
-       status = acpi_ev_disable_gpe(gpe_event_info);
+       if ((type & ACPI_GPE_TYPE_WAKE) && gpe_event_info->runtime_count) {
+               if (--gpe_event_info->runtime_count == 0)
+                       acpi_ev_disable_gpe(gpe_event_info);
+       }
+
+       if ((type & ACPI_GPE_TYPE_RUNTIME) && gpe_event_info->wakeup_count) {
+               /*
+                * Wake-up GPEs are not enabled after leaving system sleep
+                * states, so we don't need to disable them here.
+                */
+               if (--gpe_event_info->wakeup_count == 0)
+                       acpi_ev_update_gpe_enable_masks(gpe_event_info);
+       }
 
 unlock_and_exit:
        acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
        return_ACPI_STATUS(status);
 }
-
 ACPI_EXPORT_SYMBOL(acpi_disable_gpe)
 
 /*******************************************************************************
 
 
        if (device->wakeup.flags.valid) {
                /* Button's GPE is run-wake GPE */
-               acpi_set_gpe_type(device->wakeup.gpe_device,
-                                 device->wakeup.gpe_number,
-                                 ACPI_GPE_TYPE_WAKE_RUN);
                acpi_enable_gpe(device->wakeup.gpe_device,
-                               device->wakeup.gpe_number);
+                               device->wakeup.gpe_number,
+                               ACPI_GPE_TYPE_WAKE_RUN);
                device->wakeup.state.enabled = 1;
        }
 
 {
        struct acpi_button *button = acpi_driver_data(device);
 
+       if (device->wakeup.flags.valid) {
+               acpi_disable_gpe(device->wakeup.gpe_device,
+                               device->wakeup.gpe_number,
+                               ACPI_GPE_TYPE_WAKE_RUN);
+               device->wakeup.state.enabled = 0;
+       }
+
        acpi_button_remove_fs(device);
        input_unregister_device(button->input);
        kfree(button);
 
        pr_debug(PREFIX "transaction start\n");
        /* disable GPE during transaction if storm is detected */
        if (test_bit(EC_FLAGS_GPE_STORM, &ec->flags)) {
-               acpi_disable_gpe(NULL, ec->gpe);
+               acpi_set_gpe(NULL, ec->gpe, ACPI_GPE_DISABLE);
        }
 
        status = acpi_ec_transaction_unlocked(ec, t);
        if (test_bit(EC_FLAGS_GPE_STORM, &ec->flags)) {
                msleep(1);
                /* it is safe to enable GPE outside of transaction */
-               acpi_enable_gpe(NULL, ec->gpe);
+               acpi_set_gpe(NULL, ec->gpe, ACPI_GPE_ENABLE);
        } else if (t->irq_count > ACPI_EC_STORM_THRESHOLD) {
                pr_info(PREFIX "GPE storm detected, "
                        "transactions will use polling mode\n");
                                  &acpi_ec_gpe_handler, ec);
        if (ACPI_FAILURE(status))
                return -ENODEV;
-       acpi_set_gpe_type(NULL, ec->gpe, ACPI_GPE_TYPE_RUNTIME);
-       acpi_enable_gpe(NULL, ec->gpe);
+
+       acpi_enable_gpe(NULL, ec->gpe, ACPI_GPE_TYPE_RUNTIME);
        status = acpi_install_address_space_handler(ec->handle,
                                                    ACPI_ADR_SPACE_EC,
                                                    &acpi_ec_space_handler,
                } else {
                        acpi_remove_gpe_handler(NULL, ec->gpe,
                                &acpi_ec_gpe_handler);
+                       acpi_disable_gpe(NULL, ec->gpe, ACPI_GPE_TYPE_RUNTIME);
                        return -ENODEV;
                }
        }
 
 static void ec_remove_handlers(struct acpi_ec *ec)
 {
+       acpi_disable_gpe(NULL, ec->gpe, ACPI_GPE_TYPE_RUNTIME);
        if (ACPI_FAILURE(acpi_remove_address_space_handler(ec->handle,
                                ACPI_ADR_SPACE_EC, &acpi_ec_space_handler)))
                pr_err(PREFIX "failed to remove space handler\n");
 {
        struct acpi_ec *ec = acpi_driver_data(device);
        /* Stop using GPE */
-       acpi_disable_gpe(NULL, ec->gpe);
+       acpi_set_gpe(NULL, ec->gpe, ACPI_GPE_DISABLE);
        return 0;
 }
 
 {
        struct acpi_ec *ec = acpi_driver_data(device);
        /* Enable use of GPE back */
-       acpi_enable_gpe(NULL, ec->gpe);
+       acpi_set_gpe(NULL, ec->gpe, ACPI_GPE_ENABLE);
        return 0;
 }
 
 
                return -ENODEV;
        }
 
-       error = enable ?
-               acpi_enable_wakeup_device_power(adev, acpi_target_sleep_state) :
-               acpi_disable_wakeup_device_power(adev);
+       if (enable) {
+               error = acpi_enable_wakeup_device_power(adev,
+                                               acpi_target_sleep_state);
+               if (!error)
+                       acpi_enable_gpe(adev->wakeup.gpe_device,
+                                       adev->wakeup.gpe_number,
+                                       ACPI_GPE_TYPE_WAKE);
+       } else {
+               acpi_disable_gpe(adev->wakeup.gpe_device, adev->wakeup.gpe_number,
+                               ACPI_GPE_TYPE_WAKE);
+               error = acpi_disable_wakeup_device_power(adev);
+       }
        if (!error)
                dev_info(dev, "wake-up capability %s by ACPI\n",
                                enable ? "enabled" : "disabled");
 
        if (index < num_gpes) {
                if (!strcmp(buf, "disable\n") &&
                                (status & ACPI_EVENT_FLAG_ENABLED))
-                       result = acpi_disable_gpe(handle, index);
+                       result = acpi_set_gpe(handle, index, ACPI_GPE_DISABLE);
                else if (!strcmp(buf, "enable\n") &&
                                !(status & ACPI_EVENT_FLAG_ENABLED))
-                       result = acpi_enable_gpe(handle, index);
+                       result = acpi_set_gpe(handle, index, ACPI_GPE_ENABLE);
                else if (!strcmp(buf, "clear\n") &&
                                (status & ACPI_EVENT_FLAG_SET))
                        result = acpi_clear_gpe(handle, index, ACPI_NOT_ISR);
 
 ACPI_MODULE_NAME("wakeup_devices")
 
 /**
- * acpi_enable_wakeup_device_prep - prepare wakeup devices
- *     @sleep_state:   ACPI state
- * Enable all wakup devices power if the devices' wakeup level
- * is higher than requested sleep level
+ * acpi_enable_wakeup_device_prep - Prepare wake-up devices.
+ * @sleep_state: ACPI system sleep state.
+ *
+ * Enable all wake-up devices' power, unless the requested system sleep state is
+ * too deep.
  */
-
 void acpi_enable_wakeup_device_prep(u8 sleep_state)
 {
        struct list_head *node, *next;
                                                       struct acpi_device,
                                                       wakeup_list);
 
-               if (!dev->wakeup.flags.valid ||
-                   !dev->wakeup.state.enabled ||
-                   (sleep_state > (u32) dev->wakeup.sleep_state))
+               if (!dev->wakeup.flags.valid || !dev->wakeup.state.enabled
+                   || (sleep_state > (u32) dev->wakeup.sleep_state))
                        continue;
 
                acpi_enable_wakeup_device_power(dev, sleep_state);
 }
 
 /**
- * acpi_enable_wakeup_device - enable wakeup devices
- *     @sleep_state:   ACPI state
- * Enable all wakup devices's GPE
+ * acpi_enable_wakeup_device - Enable wake-up device GPEs.
+ * @sleep_state: ACPI system sleep state.
+ *
+ * Enable all wake-up devices' GPEs, with the assumption that
+ * acpi_disable_all_gpes() was executed before, so we don't need to disable any
+ * GPEs here.
  */
 void acpi_enable_wakeup_device(u8 sleep_state)
 {
                if (!dev->wakeup.flags.valid)
                        continue;
 
-               /* If users want to disable run-wake GPE,
-                * we only disable it for wake and leave it for runtime
-                */
                if ((!dev->wakeup.state.enabled && !dev->wakeup.prepare_count)
-                   || sleep_state > (u32) dev->wakeup.sleep_state) {
-                       if (dev->wakeup.flags.run_wake) {
-                               /* set_gpe_type will disable GPE, leave it like that */
-                               acpi_set_gpe_type(dev->wakeup.gpe_device,
-                                                 dev->wakeup.gpe_number,
-                                                 ACPI_GPE_TYPE_RUNTIME);
-                       }
+                   || sleep_state > (u32) dev->wakeup.sleep_state)
                        continue;
-               }
-               if (!dev->wakeup.flags.run_wake)
-                       acpi_enable_gpe(dev->wakeup.gpe_device,
-                                       dev->wakeup.gpe_number);
+
+               /* The wake-up power should have been enabled already. */
+               acpi_set_gpe(dev->wakeup.gpe_device, dev->wakeup.gpe_number,
+                               ACPI_GPE_ENABLE);
        }
 }
 
 /**
- * acpi_disable_wakeup_device - disable devices' wakeup capability
- *     @sleep_state:   ACPI state
- * Disable all wakup devices's GPE and wakeup capability
+ * acpi_disable_wakeup_device - Disable devices' wakeup capability.
+ * @sleep_state: ACPI system sleep state.
+ *
+ * This function only affects devices with wakeup.state.enabled set, which means
+ * that it reverses the changes made by acpi_enable_wakeup_device_prep().
  */
 void acpi_disable_wakeup_device(u8 sleep_state)
 {
                struct acpi_device *dev =
                        container_of(node, struct acpi_device, wakeup_list);
 
-               if (!dev->wakeup.flags.valid)
-                       continue;
-
-               if ((!dev->wakeup.state.enabled && !dev->wakeup.prepare_count)
-                   || sleep_state > (u32) dev->wakeup.sleep_state) {
-                       if (dev->wakeup.flags.run_wake) {
-                               acpi_set_gpe_type(dev->wakeup.gpe_device,
-                                                 dev->wakeup.gpe_number,
-                                                 ACPI_GPE_TYPE_WAKE_RUN);
-                               /* Re-enable it, since set_gpe_type will disable it */
-                               acpi_enable_gpe(dev->wakeup.gpe_device,
-                                               dev->wakeup.gpe_number);
-                       }
+               if (!dev->wakeup.flags.valid || !dev->wakeup.state.enabled
+                   || (sleep_state > (u32) dev->wakeup.sleep_state))
                        continue;
-               }
 
                acpi_disable_wakeup_device_power(dev);
-               /* Never disable run-wake GPE */
-               if (!dev->wakeup.flags.run_wake) {
-                       acpi_disable_gpe(dev->wakeup.gpe_device,
-                                        dev->wakeup.gpe_number);
-                       acpi_clear_gpe(dev->wakeup.gpe_device,
-                                      dev->wakeup.gpe_number, ACPI_NOT_ISR);
-               }
        }
 }
 
                /* In case user doesn't load button driver */
                if (!dev->wakeup.flags.run_wake || dev->wakeup.state.enabled)
                        continue;
-               acpi_set_gpe_type(dev->wakeup.gpe_device,
-                                 dev->wakeup.gpe_number,
-                                 ACPI_GPE_TYPE_WAKE_RUN);
-               acpi_enable_gpe(dev->wakeup.gpe_device,
-                               dev->wakeup.gpe_number);
+               acpi_enable_gpe(dev->wakeup.gpe_device, dev->wakeup.gpe_number,
+                               ACPI_GPE_TYPE_WAKE);
                dev->wakeup.state.enabled = 1;
        }
        mutex_unlock(&acpi_device_lock);
 
 /*
  * GPE Interfaces
  */
-acpi_status acpi_set_gpe_type(acpi_handle gpe_device, u32 gpe_number, u8 type);
+acpi_status acpi_set_gpe(acpi_handle gpe_device, u32 gpe_number, u8 action);
 
-acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number);
+acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number, u8 type);
 
-acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number);
+acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number, u8 type);
 
 acpi_status acpi_clear_gpe(acpi_handle gpe_device, u32 gpe_number, u32 flags);
 
 
 
 /*
  * GPE info flags - Per GPE
- * +-+-+-+---+---+-+
- * |7|6|5|4:3|2:1|0|
- * +-+-+-+---+---+-+
- *  | | |  |   |  |
- *  | | |  |   |  +--- Interrupt type: Edge or Level Triggered
- *  | | |  |   +--- Type: Wake-only, Runtime-only, or wake/runtime
+ * +-+-+-+---+-+-+-+
+ * |7|6|5|4:3|2|1|0|
+ * +-+-+-+---+-+-+-+
+ *  | | |  |  | | |
+ *  | | |  |  | | +--- Interrupt type: Edge or Level Triggered
+ *  | | |  |  | +--- GPE can wake the system
+ *  | | |  |  +--- Unused
  *  | | |  +--- Type of dispatch -- to method, handler, or none
- *  | | +--- Enabled for runtime?
- *  | +--- Enabled for wake?
+ *  | | +--- Unused
+ *  | +--- Unused
  *  +--- Unused
  */
 #define ACPI_GPE_XRUPT_TYPE_MASK        (u8) 0x01
 #define ACPI_GPE_TYPE_WAKE_RUN          (u8) 0x06
 #define ACPI_GPE_TYPE_WAKE              (u8) 0x02
 #define ACPI_GPE_TYPE_RUNTIME           (u8) 0x04      /* Default */
+#define ACPI_GPE_CAN_WAKE              (u8) 0x02
 
 #define ACPI_GPE_DISPATCH_MASK          (u8) 0x18
 #define ACPI_GPE_DISPATCH_HANDLER       (u8) 0x08
 #define ACPI_GPE_DISPATCH_METHOD        (u8) 0x10
 #define ACPI_GPE_DISPATCH_NOT_USED      (u8) 0x00      /* Default */
 
-#define ACPI_GPE_RUN_ENABLE_MASK        (u8) 0x20
-#define ACPI_GPE_RUN_ENABLED            (u8) 0x20
-#define ACPI_GPE_RUN_DISABLED           (u8) 0x00      /* Default */
-
-#define ACPI_GPE_WAKE_ENABLE_MASK       (u8) 0x40
-#define ACPI_GPE_WAKE_ENABLED           (u8) 0x40
-#define ACPI_GPE_WAKE_DISABLED          (u8) 0x00      /* Default */
-
-#define ACPI_GPE_ENABLE_MASK            (u8) 0x60      /* Both run/wake */
-
 /*
  * Flags for GPE and Lock interfaces
  */