]> Pileus Git - ~andy/linux/blobdiff - drivers/acpi/events/evgpe.c
ACPI: ACPICA 20060608
[~andy/linux] / drivers / acpi / events / evgpe.c
index aa179dc78011be4aafada48979f2f241b2567a32..f01d339407f8cc3c42e35b81f0a083ae32e5daf0 100644 (file)
@@ -382,6 +382,7 @@ u32 acpi_ev_gpe_detect(struct acpi_gpe_xrupt_info * gpe_xrupt_list)
        u32 status_reg;
        u32 enable_reg;
        acpi_cpu_flags flags;
+       acpi_cpu_flags hw_flags;
        acpi_native_uint i;
        acpi_native_uint j;
 
@@ -393,9 +394,12 @@ u32 acpi_ev_gpe_detect(struct acpi_gpe_xrupt_info * gpe_xrupt_list)
                return (int_status);
        }
 
-       /* Examine all GPE blocks attached to this interrupt level */
+       /* We need to hold the GPE lock now, hardware lock in the loop */
 
        flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
+
+       /* Examine all GPE blocks attached to this interrupt level */
+
        gpe_block = gpe_xrupt_list->gpe_block_list_head;
        while (gpe_block) {
                /*
@@ -409,6 +413,8 @@ u32 acpi_ev_gpe_detect(struct acpi_gpe_xrupt_info * gpe_xrupt_list)
 
                        gpe_register_info = &gpe_block->register_info[i];
 
+                       hw_flags = acpi_os_acquire_lock(acpi_gbl_hardware_lock);
+
                        /* Read the Status Register */
 
                        status =
@@ -417,6 +423,8 @@ u32 acpi_ev_gpe_detect(struct acpi_gpe_xrupt_info * gpe_xrupt_list)
                                                   &gpe_register_info->
                                                   status_address);
                        if (ACPI_FAILURE(status)) {
+                               acpi_os_release_lock(acpi_gbl_hardware_lock,
+                                                    hw_flags);
                                goto unlock_and_exit;
                        }
 
@@ -427,6 +435,8 @@ u32 acpi_ev_gpe_detect(struct acpi_gpe_xrupt_info * gpe_xrupt_list)
                                                   &enable_reg,
                                                   &gpe_register_info->
                                                   enable_address);
+                       acpi_os_release_lock(acpi_gbl_hardware_lock, hw_flags);
+
                        if (ACPI_FAILURE(status)) {
                                goto unlock_and_exit;
                        }
@@ -488,9 +498,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_exece
- *              (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.
  *
@@ -499,10 +509,9 @@ 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);
 
@@ -540,22 +549,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_EXCEPTION((AE_INFO, status,
-                                       "While evaluating method [%4.4s] for GPE[%2X]",
+                                       "While evaluating GPE method [%4.4s]",
                                        acpi_ut_get_node_name
                                        (local_gpe_event_info.dispatch.
-                                        method_node), gpe_number));
+                                        method_node)));
                }
        }