ACPI: VIDEO: Adjust current level to closest available one.
[safe/jmp/linux-2.6] / drivers / acpi / events / evgpe.c
index f51c3b1..e22f4a9 100644 (file)
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2007, R. Byron Moore
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -69,7 +69,7 @@ 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");
+       ACPI_FUNCTION_TRACE(ev_set_gpe_type);
 
        /* Validate type and update register enable masks */
 
@@ -115,13 +115,15 @@ 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;
 
-       ACPI_FUNCTION_TRACE("ev_update_gpe_enable_masks");
+       ACPI_FUNCTION_TRACE(ev_update_gpe_enable_masks);
 
        gpe_register_info = gpe_event_info->register_info;
        if (!gpe_register_info) {
                return_ACPI_STATUS(AE_NOT_EXIST);
        }
-       register_bit = gpe_event_info->register_bit;
+       register_bit = (u8)
+           (1 <<
+            (gpe_event_info->gpe_number - gpe_register_info->base_gpe_number));
 
        /* 1) Disable case.  Simply clear all enable bits */
 
@@ -178,7 +180,7 @@ acpi_ev_enable_gpe(struct acpi_gpe_event_info *gpe_event_info,
 {
        acpi_status status;
 
-       ACPI_FUNCTION_TRACE("ev_enable_gpe");
+       ACPI_FUNCTION_TRACE(ev_enable_gpe);
 
        /* Make sure HW enable masks are updated */
 
@@ -207,6 +209,7 @@ acpi_ev_enable_gpe(struct acpi_gpe_event_info *gpe_event_info,
                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);
@@ -243,7 +246,7 @@ acpi_status acpi_ev_disable_gpe(struct acpi_gpe_event_info *gpe_event_info)
 {
        acpi_status status;
 
-       ACPI_FUNCTION_TRACE("ev_disable_gpe");
+       ACPI_FUNCTION_TRACE(ev_disable_gpe);
 
        if (!(gpe_event_info->flags & ACPI_GPE_ENABLE_MASK)) {
                return_ACPI_STATUS(AE_OK);
@@ -313,6 +316,7 @@ struct acpi_gpe_event_info *acpi_ev_get_gpe_event_info(acpi_handle gpe_device,
        /* A NULL gpe_block means use the FADT-defined GPE block(s) */
 
        if (!gpe_device) {
+
                /* Examine GPE Block 0 and 1 (These blocks are permanent) */
 
                for (i = 0; i < ACPI_MAX_GPE_BLOCKS; i++) {
@@ -337,9 +341,8 @@ struct acpi_gpe_event_info *acpi_ev_get_gpe_event_info(acpi_handle gpe_device,
 
        /* A Non-NULL gpe_device means this is a GPE Block Device */
 
-       obj_desc =
-           acpi_ns_get_attached_object((struct acpi_namespace_node *)
-                                       gpe_device);
+       obj_desc = acpi_ns_get_attached_object((struct acpi_namespace_node *)
+                                              gpe_device);
        if (!obj_desc || !obj_desc->device.gpe_block) {
                return (NULL);
        }
@@ -372,18 +375,18 @@ struct acpi_gpe_event_info *acpi_ev_get_gpe_event_info(acpi_handle gpe_device,
 
 u32 acpi_ev_gpe_detect(struct acpi_gpe_xrupt_info * gpe_xrupt_list)
 {
+       acpi_status status;
+       struct acpi_gpe_block_info *gpe_block;
+       struct acpi_gpe_register_info *gpe_register_info;
        u32 int_status = ACPI_INTERRUPT_NOT_HANDLED;
        u8 enabled_status_byte;
-       struct acpi_gpe_register_info *gpe_register_info;
        u32 status_reg;
        u32 enable_reg;
-       u32 flags;
-       acpi_status status;
-       struct acpi_gpe_block_info *gpe_block;
+       acpi_cpu_flags flags;
        acpi_native_uint i;
        acpi_native_uint j;
 
-       ACPI_FUNCTION_NAME("ev_gpe_detect");
+       ACPI_FUNCTION_NAME(ev_gpe_detect);
 
        /* Check for the case where there are no GPEs */
 
@@ -391,9 +394,15 @@ u32 acpi_ev_gpe_detect(struct acpi_gpe_xrupt_info * gpe_xrupt_list)
                return (int_status);
        }
 
+       /*
+        * We need to obtain the GPE lock for both the data structs and registers
+        * Note: Not necessary to obtain the hardware lock, since the GPE registers
+        * are owned by the gpe_lock.
+        */
+       flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
+
        /* Examine all GPE blocks attached to this interrupt level */
 
-       flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
        gpe_block = gpe_xrupt_list->gpe_block_list_head;
        while (gpe_block) {
                /*
@@ -402,6 +411,7 @@ u32 acpi_ev_gpe_detect(struct acpi_gpe_xrupt_info * gpe_xrupt_list)
                 * Find all currently active GP events.
                 */
                for (i = 0; i < gpe_block->register_count; i++) {
+
                        /* Get the next status/enable pair */
 
                        gpe_register_info = &gpe_block->register_info[i];
@@ -437,6 +447,7 @@ u32 acpi_ev_gpe_detect(struct acpi_gpe_xrupt_info * gpe_xrupt_list)
 
                        enabled_status_byte = (u8) (status_reg & enable_reg);
                        if (!enabled_status_byte) {
+
                                /* No active GPEs in this register, move on */
 
                                continue;
@@ -445,10 +456,10 @@ u32 acpi_ev_gpe_detect(struct acpi_gpe_xrupt_info * gpe_xrupt_list)
                        /* Now look at the individual GPEs in this byte register */
 
                        for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++) {
+
                                /* Examine one GPE bit */
 
-                               if (enabled_status_byte &
-                                   acpi_gbl_decode_to8bit[j]) {
+                               if (enabled_status_byte & (1 << j)) {
                                        /*
                                         * Found an active GPE. Dispatch the event to a handler
                                         * or method.
@@ -483,9 +494,9 @@ u32 acpi_ev_gpe_detect(struct acpi_gpe_xrupt_info * gpe_xrupt_list)
  *
  * RETURN:      None
  *
- * DESCRIPTION: Perform the actual execution of a GPE control method.  This
- *              function is called from an invocation of acpi_os_queue_for_execution
- *              (and therefore does NOT execute at interrupt level) so that
+ * DESCRIPTION: Perform the actual execution of a GPE control method. This
+ *              function is called from an invocation of acpi_os_execute and
+ *              therefore does NOT execute at interrupt level - so that
  *              the control method itself is not executed in the context of
  *              an interrupt handler.
  *
@@ -494,12 +505,11 @@ u32 acpi_ev_gpe_detect(struct acpi_gpe_xrupt_info * gpe_xrupt_list)
 static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context)
 {
        struct acpi_gpe_event_info *gpe_event_info = (void *)context;
-       u32 gpe_number = 0;
        acpi_status status;
        struct acpi_gpe_event_info local_gpe_event_info;
-       struct acpi_parameter_info info;
+       struct acpi_evaluate_info *info;
 
-       ACPI_FUNCTION_TRACE("ev_asynch_execute_gpe_method");
+       ACPI_FUNCTION_TRACE(ev_asynch_execute_gpe_method);
 
        status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
        if (ACPI_FAILURE(status)) {
@@ -535,18 +545,35 @@ static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context)
         */
        if ((local_gpe_event_info.flags & ACPI_GPE_DISPATCH_MASK) ==
            ACPI_GPE_DISPATCH_METHOD) {
-               /*
-                * Invoke the GPE Method (_Lxx, _Exx) i.e., evaluate the _Lxx/_Exx
-                * control method that corresponds to this GPE
-                */
-               info.node = local_gpe_event_info.dispatch.method_node;
-               info.parameters =
-                   ACPI_CAST_PTR(union acpi_operand_object *, gpe_event_info);
-               info.parameter_type = ACPI_PARAM_GPE;
 
-               status = acpi_ns_evaluate_by_handle(&info);
+               /* Allocate the evaluation information block */
+
+               info = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_evaluate_info));
+               if (!info) {
+                       status = AE_NO_MEMORY;
+               } else {
+                       /*
+                        * Invoke the GPE Method (_Lxx, _Exx) i.e., evaluate the _Lxx/_Exx
+                        * control method that corresponds to this GPE
+                        */
+                       info->prefix_node =
+                           local_gpe_event_info.dispatch.method_node;
+                       info->parameters =
+                           ACPI_CAST_PTR(union acpi_operand_object *,
+                                         gpe_event_info);
+                       info->parameter_type = ACPI_PARAM_GPE;
+                       info->flags = ACPI_IGNORE_RETURN_VALUE;
+
+                       status = acpi_ns_evaluate(info);
+                       ACPI_FREE(info);
+               }
+
                if (ACPI_FAILURE(status)) {
-                       ACPI_REPORT_ERROR(("%s while evaluating method [%4.4s] for GPE[%2X]\n", acpi_format_exception(status), acpi_ut_get_node_name(local_gpe_event_info.dispatch.method_node), gpe_number));
+                       ACPI_EXCEPTION((AE_INFO, status,
+                                       "while evaluating GPE method [%4.4s]",
+                                       acpi_ut_get_node_name
+                                       (local_gpe_event_info.dispatch.
+                                        method_node)));
                }
        }
 
@@ -589,7 +616,9 @@ acpi_ev_gpe_dispatch(struct acpi_gpe_event_info *gpe_event_info, u32 gpe_number)
 {
        acpi_status status;
 
-       ACPI_FUNCTION_TRACE("ev_gpe_dispatch");
+       ACPI_FUNCTION_TRACE(ev_gpe_dispatch);
+
+       acpi_gpe_count++;
 
        /*
         * If edge-triggered, clear the GPE status bit now.  Note that
@@ -599,25 +628,19 @@ acpi_ev_gpe_dispatch(struct acpi_gpe_event_info *gpe_event_info, u32 gpe_number)
            ACPI_GPE_EDGE_TRIGGERED) {
                status = acpi_hw_clear_gpe(gpe_event_info);
                if (ACPI_FAILURE(status)) {
-                       ACPI_REPORT_ERROR(("acpi_ev_gpe_dispatch: %s, Unable to clear GPE[%2X]\n", acpi_format_exception(status), gpe_number));
+                       ACPI_EXCEPTION((AE_INFO, status,
+                                       "Unable to clear GPE[%2X]",
+                                       gpe_number));
                        return_UINT32(ACPI_INTERRUPT_NOT_HANDLED);
                }
        }
 
-       /* Save current system state */
-
-       if (acpi_gbl_system_awake_and_running) {
-               ACPI_SET_BIT(gpe_event_info->flags, ACPI_GPE_SYSTEM_RUNNING);
-       } else {
-               ACPI_CLEAR_BIT(gpe_event_info->flags, ACPI_GPE_SYSTEM_RUNNING);
-       }
-
        /*
-        * Dispatch the GPE to either an installed handler, or the control
-        * method associated with this GPE (_Lxx or _Exx).
-        * If a handler exists, we invoke it and do not attempt to run the method.
-        * If there is neither a handler nor a method, we disable the level to
-        * prevent further events from coming in here.
+        * Dispatch the GPE to either an installed handler, or the control method
+        * associated with this GPE (_Lxx or _Exx). If a handler exists, we invoke
+        * it and do not attempt to run the method. If there is neither a handler
+        * nor a method, we disable this GPE to prevent further such pointless
+        * events from firing.
         */
        switch (gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) {
        case ACPI_GPE_DISPATCH_HANDLER:
@@ -637,7 +660,9 @@ acpi_ev_gpe_dispatch(struct acpi_gpe_event_info *gpe_event_info, u32 gpe_number)
                    ACPI_GPE_LEVEL_TRIGGERED) {
                        status = acpi_hw_clear_gpe(gpe_event_info);
                        if (ACPI_FAILURE(status)) {
-                               ACPI_REPORT_ERROR(("acpi_ev_gpe_dispatch: %s, Unable to clear GPE[%2X]\n", acpi_format_exception(status), gpe_number));
+                               ACPI_EXCEPTION((AE_INFO, status,
+                                               "Unable to clear GPE[%2X]",
+                                               gpe_number));
                                return_UINT32(ACPI_INTERRUPT_NOT_HANDLED);
                        }
                }
@@ -646,12 +671,14 @@ acpi_ev_gpe_dispatch(struct acpi_gpe_event_info *gpe_event_info, u32 gpe_number)
        case ACPI_GPE_DISPATCH_METHOD:
 
                /*
-                * Disable GPE, so it doesn't keep firing before the method has a
-                * chance to run.
+                * Disable the GPE, so it doesn't keep firing before the method has a
+                * chance to run (it runs asynchronously with interrupts enabled).
                 */
                status = acpi_ev_disable_gpe(gpe_event_info);
                if (ACPI_FAILURE(status)) {
-                       ACPI_REPORT_ERROR(("acpi_ev_gpe_dispatch: %s, Unable to disable GPE[%2X]\n", acpi_format_exception(status), gpe_number));
+                       ACPI_EXCEPTION((AE_INFO, status,
+                                       "Unable to disable GPE[%2X]",
+                                       gpe_number));
                        return_UINT32(ACPI_INTERRUPT_NOT_HANDLED);
                }
 
@@ -659,11 +686,13 @@ acpi_ev_gpe_dispatch(struct acpi_gpe_event_info *gpe_event_info, u32 gpe_number)
                 * Execute the method associated with the GPE
                 * NOTE: Level-triggered GPEs are cleared after the method completes.
                 */
-               status = acpi_os_queue_for_execution(OSD_PRIORITY_GPE,
-                                                    acpi_ev_asynch_execute_gpe_method,
-                                                    gpe_event_info);
+               status = acpi_os_execute(OSL_GPE_HANDLER,
+                                        acpi_ev_asynch_execute_gpe_method,
+                                        gpe_event_info);
                if (ACPI_FAILURE(status)) {
-                       ACPI_REPORT_ERROR(("acpi_ev_gpe_dispatch: %s, Unable to queue handler for GPE[%2X] - event disabled\n", acpi_format_exception(status), gpe_number));
+                       ACPI_EXCEPTION((AE_INFO, status,
+                                       "Unable to queue handler for GPE[%2X] - event disabled",
+                                       gpe_number));
                }
                break;
 
@@ -671,15 +700,19 @@ acpi_ev_gpe_dispatch(struct acpi_gpe_event_info *gpe_event_info, u32 gpe_number)
 
                /* No handler or method to run! */
 
-               ACPI_REPORT_ERROR(("acpi_ev_gpe_dispatch: No handler or method for GPE[%2X], disabling event\n", gpe_number));
+               ACPI_ERROR((AE_INFO,
+                           "No handler or method for GPE[%2X], disabling event",
+                           gpe_number));
 
                /*
-                * Disable the GPE.  The GPE will remain disabled until the ACPI
+                * Disable the GPE. The GPE will remain disabled until the ACPI
                 * Core Subsystem is restarted, or a handler is installed.
                 */
                status = acpi_ev_disable_gpe(gpe_event_info);
                if (ACPI_FAILURE(status)) {
-                       ACPI_REPORT_ERROR(("acpi_ev_gpe_dispatch: %s, Unable to disable GPE[%2X]\n", acpi_format_exception(status), gpe_number));
+                       ACPI_EXCEPTION((AE_INFO, status,
+                                       "Unable to disable GPE[%2X]",
+                                       gpe_number));
                        return_UINT32(ACPI_INTERRUPT_NOT_HANDLED);
                }
                break;
@@ -687,48 +720,3 @@ acpi_ev_gpe_dispatch(struct acpi_gpe_event_info *gpe_event_info, u32 gpe_number)
 
        return_UINT32(ACPI_INTERRUPT_HANDLED);
 }
-
-#ifdef ACPI_GPE_NOTIFY_CHECK
-/*******************************************************************************
- * TBD: NOT USED, PROTOTYPE ONLY AND WILL PROBABLY BE REMOVED
- *
- * FUNCTION:    acpi_ev_check_for_wake_only_gpe
- *
- * PARAMETERS:  gpe_event_info  - info for this GPE
- *
- * RETURN:      Status
- *
- * DESCRIPTION: Determine if a a GPE is "wake-only".
- *
- *              Called from Notify() code in interpreter when a "device_wake"
- *              Notify comes in.
- *
- ******************************************************************************/
-
-acpi_status
-acpi_ev_check_for_wake_only_gpe(struct acpi_gpe_event_info *gpe_event_info)
-{
-       acpi_status status;
-
-       ACPI_FUNCTION_TRACE("ev_check_for_wake_only_gpe");
-
-       if ((gpe_event_info) && /* Only >0 for _Lxx/_Exx */
-           ((gpe_event_info->flags & ACPI_GPE_SYSTEM_MASK) == ACPI_GPE_SYSTEM_RUNNING)) {      /* System state at GPE time */
-               /* This must be a wake-only GPE, disable it */
-
-               status = acpi_ev_disable_gpe(gpe_event_info);
-
-               /* Set GPE to wake-only.  Do not change wake disabled/enabled status */
-
-               acpi_ev_set_gpe_type(gpe_event_info, ACPI_GPE_TYPE_WAKE);
-
-               ACPI_REPORT_INFO(("GPE %p was updated from wake/run to wake-only\n", gpe_event_info));
-
-               /* This was a wake-only GPE */
-
-               return_ACPI_STATUS(AE_WAKE_ONLY_GPE);
-       }
-
-       return_ACPI_STATUS(AE_OK);
-}
-#endif