]> bbs.cooldavid.org Git - net-next-2.6.git/blobdiff - drivers/acpi/acpica/evxfevnt.c
Merge branch 'acpica-gpe' into release
[net-next-2.6.git] / drivers / acpi / acpica / evxfevnt.c
index b094cc0183d7355cef57aa2131e97e92be20c947..304825528d4803d22e025b9fb6d2220b10851d0b 100644 (file)
@@ -70,6 +70,7 @@ acpi_ev_get_gpe_device(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
 acpi_status acpi_enable(void)
 {
        acpi_status status;
+       int retry;
 
        ACPI_FUNCTION_TRACE(acpi_enable);
 
@@ -98,16 +99,18 @@ acpi_status acpi_enable(void)
 
        /* Sanity check that transition succeeded */
 
-       if (acpi_hw_get_mode() != ACPI_SYS_MODE_ACPI) {
-               ACPI_ERROR((AE_INFO,
-                           "Hardware did not enter ACPI mode"));
-               return_ACPI_STATUS(AE_NO_HARDWARE_RESPONSE);
+       for (retry = 0; retry < 30000; ++retry) {
+               if (acpi_hw_get_mode() == ACPI_SYS_MODE_ACPI) {
+                       if (retry != 0)
+                               ACPI_WARNING((AE_INFO,
+                               "Platform took > %d00 usec to enter ACPI mode", retry));
+                       return_ACPI_STATUS(AE_OK);
+               }
+               acpi_os_stall(100);     /* 100 usec */
        }
 
-       ACPI_DEBUG_PRINT((ACPI_DB_INIT,
-                         "Transition to ACPI mode successful\n"));
-
-       return_ACPI_STATUS(AE_OK);
+       ACPI_ERROR((AE_INFO, "Hardware did not enter ACPI mode"));
+       return_ACPI_STATUS(AE_NO_HARDWARE_RESPONSE);
 }
 
 ACPI_EXPORT_SYMBOL(acpi_enable)
@@ -208,66 +211,6 @@ acpi_status acpi_enable_event(u32 event, u32 flags)
 
 ACPI_EXPORT_SYMBOL(acpi_enable_event)
 
-/*******************************************************************************
- *
- * FUNCTION:    acpi_set_gpe
- *
- * PARAMETERS:  gpe_device      - Parent GPE Device. NULL for GPE0/GPE1
- *              gpe_number      - GPE level within the GPE block
- *              action          - ACPI_GPE_ENABLE or ACPI_GPE_DISABLE
- *
- * RETURN:      Status
- *
- * DESCRIPTION: Enable or disable an individual GPE. This function bypasses
- *              the reference count mechanism used in the acpi_enable_gpe and
- *              acpi_disable_gpe interfaces -- and should be used with care.
- *
- * Note: Typically used to disable a runtime GPE for short period of time,
- * then re-enable it, without disturbing the existing reference counts. This
- * is useful, for example, in the Embedded Controller (EC) driver.
- *
- ******************************************************************************/
-acpi_status acpi_set_gpe(acpi_handle gpe_device, u32 gpe_number, u8 action)
-{
-       struct acpi_gpe_event_info *gpe_event_info;
-       acpi_status status;
-       acpi_cpu_flags flags;
-
-       ACPI_FUNCTION_TRACE(acpi_set_gpe);
-
-       flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
-
-       /* Ensure that we have a valid GPE number */
-
-       gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
-       if (!gpe_event_info) {
-               status = AE_BAD_PARAMETER;
-               goto unlock_and_exit;
-       }
-
-       /* Perform the action */
-
-       switch (action) {
-       case ACPI_GPE_ENABLE:
-               status = acpi_ev_enable_gpe(gpe_event_info);
-               break;
-
-       case ACPI_GPE_DISABLE:
-               status = acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_DISABLE);
-               break;
-
-       default:
-               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)
-
 /*******************************************************************************
  *
  * FUNCTION:    acpi_gpe_wakeup
@@ -296,7 +239,7 @@ acpi_status acpi_gpe_wakeup(acpi_handle gpe_device, u32 gpe_number, u8 action)
        /* Ensure that we have a valid GPE number */
 
        gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
-       if (!gpe_event_info) {
+       if (!gpe_event_info || !(gpe_event_info->flags & ACPI_GPE_CAN_WAKE)) {
                status = AE_BAD_PARAMETER;
                goto unlock_and_exit;
        }
@@ -351,7 +294,7 @@ ACPI_EXPORT_SYMBOL(acpi_gpe_wakeup)
  ******************************************************************************/
 acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number)
 {
-       acpi_status status = AE_OK;
+       acpi_status status = AE_BAD_PARAMETER;
        struct acpi_gpe_event_info *gpe_event_info;
        acpi_cpu_flags flags;
 
@@ -362,28 +305,10 @@ acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number)
        /* Ensure that we have a valid GPE number */
 
        gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
-       if (!gpe_event_info) {
-               status = AE_BAD_PARAMETER;
-               goto unlock_and_exit;
+       if (gpe_event_info) {
+               status = acpi_raw_enable_gpe(gpe_event_info);
        }
 
-       if (gpe_event_info->runtime_count == ACPI_UINT8_MAX) {
-               status = AE_LIMIT;      /* Too many references */
-               goto unlock_and_exit;
-       }
-
-       gpe_event_info->runtime_count++;
-       if (gpe_event_info->runtime_count == 1) {
-               status = acpi_ev_update_gpe_enable_mask(gpe_event_info);
-               if (ACPI_SUCCESS(status)) {
-                       status = acpi_ev_enable_gpe(gpe_event_info);
-               }
-               if (ACPI_FAILURE(status)) {
-                       gpe_event_info->runtime_count--;
-               }
-       }
-
-unlock_and_exit:
        acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
        return_ACPI_STATUS(status);
 }
@@ -405,7 +330,7 @@ ACPI_EXPORT_SYMBOL(acpi_enable_gpe)
  ******************************************************************************/
 acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number)
 {
-       acpi_status status = AE_OK;
+       acpi_status status = AE_BAD_PARAMETER;
        struct acpi_gpe_event_info *gpe_event_info;
        acpi_cpu_flags flags;
 
@@ -415,37 +340,64 @@ acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number)
 
        /* Ensure that we have a valid GPE number */
 
+       gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
+       if (gpe_event_info) {
+               status = acpi_raw_disable_gpe(gpe_event_info) ;
+       }
+
+       acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
+       return_ACPI_STATUS(status);
+}
+ACPI_EXPORT_SYMBOL(acpi_disable_gpe)
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_gpe_can_wake
+ *
+ * PARAMETERS:  gpe_device      - Parent GPE Device. NULL for GPE0/GPE1
+ *              gpe_number      - GPE level within the GPE block
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Set the ACPI_GPE_CAN_WAKE flag for the given GPE.  If the GPE
+ *              has a corresponding method and is currently enabled, disable it
+ *              (GPEs with corresponding methods are enabled unconditionally
+ *              during initialization, but GPEs that can wake up are expected
+ *              to be initially disabled).
+ *
+ ******************************************************************************/
+acpi_status acpi_gpe_can_wake(acpi_handle gpe_device, u32 gpe_number)
+{
+       acpi_status status = AE_OK;
+       struct acpi_gpe_event_info *gpe_event_info;
+       acpi_cpu_flags flags;
+
+       ACPI_FUNCTION_TRACE(acpi_gpe_can_wake);
+
+       flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
+
+       /* Ensure that we have a valid GPE number */
+
        gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
        if (!gpe_event_info) {
                status = AE_BAD_PARAMETER;
                goto unlock_and_exit;
        }
 
-       /* Hardware-disable a runtime GPE on removal of the last reference */
-
-       if (!gpe_event_info->runtime_count) {
-               status = AE_LIMIT;      /* There are no references to remove */
+       if (gpe_event_info->flags & ACPI_GPE_CAN_WAKE) {
                goto unlock_and_exit;
        }
 
-       gpe_event_info->runtime_count--;
-       if (!gpe_event_info->runtime_count) {
-               status = acpi_ev_update_gpe_enable_mask(gpe_event_info);
-               if (ACPI_SUCCESS(status)) {
-                       status =
-                           acpi_hw_low_set_gpe(gpe_event_info,
-                                               ACPI_GPE_DISABLE);
-               }
-               if (ACPI_FAILURE(status)) {
-                       gpe_event_info->runtime_count++;
-               }
+       gpe_event_info->flags |= ACPI_GPE_CAN_WAKE;
+       if (gpe_event_info->flags & ACPI_GPE_DISPATCH_METHOD) {
+               (void)acpi_raw_disable_gpe(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)
+ACPI_EXPORT_SYMBOL(acpi_gpe_can_wake)
 
 /*******************************************************************************
  *
@@ -763,7 +715,7 @@ acpi_install_gpe_block(acpi_handle gpe_device,
 
        obj_desc->device.gpe_block = gpe_block;
 
-       /* Run the _PRW methods and enable the runtime GPEs in the new block */
+       /* Enable the runtime GPEs in the new block */
 
        status = acpi_ev_initialize_gpe_block(node, gpe_block);