On Sat, 2010-03-20 at 18:28 +0100, angelo wrote:
> I confirm this bug in HP Pavillion dv6-2044el, debian squeeze updated at 
> 20.03.2010 (apt-get update + upgrade).
> 
> BIOS updated today to the last available F.13
> Kernel version 2.6.30
> 
> happy to contribute with help as needed, i can recompile the kernel easily.

There were some bug fixes/workarounds in ACPI support in Linux 2.6.33
which might be relevant.  Please test this patch against package version
2.6.32-10, following the instructions at
<http://kernel-handbook.alioth.debian.org/ch-common-tasks.html#s-common-official>.

Ben.

--- a/drivers/acpi/acpica/nseval.c
+++ b/drivers/acpi/acpica/nseval.c
@@ -367,49 +367,87 @@
                         struct acpi_evaluate_info *info)
 {
-       union acpi_operand_object *root_obj;
+       union acpi_operand_object *parent_obj;
+       struct acpi_namespace_node *parent_node;
+       acpi_object_type type;
        acpi_status status;
 
        ACPI_FUNCTION_TRACE(ns_exec_module_code);
 
+       /*
+        * Get the parent node. We cheat by using the next_object field
+        * of the method object descriptor.
+        */
+       parent_node = ACPI_CAST_PTR(struct acpi_namespace_node,
+                                   method_obj->method.next_object);
+       type = acpi_ns_get_type(parent_node);
+
+       /*
+        * Get the region handler and save it in the method object. We may need
+        * this if an operation region declaration causes a _REG method to be 
run.
+        *
+        * We can't do this in acpi_ps_link_module_code because
+        * acpi_gbl_root_node->Object is NULL at PASS1.
+        */
+       if ((type == ACPI_TYPE_DEVICE) && parent_node->object) {
+               method_obj->method.extra.handler =
+                   parent_node->object->device.handler;
+       }
+
+       /* Must clear next_object (acpi_ns_attach_object needs the field) */
+
+       method_obj->method.next_object = NULL;
+
        /* Initialize the evaluation information block */
 
        ACPI_MEMSET(info, 0, sizeof(struct acpi_evaluate_info));
-       info->prefix_node = acpi_gbl_root_node;
+       info->prefix_node = parent_node;
 
        /*
-        * Get the currently attached root object. Add a reference, because the
+        * Get the currently attached parent object. Add a reference, because 
the
         * ref count will be decreased when the method object is installed to
-        * the root node.
+        * the parent node.
         */
-       root_obj = acpi_ns_get_attached_object(acpi_gbl_root_node);
-       acpi_ut_add_reference(root_obj);
+       parent_obj = acpi_ns_get_attached_object(parent_node);
+       if (parent_obj) {
+               acpi_ut_add_reference(parent_obj);
+       }
 
-       /* Install the method (module-level code) in the root node */
+       /* Install the method (module-level code) in the parent node */
 
-       status = acpi_ns_attach_object(acpi_gbl_root_node, method_obj,
+       status = acpi_ns_attach_object(parent_node, method_obj,
                                       ACPI_TYPE_METHOD);
        if (ACPI_FAILURE(status)) {
                goto exit;
        }
 
-       /* Execute the root node as a control method */
+       /* Execute the parent node as a control method */
 
        status = acpi_ns_evaluate(info);
 
        ACPI_DEBUG_PRINT((ACPI_DB_INIT, "Executed module-level code at %p\n",
                          method_obj->method.aml_start));
 
+       /* Delete a possible implicit return value (in slack mode) */
+
+       if (info->return_object) {
+               acpi_ut_remove_reference(info->return_object);
+       }
+
        /* Detach the temporary method object */
 
-       acpi_ns_detach_object(acpi_gbl_root_node);
+       acpi_ns_detach_object(parent_node);
 
-       /* Restore the original root object */
+       /* Restore the original parent object */
 
-       status =
-           acpi_ns_attach_object(acpi_gbl_root_node, root_obj,
-                                 ACPI_TYPE_DEVICE);
+       if (parent_obj) {
+               status = acpi_ns_attach_object(parent_node, parent_obj, type);
+       } else {
+               parent_node->type = (u8)type;
+       }
 
       exit:
-       acpi_ut_remove_reference(root_obj);
+       if (parent_obj) {
+               acpi_ut_remove_reference(parent_obj);
+       }
        return_VOID;
 }
--- a/drivers/acpi/acpica/psloop.c
+++ b/drivers/acpi/acpica/psloop.c
@@ -87,7 +87,8 @@ acpi_ps_complete_final_op(struct acpi_walk_state *walk_state,
                          union acpi_parse_object *op, acpi_status status);
 
 static void
-acpi_ps_link_module_code(u8 *aml_start, u32 aml_length, acpi_owner_id 
owner_id);
+acpi_ps_link_module_code(union acpi_parse_object *parent_op,
+                        u8 *aml_start, u32 aml_length, acpi_owner_id owner_id);
 
 
/*******************************************************************************
  *
@@ -479,11 +480,14 @@ acpi_ps_get_arguments(struct acpi_walk_state *walk_state,
                                 */
                                if (walk_state->pass_number ==
                                    ACPI_IMODE_LOAD_PASS1) {
-                                       acpi_ps_link_module_code(aml_op_start,
-                                                                walk_state->
+                                       acpi_ps_link_module_code(op->common.
+                                                                parent,
+                                                                aml_op_start,
+                                                                (u32)
+                                                                (walk_state->
                                                                 parser_state.
                                                                 pkg_end -
-                                                                aml_op_start,
+                                                                aml_op_start),
                                                                 walk_state->
                                                                 owner_id);
                                }
@@ -598,7 +602,8 @@ acpi_ps_get_arguments(struct acpi_walk_state *walk_state,
  *
  * FUNCTION:    acpi_ps_link_module_code
  *
- * PARAMETERS:  aml_start           - Pointer to the AML
+ * PARAMETERS:  parent_op           - Parent parser op
+ *              aml_start           - Pointer to the AML
  *              aml_length          - Length of executable AML
  *              owner_id            - owner_id of module level code
  *
@@ -611,11 +616,13 @@ acpi_ps_get_arguments(struct acpi_walk_state *walk_state,
  
******************************************************************************/
 
 static void
-acpi_ps_link_module_code(u8 *aml_start, u32 aml_length, acpi_owner_id owner_id)
+acpi_ps_link_module_code(union acpi_parse_object *parent_op,
+                        u8 *aml_start, u32 aml_length, acpi_owner_id owner_id)
 {
        union acpi_operand_object *prev;
        union acpi_operand_object *next;
        union acpi_operand_object *method_obj;
+       struct acpi_namespace_node *parent_node;
 
        /* Get the tail of the list */
 
@@ -639,11 +646,24 @@ acpi_ps_link_module_code(u8 *aml_start, u32 aml_length, 
acpi_owner_id owner_id)
                        return;
                }
 
+               if (parent_op->common.node) {
+                       parent_node = parent_op->common.node;
+               } else {
+                       parent_node = acpi_gbl_root_node;
+               }
+
                method_obj->method.aml_start = aml_start;
                method_obj->method.aml_length = aml_length;
                method_obj->method.owner_id = owner_id;
                method_obj->method.flags |= AOPOBJ_MODULE_LEVEL;
 
+               /*
+                * Save the parent node in next_object. This is cheating, but we
+                * don't want to expand the method object.
+                */
+               method_obj->method.next_object =
+                   ACPI_CAST_PTR(union acpi_operand_object, parent_node);
+
                if (!prev) {
                        acpi_gbl_module_code_list = method_obj;
                } else {
--- a/drivers/acpi/acpica/acobject.h
+++ b/drivers/acpi/acpica/acobject.h
@@ -180,7 +180,11 @@ struct acpi_object_method {
        u8 sync_level;
        union acpi_operand_object *mutex;
        u8 *aml_start;
-       ACPI_INTERNAL_METHOD implementation;
+       union {
+               ACPI_INTERNAL_METHOD implementation;
+               union acpi_operand_object *handler;
+       } extra;
+
        u32 aml_length;
        u8 thread_count;
        acpi_owner_id owner_id;
--- a/drivers/acpi/acpica/dsmethod.c
+++ b/drivers/acpi/acpica/dsmethod.c
@@ -414,7 +414,7 @@ acpi_ds_call_control_method(struct acpi_thread_state 
*thread,
        /* Invoke an internal method if necessary */
 
        if (obj_desc->method.method_flags & AML_METHOD_INTERNAL_ONLY) {
-               status = obj_desc->method.implementation(next_walk_state);
+               status = obj_desc->method.extra.implementation(next_walk_state);
                if (status == AE_OK) {
                        status = AE_CTRL_TERMINATE;
                }
--- a/drivers/acpi/acpica/evrgnini.c
+++ b/drivers/acpi/acpica/evrgnini.c
@@ -575,6 +575,21 @@ acpi_ev_initialize_region(union acpi_operand_object 
*region_obj,
                                handler_obj = obj_desc->thermal_zone.handler;
                                break;
 
+                       case ACPI_TYPE_METHOD:
+                               /*
+                                * If we are executing module level code, the 
original
+                                * Node's object was replaced by this Method 
object and we
+                                * saved the handler in the method object.
+                                *
+                                * See acpi_ns_exec_module_code
+                                */
+                               if (obj_desc->method.
+                                   flags & AOPOBJ_MODULE_LEVEL) {
+                                       handler_obj =
+                                           obj_desc->method.extra.handler;
+                               }
+                               break;
+
                        default:
                                /* Ignore other objects */
                                break;
--- a/drivers/acpi/acpica/nsaccess.c
+++ b/drivers/acpi/acpica/nsaccess.c
@@ -165,7 +165,7 @@ acpi_status acpi_ns_root_initialize(void)
 
                                obj_desc->method.method_flags =
                                    AML_METHOD_INTERNAL_ONLY;
-                               obj_desc->method.implementation =
+                               obj_desc->method.extra.implementation =
                                    acpi_ut_osi_implementation;
 #endif
                                break;
--- a/drivers/acpi/acpica/psxface.c
+++ b/drivers/acpi/acpica/psxface.c
@@ -287,7 +287,8 @@ acpi_status acpi_ps_execute_method(struct 
acpi_evaluate_info *info)
        /* Invoke an internal method if necessary */
 
        if (info->obj_desc->method.method_flags & AML_METHOD_INTERNAL_ONLY) {
-               status = info->obj_desc->method.implementation(walk_state);
+               status =
+                   info->obj_desc->method.extra.implementation(walk_state);
                info->return_object = walk_state->return_desc;
 
                /* Cleanup states */
--- END ---

-- 
Ben Hutchings
Once a job is fouled up, anything done to improve it makes it worse.

Attachment: signature.asc
Description: This is a digitally signed message part

Reply via email to