diff options
Diffstat (limited to 'drivers/acpi')
61 files changed, 3409 insertions, 2698 deletions
diff --git a/drivers/acpi/dispatcher/dsinit.c b/drivers/acpi/dispatcher/dsinit.c index d7790db5017..bcd1d472b90 100644 --- a/drivers/acpi/dispatcher/dsinit.c +++ b/drivers/acpi/dispatcher/dsinit.c @@ -86,20 +86,20 @@ acpi_ds_init_one_object ( void *context, void **return_value) { + struct acpi_init_walk_info *info = (struct acpi_init_walk_info *) context; + struct acpi_namespace_node *node = (struct acpi_namespace_node *) obj_handle; acpi_object_type type; acpi_status status; - struct acpi_init_walk_info *info = (struct acpi_init_walk_info *) context; ACPI_FUNCTION_NAME ("ds_init_one_object"); /* - * We are only interested in objects owned by the table that + * We are only interested in NS nodes owned by the table that * was just loaded */ - if (((struct acpi_namespace_node *) obj_handle)->owner_id != - info->table_desc->table_id) { + if (node->owner_id != info->table_desc->owner_id) { return (AE_OK); } @@ -126,8 +126,6 @@ acpi_ds_init_one_object ( case ACPI_TYPE_METHOD: - info->method_count++; - /* * Print a dot for each method unless we are going to print * the entire pathname @@ -143,7 +141,7 @@ acpi_ds_init_one_object ( * on a per-table basis. Currently, we just use a global for the width. */ if (info->table_desc->pointer->revision == 1) { - ((struct acpi_namespace_node *) obj_handle)->flags |= ANOBJ_DATA_WIDTH_32; + node->flags |= ANOBJ_DATA_WIDTH_32; } /* @@ -153,22 +151,14 @@ acpi_ds_init_one_object ( status = acpi_ds_parse_method (obj_handle); if (ACPI_FAILURE (status)) { ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, - "Method %p [%4.4s] - parse failure, %s\n", + "\n+Method %p [%4.4s] - parse failure, %s\n", obj_handle, acpi_ut_get_node_name (obj_handle), acpi_format_exception (status))); /* This parse failed, but we will continue parsing more methods */ - - break; } - /* - * Delete the parse tree. We simply re-parse the method - * for every execution since there isn't much overhead - */ - acpi_ns_delete_namespace_subtree (obj_handle); - acpi_ns_delete_namespace_by_owner ( - ((struct acpi_namespace_node *) obj_handle)->object->method.owning_id); + info->method_count++; break; @@ -237,7 +227,7 @@ acpi_ds_initialize_objects ( ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT, "\nTable [%4.4s](id %4.4X) - %hd Objects with %hd Devices %hd Methods %hd Regions\n", - table_desc->pointer->signature, table_desc->table_id, info.object_count, + table_desc->pointer->signature, table_desc->owner_id, info.object_count, info.device_count, info.method_count, info.op_region_count)); ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, diff --git a/drivers/acpi/dispatcher/dsmethod.c b/drivers/acpi/dispatcher/dsmethod.c index 9fc3f4c033e..e344c06ed33 100644 --- a/drivers/acpi/dispatcher/dsmethod.c +++ b/drivers/acpi/dispatcher/dsmethod.c @@ -58,12 +58,11 @@ * * FUNCTION: acpi_ds_parse_method * - * PARAMETERS: obj_handle - Method node + * PARAMETERS: Node - Method node * * RETURN: Status * - * DESCRIPTION: Call the parser and parse the AML that is associated with the - * method. + * DESCRIPTION: Parse the AML that is associated with the method. * * MUTEX: Assumes parser is locked * @@ -71,31 +70,28 @@ acpi_status acpi_ds_parse_method ( - acpi_handle obj_handle) + struct acpi_namespace_node *node) { acpi_status status; union acpi_operand_object *obj_desc; union acpi_parse_object *op; - struct acpi_namespace_node *node; - acpi_owner_id owner_id; struct acpi_walk_state *walk_state; - ACPI_FUNCTION_TRACE_PTR ("ds_parse_method", obj_handle); + ACPI_FUNCTION_TRACE_PTR ("ds_parse_method", node); /* Parameter Validation */ - if (!obj_handle) { + if (!node) { return_ACPI_STATUS (AE_NULL_ENTRY); } ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "**** Parsing [%4.4s] **** named_obj=%p\n", - acpi_ut_get_node_name (obj_handle), obj_handle)); + acpi_ut_get_node_name (node), node)); /* Extract the method object from the method Node */ - node = (struct acpi_namespace_node *) obj_handle; obj_desc = acpi_ns_get_attached_object (node); if (!obj_desc) { return_ACPI_STATUS (AE_NULL_OBJECT); @@ -132,14 +128,18 @@ acpi_ds_parse_method ( * objects (such as Operation Regions) can be created during the * first pass parse. */ - owner_id = acpi_ut_allocate_owner_id (ACPI_OWNER_TYPE_METHOD); - obj_desc->method.owning_id = owner_id; + status = acpi_ut_allocate_owner_id (&obj_desc->method.owner_id); + if (ACPI_FAILURE (status)) { + goto cleanup; + } /* Create and initialize a new walk state */ - walk_state = acpi_ds_create_walk_state (owner_id, NULL, NULL, NULL); + walk_state = acpi_ds_create_walk_state ( + obj_desc->method.owner_id, NULL, NULL, NULL); if (!walk_state) { - return_ACPI_STATUS (AE_NO_MEMORY); + status = AE_NO_MEMORY; + goto cleanup2; } status = acpi_ds_init_aml_walk (walk_state, op, node, @@ -147,7 +147,7 @@ acpi_ds_parse_method ( obj_desc->method.aml_length, NULL, 1); if (ACPI_FAILURE (status)) { acpi_ds_delete_walk_state (walk_state); - return_ACPI_STATUS (status); + goto cleanup2; } /* @@ -161,13 +161,25 @@ acpi_ds_parse_method ( */ status = acpi_ps_parse_aml (walk_state); if (ACPI_FAILURE (status)) { - return_ACPI_STATUS (status); + goto cleanup2; } ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "**** [%4.4s] Parsed **** named_obj=%p Op=%p\n", - acpi_ut_get_node_name (obj_handle), obj_handle, op)); + acpi_ut_get_node_name (node), node, op)); + + /* + * Delete the parse tree. We simply re-parse the method for every + * execution since there isn't much overhead (compared to keeping lots + * of parse trees around) + */ + acpi_ns_delete_namespace_subtree (node); + acpi_ns_delete_namespace_by_owner (obj_desc->method.owner_id); + +cleanup2: + acpi_ut_release_owner_id (&obj_desc->method.owner_id); +cleanup: acpi_ps_delete_parse_tree (op); return_ACPI_STATUS (status); } @@ -263,7 +275,7 @@ acpi_ds_call_control_method ( { acpi_status status; struct acpi_namespace_node *method_node; - struct acpi_walk_state *next_walk_state; + struct acpi_walk_state *next_walk_state = NULL; union acpi_operand_object *obj_desc; struct acpi_parameter_info info; u32 i; @@ -287,20 +299,23 @@ acpi_ds_call_control_method ( return_ACPI_STATUS (AE_NULL_OBJECT); } - obj_desc->method.owning_id = acpi_ut_allocate_owner_id (ACPI_OWNER_TYPE_METHOD); + status = acpi_ut_allocate_owner_id (&obj_desc->method.owner_id); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } /* Init for new method, wait on concurrency semaphore */ status = acpi_ds_begin_method_execution (method_node, obj_desc, this_walk_state->method_node); if (ACPI_FAILURE (status)) { - return_ACPI_STATUS (status); + goto cleanup; } if (!(obj_desc->method.method_flags & AML_METHOD_INTERNAL_ONLY)) { /* 1) Parse: Create a new walk state for the preempting walk */ - next_walk_state = acpi_ds_create_walk_state (obj_desc->method.owning_id, + next_walk_state = acpi_ds_create_walk_state (obj_desc->method.owner_id, op, obj_desc, NULL); if (!next_walk_state) { return_ACPI_STATUS (AE_NO_MEMORY); @@ -330,7 +345,7 @@ acpi_ds_call_control_method ( /* 2) Execute: Create a new state for the preempting walk */ - next_walk_state = acpi_ds_create_walk_state (obj_desc->method.owning_id, + next_walk_state = acpi_ds_create_walk_state (obj_desc->method.owner_id, NULL, obj_desc, thread); if (!next_walk_state) { status = AE_NO_MEMORY; @@ -381,6 +396,7 @@ acpi_ds_call_control_method ( /* On error, we must delete the new walk state */ cleanup: + acpi_ut_release_owner_id (&obj_desc->method.owner_id); if (next_walk_state && (next_walk_state->method_desc)) { /* Decrement the thread count on the method parse tree */ @@ -552,8 +568,7 @@ acpi_ds_terminate_control_method ( */ if ((walk_state->method_desc->method.concurrency == 1) && (!walk_state->method_desc->method.semaphore)) { - status = acpi_os_create_semaphore (1, - 1, + status = acpi_os_create_semaphore (1, 1, &walk_state->method_desc->method.semaphore); } @@ -582,8 +597,10 @@ acpi_ds_terminate_control_method ( * Delete any namespace entries created anywhere else within * the namespace */ - acpi_ns_delete_namespace_by_owner (walk_state->method_desc->method.owning_id); + acpi_ns_delete_namespace_by_owner (walk_state->method_desc->method.owner_id); status = acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); + acpi_ut_release_owner_id (&walk_state->method_desc->method.owner_id); + if (ACPI_FAILURE (status)) { return_ACPI_STATUS (status); } diff --git a/drivers/acpi/dispatcher/dsmthdat.c b/drivers/acpi/dispatcher/dsmthdat.c index f7998306f75..c83d53fd639 100644 --- a/drivers/acpi/dispatcher/dsmthdat.c +++ b/drivers/acpi/dispatcher/dsmthdat.c @@ -633,22 +633,11 @@ acpi_ds_store_object_to_local ( */ if (opcode == AML_ARG_OP) { /* - * Make sure that the object is the correct type. This may be - * overkill, butit is here because references were NS nodes in - * the past. Now they are operand objects of type Reference. - */ - if (ACPI_GET_DESCRIPTOR_TYPE (current_obj_desc) != ACPI_DESC_TYPE_OPERAND) { - ACPI_REPORT_ERROR (( - "Invalid descriptor type while storing to method arg: [%s]\n", - acpi_ut_get_descriptor_name (current_obj_desc))); - return_ACPI_STATUS (AE_AML_INTERNAL); - } - - /* * If we have a valid reference object that came from ref_of(), * do the indirect store */ - if ((current_obj_desc->common.type == ACPI_TYPE_LOCAL_REFERENCE) && + if ((ACPI_GET_DESCRIPTOR_TYPE (current_obj_desc) == ACPI_DESC_TYPE_OPERAND) && + (current_obj_desc->common.type == ACPI_TYPE_LOCAL_REFERENCE) && (current_obj_desc->reference.opcode == AML_REF_OF_OP)) { ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Arg (%p) is an obj_ref(Node), storing in node %p\n", diff --git a/drivers/acpi/dispatcher/dsobject.c b/drivers/acpi/dispatcher/dsobject.c index bfbae4e4c66..1eee2d54180 100644 --- a/drivers/acpi/dispatcher/dsobject.c +++ b/drivers/acpi/dispatcher/dsobject.c @@ -547,6 +547,9 @@ acpi_ds_init_object_from_op ( case AML_TYPE_LITERAL: obj_desc->integer.value = op->common.value.integer; +#ifndef ACPI_NO_METHOD_EXECUTION + acpi_ex_truncate_for32bit_table (obj_desc); +#endif break; diff --git a/drivers/acpi/dispatcher/dsopcode.c b/drivers/acpi/dispatcher/dsopcode.c index ba13bca28be..750bdb1ac34 100644 --- a/drivers/acpi/dispatcher/dsopcode.c +++ b/drivers/acpi/dispatcher/dsopcode.c @@ -119,14 +119,15 @@ acpi_ds_execute_arguments ( walk_state = acpi_ds_create_walk_state (0, NULL, NULL, NULL); if (!walk_state) { - return_ACPI_STATUS (AE_NO_MEMORY); + status = AE_NO_MEMORY; + goto cleanup; } status = acpi_ds_init_aml_walk (walk_state, op, NULL, aml_start, aml_length, NULL, 1); if (ACPI_FAILURE (status)) { acpi_ds_delete_walk_state (walk_state); - return_ACPI_STATUS (status); + goto cleanup; } /* Mark this parse as a deferred opcode */ @@ -138,8 +139,7 @@ acpi_ds_execute_arguments ( status = acpi_ps_parse_aml (walk_state); if (ACPI_FAILURE (status)) { - acpi_ps_delete_parse_tree (op); - return_ACPI_STATUS (status); + goto cleanup; } /* Get and init the Op created above */ @@ -160,7 +160,8 @@ acpi_ds_execute_arguments ( walk_state = acpi_ds_create_walk_state (0, NULL, NULL, NULL); if (!walk_state) { - return_ACPI_STATUS (AE_NO_MEMORY); + status = AE_NO_MEMORY; + goto cleanup; } /* Execute the opcode and arguments */ @@ -169,13 +170,15 @@ acpi_ds_execute_arguments ( aml_length, NULL, 3); if (ACPI_FAILURE (status)) { acpi_ds_delete_walk_state (walk_state); - return_ACPI_STATUS (status); + goto cleanup; } /* Mark this execution as a deferred opcode */ walk_state->deferred_node = node; status = acpi_ps_parse_aml (walk_state); + +cleanup: acpi_ps_delete_parse_tree (op); return_ACPI_STATUS (status); } diff --git a/drivers/acpi/dispatcher/dswload.c b/drivers/acpi/dispatcher/dswload.c index d1162001842..9100c0bda47 100644 --- a/drivers/acpi/dispatcher/dswload.c +++ b/drivers/acpi/dispatcher/dswload.c @@ -50,7 +50,7 @@ #include <acpi/acnamesp.h> #include <acpi/acevents.h> -#ifdef _ACPI_ASL_COMPILER +#ifdef ACPI_ASL_COMPILER #include <acpi/acdisasm.h> #endif @@ -145,15 +145,6 @@ acpi_ds_load1_begin_op ( if (op) { if (!(walk_state->op_info->flags & AML_NAMED)) { -#if 0 - if ((walk_state->op_info->class == AML_CLASS_EXECUTE) || - (walk_state->op_info->class == AML_CLASS_CONTROL)) { - acpi_os_printf ("\n\n***EXECUTABLE OPCODE %s***\n\n", - walk_state->op_info->name); - *out_op = op; - return (AE_CTRL_SKIP); - } -#endif *out_op = op; return (AE_OK); } @@ -185,7 +176,7 @@ acpi_ds_load1_begin_op ( */ status = acpi_ns_lookup (walk_state->scope_info, path, object_type, ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT, walk_state, &(node)); -#ifdef _ACPI_ASL_COMPILER +#ifdef ACPI_ASL_COMPILER if (status == AE_NOT_FOUND) { /* * Table disassembly: @@ -486,11 +477,31 @@ acpi_ds_load2_begin_op ( ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Op=%p State=%p\n", op, walk_state)); if (op) { + if ((walk_state->control_state) && + (walk_state->control_state->common.state == + ACPI_CONTROL_CONDITIONAL_EXECUTING)) { + /* We are executing a while loop outside of a method */ + + status = acpi_ds_exec_begin_op (walk_state, out_op); + return_ACPI_STATUS (status); + } + /* We only care about Namespace opcodes here */ if ((!(walk_state->op_info->flags & AML_NSOPCODE) && (walk_state->opcode != AML_INT_NAMEPATH_OP)) || (!(walk_state->op_info->flags & AML_NAMED))) { + if ((walk_state->op_info->class == AML_CLASS_EXECUTE) || + (walk_state->op_info->class == AML_CLASS_CONTROL)) { + ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, + "Begin/EXEC: %s (fl %8.8X)\n", walk_state->op_info->name, + walk_state->op_info->flags)); + + /* Executing a type1 or type2 opcode outside of a method */ + + status = acpi_ds_exec_begin_op (walk_state, out_op); + return_ACPI_STATUS (status); + } return_ACPI_STATUS (AE_OK); } @@ -558,7 +569,7 @@ acpi_ds_load2_begin_op ( ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT, walk_state, &(node)); if (ACPI_FAILURE (status)) { -#ifdef _ACPI_ASL_COMPILER +#ifdef ACPI_ASL_COMPILER if (status == AE_NOT_FOUND) { status = AE_OK; } @@ -651,8 +662,10 @@ acpi_ds_load2_begin_op ( break; } + /* Add new entry into namespace */ + status = acpi_ns_lookup (walk_state->scope_info, buffer_ptr, object_type, - ACPI_IMODE_EXECUTE, ACPI_NS_NO_UPSEARCH, + ACPI_IMODE_LOAD_PASS2, ACPI_NS_NO_UPSEARCH, walk_state, &(node)); break; } @@ -662,7 +675,6 @@ acpi_ds_load2_begin_op ( return_ACPI_STATUS (status); } - if (!op) { /* Create a new op */ @@ -676,9 +688,7 @@ acpi_ds_load2_begin_op ( if (node) { op->named.name = node->name.integer; } - if (out_op) { - *out_op = op; - } + *out_op = op; } /* @@ -725,9 +735,24 @@ acpi_ds_load2_end_op ( ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Opcode [%s] Op %p State %p\n", walk_state->op_info->name, op, walk_state)); - /* Only interested in opcodes that have namespace objects */ + /* Check if opcode had an associated namespace object */ if (!(walk_state->op_info->flags & AML_NSOBJECT)) { +#ifndef ACPI_NO_METHOD_EXECUTION + /* No namespace object. Executable opcode? */ + + if ((walk_state->op_info->class == AML_CLASS_EXECUTE) || + (walk_state->op_info->class == AML_CLASS_CONTROL)) { + ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, + "End/EXEC: %s (fl %8.8X)\n", walk_state->op_info->name, + walk_state->op_info->flags)); + + /* Executing a type1 or type2 opcode outside of a method */ + + status = acpi_ds_exec_end_op (walk_state); + return_ACPI_STATUS (status); + } +#endif return_ACPI_STATUS (AE_OK); } @@ -736,7 +761,6 @@ acpi_ds_load2_end_op ( "Ending scope Op=%p State=%p\n", op, walk_state)); } - object_type = walk_state->op_info->object_type; /* @@ -959,6 +983,7 @@ acpi_ds_load2_end_op ( ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE, walk_state, &(new_node)); if (ACPI_SUCCESS (status)) { + /* * Make sure that what we found is indeed a method * We didn't search for a method on purpose, to see if the name diff --git a/drivers/acpi/dispatcher/dswstate.c b/drivers/acpi/dispatcher/dswstate.c index 9cd3db652b3..5621665991b 100644 --- a/drivers/acpi/dispatcher/dswstate.c +++ b/drivers/acpi/dispatcher/dswstate.c @@ -261,12 +261,12 @@ acpi_ds_result_pop_from_bottom ( if (!*object) { ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, - "Null operand! State=%p #Ops=%X, Index=%X\n", + "Null operand! State=%p #Ops=%X Index=%X\n", walk_state, state->results.num_results, (u32) index)); return (AE_AML_NO_RETURN_VALUE); } - ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Obj=%p [%s], Results=%p State=%p\n", + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Obj=%p [%s] Results=%p State=%p\n", *object, (*object) ? acpi_ut_get_object_type_name (*object) : "NULL", state, walk_state)); @@ -681,7 +681,7 @@ acpi_ds_create_walk_state ( ACPI_FUNCTION_TRACE ("ds_create_walk_state"); - walk_state = acpi_ut_acquire_from_cache (ACPI_MEM_LIST_WALK); + walk_state = ACPI_MEM_CALLOCATE (sizeof (struct acpi_walk_state)); if (!walk_state) { return_PTR (NULL); } @@ -704,7 +704,7 @@ acpi_ds_create_walk_state ( status = acpi_ds_result_stack_push (walk_state); if (ACPI_FAILURE (status)) { - acpi_ut_release_to_cache (ACPI_MEM_LIST_WALK, walk_state); + ACPI_MEM_FREE (walk_state); return_PTR (NULL); } @@ -744,7 +744,7 @@ acpi_ds_init_aml_walk ( u8 *aml_start, u32 aml_length, struct acpi_parameter_info *info, - u32 pass_number) + u8 pass_number) { acpi_status status; struct acpi_parse_state *parser_state = &walk_state->parser_state; @@ -762,6 +762,7 @@ acpi_ds_init_aml_walk ( /* The next_op of the next_walk will be the beginning of the method */ walk_state->next_op = NULL; + walk_state->pass_number = pass_number; if (info) { if (info->parameter_type == ACPI_PARAM_GPE) { @@ -899,38 +900,11 @@ acpi_ds_delete_walk_state ( acpi_ut_delete_generic_state (state); } - acpi_ut_release_to_cache (ACPI_MEM_LIST_WALK, walk_state); + ACPI_MEM_FREE (walk_state); return_VOID; } -#ifdef ACPI_ENABLE_OBJECT_CACHE -/****************************************************************************** - * - * FUNCTION: acpi_ds_delete_walk_state_cache - * - * PARAMETERS: None - * - * RETURN: None - * - * DESCRIPTION: Purge the global state object cache. Used during subsystem - * termination. - * - ******************************************************************************/ - -void -acpi_ds_delete_walk_state_cache ( - void) -{ - ACPI_FUNCTION_TRACE ("ds_delete_walk_state_cache"); - - - acpi_ut_delete_generic_cache (ACPI_MEM_LIST_WALK); - return_VOID; -} -#endif - - #ifdef ACPI_OBSOLETE_FUNCTIONS /******************************************************************************* * diff --git a/drivers/acpi/events/evgpe.c b/drivers/acpi/events/evgpe.c index 081120b109b..ede834df4f6 100644 --- a/drivers/acpi/events/evgpe.c +++ b/drivers/acpi/events/evgpe.c @@ -396,6 +396,7 @@ acpi_ev_gpe_detect ( 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_native_uint i; @@ -412,7 +413,7 @@ acpi_ev_gpe_detect ( /* Examine all GPE blocks attached to this interrupt level */ - acpi_os_acquire_lock (acpi_gbl_gpe_lock, ACPI_ISR); + flags = acpi_os_acquire_lock (acpi_gbl_gpe_lock); gpe_block = gpe_xrupt_list->gpe_block_list_head; while (gpe_block) { /* @@ -476,7 +477,7 @@ acpi_ev_gpe_detect ( unlock_and_exit: - acpi_os_release_lock (acpi_gbl_gpe_lock, ACPI_ISR); + acpi_os_release_lock (acpi_gbl_gpe_lock, flags); return (int_status); } diff --git a/drivers/acpi/events/evgpeblk.c b/drivers/acpi/events/evgpeblk.c index 84186a7d17b..dfc54692b12 100644 --- a/drivers/acpi/events/evgpeblk.c +++ b/drivers/acpi/events/evgpeblk.c @@ -66,7 +66,7 @@ acpi_ev_match_prw_and_gpe ( static struct acpi_gpe_xrupt_info * acpi_ev_get_gpe_xrupt_block ( - u32 interrupt_level); + u32 interrupt_number); static acpi_status acpi_ev_delete_gpe_xrupt ( @@ -75,7 +75,7 @@ acpi_ev_delete_gpe_xrupt ( static acpi_status acpi_ev_install_gpe_block ( struct acpi_gpe_block_info *gpe_block, - u32 interrupt_level); + u32 interrupt_number); static acpi_status acpi_ev_create_gpe_info_blocks ( @@ -138,7 +138,6 @@ acpi_ev_valid_gpe_event ( * FUNCTION: acpi_ev_walk_gpe_list * * PARAMETERS: gpe_walk_callback - Routine called for each GPE block - * Flags - ACPI_NOT_ISR or ACPI_ISR * * RETURN: Status * @@ -148,18 +147,18 @@ acpi_ev_valid_gpe_event ( acpi_status acpi_ev_walk_gpe_list ( - ACPI_GPE_CALLBACK gpe_walk_callback, - u32 flags) + ACPI_GPE_CALLBACK gpe_walk_callback) { struct acpi_gpe_block_info *gpe_block; struct acpi_gpe_xrupt_info *gpe_xrupt_info; acpi_status status = AE_OK; + u32 flags; ACPI_FUNCTION_TRACE ("ev_walk_gpe_list"); - acpi_os_acquire_lock (acpi_gbl_gpe_lock, flags); + flags = acpi_os_acquire_lock (acpi_gbl_gpe_lock); /* Walk the interrupt level descriptor list */ @@ -482,7 +481,7 @@ cleanup: * * FUNCTION: acpi_ev_get_gpe_xrupt_block * - * PARAMETERS: interrupt_level - Interrupt for a GPE block + * PARAMETERS: interrupt_number - Interrupt for a GPE block * * RETURN: A GPE interrupt block * @@ -495,11 +494,12 @@ cleanup: static struct acpi_gpe_xrupt_info * acpi_ev_get_gpe_xrupt_block ( - u32 interrupt_level) + u32 interrupt_number) { struct acpi_gpe_xrupt_info *next_gpe_xrupt; struct acpi_gpe_xrupt_info *gpe_xrupt; acpi_status status; + u32 flags; ACPI_FUNCTION_TRACE ("ev_get_gpe_xrupt_block"); @@ -509,7 +509,7 @@ acpi_ev_get_gpe_xrupt_block ( next_gpe_xrupt = acpi_gbl_gpe_xrupt_list_head; while (next_gpe_xrupt) { - if (next_gpe_xrupt->interrupt_level == interrupt_level) { + if (next_gpe_xrupt->interrupt_number == interrupt_number) { return_PTR (next_gpe_xrupt); } @@ -523,11 +523,11 @@ acpi_ev_get_gpe_xrupt_block ( return_PTR (NULL); } - gpe_xrupt->interrupt_level = interrupt_level; + gpe_xrupt->interrupt_number = interrupt_number; /* Install new interrupt descriptor with spin lock */ - acpi_os_acquire_lock (acpi_gbl_gpe_lock, ACPI_NOT_ISR); + flags = acpi_os_acquire_lock (acpi_gbl_gpe_lock); if (acpi_gbl_gpe_xrupt_list_head) { next_gpe_xrupt = acpi_gbl_gpe_xrupt_list_head; while (next_gpe_xrupt->next) { @@ -540,17 +540,17 @@ acpi_ev_get_gpe_xrupt_block ( else { acpi_gbl_gpe_xrupt_list_head = gpe_xrupt; } - acpi_os_release_lock (acpi_gbl_gpe_lock, ACPI_NOT_ISR); + acpi_os_release_lock (acpi_gbl_gpe_lock, flags); /* Install new interrupt handler if not SCI_INT */ - if (interrupt_level != acpi_gbl_FADT->sci_int) { - status = acpi_os_install_interrupt_handler (interrupt_level, + if (interrupt_number != acpi_gbl_FADT->sci_int) { + status = acpi_os_install_interrupt_handler (interrupt_number, acpi_ev_gpe_xrupt_handler, gpe_xrupt); if (ACPI_FAILURE (status)) { ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Could not install GPE interrupt handler at level 0x%X\n", - interrupt_level)); + interrupt_number)); return_PTR (NULL); } } @@ -577,6 +577,7 @@ acpi_ev_delete_gpe_xrupt ( struct acpi_gpe_xrupt_info *gpe_xrupt) { acpi_status status; + u32 flags; ACPI_FUNCTION_TRACE ("ev_delete_gpe_xrupt"); @@ -584,14 +585,14 @@ acpi_ev_delete_gpe_xrupt ( /* We never want to remove the SCI interrupt handler */ - if (gpe_xrupt->interrupt_level == acpi_gbl_FADT->sci_int) { + if (gpe_xrupt->interrupt_number == acpi_gbl_FADT->sci_int) { gpe_xrupt->gpe_block_list_head = NULL; return_ACPI_STATUS (AE_OK); } /* Disable this interrupt */ - status = acpi_os_remove_interrupt_handler (gpe_xrupt->interrupt_level, + status = acpi_os_remove_interrupt_handler (gpe_xrupt->interrupt_number, acpi_ev_gpe_xrupt_handler); if (ACPI_FAILURE (status)) { return_ACPI_STATUS (status); @@ -599,7 +600,7 @@ acpi_ev_delete_gpe_xrupt ( /* Unlink the interrupt block with lock */ - acpi_os_acquire_lock (acpi_gbl_gpe_lock, ACPI_NOT_ISR); + flags = acpi_os_acquire_lock (acpi_gbl_gpe_lock); if (gpe_xrupt->previous) { gpe_xrupt->previous->next = gpe_xrupt->next; } @@ -607,7 +608,7 @@ acpi_ev_delete_gpe_xrupt ( if (gpe_xrupt->next) { gpe_xrupt->next->previous = gpe_xrupt->previous; } - acpi_os_release_lock (acpi_gbl_gpe_lock, ACPI_NOT_ISR); + acpi_os_release_lock (acpi_gbl_gpe_lock, flags); /* Free the block */ @@ -621,7 +622,7 @@ acpi_ev_delete_gpe_xrupt ( * FUNCTION: acpi_ev_install_gpe_block * * PARAMETERS: gpe_block - New GPE block - * interrupt_level - Level to be associated with this GPE block + * interrupt_number - Xrupt to be associated with this GPE block * * RETURN: Status * @@ -632,11 +633,12 @@ acpi_ev_delete_gpe_xrupt ( static acpi_status acpi_ev_install_gpe_block ( struct acpi_gpe_block_info *gpe_block, - u32 interrupt_level) + u32 interrupt_number) { struct acpi_gpe_block_info *next_gpe_block; struct acpi_gpe_xrupt_info *gpe_xrupt_block; acpi_status status; + u32 flags; ACPI_FUNCTION_TRACE ("ev_install_gpe_block"); @@ -647,7 +649,7 @@ acpi_ev_install_gpe_block ( return_ACPI_STATUS (status); } - gpe_xrupt_block = acpi_ev_get_gpe_xrupt_block (interrupt_level); + gpe_xrupt_block = acpi_ev_get_gpe_xrupt_block (interrupt_number); if (!gpe_xrupt_block) { status = AE_NO_MEMORY; goto unlock_and_exit; @@ -655,7 +657,7 @@ acpi_ev_install_gpe_block ( /* Install the new block at the end of the list with lock */ - acpi_os_acquire_lock (acpi_gbl_gpe_lock, ACPI_NOT_ISR); + flags = acpi_os_acquire_lock (acpi_gbl_gpe_lock); if (gpe_xrupt_block->gpe_block_list_head) { next_gpe_block = gpe_xrupt_block->gpe_block_list_head; while (next_gpe_block->next) { @@ -670,7 +672,7 @@ acpi_ev_install_gpe_block ( } gpe_block->xrupt_block = gpe_xrupt_block; - acpi_os_release_lock (acpi_gbl_gpe_lock, ACPI_NOT_ISR); + acpi_os_release_lock (acpi_gbl_gpe_lock, flags); unlock_and_exit: status = acpi_ut_release_mutex (ACPI_MTX_EVENTS); @@ -695,6 +697,7 @@ acpi_ev_delete_gpe_block ( struct acpi_gpe_block_info *gpe_block) { acpi_status status; + u32 flags; ACPI_FUNCTION_TRACE ("ev_install_gpe_block"); @@ -720,7 +723,7 @@ acpi_ev_delete_gpe_block ( else { /* Remove the block on this interrupt with lock */ - acpi_os_acquire_lock (acpi_gbl_gpe_lock, ACPI_NOT_ISR); + flags = acpi_os_acquire_lock (acpi_gbl_gpe_lock); if (gpe_block->previous) { gpe_block->previous->next = gpe_block->next; } @@ -731,7 +734,7 @@ acpi_ev_delete_gpe_block ( if (gpe_block->next) { gpe_block->next->previous = gpe_block->previous; } - acpi_os_release_lock (acpi_gbl_gpe_lock, ACPI_NOT_ISR); + acpi_os_release_lock (acpi_gbl_gpe_lock, flags); } /* Free the gpe_block */ @@ -887,7 +890,7 @@ error_exit: * gpe_block_address - Address and space_iD * register_count - Number of GPE register pairs in the block * gpe_block_base_number - Starting GPE number for the block - * interrupt_level - H/W interrupt for the block + * interrupt_number - H/W interrupt for the block * return_gpe_block - Where the new block descriptor is returned * * RETURN: Status @@ -902,7 +905,7 @@ acpi_ev_create_gpe_block ( struct acpi_generic_address *gpe_block_address, u32 register_count, u8 gpe_block_base_number, - u32 interrupt_level, + u32 interrupt_number, struct acpi_gpe_block_info **return_gpe_block) { struct acpi_gpe_block_info *gpe_block; @@ -948,7 +951,7 @@ acpi_ev_create_gpe_block ( /* Install the new block in the global list(s) */ - status = acpi_ev_install_gpe_block (gpe_block, interrupt_level); + status = acpi_ev_install_gpe_block (gpe_block, interrupt_number); if (ACPI_FAILURE (status)) { ACPI_MEM_FREE (gpe_block); return_ACPI_STATUS (status); @@ -1013,7 +1016,7 @@ acpi_ev_create_gpe_block ( ((gpe_block->register_count * ACPI_GPE_REGISTER_WIDTH) -1)), gpe_device->name.ascii, gpe_block->register_count, - interrupt_level)); + interrupt_number)); /* Enable all valid GPEs found above */ diff --git a/drivers/acpi/events/evmisc.c b/drivers/acpi/events/evmisc.c index 659e9095611..3df3ada4b9e 100644 --- a/drivers/acpi/events/evmisc.c +++ b/drivers/acpi/events/evmisc.c @@ -411,6 +411,9 @@ acpi_ev_init_global_lock_handler ( * with an error. */ if (status == AE_NO_HARDWARE_RESPONSE) { + ACPI_REPORT_ERROR (( + "No response from Global Lock hardware, disabling lock\n")); + acpi_gbl_global_lock_present = FALSE; status = AE_OK; } @@ -589,7 +592,7 @@ acpi_ev_terminate ( /* Disable all GPEs in all GPE blocks */ - status = acpi_ev_walk_gpe_list (acpi_hw_disable_gpe_block, ACPI_NOT_ISR); + status = acpi_ev_walk_gpe_list (acpi_hw_disable_gpe_block); /* Remove SCI handler */ @@ -602,7 +605,7 @@ acpi_ev_terminate ( /* Deallocate all handler objects installed within GPE info structs */ - status = acpi_ev_walk_gpe_list (acpi_ev_delete_gpe_handlers, ACPI_NOT_ISR); + status = acpi_ev_walk_gpe_list (acpi_ev_delete_gpe_handlers); /* Return to original mode if necessary */ diff --git a/drivers/acpi/events/evrgnini.c b/drivers/acpi/events/evrgnini.c index 95bc09c73a6..f2d53af9761 100644 --- a/drivers/acpi/events/evrgnini.c +++ b/drivers/acpi/events/evrgnini.c @@ -218,10 +218,14 @@ acpi_ev_pci_config_region_setup ( while (pci_root_node != acpi_gbl_root_node) { status = acpi_ut_execute_HID (pci_root_node, &object_hID); if (ACPI_SUCCESS (status)) { - /* Got a valid _HID, check if this is a PCI root */ - + /* + * Got a valid _HID string, check if this is a PCI root. + * New for ACPI 3.0: check for a PCI Express root also. + */ if (!(ACPI_STRNCMP (object_hID.value, PCI_ROOT_HID_STRING, - sizeof (PCI_ROOT_HID_STRING)))) { + sizeof (PCI_ROOT_HID_STRING)) || + !(ACPI_STRNCMP (object_hID.value, PCI_EXPRESS_ROOT_HID_STRING, + sizeof (PCI_EXPRESS_ROOT_HID_STRING))))) { /* Install a handler for this PCI root bridge */ status = acpi_install_address_space_handler ((acpi_handle) pci_root_node, diff --git a/drivers/acpi/events/evxface.c b/drivers/acpi/events/evxface.c index 4092d47f675..4c1c25e316a 100644 --- a/drivers/acpi/events/evxface.c +++ b/drivers/acpi/events/evxface.c @@ -591,6 +591,7 @@ acpi_install_gpe_handler ( struct acpi_gpe_event_info *gpe_event_info; struct acpi_handler_info *handler; acpi_status status; + u32 flags; ACPI_FUNCTION_TRACE ("acpi_install_gpe_handler"); @@ -643,7 +644,7 @@ acpi_install_gpe_handler ( /* Install the handler */ - acpi_os_acquire_lock (acpi_gbl_gpe_lock, ACPI_NOT_ISR); + flags = acpi_os_acquire_lock (acpi_gbl_gpe_lock); gpe_event_info->dispatch.handler = handler; /* Setup up dispatch flags to indicate handler (vs. method) */ @@ -651,7 +652,7 @@ acpi_install_gpe_handler ( gpe_event_info->flags &= ~(ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK); /* Clear bits */ gpe_event_info->flags |= (u8) (type | ACPI_GPE_DISPATCH_HANDLER); - acpi_os_release_lock (acpi_gbl_gpe_lock, ACPI_NOT_ISR); + acpi_os_release_lock (acpi_gbl_gpe_lock, flags); unlock_and_exit: @@ -685,6 +686,7 @@ acpi_remove_gpe_handler ( struct acpi_gpe_event_info *gpe_event_info; struct acpi_handler_info *handler; acpi_status status; + u32 flags; ACPI_FUNCTION_TRACE ("acpi_remove_gpe_handler"); @@ -741,7 +743,7 @@ acpi_remove_gpe_handler ( /* Remove the handler */ - acpi_os_acquire_lock (acpi_gbl_gpe_lock, ACPI_NOT_ISR); + flags = acpi_os_acquire_lock (acpi_gbl_gpe_lock); handler = gpe_event_info->dispatch.handler; /* Restore Method node (if any), set dispatch flags */ @@ -751,7 +753,7 @@ acpi_remove_gpe_handler ( if (handler->method_node) { gpe_event_info->flags |= ACPI_GPE_DISPATCH_METHOD; } - acpi_os_release_lock (acpi_gbl_gpe_lock, ACPI_NOT_ISR); + acpi_os_release_lock (acpi_gbl_gpe_lock, flags); /* Now we can free the handler object */ diff --git a/drivers/acpi/events/evxfevnt.c b/drivers/acpi/events/evxfevnt.c index f337dc2cc56..c5f74d7b64d 100644 --- a/drivers/acpi/events/evxfevnt.c +++ b/drivers/acpi/events/evxfevnt.c @@ -635,7 +635,7 @@ unlock_and_exit: * PARAMETERS: gpe_device - Handle to the parent GPE Block Device * gpe_block_address - Address and space_iD * register_count - Number of GPE register pairs in the block - * interrupt_level - H/W interrupt for the block + * interrupt_number - H/W interrupt for the block * * RETURN: Status * @@ -648,7 +648,7 @@ acpi_install_gpe_block ( acpi_handle gpe_device, struct acpi_generic_address *gpe_block_address, u32 register_count, - u32 interrupt_level) + u32 interrupt_number) { acpi_status status; union acpi_operand_object *obj_desc; @@ -681,7 +681,7 @@ acpi_install_gpe_block ( * is always zero */ status = acpi_ev_create_gpe_block (node, gpe_block_address, register_count, - 0, interrupt_level, &gpe_block); + 0, interrupt_number, &gpe_block); if (ACPI_FAILURE (status)) { goto unlock_and_exit; } diff --git a/drivers/acpi/executer/exconfig.c b/drivers/acpi/executer/exconfig.c index 734b2f24af4..d11e9ec827f 100644 --- a/drivers/acpi/executer/exconfig.c +++ b/drivers/acpi/executer/exconfig.c @@ -99,6 +99,11 @@ acpi_ex_add_table ( return_ACPI_STATUS (AE_NO_MEMORY); } + /* Init the table handle */ + + obj_desc->reference.opcode = AML_LOAD_OP; + *ddb_handle = obj_desc; + /* Install the new table into the local data structures */ ACPI_MEMSET (&table_info, 0, sizeof (struct acpi_table_desc)); @@ -109,7 +114,14 @@ acpi_ex_add_table ( table_info.allocation = ACPI_MEM_ALLOCATED; status = acpi_tb_install_table (&table_info); + obj_desc->reference.object = table_info.installed_desc; + if (ACPI_FAILURE (status)) { + if (status == AE_ALREADY_EXISTS) { + /* Table already exists, just return the handle */ + + return_ACPI_STATUS (AE_OK); + } goto cleanup; } @@ -123,16 +135,12 @@ acpi_ex_add_table ( goto cleanup; } - /* Init the table handle */ - - obj_desc->reference.opcode = AML_LOAD_OP; - obj_desc->reference.object = table_info.installed_desc; - *ddb_handle = obj_desc; return_ACPI_STATUS (AE_OK); cleanup: acpi_ut_remove_reference (obj_desc); + *ddb_handle = NULL; return_ACPI_STATUS (status); } @@ -376,16 +384,22 @@ acpi_ex_load_op ( */ status = acpi_ex_read_data_from_field (walk_state, obj_desc, &buffer_desc); if (ACPI_FAILURE (status)) { - goto cleanup; + return_ACPI_STATUS (status); } table_ptr = ACPI_CAST_PTR (struct acpi_table_header, buffer_desc->buffer.pointer); - /* Sanity check the table length */ + /* All done with the buffer_desc, delete it */ + + buffer_desc->buffer.pointer = NULL; + acpi_ut_remove_reference (buffer_desc); + + /* Sanity check the table length */ if (table_ptr->length < sizeof (struct acpi_table_header)) { - return_ACPI_STATUS (AE_BAD_HEADER); + status = AE_BAD_HEADER; + goto cleanup; } break; @@ -413,7 +427,9 @@ acpi_ex_load_op ( status = acpi_ex_add_table (table_ptr, acpi_gbl_root_node, &ddb_handle); if (ACPI_FAILURE (status)) { - goto cleanup; + /* On error, table_ptr was deallocated above */ + + return_ACPI_STATUS (status); } /* Store the ddb_handle into the Target operand */ @@ -421,17 +437,14 @@ acpi_ex_load_op ( status = acpi_ex_store (ddb_handle, target, walk_state); if (ACPI_FAILURE (status)) { (void) acpi_ex_unload_table (ddb_handle); - } - return_ACPI_STATUS (status); + /* table_ptr was deallocated above */ + return_ACPI_STATUS (status); + } cleanup: - - if (buffer_desc) { - acpi_ut_remove_reference (buffer_desc); - } - else { + if (ACPI_FAILURE (status)) { ACPI_MEM_FREE (table_ptr); } return_ACPI_STATUS (status); @@ -482,7 +495,8 @@ acpi_ex_unload_table ( * Delete the entire namespace under this table Node * (Offset contains the table_id) */ - acpi_ns_delete_namespace_by_owner (table_info->table_id); + acpi_ns_delete_namespace_by_owner (table_info->owner_id); + acpi_ut_release_owner_id (&table_info->owner_id); /* Delete the table itself */ diff --git a/drivers/acpi/executer/exconvrt.c b/drivers/acpi/executer/exconvrt.c index 97856c48bd7..21331625e66 100644 --- a/drivers/acpi/executer/exconvrt.c +++ b/drivers/acpi/executer/exconvrt.c @@ -367,7 +367,7 @@ acpi_ex_convert_to_ascii ( /* hex_length: 2 ascii hex chars per data byte */ - hex_length = ACPI_MUL_2 (data_width); + hex_length = (acpi_native_uint) ACPI_MUL_2 (data_width); for (i = 0, j = (hex_length-1); i < hex_length; i++, j--) { /* Get one hex digit, most significant digits first */ diff --git a/drivers/acpi/executer/exdump.c b/drivers/acpi/executer/exdump.c index 40850064811..4f98dceed39 100644 --- a/drivers/acpi/executer/exdump.c +++ b/drivers/acpi/executer/exdump.c @@ -51,6 +51,11 @@ #define _COMPONENT ACPI_EXECUTER ACPI_MODULE_NAME ("exdump") +/* + * The following routines are used for debug output only + */ +#if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER) + /* Local prototypes */ #ifdef ACPI_FUTURE_USAGE @@ -73,13 +78,17 @@ static void acpi_ex_out_address ( char *title, acpi_physical_address value); -#endif /* ACPI_FUTURE_USAGE */ +static void +acpi_ex_dump_reference ( + union acpi_operand_object *obj_desc); -/* - * The following routines are used for debug output only - */ -#if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER) +static void +acpi_ex_dump_package ( + union acpi_operand_object *obj_desc, + u32 level, + u32 index); +#endif /* ACPI_FUTURE_USAGE */ /******************************************************************************* * @@ -118,7 +127,7 @@ acpi_ex_dump_operand ( } if (ACPI_GET_DESCRIPTOR_TYPE (obj_desc) == ACPI_DESC_TYPE_NAMED) { - ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "%p is a NS Node: ", obj_desc)); + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "%p Namespace Node: ", obj_desc)); ACPI_DUMP_ENTRY (obj_desc, ACPI_LV_EXEC); return; } @@ -467,7 +476,7 @@ acpi_ex_dump_operands ( } ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, - "************* Stack dump from %s(%d), %s\n", + "************* Operand Stack dump from %s(%d), %s\n", module_name, line_number, note)); return; } @@ -508,7 +517,7 @@ acpi_ex_out_integer ( char *title, u32 value) { - acpi_os_printf ("%20s : %X\n", title, value); + acpi_os_printf ("%20s : %.2X\n", title, value); } static void @@ -565,9 +574,144 @@ acpi_ex_dump_node ( /******************************************************************************* * + * FUNCTION: acpi_ex_dump_reference + * + * PARAMETERS: Object - Descriptor to dump + * + * DESCRIPTION: Dumps a reference object + * + ******************************************************************************/ + +static void +acpi_ex_dump_reference ( + union acpi_operand_object *obj_desc) +{ + struct acpi_buffer ret_buf; + acpi_status status; + + + if (obj_desc->reference.opcode == AML_INT_NAMEPATH_OP) { + acpi_os_printf ("Named Object %p ", obj_desc->reference.node); + ret_buf.length = ACPI_ALLOCATE_LOCAL_BUFFER; + status = acpi_ns_handle_to_pathname (obj_desc->reference.node, &ret_buf); + if (ACPI_FAILURE (status)) { + acpi_os_printf ("Could not convert name to pathname\n"); + } + else { + acpi_os_printf ("%s\n", (char *) ret_buf.pointer); + ACPI_MEM_FREE (ret_buf.pointer); + } + } + else if (obj_desc->reference.object) { + acpi_os_printf ("\nReferenced Object: %p\n", obj_desc->reference.object); + } +} + + +/******************************************************************************* + * + * FUNCTION: acpi_ex_dump_package + * + * PARAMETERS: Object - Descriptor to dump + * Level - Indentation Level + * Index - Package index for this object + * + * DESCRIPTION: Dumps the elements of the package + * + ******************************************************************************/ + +static void +acpi_ex_dump_package ( + union acpi_operand_object *obj_desc, + u32 level, + u32 index) +{ + u32 i; + + + /* Indentation and index output */ + + if (level > 0) { + for (i = 0; i < level; i++) { + acpi_os_printf (" "); + } + + acpi_os_printf ("[%.2d] ", index); + } + + acpi_os_printf ("%p ", obj_desc); + + /* Null package elements are allowed */ + + if (!obj_desc) { + acpi_os_printf ("[Null Object]\n"); + return; + } + + /* Packages may only contain a few object types */ + + switch (ACPI_GET_OBJECT_TYPE (obj_desc)) { + case ACPI_TYPE_INTEGER: + + acpi_os_printf ("[Integer] = %8.8X%8.8X\n", + ACPI_FORMAT_UINT64 (obj_desc->integer.value)); + break; + + + case ACPI_TYPE_STRING: + + acpi_os_printf ("[String] Value: "); + for (i = 0; i < obj_desc->string.length; i++) { + acpi_os_printf ("%c", obj_desc->string.pointer[i]); + } + acpi_os_printf ("\n"); + break; + + + case ACPI_TYPE_BUFFER: + + acpi_os_printf ("[Buffer] Length %.2X = ", obj_desc->buffer.length); + if (obj_desc->buffer.length) { + acpi_ut_dump_buffer ((u8 *) obj_desc->buffer.pointer, + obj_desc->buffer.length, DB_DWORD_DISPLAY, _COMPONENT); + } + else { + acpi_os_printf ("\n"); + } + break; + + + case ACPI_TYPE_PACKAGE: + + acpi_os_printf ("[Package] Contains %d Elements: \n", + obj_desc->package.count); + + for (i = 0; i < obj_desc->package.count; i++) { + acpi_ex_dump_package (obj_desc->package.elements[i], level+1, i); + } + break; + + + case ACPI_TYPE_LOCAL_REFERENCE: + + acpi_os_printf ("[Object Reference] "); + acpi_ex_dump_reference (obj_desc); + break; + + + default: + + acpi_os_printf ("[Unknown Type] %X\n", ACPI_GET_OBJECT_TYPE (obj_desc)); + break; + } +} + + +/******************************************************************************* + * * FUNCTION: acpi_ex_dump_object_descriptor * - * PARAMETERS: *Object - Descriptor to dump + * PARAMETERS: Object - Descriptor to dump * Flags - Force display if TRUE * * DESCRIPTION: Dumps the members of the object descriptor given. @@ -579,9 +723,6 @@ acpi_ex_dump_object_descriptor ( union acpi_operand_object *obj_desc, u32 flags) { - u32 i; - - ACPI_FUNCTION_TRACE ("ex_dump_object_descriptor"); @@ -648,22 +789,13 @@ acpi_ex_dump_object_descriptor ( case ACPI_TYPE_PACKAGE: acpi_ex_out_integer ("Flags", obj_desc->package.flags); - acpi_ex_out_integer ("Count", obj_desc->package.count); - acpi_ex_out_pointer ("Elements", obj_desc->package.elements); + acpi_ex_out_integer ("Elements", obj_desc->package.count); + acpi_ex_out_pointer ("Element List", obj_desc->package.elements); /* Dump the package contents */ - if (obj_desc->package.count > 0) { - acpi_os_printf ("\nPackage Contents:\n"); - for (i = 0; i < obj_desc->package.count; i++) { - acpi_os_printf ("[%.3d] %p", i, obj_desc->package.elements[i]); - if (obj_desc->package.elements[i]) { - acpi_os_printf (" %s", - acpi_ut_get_object_type_name (obj_desc->package.elements[i])); - } - acpi_os_printf ("\n"); - } - } + acpi_os_printf ("\nPackage Contents:\n"); + acpi_ex_dump_package (obj_desc, 0, 0); break; @@ -686,7 +818,7 @@ acpi_ex_dump_object_descriptor ( acpi_ex_out_integer ("param_count", obj_desc->method.param_count); acpi_ex_out_integer ("Concurrency", obj_desc->method.concurrency); acpi_ex_out_pointer ("Semaphore", obj_desc->method.semaphore); - acpi_ex_out_integer ("owning_id", obj_desc->method.owning_id); + acpi_ex_out_integer ("owner_id", obj_desc->method.owner_id); acpi_ex_out_integer ("aml_length", obj_desc->method.aml_length); acpi_ex_out_pointer ("aml_start", obj_desc->method.aml_start); break; @@ -790,10 +922,7 @@ acpi_ex_dump_object_descriptor ( acpi_ex_out_pointer ("Node", obj_desc->reference.node); acpi_ex_out_pointer ("Where", obj_desc->reference.where); - if (obj_desc->reference.object) { - acpi_os_printf ("\nReferenced Object:\n"); - acpi_ex_dump_object_descriptor (obj_desc->reference.object, flags); - } + acpi_ex_dump_reference (obj_desc); break; diff --git a/drivers/acpi/executer/exfield.c b/drivers/acpi/executer/exfield.c index 22c8fa480f6..a690c925099 100644 --- a/drivers/acpi/executer/exfield.c +++ b/drivers/acpi/executer/exfield.c @@ -87,6 +87,9 @@ acpi_ex_read_data_from_field ( if (!obj_desc) { return_ACPI_STATUS (AE_AML_NO_OPERAND); } + if (!ret_buffer_desc) { + return_ACPI_STATUS (AE_BAD_PARAMETER); + } if (ACPI_GET_OBJECT_TYPE (obj_desc) == ACPI_TYPE_BUFFER_FIELD) { /* @@ -182,7 +185,7 @@ exit: if (ACPI_FAILURE (status)) { acpi_ut_remove_reference (buffer_desc); } - else if (ret_buffer_desc) { + else { *ret_buffer_desc = buffer_desc; } diff --git a/drivers/acpi/executer/exmisc.c b/drivers/acpi/executer/exmisc.c index 022f281345b..237ef28c813 100644 --- a/drivers/acpi/executer/exmisc.c +++ b/drivers/acpi/executer/exmisc.c @@ -302,7 +302,7 @@ acpi_ex_do_concatenate ( /* Result of two Integers is a Buffer */ /* Need enough buffer space for two integers */ - return_desc = acpi_ut_create_buffer_object ( + return_desc = acpi_ut_create_buffer_object ((acpi_size) ACPI_MUL_2 (acpi_gbl_integer_byte_width)); if (!return_desc) { status = AE_NO_MEMORY; diff --git a/drivers/acpi/executer/exnames.c b/drivers/acpi/executer/exnames.c index 639f0bd3f6d..b6ba1a7a677 100644 --- a/drivers/acpi/executer/exnames.c +++ b/drivers/acpi/executer/exnames.c @@ -438,6 +438,13 @@ acpi_ex_get_name_string ( status = AE_AML_BAD_NAME; } + if (ACPI_FAILURE (status)) { + if (name_string) { + ACPI_MEM_FREE (name_string); + } + return_ACPI_STATUS (status); + } + *out_name_string = name_string; *out_name_length = (u32) (aml_address - in_aml_address); diff --git a/drivers/acpi/executer/exoparg1.c b/drivers/acpi/executer/exoparg1.c index dbdf8262ba0..48c30f80008 100644 --- a/drivers/acpi/executer/exoparg1.c +++ b/drivers/acpi/executer/exoparg1.c @@ -113,8 +113,9 @@ acpi_ex_opcode_0A_0T_1R ( status = AE_NO_MEMORY; goto cleanup; } - +#if ACPI_MACHINE_WIDTH != 16 return_desc->integer.value = acpi_os_get_timer (); +#endif break; default: /* Unknown opcode */ @@ -127,15 +128,16 @@ acpi_ex_opcode_0A_0T_1R ( cleanup: - if (!walk_state->result_obj) { - walk_state->result_obj = return_desc; - } - /* Delete return object on error */ - if (ACPI_FAILURE (status)) { + if ((ACPI_FAILURE (status)) || walk_state->result_obj) { acpi_ut_remove_reference (return_desc); } + else { + /* Save the return value */ + + walk_state->result_obj = return_desc; + } return_ACPI_STATUS (status); } @@ -902,6 +904,7 @@ acpi_ex_opcode_1A_0T_1R ( */ return_desc = acpi_ns_get_attached_object ( (struct acpi_namespace_node *) operand[0]); + acpi_ut_add_reference (return_desc); } else { /* @@ -951,20 +954,10 @@ acpi_ex_opcode_1A_0T_1R ( * add another reference to the referenced object, however. */ return_desc = *(operand[0]->reference.where); - if (!return_desc) { - /* - * We can't return a NULL dereferenced value. This is - * an uninitialized package element and is thus a - * severe error. - */ - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, - "NULL package element obj %p\n", - operand[0])); - status = AE_AML_UNINITIALIZED_ELEMENT; - goto cleanup; + if (return_desc) { + acpi_ut_add_reference (return_desc); } - acpi_ut_add_reference (return_desc); break; diff --git a/drivers/acpi/executer/exoparg3.c b/drivers/acpi/executer/exoparg3.c index 23b068adbf5..197890f443b 100644 --- a/drivers/acpi/executer/exoparg3.c +++ b/drivers/acpi/executer/exoparg3.c @@ -160,7 +160,7 @@ acpi_ex_opcode_3A_1T_1R ( { union acpi_operand_object **operand = &walk_state->operands[0]; union acpi_operand_object *return_desc = NULL; - char *buffer; + char *buffer = NULL; acpi_status status = AE_OK; acpi_integer index; acpi_size length; @@ -193,34 +193,63 @@ acpi_ex_opcode_3A_1T_1R ( * If the index is beyond the length of the String/Buffer, or if the * requested length is zero, return a zero-length String/Buffer */ - if ((index < operand[0]->string.length) && - (length > 0)) { - /* Truncate request if larger than the actual String/Buffer */ - - if ((index + length) > - operand[0]->string.length) { - length = (acpi_size) operand[0]->string.length - - (acpi_size) index; - } + if (index >= operand[0]->string.length) { + length = 0; + } + + /* Truncate request if larger than the actual String/Buffer */ + + else if ((index + length) > operand[0]->string.length) { + length = (acpi_size) operand[0]->string.length - + (acpi_size) index; + } - /* Allocate a new buffer for the String/Buffer */ + /* Strings always have a sub-pointer, not so for buffers */ + + switch (ACPI_GET_OBJECT_TYPE (operand[0])) { + case ACPI_TYPE_STRING: + + /* Always allocate a new buffer for the String */ buffer = ACPI_MEM_CALLOCATE ((acpi_size) length + 1); if (!buffer) { status = AE_NO_MEMORY; goto cleanup; } + break; + + case ACPI_TYPE_BUFFER: + + /* If the requested length is zero, don't allocate a buffer */ + + if (length > 0) { + /* Allocate a new buffer for the Buffer */ + + buffer = ACPI_MEM_CALLOCATE (length); + if (!buffer) { + status = AE_NO_MEMORY; + goto cleanup; + } + } + break; + default: /* Should not happen */ + + status = AE_AML_OPERAND_TYPE; + goto cleanup; + } + + if (length > 0) { /* Copy the portion requested */ ACPI_MEMCPY (buffer, operand[0]->string.pointer + index, length); + } - /* Set the length of the new String/Buffer */ + /* Set the length of the new String/Buffer */ - return_desc->string.pointer = buffer; - return_desc->string.length = (u32) length; - } + return_desc->string.pointer = buffer; + return_desc->string.length = (u32) length; /* Mark buffer initialized */ @@ -244,13 +273,13 @@ cleanup: /* Delete return object on error */ - if (ACPI_FAILURE (status)) { + if (ACPI_FAILURE (status) || walk_state->result_obj) { acpi_ut_remove_reference (return_desc); } /* Set the return object and exit */ - if (!walk_state->result_obj) { + else { walk_state->result_obj = return_desc; } return_ACPI_STATUS (status); diff --git a/drivers/acpi/executer/exresop.c b/drivers/acpi/executer/exresop.c index d8b470eefe7..aaba7abcb52 100644 --- a/drivers/acpi/executer/exresop.c +++ b/drivers/acpi/executer/exresop.c @@ -426,6 +426,10 @@ acpi_ex_resolve_operands ( return_ACPI_STATUS (status); } + + if (obj_desc != *stack_ptr) { + acpi_ut_remove_reference (obj_desc); + } goto next_operand; @@ -448,6 +452,10 @@ acpi_ex_resolve_operands ( return_ACPI_STATUS (status); } + + if (obj_desc != *stack_ptr) { + acpi_ut_remove_reference (obj_desc); + } goto next_operand; @@ -471,6 +479,10 @@ acpi_ex_resolve_operands ( return_ACPI_STATUS (status); } + + if (obj_desc != *stack_ptr) { + acpi_ut_remove_reference (obj_desc); + } goto next_operand; @@ -515,6 +527,10 @@ acpi_ex_resolve_operands ( if (ACPI_FAILURE (status)) { return_ACPI_STATUS (status); } + + if (obj_desc != *stack_ptr) { + acpi_ut_remove_reference (obj_desc); + } break; default: diff --git a/drivers/acpi/executer/exstore.c b/drivers/acpi/executer/exstore.c index 2725db0901b..59dbfeaa54c 100644 --- a/drivers/acpi/executer/exstore.c +++ b/drivers/acpi/executer/exstore.c @@ -147,7 +147,7 @@ acpi_ex_do_debug_object ( case ACPI_TYPE_BUFFER: - ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DEBUG_OBJECT, "[0x%.2X]", + ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DEBUG_OBJECT, "[0x%.2X]\n", (u32) source_desc->buffer.length)); ACPI_DUMP_BUFFER (source_desc->buffer.pointer, (source_desc->buffer.length < 32) ? source_desc->buffer.length : 32); @@ -574,7 +574,7 @@ acpi_ex_store_object_to_node ( /* If no implicit conversion, drop into the default case below */ - if (!implicit_conversion) { + if ((!implicit_conversion) || (walk_state->opcode == AML_COPY_OP)) { /* Force execution of default (no implicit conversion) */ target_type = ACPI_TYPE_ANY; @@ -634,7 +634,7 @@ acpi_ex_store_object_to_node ( default: ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, - "Storing %s (%p) directly into node (%p), no implicit conversion\n", + "Storing %s (%p) directly into node (%p) with no implicit conversion\n", acpi_ut_get_object_type_name (source_desc), source_desc, node)); /* No conversions for all other types. Just attach the source object */ diff --git a/drivers/acpi/executer/exstoren.c b/drivers/acpi/executer/exstoren.c index 120f30ed0bd..433588ab432 100644 --- a/drivers/acpi/executer/exstoren.c +++ b/drivers/acpi/executer/exstoren.c @@ -265,10 +265,6 @@ acpi_ex_store_object_to_object ( case ACPI_TYPE_BUFFER: - /* - * Note: There is different store behavior depending on the original - * source type - */ status = acpi_ex_store_buffer_to_buffer (actual_src_desc, dest_desc); break; diff --git a/drivers/acpi/executer/exutils.c b/drivers/acpi/executer/exutils.c index 5c7ec0c0417..d00b0dcba96 100644 --- a/drivers/acpi/executer/exutils.c +++ b/drivers/acpi/executer/exutils.c @@ -369,7 +369,7 @@ acpi_ex_eisa_id_to_string ( * * RETURN: None, string * - * DESCRIPTOIN: Convert a number to string representation. Assumes string + * DESCRIPTION: Convert a number to string representation. Assumes string * buffer is large enough to hold the string. * ******************************************************************************/ diff --git a/drivers/acpi/hardware/hwgpe.c b/drivers/acpi/hardware/hwgpe.c index 8daeabb2fc7..3536bbb990c 100644 --- a/drivers/acpi/hardware/hwgpe.c +++ b/drivers/acpi/hardware/hwgpe.c @@ -374,7 +374,7 @@ acpi_hw_enable_wakeup_gpe_block ( * * FUNCTION: acpi_hw_disable_all_gpes * - * PARAMETERS: Flags - ACPI_NOT_ISR or ACPI_ISR + * PARAMETERS: None * * RETURN: Status * @@ -384,7 +384,7 @@ acpi_hw_enable_wakeup_gpe_block ( acpi_status acpi_hw_disable_all_gpes ( - u32 flags) + void) { acpi_status status; @@ -392,8 +392,8 @@ acpi_hw_disable_all_gpes ( ACPI_FUNCTION_TRACE ("hw_disable_all_gpes"); - status = acpi_ev_walk_gpe_list (acpi_hw_disable_gpe_block, flags); - status = acpi_ev_walk_gpe_list (acpi_hw_clear_gpe_block, flags); + status = acpi_ev_walk_gpe_list (acpi_hw_disable_gpe_block); + status = acpi_ev_walk_gpe_list (acpi_hw_clear_gpe_block); return_ACPI_STATUS (status); } @@ -402,7 +402,7 @@ acpi_hw_disable_all_gpes ( * * FUNCTION: acpi_hw_enable_all_runtime_gpes * - * PARAMETERS: Flags - ACPI_NOT_ISR or ACPI_ISR + * PARAMETERS: None * * RETURN: Status * @@ -412,7 +412,7 @@ acpi_hw_disable_all_gpes ( acpi_status acpi_hw_enable_all_runtime_gpes ( - u32 flags) + void) { acpi_status status; @@ -420,7 +420,7 @@ acpi_hw_enable_all_runtime_gpes ( ACPI_FUNCTION_TRACE ("hw_enable_all_runtime_gpes"); - status = acpi_ev_walk_gpe_list (acpi_hw_enable_runtime_gpe_block, flags); + status = acpi_ev_walk_gpe_list (acpi_hw_enable_runtime_gpe_block); return_ACPI_STATUS (status); } @@ -429,7 +429,7 @@ acpi_hw_enable_all_runtime_gpes ( * * FUNCTION: acpi_hw_enable_all_wakeup_gpes * - * PARAMETERS: Flags - ACPI_NOT_ISR or ACPI_ISR + * PARAMETERS: None * * RETURN: Status * @@ -439,7 +439,7 @@ acpi_hw_enable_all_runtime_gpes ( acpi_status acpi_hw_enable_all_wakeup_gpes ( - u32 flags) + void) { acpi_status status; @@ -447,7 +447,7 @@ acpi_hw_enable_all_wakeup_gpes ( ACPI_FUNCTION_TRACE ("hw_enable_all_wakeup_gpes"); - status = acpi_ev_walk_gpe_list (acpi_hw_enable_wakeup_gpe_block, flags); + status = acpi_ev_walk_gpe_list (acpi_hw_enable_wakeup_gpe_block); return_ACPI_STATUS (status); } diff --git a/drivers/acpi/hardware/hwregs.c b/drivers/acpi/hardware/hwregs.c index 6d9e4eb8483..04a058565d8 100644 --- a/drivers/acpi/hardware/hwregs.c +++ b/drivers/acpi/hardware/hwregs.c @@ -106,7 +106,7 @@ acpi_hw_clear_acpi_status ( /* Clear the GPE Bits in all GPE registers in all GPE blocks */ - status = acpi_ev_walk_gpe_list (acpi_hw_clear_gpe_block, ACPI_ISR); + status = acpi_ev_walk_gpe_list (acpi_hw_clear_gpe_block); unlock_and_exit: if (flags & ACPI_MTX_LOCK) { diff --git a/drivers/acpi/hardware/hwsleep.c b/drivers/acpi/hardware/hwsleep.c index 415d342aeab..cedee0c43b5 100644 --- a/drivers/acpi/hardware/hwsleep.c +++ b/drivers/acpi/hardware/hwsleep.c @@ -274,13 +274,13 @@ acpi_enter_sleep_state ( * 1) Disable/Clear all GPEs * 2) Enable all wakeup GPEs */ - status = acpi_hw_disable_all_gpes (ACPI_ISR); + status = acpi_hw_disable_all_gpes (); if (ACPI_FAILURE (status)) { return_ACPI_STATUS (status); } acpi_gbl_system_awake_and_running = FALSE; - status = acpi_hw_enable_all_wakeup_gpes (ACPI_ISR); + status = acpi_hw_enable_all_wakeup_gpes (); if (ACPI_FAILURE (status)) { return_ACPI_STATUS (status); } @@ -424,13 +424,13 @@ acpi_enter_sleep_state_s4bios ( * 1) Disable/Clear all GPEs * 2) Enable all wakeup GPEs */ - status = acpi_hw_disable_all_gpes (ACPI_ISR); + status = acpi_hw_disable_all_gpes (); if (ACPI_FAILURE (status)) { return_ACPI_STATUS (status); } acpi_gbl_system_awake_and_running = FALSE; - status = acpi_hw_enable_all_wakeup_gpes (ACPI_ISR); + status = acpi_hw_enable_all_wakeup_gpes (); if (ACPI_FAILURE (status)) { return_ACPI_STATUS (status); } @@ -557,13 +557,13 @@ acpi_leave_sleep_state ( * 1) Disable/Clear all GPEs * 2) Enable all runtime GPEs */ - status = acpi_hw_disable_all_gpes (ACPI_NOT_ISR); + status = acpi_hw_disable_all_gpes (); if (ACPI_FAILURE (status)) { return_ACPI_STATUS (status); } acpi_gbl_system_awake_and_running = TRUE; - status = acpi_hw_enable_all_runtime_gpes (ACPI_NOT_ISR); + status = acpi_hw_enable_all_runtime_gpes (); if (ACPI_FAILURE (status)) { return_ACPI_STATUS (status); } diff --git a/drivers/acpi/namespace/nsaccess.c b/drivers/acpi/namespace/nsaccess.c index ece7a9dedd5..7589e1fdf25 100644 --- a/drivers/acpi/namespace/nsaccess.c +++ b/drivers/acpi/namespace/nsaccess.c @@ -159,19 +159,20 @@ acpi_ns_root_initialize ( obj_desc->method.param_count = (u8) ACPI_TO_INTEGER (val); obj_desc->common.flags |= AOPOBJ_DATA_VALID; -#if defined (_ACPI_ASL_COMPILER) || defined (_ACPI_DUMP_App) +#if defined (ACPI_ASL_COMPILER) - /* - * i_aSL Compiler cheats by putting parameter count - * in the owner_iD - */ - new_node->owner_id = obj_desc->method.param_count; + /* save the parameter count for the i_aSL compiler */ + + new_node->value = obj_desc->method.param_count; #else /* Mark this as a very SPECIAL method */ obj_desc->method.method_flags = AML_METHOD_INTERNAL_ONLY; + +#ifndef ACPI_DUMP_APP obj_desc->method.implementation = acpi_ut_osi_implementation; #endif +#endif break; case ACPI_TYPE_INTEGER: diff --git a/drivers/acpi/namespace/nsalloc.c b/drivers/acpi/namespace/nsalloc.c index 5653a19d717..21d560decbf 100644 --- a/drivers/acpi/namespace/nsalloc.c +++ b/drivers/acpi/namespace/nsalloc.c @@ -83,7 +83,7 @@ acpi_ns_create_node ( return_PTR (NULL); } - ACPI_MEM_TRACKING (acpi_gbl_memory_lists[ACPI_MEM_LIST_NSNODE].total_allocated++); + ACPI_MEM_TRACKING (acpi_gbl_ns_node_list->total_allocated++); node->name.integer = name; node->reference_count = 1; @@ -151,7 +151,7 @@ acpi_ns_delete_node ( } } - ACPI_MEM_TRACKING (acpi_gbl_memory_lists[ACPI_MEM_LIST_NSNODE].total_freed++); + ACPI_MEM_TRACKING (acpi_gbl_ns_node_list->total_freed++); /* * Detach an object if there is one then delete the node @@ -176,10 +176,9 @@ acpi_ns_delete_node ( * DESCRIPTION: Initialize a new namespace node and install it amongst * its peers. * - * Note: Current namespace lookup is linear search. However, the - * nodes are linked in alphabetical order to 1) put all reserved - * names (start with underscore) first, and to 2) make a readable - * namespace dump. + * Note: Current namespace lookup is linear search. This appears + * to be sufficient as namespace searches consume only a small + * fraction of the execution time of the ACPI subsystem. * ******************************************************************************/ @@ -190,12 +189,8 @@ acpi_ns_install_node ( struct acpi_namespace_node *node, /* New Child*/ acpi_object_type type) { - u16 owner_id = 0; + acpi_owner_id owner_id = 0; struct acpi_namespace_node *child_node; -#ifdef ACPI_ALPHABETIC_NAMESPACE - - struct acpi_namespace_node *previous_child_node; -#endif ACPI_FUNCTION_TRACE ("ns_install_node"); @@ -219,57 +214,6 @@ acpi_ns_install_node ( node->peer = parent_node; } else { -#ifdef ACPI_ALPHABETIC_NAMESPACE - /* - * Walk the list whilst searching for the correct - * alphabetic placement. - */ - previous_child_node = NULL; - while (acpi_ns_compare_names (acpi_ut_get_node_name (child_node), - acpi_ut_get_node_name (node)) < 0) { - if (child_node->flags & ANOBJ_END_OF_PEER_LIST) { - /* Last peer; Clear end-of-list flag */ - - child_node->flags &= ~ANOBJ_END_OF_PEER_LIST; - - /* This node is the new peer to the child node */ - - child_node->peer = node; - - /* This node is the new end-of-list */ - - node->flags |= ANOBJ_END_OF_PEER_LIST; - node->peer = parent_node; - break; - } - - /* Get next peer */ - - previous_child_node = child_node; - child_node = child_node->peer; - } - - /* Did the node get inserted at the end-of-list? */ - - if (!(node->flags & ANOBJ_END_OF_PEER_LIST)) { - /* - * Loop above terminated without reaching the end-of-list. - * Insert the new node at the current location - */ - if (previous_child_node) { - /* Insert node alphabetically */ - - node->peer = child_node; - previous_child_node->peer = node; - } - else { - /* Insert node alphabetically at start of list */ - - node->peer = child_node; - parent_node->child = node; - } - } -#else while (!(child_node->flags & ANOBJ_END_OF_PEER_LIST)) { child_node = child_node->peer; } @@ -279,9 +223,8 @@ acpi_ns_install_node ( /* Clear end-of-list flag */ child_node->flags &= ~ANOBJ_END_OF_PEER_LIST; - node->flags |= ANOBJ_END_OF_PEER_LIST; + node->flags |= ANOBJ_END_OF_PEER_LIST; node->peer = parent_node; -#endif } /* Init the new entry */ @@ -362,7 +305,7 @@ acpi_ns_delete_children ( /* Now we can free this child object */ - ACPI_MEM_TRACKING (acpi_gbl_memory_lists[ACPI_MEM_LIST_NSNODE].total_freed++); + ACPI_MEM_TRACKING (acpi_gbl_ns_node_list->total_freed++); ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "Object %p, Remaining %X\n", child_node, acpi_gbl_current_node_count)); @@ -559,7 +502,7 @@ acpi_ns_remove_reference ( void acpi_ns_delete_namespace_by_owner ( - u16 owner_id) + acpi_owner_id owner_id) { struct acpi_namespace_node *child_node; struct acpi_namespace_node *deletion_node; @@ -570,6 +513,10 @@ acpi_ns_delete_namespace_by_owner ( ACPI_FUNCTION_TRACE_U32 ("ns_delete_namespace_by_owner", owner_id); + if (owner_id == 0) { + return_VOID; + } + parent_node = acpi_gbl_root_node; child_node = NULL; deletion_node = NULL; @@ -639,54 +586,3 @@ acpi_ns_delete_namespace_by_owner ( } -#ifdef ACPI_ALPHABETIC_NAMESPACE -/******************************************************************************* - * - * FUNCTION: acpi_ns_compare_names - * - * PARAMETERS: Name1 - First name to compare - * Name2 - Second name to compare - * - * RETURN: value from strncmp - * - * DESCRIPTION: Compare two ACPI names. Names that are prefixed with an - * underscore are forced to be alphabetically first. - * - ******************************************************************************/ - -int -acpi_ns_compare_names ( - char *name1, - char *name2) -{ - char reversed_name1[ACPI_NAME_SIZE]; - char reversed_name2[ACPI_NAME_SIZE]; - u32 i; - u32 j; - - - /* - * Replace all instances of "underscore" with a value that is smaller so - * that all names that are prefixed with underscore(s) are alphabetically - * first. - * - * Reverse the name bytewise so we can just do a 32-bit compare instead - * of a strncmp. - */ - for (i = 0, j= (ACPI_NAME_SIZE - 1); i < ACPI_NAME_SIZE; i++, j--) { - reversed_name1[j] = name1[i]; - if (name1[i] == '_') { - reversed_name1[j] = '*'; - } - - reversed_name2[j] = name2[i]; - if (name2[i] == '_') { - reversed_name2[j] = '*'; - } - } - - return (*(int *) reversed_name1 - *(int *) reversed_name2); -} -#endif - - diff --git a/drivers/acpi/namespace/nsdump.c b/drivers/acpi/namespace/nsdump.c index 6c2aef0e0dd..5d25add6b03 100644 --- a/drivers/acpi/namespace/nsdump.c +++ b/drivers/acpi/namespace/nsdump.c @@ -85,6 +85,9 @@ acpi_ns_print_pathname ( u32 num_segments, char *pathname) { + acpi_native_uint i; + + ACPI_FUNCTION_NAME ("ns_print_pathname"); @@ -97,9 +100,13 @@ acpi_ns_print_pathname ( ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "[")); while (num_segments) { - acpi_os_printf ("%4.4s", pathname); - pathname += ACPI_NAME_SIZE; + for (i = 0; i < 4; i++) { + ACPI_IS_PRINT (pathname[i]) ? + acpi_os_printf ("%c", pathname[i]) : + acpi_os_printf ("?"); + } + pathname += ACPI_NAME_SIZE; num_segments--; if (num_segments) { acpi_os_printf ("."); @@ -203,38 +210,42 @@ acpi_ns_dump_one_object ( /* Check if the owner matches */ - if ((info->owner_id != ACPI_UINT32_MAX) && + if ((info->owner_id != ACPI_OWNER_ID_MAX) && (info->owner_id != this_node->owner_id)) { return (AE_OK); } - /* Indent the object according to the level */ + if (!(info->display_type & ACPI_DISPLAY_SHORT)) { + /* Indent the object according to the level */ - acpi_os_printf ("%2d%*s", (u32) level - 1, (int) level * 2, " "); + acpi_os_printf ("%2d%*s", (u32) level - 1, (int) level * 2, " "); - /* Check the node type and name */ + /* Check the node type and name */ - if (type > ACPI_TYPE_LOCAL_MAX) { - ACPI_REPORT_WARNING (("Invalid ACPI Type %08X\n", type)); - } + if (type > ACPI_TYPE_LOCAL_MAX) { + ACPI_REPORT_WARNING (("Invalid ACPI Type %08X\n", type)); + } - if (!acpi_ut_valid_acpi_name (this_node->name.integer)) { - ACPI_REPORT_WARNING (("Invalid ACPI Name %08X\n", - this_node->name.integer)); + if (!acpi_ut_valid_acpi_name (this_node->name.integer)) { + ACPI_REPORT_WARNING (("Invalid ACPI Name %08X\n", + this_node->name.integer)); + } + + acpi_os_printf ("%4.4s", acpi_ut_get_node_name (this_node)); } /* * Now we can print out the pertinent information */ - acpi_os_printf ("%4.4s %-12s %p ", - acpi_ut_get_node_name (this_node), acpi_ut_get_type_name (type), this_node); + acpi_os_printf (" %-12s %p ", + acpi_ut_get_type_name (type), this_node); dbg_level = acpi_dbg_level; acpi_dbg_level = 0; obj_desc = acpi_ns_get_attached_object (this_node); acpi_dbg_level = dbg_level; - switch (info->display_type) { + switch (info->display_type & ACPI_DISPLAY_MASK) { case ACPI_DISPLAY_SUMMARY: if (!obj_desc) { @@ -475,7 +486,7 @@ acpi_ns_dump_one_object ( while (obj_desc) { obj_type = ACPI_TYPE_INVALID; - acpi_os_printf (" Attached Object %p: ", obj_desc); + acpi_os_printf ("Attached Object %p: ", obj_desc); /* Decode the type of attached object and dump the contents */ @@ -484,9 +495,9 @@ acpi_ns_dump_one_object ( acpi_os_printf ("(Ptr to Node)\n"); bytes_to_dump = sizeof (struct acpi_namespace_node); + ACPI_DUMP_BUFFER (obj_desc, bytes_to_dump); break; - case ACPI_DESC_TYPE_OPERAND: obj_type = ACPI_GET_OBJECT_TYPE (obj_desc); @@ -497,24 +508,19 @@ acpi_ns_dump_one_object ( bytes_to_dump = 32; } else { - acpi_os_printf ("(Ptr to ACPI Object type %s, %X)\n", - acpi_ut_get_type_name (obj_type), obj_type); + acpi_os_printf ("(Ptr to ACPI Object type %X [%s])\n", + obj_type, acpi_ut_get_type_name (obj_type)); bytes_to_dump = sizeof (union acpi_operand_object); } - break; + ACPI_DUMP_BUFFER (obj_desc, bytes_to_dump); + break; default: - acpi_os_printf ( - "(String or Buffer ptr - not an object descriptor) [%s]\n", - acpi_ut_get_descriptor_name (obj_desc)); - bytes_to_dump = 16; break; } - ACPI_DUMP_BUFFER (obj_desc, bytes_to_dump); - /* If value is NOT an internal object, we are done */ if (ACPI_GET_DESCRIPTOR_TYPE (obj_desc) != ACPI_DESC_TYPE_OPERAND) { @@ -525,13 +531,17 @@ acpi_ns_dump_one_object ( * Valid object, get the pointer to next level, if any */ switch (obj_type) { + case ACPI_TYPE_BUFFER: case ACPI_TYPE_STRING: + /* + * NOTE: takes advantage of common fields between string/buffer + */ + bytes_to_dump = obj_desc->string.length; obj_desc = (void *) obj_desc->string.pointer; - break; - - case ACPI_TYPE_BUFFER: - obj_desc = (void *) obj_desc->buffer.pointer; - break; + acpi_os_printf ( "(Buffer/String pointer %p length %X)\n", + obj_desc, bytes_to_dump); + ACPI_DUMP_BUFFER (obj_desc, bytes_to_dump); + goto cleanup; case ACPI_TYPE_BUFFER_FIELD: obj_desc = (union acpi_operand_object *) obj_desc->buffer_field.buffer_obj; @@ -595,7 +605,7 @@ acpi_ns_dump_objects ( acpi_object_type type, u8 display_type, u32 max_depth, - u32 owner_id, + acpi_owner_id owner_id, acpi_handle start_handle) { struct acpi_walk_info info; @@ -640,14 +650,14 @@ acpi_ns_dump_entry ( info.debug_level = debug_level; - info.owner_id = ACPI_UINT32_MAX; + info.owner_id = ACPI_OWNER_ID_MAX; info.display_type = ACPI_DISPLAY_SUMMARY; (void) acpi_ns_dump_one_object (handle, 1, &info, NULL); } -#ifdef _ACPI_ASL_COMPILER +#ifdef ACPI_ASL_COMPILER /******************************************************************************* * * FUNCTION: acpi_ns_dump_tables @@ -691,7 +701,7 @@ acpi_ns_dump_tables ( } acpi_ns_dump_objects (ACPI_TYPE_ANY, ACPI_DISPLAY_OBJECTS, max_depth, - ACPI_UINT32_MAX, search_handle); + ACPI_OWNER_ID_MAX, search_handle); return_VOID; } #endif /* _ACPI_ASL_COMPILER */ diff --git a/drivers/acpi/namespace/nseval.c b/drivers/acpi/namespace/nseval.c index 1ae89a1c882..908cffd5e72 100644 --- a/drivers/acpi/namespace/nseval.c +++ b/drivers/acpi/namespace/nseval.c @@ -365,6 +365,7 @@ acpi_ns_evaluate_by_handle ( * * PARAMETERS: Info - Method info block, contains: * Node - Method Node to execute + * obj_desc - Method object * Parameters - List of parameters to pass to the method, * terminated by NULL. Params itself may be * NULL if no parameters are being passed. @@ -387,7 +388,6 @@ acpi_ns_execute_control_method ( struct acpi_parameter_info *info) { acpi_status status; - union acpi_operand_object *obj_desc; ACPI_FUNCTION_TRACE ("ns_execute_control_method"); @@ -395,8 +395,8 @@ acpi_ns_execute_control_method ( /* Verify that there is a method associated with this object */ - obj_desc = acpi_ns_get_attached_object (info->node); - if (!obj_desc) { + info->obj_desc = acpi_ns_get_attached_object (info->node); + if (!info->obj_desc) { ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "No attached method object\n")); (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); @@ -407,7 +407,7 @@ acpi_ns_execute_control_method ( ACPI_LV_INFO, _COMPONENT); ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Method at AML address %p Length %X\n", - obj_desc->method.aml_start + 1, obj_desc->method.aml_length - 1)); + info->obj_desc->method.aml_start + 1, info->obj_desc->method.aml_length - 1)); /* * Unlock the namespace before execution. This allows namespace access @@ -430,7 +430,7 @@ acpi_ns_execute_control_method ( return_ACPI_STATUS (status); } - status = acpi_psx_execute (info); + status = acpi_ps_execute_method (info); acpi_ex_exit_interpreter (); return_ACPI_STATUS (status); diff --git a/drivers/acpi/namespace/nsload.c b/drivers/acpi/namespace/nsload.c index 34e49701660..1428a84a31e 100644 --- a/drivers/acpi/namespace/nsload.c +++ b/drivers/acpi/namespace/nsload.c @@ -198,7 +198,7 @@ acpi_ns_load_table_by_type ( switch (table_type) { case ACPI_TABLE_DSDT: - ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Loading DSDT\n")); + ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Namespace load: DSDT\n")); table_desc = acpi_gbl_table_lists[ACPI_TABLE_DSDT].next; @@ -218,17 +218,18 @@ acpi_ns_load_table_by_type ( case ACPI_TABLE_SSDT: + case ACPI_TABLE_PSDT: - ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Loading %d SSDTs\n", - acpi_gbl_table_lists[ACPI_TABLE_SSDT].count)); + ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Namespace load: %d SSDT or PSDTs\n", + acpi_gbl_table_lists[table_type].count)); /* - * Traverse list of SSDT tables + * Traverse list of SSDT or PSDT tables */ - table_desc = acpi_gbl_table_lists[ACPI_TABLE_SSDT].next; - for (i = 0; i < acpi_gbl_table_lists[ACPI_TABLE_SSDT].count; i++) { + table_desc = acpi_gbl_table_lists[table_type].next; + for (i = 0; i < acpi_gbl_table_lists[table_type].count; i++) { /* - * Only attempt to load table if it is not + * Only attempt to load table into namespace if it is not * already loaded! */ if (!table_desc->loaded_into_namespace) { @@ -245,33 +246,6 @@ acpi_ns_load_table_by_type ( break; - case ACPI_TABLE_PSDT: - - ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Loading %d PSDTs\n", - acpi_gbl_table_lists[ACPI_TABLE_PSDT].count)); - - /* - * Traverse list of PSDT tables - */ - table_desc = acpi_gbl_table_lists[ACPI_TABLE_PSDT].next; - - for (i = 0; i < acpi_gbl_table_lists[ACPI_TABLE_PSDT].count; i++) { - /* Only attempt to load table if it is not already loaded! */ - - if (!table_desc->loaded_into_namespace) { - status = acpi_ns_load_table (table_desc, acpi_gbl_root_node); - if (ACPI_FAILURE (status)) { - break; - } - - table_desc->loaded_into_namespace = TRUE; - } - - table_desc = table_desc->next; - } - break; - - default: status = AE_SUPPORT; break; diff --git a/drivers/acpi/namespace/nsparse.c b/drivers/acpi/namespace/nsparse.c index a0e13e8d376..24bed931d39 100644 --- a/drivers/acpi/namespace/nsparse.c +++ b/drivers/acpi/namespace/nsparse.c @@ -67,7 +67,7 @@ acpi_status acpi_ns_one_complete_parse ( - u32 pass_number, + u8 pass_number, struct acpi_table_desc *table_desc) { union acpi_parse_object *parse_root; @@ -87,7 +87,7 @@ acpi_ns_one_complete_parse ( /* Create and initialize a new walk state */ - walk_state = acpi_ds_create_walk_state (table_desc->table_id, + walk_state = acpi_ds_create_walk_state (table_desc->owner_id, NULL, NULL, NULL); if (!walk_state) { acpi_ps_free_op (parse_root); @@ -146,6 +146,7 @@ acpi_ns_parse_table ( * to service the entire parse. The second pass of the parse then * performs another complete parse of the AML.. */ + ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "**** Start pass 1\n")); status = acpi_ns_one_complete_parse (1, table_desc); if (ACPI_FAILURE (status)) { return_ACPI_STATUS (status); @@ -160,6 +161,7 @@ acpi_ns_parse_table ( * overhead of this is compensated for by the fact that the * parse objects are all cached. */ + ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "**** Start pass 2\n")); status = acpi_ns_one_complete_parse (2, table_desc); if (ACPI_FAILURE (status)) { return_ACPI_STATUS (status); diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index 7289da3c4db..f3a807c342c 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c @@ -782,54 +782,6 @@ acpi_os_delete_lock ( return_VOID; } -/* - * Acquire a spinlock. - * - * handle is a pointer to the spinlock_t. - * flags is *not* the result of save_flags - it is an ACPI-specific flag variable - * that indicates whether we are at interrupt level. - */ -void -acpi_os_acquire_lock ( - acpi_handle handle, - u32 flags) -{ - ACPI_FUNCTION_TRACE ("os_acquire_lock"); - - ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, "Acquiring spinlock[%p] from %s level\n", handle, - ((flags & ACPI_NOT_ISR) ? "non-interrupt" : "interrupt"))); - - if (flags & ACPI_NOT_ISR) - ACPI_DISABLE_IRQS(); - - spin_lock((spinlock_t *)handle); - - return_VOID; -} - - -/* - * Release a spinlock. See above. - */ -void -acpi_os_release_lock ( - acpi_handle handle, - u32 flags) -{ - ACPI_FUNCTION_TRACE ("os_release_lock"); - - ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, "Releasing spinlock[%p] from %s level\n", handle, - ((flags & ACPI_NOT_ISR) ? "non-interrupt" : "interrupt"))); - - spin_unlock((spinlock_t *)handle); - - if (flags & ACPI_NOT_ISR) - ACPI_ENABLE_IRQS(); - - return_VOID; -} - - acpi_status acpi_os_create_semaphore( u32 max_units, @@ -1176,3 +1128,151 @@ unsigned int max_cstate = ACPI_PROCESSOR_MAX_POWER; EXPORT_SYMBOL(max_cstate); + +/* + * Acquire a spinlock. + * + * handle is a pointer to the spinlock_t. + * flags is *not* the result of save_flags - it is an ACPI-specific flag variable + * that indicates whether we are at interrupt level. + */ + +unsigned long +acpi_os_acquire_lock ( + acpi_handle handle) +{ + unsigned long flags; + spin_lock_irqsave((spinlock_t *)handle, flags); + return flags; +} + +/* + * Release a spinlock. See above. + */ + +void +acpi_os_release_lock ( + acpi_handle handle, + unsigned long flags) +{ + spin_unlock_irqrestore((spinlock_t *)handle, flags); +} + + +#ifndef ACPI_USE_LOCAL_CACHE + +/******************************************************************************* + * + * FUNCTION: acpi_os_create_cache + * + * PARAMETERS: CacheName - Ascii name for the cache + * ObjectSize - Size of each cached object + * MaxDepth - Maximum depth of the cache (in objects) + * ReturnCache - Where the new cache object is returned + * + * RETURN: Status + * + * DESCRIPTION: Create a cache object + * + ******************************************************************************/ + +acpi_status +acpi_os_create_cache ( + char *name, + u16 size, + u16 depth, + acpi_cache_t **cache) +{ + *cache = kmem_cache_create (name, size, 0, 0, NULL, NULL); + return AE_OK; +} + +/******************************************************************************* + * + * FUNCTION: acpi_os_purge_cache + * + * PARAMETERS: Cache - Handle to cache object + * + * RETURN: Status + * + * DESCRIPTION: Free all objects within the requested cache. + * + ******************************************************************************/ + +acpi_status +acpi_os_purge_cache ( + acpi_cache_t *cache) +{ + (void) kmem_cache_shrink(cache); + return (AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_os_delete_cache + * + * PARAMETERS: Cache - Handle to cache object + * + * RETURN: Status + * + * DESCRIPTION: Free all objects within the requested cache and delete the + * cache object. + * + ******************************************************************************/ + +acpi_status +acpi_os_delete_cache ( + acpi_cache_t *cache) +{ + (void)kmem_cache_destroy(cache); + return (AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_os_release_object + * + * PARAMETERS: Cache - Handle to cache object + * Object - The object to be released + * + * RETURN: None + * + * DESCRIPTION: Release an object to the specified cache. If cache is full, + * the object is deleted. + * + ******************************************************************************/ + +acpi_status +acpi_os_release_object ( + acpi_cache_t *cache, + void *object) +{ + kmem_cache_free(cache, object); + return (AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_os_acquire_object + * + * PARAMETERS: Cache - Handle to cache object + * ReturnObject - Where the object is returned + * + * RETURN: Status + * + * DESCRIPTION: Get an object from the specified cache. If cache is empty, + * the object is allocated. + * + ******************************************************************************/ + +void * +acpi_os_acquire_object ( + acpi_cache_t *cache) +{ + void *object = kmem_cache_alloc(cache, GFP_KERNEL); + WARN_ON(!object); + return object; +} + +#endif + diff --git a/drivers/acpi/parser/Makefile b/drivers/acpi/parser/Makefile index bbdd286c660..db24ee09cf1 100644 --- a/drivers/acpi/parser/Makefile +++ b/drivers/acpi/parser/Makefile @@ -2,7 +2,7 @@ # Makefile for all Linux ACPI interpreter subdirectories # -obj-y := psargs.o psparse.o pstree.o pswalk.o \ +obj-y := psargs.o psparse.o psloop.o pstree.o pswalk.o \ psopcode.o psscope.o psutils.o psxface.o EXTRA_CFLAGS += $(ACPI_CFLAGS) diff --git a/drivers/acpi/parser/psloop.c b/drivers/acpi/parser/psloop.c new file mode 100644 index 00000000000..551d54bdbec --- /dev/null +++ b/drivers/acpi/parser/psloop.c @@ -0,0 +1,781 @@ +/****************************************************************************** + * + * Module Name: psloop - Main AML parse loop + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2005, R. Byron Moore + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + + +/* + * Parse the AML and build an operation tree as most interpreters, + * like Perl, do. Parsing is done by hand rather than with a YACC + * generated parser to tightly constrain stack and dynamic memory + * usage. At the same time, parsing is kept flexible and the code + * fairly compact by parsing based on a list of AML opcode + * templates in aml_op_info[] + */ + +#include <acpi/acpi.h> +#include <acpi/acparser.h> +#include <acpi/acdispat.h> +#include <acpi/amlcode.h> + +#define _COMPONENT ACPI_PARSER + ACPI_MODULE_NAME ("psloop") + +static u32 acpi_gbl_depth = 0; + + +/******************************************************************************* + * + * FUNCTION: acpi_ps_parse_loop + * + * PARAMETERS: walk_state - Current state + * + * RETURN: Status + * + * DESCRIPTION: Parse AML (pointed to by the current parser state) and return + * a tree of ops. + * + ******************************************************************************/ + +acpi_status +acpi_ps_parse_loop ( + struct acpi_walk_state *walk_state) +{ + acpi_status status = AE_OK; + acpi_status status2; + union acpi_parse_object *op = NULL; /* current op */ + union acpi_parse_object *arg = NULL; + union acpi_parse_object *pre_op = NULL; + struct acpi_parse_state *parser_state; + u8 *aml_op_start = NULL; + + + ACPI_FUNCTION_TRACE_PTR ("ps_parse_loop", walk_state); + + if (walk_state->descending_callback == NULL) { + return_ACPI_STATUS (AE_BAD_PARAMETER); + } + + parser_state = &walk_state->parser_state; + walk_state->arg_types = 0; + +#if (!defined (ACPI_NO_METHOD_EXECUTION) && !defined (ACPI_CONSTANT_EVAL_ONLY)) + + if (walk_state->walk_type & ACPI_WALK_METHOD_RESTART) { + /* We are restarting a preempted control method */ + + if (acpi_ps_has_completed_scope (parser_state)) { + /* + * We must check if a predicate to an IF or WHILE statement + * was just completed + */ + if ((parser_state->scope->parse_scope.op) && + ((parser_state->scope->parse_scope.op->common.aml_opcode == AML_IF_OP) || + (parser_state->scope->parse_scope.op->common.aml_opcode == AML_WHILE_OP)) && + (walk_state->control_state) && + (walk_state->control_state->common.state == + ACPI_CONTROL_PREDICATE_EXECUTING)) { + /* + * A predicate was just completed, get the value of the + * predicate and branch based on that value + */ + walk_state->op = NULL; + status = acpi_ds_get_predicate_value (walk_state, ACPI_TO_POINTER (TRUE)); + if (ACPI_FAILURE (status) && + ((status & AE_CODE_MASK) != AE_CODE_CONTROL)) { + if (status == AE_AML_NO_RETURN_VALUE) { + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, + "Invoked method did not return a value, %s\n", + acpi_format_exception (status))); + + } + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, + "get_predicate Failed, %s\n", + acpi_format_exception (status))); + return_ACPI_STATUS (status); + } + + status = acpi_ps_next_parse_state (walk_state, op, status); + } + + acpi_ps_pop_scope (parser_state, &op, + &walk_state->arg_types, &walk_state->arg_count); + ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "Popped scope, Op=%p\n", op)); + } + else if (walk_state->prev_op) { + /* We were in the middle of an op */ + + op = walk_state->prev_op; + walk_state->arg_types = walk_state->prev_arg_types; + } + } +#endif + + /* Iterative parsing loop, while there is more AML to process: */ + + while ((parser_state->aml < parser_state->aml_end) || (op)) { + aml_op_start = parser_state->aml; + if (!op) { + /* Get the next opcode from the AML stream */ + + walk_state->aml_offset = (u32) ACPI_PTR_DIFF (parser_state->aml, + parser_state->aml_start); + walk_state->opcode = acpi_ps_peek_opcode (parser_state); + + /* + * First cut to determine what we have found: + * 1) A valid AML opcode + * 2) A name string + * 3) An unknown/invalid opcode + */ + walk_state->op_info = acpi_ps_get_opcode_info (walk_state->opcode); + switch (walk_state->op_info->class) { + case AML_CLASS_ASCII: + case AML_CLASS_PREFIX: + /* + * Starts with a valid prefix or ASCII char, this is a name + * string. Convert the bare name string to a namepath. + */ + walk_state->opcode = AML_INT_NAMEPATH_OP; + walk_state->arg_types = ARGP_NAMESTRING; + break; + + case AML_CLASS_UNKNOWN: + + /* The opcode is unrecognized. Just skip unknown opcodes */ + + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, + "Found unknown opcode %X at AML address %p offset %X, ignoring\n", + walk_state->opcode, parser_state->aml, walk_state->aml_offset)); + + ACPI_DUMP_BUFFER (parser_state->aml, 128); + + /* Assume one-byte bad opcode */ + + parser_state->aml++; + continue; + + default: + + /* Found opcode info, this is a normal opcode */ + + parser_state->aml += acpi_ps_get_opcode_size (walk_state->opcode); + walk_state->arg_types = walk_state->op_info->parse_args; + break; + } + + /* Create Op structure and append to parent's argument list */ + + if (walk_state->op_info->flags & AML_NAMED) { + /* Allocate a new pre_op if necessary */ + + if (!pre_op) { + pre_op = acpi_ps_alloc_op (walk_state->opcode); + if (!pre_op) { + status = AE_NO_MEMORY; + goto close_this_op; + } + } + + pre_op->common.value.arg = NULL; + pre_op->common.aml_opcode = walk_state->opcode; + + /* + * Get and append arguments until we find the node that contains + * the name (the type ARGP_NAME). + */ + while (GET_CURRENT_ARG_TYPE (walk_state->arg_types) && + (GET_CURRENT_ARG_TYPE (walk_state->arg_types) != ARGP_NAME)) { + status = acpi_ps_get_next_arg (walk_state, parser_state, + GET_CURRENT_ARG_TYPE (walk_state->arg_types), &arg); + if (ACPI_FAILURE (status)) { + goto close_this_op; + } + + acpi_ps_append_arg (pre_op, arg); + INCREMENT_ARG_LIST (walk_state->arg_types); + } + + /* + * Make sure that we found a NAME and didn't run out of + * arguments + */ + if (!GET_CURRENT_ARG_TYPE (walk_state->arg_types)) { + status = AE_AML_NO_OPERAND; + goto close_this_op; + } + + /* We know that this arg is a name, move to next arg */ + + INCREMENT_ARG_LIST (walk_state->arg_types); + + /* + * Find the object. This will either insert the object into + * the namespace or simply look it up + */ + walk_state->op = NULL; + + status = walk_state->descending_callback (walk_state, &op); + if (ACPI_FAILURE (status)) { + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, + "During name lookup/catalog, %s\n", + acpi_format_exception (status))); + goto close_this_op; + } + + if (!op) { + continue; + } + + status = acpi_ps_next_parse_state (walk_state, op, status); + if (status == AE_CTRL_PENDING) { + status = AE_OK; + goto close_this_op; + } + + if (ACPI_FAILURE (status)) { + goto close_this_op; + } + + acpi_ps_append_arg (op, pre_op->common.value.arg); + acpi_gbl_depth++; + + if (op->common.aml_opcode == AML_REGION_OP) { + /* + * Defer final parsing of an operation_region body, + * because we don't have enough info in the first pass + * to parse it correctly (i.e., there may be method + * calls within the term_arg elements of the body.) + * + * However, we must continue parsing because + * the opregion is not a standalone package -- + * we don't know where the end is at this point. + * + * (Length is unknown until parse of the body complete) + */ + op->named.data = aml_op_start; + op->named.length = 0; + } + } + else { + /* Not a named opcode, just allocate Op and append to parent */ + + walk_state->op_info = acpi_ps_get_opcode_info (walk_state->opcode); + op = acpi_ps_alloc_op (walk_state->opcode); + if (!op) { + status = AE_NO_MEMORY; + goto close_this_op; + } + + if (walk_state->op_info->flags & AML_CREATE) { + /* + * Backup to beginning of create_xXXfield declaration + * body_length is unknown until we parse the body + */ + op->named.data = aml_op_start; + op->named.length = 0; + } + + acpi_ps_append_arg (acpi_ps_get_parent_scope (parser_state), op); + + if ((walk_state->descending_callback != NULL)) { + /* + * Find the object. This will either insert the object into + * the namespace or simply look it up + */ + walk_state->op = op; + + status = walk_state->descending_callback (walk_state, &op); + status = acpi_ps_next_parse_state (walk_state, op, status); + if (status == AE_CTRL_PENDING) { + status = AE_OK; + goto close_this_op; + } + + if (ACPI_FAILURE (status)) { + goto close_this_op; + } + } + } + + op->common.aml_offset = walk_state->aml_offset; + + if (walk_state->op_info) { + ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, + "Opcode %4.4X [%s] Op %p Aml %p aml_offset %5.5X\n", + (u32) op->common.aml_opcode, walk_state->op_info->name, + op, parser_state->aml, op->common.aml_offset)); + } + } + + + /* + * Start arg_count at zero because we don't know if there are + * any args yet + */ + walk_state->arg_count = 0; + + /* Are there any arguments that must be processed? */ + + if (walk_state->arg_types) { + /* Get arguments */ + + switch (op->common.aml_opcode) { + case AML_BYTE_OP: /* AML_BYTEDATA_ARG */ + case AML_WORD_OP: /* AML_WORDDATA_ARG */ + case AML_DWORD_OP: /* AML_DWORDATA_ARG */ + case AML_QWORD_OP: /* AML_QWORDATA_ARG */ + case AML_STRING_OP: /* AML_ASCIICHARLIST_ARG */ + + /* Fill in constant or string argument directly */ + + acpi_ps_get_next_simple_arg (parser_state, + GET_CURRENT_ARG_TYPE (walk_state->arg_types), op); + break; + + case AML_INT_NAMEPATH_OP: /* AML_NAMESTRING_ARG */ + + status = acpi_ps_get_next_namepath (walk_state, parser_state, op, 1); + if (ACPI_FAILURE (status)) { + goto close_this_op; + } + + walk_state->arg_types = 0; + break; + + default: + /* + * Op is not a constant or string, append each argument + * to the Op + */ + while (GET_CURRENT_ARG_TYPE (walk_state->arg_types) && + !walk_state->arg_count) { + walk_state->aml_offset = (u32) + ACPI_PTR_DIFF (parser_state->aml, parser_state->aml_start); + + status = acpi_ps_get_next_arg (walk_state, parser_state, + GET_CURRENT_ARG_TYPE (walk_state->arg_types), + &arg); + if (ACPI_FAILURE (status)) { + goto close_this_op; + } + + if (arg) { + arg->common.aml_offset = walk_state->aml_offset; + acpi_ps_append_arg (op, arg); + } + INCREMENT_ARG_LIST (walk_state->arg_types); + } + + + /* Special processing for certain opcodes */ + + /* TBD (remove): Temporary mechanism to disable this code if needed */ + +#ifdef ACPI_ENABLE_MODULE_LEVEL_CODE + + if ((walk_state->pass_number <= ACPI_IMODE_LOAD_PASS1) && + ((walk_state->parse_flags & ACPI_PARSE_DISASSEMBLE) == 0)) { + /* + * We want to skip If/Else/While constructs during Pass1 + * because we want to actually conditionally execute the + * code during Pass2. + * + * Except for disassembly, where we always want to + * walk the If/Else/While packages + */ + switch (op->common.aml_opcode) { + case AML_IF_OP: + case AML_ELSE_OP: + case AML_WHILE_OP: + + ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, + "Pass1: Skipping an If/Else/While body\n")); + + /* Skip body of if/else/while in pass 1 */ + + parser_state->aml = parser_state->pkg_end; + walk_state->arg_count = 0; + break; + + default: + break; + } + } +#endif + switch (op->common.aml_opcode) { + case AML_METHOD_OP: + + /* + * Skip parsing of control method + * because we don't have enough info in the first pass + * to parse it correctly. + * + * Save the length and address of the body + */ + op->named.data = parser_state->aml; + op->named.length = (u32) (parser_state->pkg_end - + parser_state->aml); + + /* Skip body of method */ + + parser_state->aml = parser_state->pkg_end; + walk_state->arg_count = 0; + break; + + case AML_BUFFER_OP: + case AML_PACKAGE_OP: + case AML_VAR_PACKAGE_OP: + + if ((op->common.parent) && + (op->common.parent->common.aml_opcode == AML_NAME_OP) && + (walk_state->pass_number <= ACPI_IMODE_LOAD_PASS2)) { + /* + * Skip parsing of Buffers and Packages + * because we don't have enough info in the first pass + * to parse them correctly. + */ + op->named.data = aml_op_start; + op->named.length = (u32) (parser_state->pkg_end - + aml_op_start); + + /* Skip body */ + + parser_state->aml = parser_state->pkg_end; + walk_state->arg_count = 0; + } + break; + + case AML_WHILE_OP: + + if (walk_state->control_state) { + walk_state->control_state->control.package_end = + parser_state->pkg_end; + } + break; + + default: + + /* No action for all other opcodes */ + break; + } + break; + } + } + + /* Check for arguments that need to be processed */ + + if (walk_state->arg_count) { + /* + * There are arguments (complex ones), push Op and + * prepare for argument + */ + status = acpi_ps_push_scope (parser_state, op, + walk_state->arg_types, walk_state->arg_count); + if (ACPI_FAILURE (status)) { + goto close_this_op; + } + op = NULL; + continue; + } + + /* + * All arguments have been processed -- Op is complete, + * prepare for next + */ + walk_state->op_info = acpi_ps_get_opcode_info (op->common.aml_opcode); + if (walk_state->op_info->flags & AML_NAMED) { + if (acpi_gbl_depth) { + acpi_gbl_depth--; + } + + if (op->common.aml_opcode == AML_REGION_OP) { + /* + * Skip parsing of control method or opregion body, + * because we don't have enough info in the first pass + * to parse them correctly. + * + * Completed parsing an op_region declaration, we now + * know the length. + */ + op->named.length = (u32) (parser_state->aml - op->named.data); + } + } + + if (walk_state->op_info->flags & AML_CREATE) { + /* + * Backup to beginning of create_xXXfield declaration (1 for + * Opcode) + * + * body_length is unknown until we parse the body + */ + op->named.length = (u32) (parser_state->aml - op->named.data); + } + + /* This op complete, notify the dispatcher */ + + if (walk_state->ascending_callback != NULL) { + walk_state->op = op; + walk_state->opcode = op->common.aml_opcode; + + status = walk_state->ascending_callback (walk_state); + status = acpi_ps_next_parse_state (walk_state, op, status); + if (status == AE_CTRL_PENDING) { + status = AE_OK; + goto close_this_op; + } + } + + +close_this_op: + /* + * Finished one argument of the containing scope + */ + parser_state->scope->parse_scope.arg_count--; + + /* Finished with pre_op */ + + if (pre_op) { + acpi_ps_free_op (pre_op); + pre_op = NULL; + } + + /* Close this Op (will result in parse subtree deletion) */ + + status2 = acpi_ps_complete_this_op (walk_state, op); + if (ACPI_FAILURE (status2)) { + return_ACPI_STATUS (status2); + } + op = NULL; + + switch (status) { + case AE_OK: + break; + + + case AE_CTRL_TRANSFER: + + /* We are about to transfer to a called method. */ + + walk_state->prev_op = op; + walk_state->prev_arg_types = walk_state->arg_types; + return_ACPI_STATUS (status); + + + case AE_CTRL_END: + + acpi_ps_pop_scope (parser_state, &op, + &walk_state->arg_types, &walk_state->arg_count); + + if (op) { + walk_state->op = op; + walk_state->op_info = acpi_ps_get_opcode_info (op->common.aml_opcode); + walk_state->opcode = op->common.aml_opcode; + + status = walk_state->ascending_callback (walk_state); + status = acpi_ps_next_parse_state (walk_state, op, status); + + status2 = acpi_ps_complete_this_op (walk_state, op); + if (ACPI_FAILURE (status2)) { + return_ACPI_STATUS (status2); + } + op = NULL; + } + status = AE_OK; + break; + + + case AE_CTRL_BREAK: + case AE_CTRL_CONTINUE: + + /* Pop off scopes until we find the While */ + + while (!op || (op->common.aml_opcode != AML_WHILE_OP)) { + acpi_ps_pop_scope (parser_state, &op, + &walk_state->arg_types, &walk_state->arg_count); + } + + /* Close this iteration of the While loop */ + + walk_state->op = op; + walk_state->op_info = acpi_ps_get_opcode_info (op->common.aml_opcode); + walk_state->opcode = op->common.aml_opcode; + + status = walk_state->ascending_callback (walk_state); + status = acpi_ps_next_parse_state (walk_state, op, status); + + status2 = acpi_ps_complete_this_op (walk_state, op); + if (ACPI_FAILURE (status2)) { + return_ACPI_STATUS (status2); + } + op = NULL; + + status = AE_OK; + break; + + + case AE_CTRL_TERMINATE: + + status = AE_OK; + + /* Clean up */ + do { + if (op) { + status2 = acpi_ps_complete_this_op (walk_state, op); + if (ACPI_FAILURE (status2)) { + return_ACPI_STATUS (status2); + } + } + acpi_ps_pop_scope (parser_state, &op, + &walk_state->arg_types, &walk_state->arg_count); + + } while (op); + + return_ACPI_STATUS (status); + + + default: /* All other non-AE_OK status */ + + do { + if (op) { + status2 = acpi_ps_complete_this_op (walk_state, op); + if (ACPI_FAILURE (status2)) { + return_ACPI_STATUS (status2); + } + } + acpi_ps_pop_scope (parser_state, &op, + &walk_state->arg_types, &walk_state->arg_count); + + } while (op); + + + /* + * TBD: Cleanup parse ops on error + */ +#if 0 + if (op == NULL) { + acpi_ps_pop_scope (parser_state, &op, + &walk_state->arg_types, &walk_state->arg_count); + } +#endif + walk_state->prev_op = op; + walk_state->prev_arg_types = walk_state->arg_types; + return_ACPI_STATUS (status); + } + + /* This scope complete? */ + + if (acpi_ps_has_completed_scope (parser_state)) { + acpi_ps_pop_scope (parser_state, &op, + &walk_state->arg_types, &walk_state->arg_count); + ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "Popped scope, Op=%p\n", op)); + } + else { + op = NULL; + } + + } /* while parser_state->Aml */ + + + /* + * Complete the last Op (if not completed), and clear the scope stack. + * It is easily possible to end an AML "package" with an unbounded number + * of open scopes (such as when several ASL blocks are closed with + * sequential closing braces). We want to terminate each one cleanly. + */ + ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "AML package complete at Op %p\n", op)); + do { + if (op) { + if (walk_state->ascending_callback != NULL) { + walk_state->op = op; + walk_state->op_info = acpi_ps_get_opcode_info (op->common.aml_opcode); + walk_state->opcode = op->common.aml_opcode; + + status = walk_state->ascending_callback (walk_state); + status = acpi_ps_next_parse_state (walk_state, op, status); + if (status == AE_CTRL_PENDING) { + status = AE_OK; + goto close_this_op; + } + + if (status == AE_CTRL_TERMINATE) { + status = AE_OK; + + /* Clean up */ + do { + if (op) { + status2 = acpi_ps_complete_this_op (walk_state, op); + if (ACPI_FAILURE (status2)) { + return_ACPI_STATUS (status2); + } + } + + acpi_ps_pop_scope (parser_state, &op, + &walk_state->arg_types, &walk_state->arg_count); + + } while (op); + + return_ACPI_STATUS (status); + } + + else if (ACPI_FAILURE (status)) { + /* First error is most important */ + + (void) acpi_ps_complete_this_op (walk_state, op); + return_ACPI_STATUS (status); + } + } + + status2 = acpi_ps_complete_this_op (walk_state, op); + if (ACPI_FAILURE (status2)) { + return_ACPI_STATUS (status2); + } + } + + acpi_ps_pop_scope (parser_state, &op, &walk_state->arg_types, + &walk_state->arg_count); + + } while (op); + + return_ACPI_STATUS (status); +} + + diff --git a/drivers/acpi/parser/psopcode.c b/drivers/acpi/parser/psopcode.c index 5744673568c..6f7594a516d 100644 --- a/drivers/acpi/parser/psopcode.c +++ b/drivers/acpi/parser/psopcode.c @@ -311,7 +311,7 @@ const struct acpi_opcode_info acpi_gbl_aml_op_info[AML_NUM_OPCODES] = /* ACPI 2.0 opcodes */ /* 6E */ ACPI_OP ("QwordConst", ARGP_QWORD_OP, ARGI_QWORD_OP, ACPI_TYPE_INTEGER, AML_CLASS_ARGUMENT, AML_TYPE_LITERAL, AML_CONSTANT), -/* 6F */ ACPI_OP ("Package /*Var*/", ARGP_VAR_PACKAGE_OP, ARGI_VAR_PACKAGE_OP, ACPI_TYPE_PACKAGE, AML_CLASS_CREATE, AML_TYPE_CREATE_OBJECT, AML_HAS_ARGS | AML_DEFER), +/* 6F */ ACPI_OP ("Package", /* Var */ ARGP_VAR_PACKAGE_OP, ARGI_VAR_PACKAGE_OP, ACPI_TYPE_PACKAGE, AML_CLASS_CREATE, AML_TYPE_CREATE_OBJECT, AML_HAS_ARGS | AML_DEFER), /* 70 */ ACPI_OP ("ConcatenateResTemplate", ARGP_CONCAT_RES_OP, ARGI_CONCAT_RES_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R, AML_FLAGS_EXEC_2A_1T_1R | AML_CONSTANT), /* 71 */ ACPI_OP ("Mod", ARGP_MOD_OP, ARGI_MOD_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R, AML_FLAGS_EXEC_2A_1T_1R | AML_CONSTANT), /* 72 */ ACPI_OP ("CreateQWordField", ARGP_CREATE_QWORD_FIELD_OP,ARGI_CREATE_QWORD_FIELD_OP, ACPI_TYPE_BUFFER_FIELD, AML_CLASS_CREATE, AML_TYPE_CREATE_FIELD, AML_HAS_ARGS | AML_NSOBJECT | AML_NSNODE | AML_DEFER | AML_CREATE), @@ -428,33 +428,23 @@ acpi_ps_get_opcode_info ( /* * Detect normal 8-bit opcode or extended 16-bit opcode */ - switch ((u8) (opcode >> 8)) { - case 0: - + if (!(opcode & 0xFF00)) { /* Simple (8-bit) opcode: 0-255, can't index beyond table */ return (&acpi_gbl_aml_op_info [acpi_gbl_short_op_index [(u8) opcode]]); + } - case AML_EXTOP: - - /* Extended (16-bit, prefix+opcode) opcode */ - - if (((u8) opcode) <= MAX_EXTENDED_OPCODE) { - return (&acpi_gbl_aml_op_info [acpi_gbl_long_op_index [(u8) opcode]]); - } - - /* Else fall through to error case below */ - /*lint -fallthrough */ - - default: + if (((opcode & 0xFF00) == AML_EXTENDED_OPCODE) && + (((u8) opcode) <= MAX_EXTENDED_OPCODE)) { + /* Valid extended (16-bit) opcode */ - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, - "Unknown AML opcode [%4.4X]\n", opcode)); - break; + return (&acpi_gbl_aml_op_info [acpi_gbl_long_op_index [(u8) opcode]]); } + /* Unknown AML opcode */ - /* Default is "unknown opcode" */ + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, + "Unknown AML opcode [%4.4X]\n", opcode)); return (&acpi_gbl_aml_op_info [_UNK]); } diff --git a/drivers/acpi/parser/psparse.c b/drivers/acpi/parser/psparse.c index bbfdc1a58c2..16b84a3d043 100644 --- a/drivers/acpi/parser/psparse.c +++ b/drivers/acpi/parser/psparse.c @@ -62,26 +62,6 @@ ACPI_MODULE_NAME ("psparse") -static u32 acpi_gbl_depth = 0; - -/* Local prototypes */ - -static void -acpi_ps_complete_this_op ( - struct acpi_walk_state *walk_state, - union acpi_parse_object *op); - -static acpi_status -acpi_ps_next_parse_state ( - struct acpi_walk_state *walk_state, - union acpi_parse_object *op, - acpi_status callback_status); - -static acpi_status -acpi_ps_parse_loop ( - struct acpi_walk_state *walk_state); - - /******************************************************************************* * * FUNCTION: acpi_ps_get_opcode_size @@ -134,8 +114,8 @@ acpi_ps_peek_opcode ( aml = parser_state->aml; opcode = (u16) ACPI_GET8 (aml); - if (opcode == AML_EXTOP) { - /* Extended opcode */ + if (opcode == AML_EXTENDED_OP_PREFIX) { + /* Extended opcode, get the second opcode byte */ aml++; opcode = (u16) ((opcode << 8) | ACPI_GET8 (aml)); @@ -152,13 +132,13 @@ acpi_ps_peek_opcode ( * PARAMETERS: walk_state - Current State * Op - Op to complete * - * RETURN: None. + * RETURN: Status * * DESCRIPTION: Perform any cleanup at the completion of an Op. * ******************************************************************************/ -static void +acpi_status acpi_ps_complete_this_op ( struct acpi_walk_state *walk_state, union acpi_parse_object *op) @@ -175,19 +155,26 @@ acpi_ps_complete_this_op ( /* Check for null Op, can happen if AML code is corrupt */ if (!op) { - return_VOID; + return_ACPI_STATUS (AE_OK); /* OK for now */ } /* Delete this op and the subtree below it if asked to */ if (((walk_state->parse_flags & ACPI_PARSE_TREE_MASK) != ACPI_PARSE_DELETE_TREE) || (walk_state->op_info->class == AML_CLASS_ARGUMENT)) { - return_VOID; + return_ACPI_STATUS (AE_OK); } /* Make sure that we only delete this subtree */ if (op->common.parent) { + prev = op->common.parent->common.value.arg; + if (!prev) { + /* Nothing more to do */ + + goto cleanup; + } + /* * Check if we need to replace the operator and its subtree * with a return value op (placeholder op) @@ -206,7 +193,7 @@ acpi_ps_complete_this_op ( */ replacement_op = acpi_ps_alloc_op (AML_INT_RETURN_VALUE_OP); if (!replacement_op) { - goto cleanup; + goto allocate_error; } break; @@ -223,18 +210,17 @@ acpi_ps_complete_this_op ( (op->common.parent->common.aml_opcode == AML_VAR_PACKAGE_OP)) { replacement_op = acpi_ps_alloc_op (AML_INT_RETURN_VALUE_OP); if (!replacement_op) { - goto cleanup; + goto allocate_error; } } - - if ((op->common.parent->common.aml_opcode == AML_NAME_OP) && - (walk_state->descending_callback != acpi_ds_exec_begin_op)) { + else if ((op->common.parent->common.aml_opcode == AML_NAME_OP) && + (walk_state->pass_number <= ACPI_IMODE_LOAD_PASS2)) { if ((op->common.aml_opcode == AML_BUFFER_OP) || (op->common.aml_opcode == AML_PACKAGE_OP) || (op->common.aml_opcode == AML_VAR_PACKAGE_OP)) { replacement_op = acpi_ps_alloc_op (op->common.aml_opcode); if (!replacement_op) { - goto cleanup; + goto allocate_error; } replacement_op->named.data = op->named.data; @@ -244,15 +230,15 @@ acpi_ps_complete_this_op ( break; default: + replacement_op = acpi_ps_alloc_op (AML_INT_RETURN_VALUE_OP); if (!replacement_op) { - goto cleanup; + goto allocate_error; } } /* We must unlink this op from the parent tree */ - prev = op->common.parent->common.value.arg; if (prev == op) { /* This op is the first in the list */ @@ -298,7 +284,15 @@ cleanup: /* Now we can actually delete the subtree rooted at Op */ acpi_ps_delete_parse_tree (op); - return_VOID; + return_ACPI_STATUS (AE_OK); + + +allocate_error: + + /* Always delete the subtree, even on error */ + + acpi_ps_delete_parse_tree (op); + return_ACPI_STATUS (AE_NO_MEMORY); } @@ -317,7 +311,7 @@ cleanup: * ******************************************************************************/ -static acpi_status +acpi_status acpi_ps_next_parse_state ( struct acpi_walk_state *walk_state, union acpi_parse_object *op, @@ -427,663 +421,6 @@ acpi_ps_next_parse_state ( /******************************************************************************* * - * FUNCTION: acpi_ps_parse_loop - * - * PARAMETERS: walk_state - Current state - * - * RETURN: Status - * - * DESCRIPTION: Parse AML (pointed to by the current parser state) and return - * a tree of ops. - * - ******************************************************************************/ - -static acpi_status -acpi_ps_parse_loop ( - struct acpi_walk_state *walk_state) -{ - acpi_status status = AE_OK; - union acpi_parse_object *op = NULL; /* current op */ - union acpi_parse_object *arg = NULL; - union acpi_parse_object *pre_op = NULL; - struct acpi_parse_state *parser_state; - u8 *aml_op_start = NULL; - - - ACPI_FUNCTION_TRACE_PTR ("ps_parse_loop", walk_state); - - if (walk_state->descending_callback == NULL) { - return_ACPI_STATUS (AE_BAD_PARAMETER); - } - - parser_state = &walk_state->parser_state; - walk_state->arg_types = 0; - -#if (!defined (ACPI_NO_METHOD_EXECUTION) && !defined (ACPI_CONSTANT_EVAL_ONLY)) - - if (walk_state->walk_type & ACPI_WALK_METHOD_RESTART) { - /* We are restarting a preempted control method */ - - if (acpi_ps_has_completed_scope (parser_state)) { - /* - * We must check if a predicate to an IF or WHILE statement - * was just completed - */ - if ((parser_state->scope->parse_scope.op) && - ((parser_state->scope->parse_scope.op->common.aml_opcode == AML_IF_OP) || - (parser_state->scope->parse_scope.op->common.aml_opcode == AML_WHILE_OP)) && - (walk_state->control_state) && - (walk_state->control_state->common.state == - ACPI_CONTROL_PREDICATE_EXECUTING)) { - /* - * A predicate was just completed, get the value of the - * predicate and branch based on that value - */ - walk_state->op = NULL; - status = acpi_ds_get_predicate_value (walk_state, ACPI_TO_POINTER (TRUE)); - if (ACPI_FAILURE (status) && - ((status & AE_CODE_MASK) != AE_CODE_CONTROL)) { - if (status == AE_AML_NO_RETURN_VALUE) { - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, - "Invoked method did not return a value, %s\n", - acpi_format_exception (status))); - - } - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, - "get_predicate Failed, %s\n", - acpi_format_exception (status))); - return_ACPI_STATUS (status); - } - - status = acpi_ps_next_parse_state (walk_state, op, status); - } - - acpi_ps_pop_scope (parser_state, &op, - &walk_state->arg_types, &walk_state->arg_count); - ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "Popped scope, Op=%p\n", op)); - } - else if (walk_state->prev_op) { - /* We were in the middle of an op */ - - op = walk_state->prev_op; - walk_state->arg_types = walk_state->prev_arg_types; - } - } -#endif - - /* Iterative parsing loop, while there is more AML to process: */ - - while ((parser_state->aml < parser_state->aml_end) || (op)) { - aml_op_start = parser_state->aml; - if (!op) { - /* Get the next opcode from the AML stream */ - - walk_state->aml_offset = (u32) ACPI_PTR_DIFF (parser_state->aml, - parser_state->aml_start); - walk_state->opcode = acpi_ps_peek_opcode (parser_state); - - /* - * First cut to determine what we have found: - * 1) A valid AML opcode - * 2) A name string - * 3) An unknown/invalid opcode - */ - walk_state->op_info = acpi_ps_get_opcode_info (walk_state->opcode); - switch (walk_state->op_info->class) { - case AML_CLASS_ASCII: - case AML_CLASS_PREFIX: - /* - * Starts with a valid prefix or ASCII char, this is a name - * string. Convert the bare name string to a namepath. - */ - walk_state->opcode = AML_INT_NAMEPATH_OP; - walk_state->arg_types = ARGP_NAMESTRING; - break; - - case AML_CLASS_UNKNOWN: - - /* The opcode is unrecognized. Just skip unknown opcodes */ - - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, - "Found unknown opcode %X at AML address %p offset %X, ignoring\n", - walk_state->opcode, parser_state->aml, walk_state->aml_offset)); - - ACPI_DUMP_BUFFER (parser_state->aml, 128); - - /* Assume one-byte bad opcode */ - - parser_state->aml++; - continue; - - default: - - /* Found opcode info, this is a normal opcode */ - - parser_state->aml += acpi_ps_get_opcode_size (walk_state->opcode); - walk_state->arg_types = walk_state->op_info->parse_args; - break; - } - - /* Create Op structure and append to parent's argument list */ - - if (walk_state->op_info->flags & AML_NAMED) { - /* Allocate a new pre_op if necessary */ - - if (!pre_op) { - pre_op = acpi_ps_alloc_op (walk_state->opcode); - if (!pre_op) { - status = AE_NO_MEMORY; - goto close_this_op; - } - } - - pre_op->common.value.arg = NULL; - pre_op->common.aml_opcode = walk_state->opcode; - - /* - * Get and append arguments until we find the node that contains - * the name (the type ARGP_NAME). - */ - while (GET_CURRENT_ARG_TYPE (walk_state->arg_types) && - (GET_CURRENT_ARG_TYPE (walk_state->arg_types) != ARGP_NAME)) { - status = acpi_ps_get_next_arg (walk_state, parser_state, - GET_CURRENT_ARG_TYPE (walk_state->arg_types), &arg); - if (ACPI_FAILURE (status)) { - goto close_this_op; - } - - acpi_ps_append_arg (pre_op, arg); - INCREMENT_ARG_LIST (walk_state->arg_types); - } - - /* - * Make sure that we found a NAME and didn't run out of - * arguments - */ - if (!GET_CURRENT_ARG_TYPE (walk_state->arg_types)) { - status = AE_AML_NO_OPERAND; - goto close_this_op; - } - - /* We know that this arg is a name, move to next arg */ - - INCREMENT_ARG_LIST (walk_state->arg_types); - - /* - * Find the object. This will either insert the object into - * the namespace or simply look it up - */ - walk_state->op = NULL; - - status = walk_state->descending_callback (walk_state, &op); - if (ACPI_FAILURE (status)) { - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, - "During name lookup/catalog, %s\n", - acpi_format_exception (status))); - goto close_this_op; - } - - if (!op) { - continue; - } - - status = acpi_ps_next_parse_state (walk_state, op, status); - if (status == AE_CTRL_PENDING) { - status = AE_OK; - goto close_this_op; - } - - if (ACPI_FAILURE (status)) { - goto close_this_op; - } - - acpi_ps_append_arg (op, pre_op->common.value.arg); - acpi_gbl_depth++; - - if (op->common.aml_opcode == AML_REGION_OP) { - /* - * Defer final parsing of an operation_region body, - * because we don't have enough info in the first pass - * to parse it correctly (i.e., there may be method - * calls within the term_arg elements of the body.) - * - * However, we must continue parsing because - * the opregion is not a standalone package -- - * we don't know where the end is at this point. - * - * (Length is unknown until parse of the body complete) - */ - op->named.data = aml_op_start; - op->named.length = 0; - } - } - else { - /* Not a named opcode, just allocate Op and append to parent */ - - walk_state->op_info = acpi_ps_get_opcode_info (walk_state->opcode); - op = acpi_ps_alloc_op (walk_state->opcode); - if (!op) { - status = AE_NO_MEMORY; - goto close_this_op; - } - - if (walk_state->op_info->flags & AML_CREATE) { - /* - * Backup to beginning of create_xXXfield declaration - * body_length is unknown until we parse the body - */ - op->named.data = aml_op_start; - op->named.length = 0; - } - - acpi_ps_append_arg (acpi_ps_get_parent_scope (parser_state), op); - - if ((walk_state->descending_callback != NULL)) { - /* - * Find the object. This will either insert the object into - * the namespace or simply look it up - */ - walk_state->op = op; - - status = walk_state->descending_callback (walk_state, &op); - status = acpi_ps_next_parse_state (walk_state, op, status); - if (status == AE_CTRL_PENDING) { - status = AE_OK; - goto close_this_op; - } - - if (ACPI_FAILURE (status)) { - goto close_this_op; - } - } - } - - op->common.aml_offset = walk_state->aml_offset; - - if (walk_state->op_info) { - ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, - "Opcode %4.4X [%s] Op %p Aml %p aml_offset %5.5X\n", - (u32) op->common.aml_opcode, walk_state->op_info->name, - op, parser_state->aml, op->common.aml_offset)); - } - } - - - /* - * Start arg_count at zero because we don't know if there are - * any args yet - */ - walk_state->arg_count = 0; - - /* Are there any arguments that must be processed? */ - - if (walk_state->arg_types) { - /* Get arguments */ - - switch (op->common.aml_opcode) { - case AML_BYTE_OP: /* AML_BYTEDATA_ARG */ - case AML_WORD_OP: /* AML_WORDDATA_ARG */ - case AML_DWORD_OP: /* AML_DWORDATA_ARG */ - case AML_QWORD_OP: /* AML_QWORDATA_ARG */ - case AML_STRING_OP: /* AML_ASCIICHARLIST_ARG */ - - /* Fill in constant or string argument directly */ - - acpi_ps_get_next_simple_arg (parser_state, - GET_CURRENT_ARG_TYPE (walk_state->arg_types), op); - break; - - case AML_INT_NAMEPATH_OP: /* AML_NAMESTRING_ARG */ - - status = acpi_ps_get_next_namepath (walk_state, parser_state, op, 1); - if (ACPI_FAILURE (status)) { - goto close_this_op; - } - - walk_state->arg_types = 0; - break; - - default: - - /* - * Op is not a constant or string, append each argument - * to the Op - */ - while (GET_CURRENT_ARG_TYPE (walk_state->arg_types) && - !walk_state->arg_count) { - walk_state->aml_offset = (u32) - ACPI_PTR_DIFF (parser_state->aml, parser_state->aml_start); - - status = acpi_ps_get_next_arg (walk_state, parser_state, - GET_CURRENT_ARG_TYPE (walk_state->arg_types), - &arg); - if (ACPI_FAILURE (status)) { - goto close_this_op; - } - - if (arg) { - arg->common.aml_offset = walk_state->aml_offset; - acpi_ps_append_arg (op, arg); - } - INCREMENT_ARG_LIST (walk_state->arg_types); - } - - /* Special processing for certain opcodes */ - - switch (op->common.aml_opcode) { - case AML_METHOD_OP: - - /* - * Skip parsing of control method - * because we don't have enough info in the first pass - * to parse it correctly. - * - * Save the length and address of the body - */ - op->named.data = parser_state->aml; - op->named.length = (u32) (parser_state->pkg_end - - parser_state->aml); - - /* Skip body of method */ - - parser_state->aml = parser_state->pkg_end; - walk_state->arg_count = 0; - break; - - case AML_BUFFER_OP: - case AML_PACKAGE_OP: - case AML_VAR_PACKAGE_OP: - - if ((op->common.parent) && - (op->common.parent->common.aml_opcode == AML_NAME_OP) && - (walk_state->descending_callback != acpi_ds_exec_begin_op)) { - /* - * Skip parsing of Buffers and Packages - * because we don't have enough info in the first pass - * to parse them correctly. - */ - op->named.data = aml_op_start; - op->named.length = (u32) (parser_state->pkg_end - - aml_op_start); - - /* Skip body */ - - parser_state->aml = parser_state->pkg_end; - walk_state->arg_count = 0; - } - break; - - case AML_WHILE_OP: - - if (walk_state->control_state) { - walk_state->control_state->control.package_end = - parser_state->pkg_end; - } - break; - - default: - - /* No action for all other opcodes */ - break; - } - break; - } - } - - /* Check for arguments that need to be processed */ - - if (walk_state->arg_count) { - /* - * There are arguments (complex ones), push Op and - * prepare for argument - */ - status = acpi_ps_push_scope (parser_state, op, - walk_state->arg_types, walk_state->arg_count); - if (ACPI_FAILURE (status)) { - goto close_this_op; - } - op = NULL; - continue; - } - - /* - * All arguments have been processed -- Op is complete, - * prepare for next - */ - walk_state->op_info = acpi_ps_get_opcode_info (op->common.aml_opcode); - if (walk_state->op_info->flags & AML_NAMED) { - if (acpi_gbl_depth) { - acpi_gbl_depth--; - } - - if (op->common.aml_opcode == AML_REGION_OP) { - /* - * Skip parsing of control method or opregion body, - * because we don't have enough info in the first pass - * to parse them correctly. - * - * Completed parsing an op_region declaration, we now - * know the length. - */ - op->named.length = (u32) (parser_state->aml - op->named.data); - } - } - - if (walk_state->op_info->flags & AML_CREATE) { - /* - * Backup to beginning of create_xXXfield declaration (1 for - * Opcode) - * - * body_length is unknown until we parse the body - */ - op->named.length = (u32) (parser_state->aml - op->named.data); - } - - /* This op complete, notify the dispatcher */ - - if (walk_state->ascending_callback != NULL) { - walk_state->op = op; - walk_state->opcode = op->common.aml_opcode; - - status = walk_state->ascending_callback (walk_state); - status = acpi_ps_next_parse_state (walk_state, op, status); - if (status == AE_CTRL_PENDING) { - status = AE_OK; - goto close_this_op; - } - } - - -close_this_op: - /* - * Finished one argument of the containing scope - */ - parser_state->scope->parse_scope.arg_count--; - - /* Close this Op (will result in parse subtree deletion) */ - - acpi_ps_complete_this_op (walk_state, op); - op = NULL; - if (pre_op) { - acpi_ps_free_op (pre_op); - pre_op = NULL; - } - - switch (status) { - case AE_OK: - break; - - - case AE_CTRL_TRANSFER: - - /* We are about to transfer to a called method. */ - - walk_state->prev_op = op; - walk_state->prev_arg_types = walk_state->arg_types; - return_ACPI_STATUS (status); - - - case AE_CTRL_END: - - acpi_ps_pop_scope (parser_state, &op, - &walk_state->arg_types, &walk_state->arg_count); - - if (op) { - walk_state->op = op; - walk_state->op_info = acpi_ps_get_opcode_info (op->common.aml_opcode); - walk_state->opcode = op->common.aml_opcode; - - status = walk_state->ascending_callback (walk_state); - status = acpi_ps_next_parse_state (walk_state, op, status); - - acpi_ps_complete_this_op (walk_state, op); - op = NULL; - } - status = AE_OK; - break; - - - case AE_CTRL_BREAK: - case AE_CTRL_CONTINUE: - - /* Pop off scopes until we find the While */ - - while (!op || (op->common.aml_opcode != AML_WHILE_OP)) { - acpi_ps_pop_scope (parser_state, &op, - &walk_state->arg_types, &walk_state->arg_count); - } - - /* Close this iteration of the While loop */ - - walk_state->op = op; - walk_state->op_info = acpi_ps_get_opcode_info (op->common.aml_opcode); - walk_state->opcode = op->common.aml_opcode; - - status = walk_state->ascending_callback (walk_state); - status = acpi_ps_next_parse_state (walk_state, op, status); - - acpi_ps_complete_this_op (walk_state, op); - op = NULL; - - status = AE_OK; - break; - - - case AE_CTRL_TERMINATE: - - status = AE_OK; - - /* Clean up */ - do { - if (op) { - acpi_ps_complete_this_op (walk_state, op); - } - acpi_ps_pop_scope (parser_state, &op, - &walk_state->arg_types, &walk_state->arg_count); - - } while (op); - - return_ACPI_STATUS (status); - - - default: /* All other non-AE_OK status */ - - do { - if (op) { - acpi_ps_complete_this_op (walk_state, op); - } - acpi_ps_pop_scope (parser_state, &op, - &walk_state->arg_types, &walk_state->arg_count); - - } while (op); - - - /* - * TBD: Cleanup parse ops on error - */ -#if 0 - if (op == NULL) { - acpi_ps_pop_scope (parser_state, &op, - &walk_state->arg_types, &walk_state->arg_count); - } -#endif - walk_state->prev_op = op; - walk_state->prev_arg_types = walk_state->arg_types; - return_ACPI_STATUS (status); - } - - /* This scope complete? */ - - if (acpi_ps_has_completed_scope (parser_state)) { - acpi_ps_pop_scope (parser_state, &op, - &walk_state->arg_types, &walk_state->arg_count); - ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "Popped scope, Op=%p\n", op)); - } - else { - op = NULL; - } - - } /* while parser_state->Aml */ - - - /* - * Complete the last Op (if not completed), and clear the scope stack. - * It is easily possible to end an AML "package" with an unbounded number - * of open scopes (such as when several ASL blocks are closed with - * sequential closing braces). We want to terminate each one cleanly. - */ - ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "AML package complete at Op %p\n", op)); - do { - if (op) { - if (walk_state->ascending_callback != NULL) { - walk_state->op = op; - walk_state->op_info = acpi_ps_get_opcode_info (op->common.aml_opcode); - walk_state->opcode = op->common.aml_opcode; - - status = walk_state->ascending_callback (walk_state); - status = acpi_ps_next_parse_state (walk_state, op, status); - if (status == AE_CTRL_PENDING) { - status = AE_OK; - goto close_this_op; - } - - if (status == AE_CTRL_TERMINATE) { - status = AE_OK; - - /* Clean up */ - do { - if (op) { - acpi_ps_complete_this_op (walk_state, op); - } - - acpi_ps_pop_scope (parser_state, &op, - &walk_state->arg_types, &walk_state->arg_count); - - } while (op); - - return_ACPI_STATUS (status); - } - - else if (ACPI_FAILURE (status)) { - acpi_ps_complete_this_op (walk_state, op); - return_ACPI_STATUS (status); - } - } - - acpi_ps_complete_this_op (walk_state, op); - } - - acpi_ps_pop_scope (parser_state, &op, &walk_state->arg_types, - &walk_state->arg_count); - - } while (op); - - return_ACPI_STATUS (status); -} - - -/******************************************************************************* - * * FUNCTION: acpi_ps_parse_aml * * PARAMETERS: walk_state - Current state diff --git a/drivers/acpi/parser/psutils.c b/drivers/acpi/parser/psutils.c index a10f88715d4..4221b41ae1a 100644 --- a/drivers/acpi/parser/psutils.c +++ b/drivers/acpi/parser/psutils.c @@ -154,12 +154,14 @@ acpi_ps_alloc_op ( if (flags == ACPI_PARSEOP_GENERIC) { /* The generic op (default) is by far the most common (16 to 1) */ - op = acpi_ut_acquire_from_cache (ACPI_MEM_LIST_PSNODE); + op = acpi_os_acquire_object (acpi_gbl_ps_node_cache); + memset(op, 0, sizeof(struct acpi_parse_obj_common)); } else { /* Extended parseop */ - op = acpi_ut_acquire_from_cache (ACPI_MEM_LIST_PSNODE_EXT); + op = acpi_os_acquire_object (acpi_gbl_ps_node_ext_cache); + memset(op, 0, sizeof(struct acpi_parse_obj_named)); } /* Initialize the Op */ @@ -198,41 +200,14 @@ acpi_ps_free_op ( } if (op->common.flags & ACPI_PARSEOP_GENERIC) { - acpi_ut_release_to_cache (ACPI_MEM_LIST_PSNODE, op); + (void) acpi_os_release_object (acpi_gbl_ps_node_cache, op); } else { - acpi_ut_release_to_cache (ACPI_MEM_LIST_PSNODE_EXT, op); + (void) acpi_os_release_object (acpi_gbl_ps_node_ext_cache, op); } } -#ifdef ACPI_ENABLE_OBJECT_CACHE -/******************************************************************************* - * - * FUNCTION: acpi_ps_delete_parse_cache - * - * PARAMETERS: None - * - * RETURN: None - * - * DESCRIPTION: Free all objects that are on the parse cache list. - * - ******************************************************************************/ - -void -acpi_ps_delete_parse_cache ( - void) -{ - ACPI_FUNCTION_TRACE ("ps_delete_parse_cache"); - - - acpi_ut_delete_generic_cache (ACPI_MEM_LIST_PSNODE); - acpi_ut_delete_generic_cache (ACPI_MEM_LIST_PSNODE_EXT); - return_VOID; -} -#endif - - /******************************************************************************* * * FUNCTION: Utility functions diff --git a/drivers/acpi/parser/psxface.c b/drivers/acpi/parser/psxface.c index dba893648e8..d1541fabaf0 100644 --- a/drivers/acpi/parser/psxface.c +++ b/drivers/acpi/parser/psxface.c @@ -46,19 +46,30 @@ #include <acpi/acparser.h> #include <acpi/acdispat.h> #include <acpi/acinterp.h> -#include <acpi/acnamesp.h> #define _COMPONENT ACPI_PARSER ACPI_MODULE_NAME ("psxface") +/* Local Prototypes */ + +static acpi_status +acpi_ps_execute_pass ( + struct acpi_parameter_info *info); + +static void +acpi_ps_update_parameter_list ( + struct acpi_parameter_info *info, + u16 action); + /******************************************************************************* * - * FUNCTION: acpi_psx_execute + * FUNCTION: acpi_ps_execute_method * * PARAMETERS: Info - Method info block, contains: * Node - Method Node to execute + * obj_desc - Method object * Parameters - List of parameters to pass to the method, * terminated by NULL. Params itself may be * NULL if no parameters are being passed. @@ -67,6 +78,7 @@ * parameter_type - Type of Parameter list * return_object - Where to put method's return value (if * any). If NULL, no value is returned. + * pass_number - Parse or execute pass * * RETURN: Status * @@ -75,171 +87,194 @@ ******************************************************************************/ acpi_status -acpi_psx_execute ( +acpi_ps_execute_method ( struct acpi_parameter_info *info) { acpi_status status; - union acpi_operand_object *obj_desc; - u32 i; - union acpi_parse_object *op; - struct acpi_walk_state *walk_state; - ACPI_FUNCTION_TRACE ("psx_execute"); + ACPI_FUNCTION_TRACE ("ps_execute_method"); - /* Validate the Node and get the attached object */ + /* Validate the Info and method Node */ if (!info || !info->node) { return_ACPI_STATUS (AE_NULL_ENTRY); } - obj_desc = acpi_ns_get_attached_object (info->node); - if (!obj_desc) { - return_ACPI_STATUS (AE_NULL_OBJECT); - } - /* Init for new method, wait on concurrency semaphore */ - status = acpi_ds_begin_method_execution (info->node, obj_desc, NULL); + status = acpi_ds_begin_method_execution (info->node, info->obj_desc, NULL); if (ACPI_FAILURE (status)) { return_ACPI_STATUS (status); } - if ((info->parameter_type == ACPI_PARAM_ARGS) && - (info->parameters)) { - /* - * The caller "owns" the parameters, so give each one an extra - * reference - */ - for (i = 0; info->parameters[i]; i++) { - acpi_ut_add_reference (info->parameters[i]); - } - } - - /* - * 1) Perform the first pass parse of the method to enter any - * named objects that it creates into the namespace - */ - ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, - "**** Begin Method Parse **** Entry=%p obj=%p\n", - info->node, obj_desc)); - - /* Create and init a Root Node */ - - op = acpi_ps_create_scope_op (); - if (!op) { - status = AE_NO_MEMORY; - goto cleanup1; - } - /* * Get a new owner_id for objects created by this method. Namespace * objects (such as Operation Regions) can be created during the * first pass parse. */ - obj_desc->method.owning_id = acpi_ut_allocate_owner_id (ACPI_OWNER_TYPE_METHOD); - - /* Create and initialize a new walk state */ - - walk_state = acpi_ds_create_walk_state (obj_desc->method.owning_id, - NULL, NULL, NULL); - if (!walk_state) { - status = AE_NO_MEMORY; - goto cleanup2; - } - - status = acpi_ds_init_aml_walk (walk_state, op, info->node, - obj_desc->method.aml_start, - obj_desc->method.aml_length, NULL, 1); + status = acpi_ut_allocate_owner_id (&info->obj_desc->method.owner_id); if (ACPI_FAILURE (status)) { - goto cleanup3; + return_ACPI_STATUS (status); } - /* Parse the AML */ + /* + * The caller "owns" the parameters, so give each one an extra + * reference + */ + acpi_ps_update_parameter_list (info, REF_INCREMENT); - status = acpi_ps_parse_aml (walk_state); - acpi_ps_delete_parse_tree (op); + /* + * 1) Perform the first pass parse of the method to enter any + * named objects that it creates into the namespace + */ + ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, + "**** Begin Method Parse **** Entry=%p obj=%p\n", + info->node, info->obj_desc)); + + info->pass_number = 1; + status = acpi_ps_execute_pass (info); if (ACPI_FAILURE (status)) { - goto cleanup1; /* Walk state is already deleted */ + goto cleanup; } /* - * 2) Execute the method. Performs second pass parse simultaneously + * 2) Execute the method. Performs second pass parse simultaneously */ ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "**** Begin Method Execution **** Entry=%p obj=%p\n", - info->node, obj_desc)); + info->node, info->obj_desc)); - /* Create and init a Root Node */ + info->pass_number = 3; + status = acpi_ps_execute_pass (info); - op = acpi_ps_create_scope_op (); - if (!op) { - status = AE_NO_MEMORY; - goto cleanup1; + +cleanup: + if (info->obj_desc->method.owner_id) { + acpi_ut_release_owner_id (&info->obj_desc->method.owner_id); } - /* Init new op with the method name and pointer back to the NS node */ + /* Take away the extra reference that we gave the parameters above */ - acpi_ps_set_name (op, info->node->name.integer); - op->common.node = info->node; + acpi_ps_update_parameter_list (info, REF_DECREMENT); - /* Create and initialize a new walk state */ + /* Exit now if error above */ - walk_state = acpi_ds_create_walk_state (0, NULL, NULL, NULL); - if (!walk_state) { - status = AE_NO_MEMORY; - goto cleanup2; + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); } - status = acpi_ds_init_aml_walk (walk_state, op, info->node, - obj_desc->method.aml_start, - obj_desc->method.aml_length, info, 3); - if (ACPI_FAILURE (status)) { - goto cleanup3; + /* + * If the method has returned an object, signal this to the caller with + * a control exception code + */ + if (info->return_object) { + ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "Method returned obj_desc=%p\n", + info->return_object)); + ACPI_DUMP_STACK_ENTRY (info->return_object); + + status = AE_CTRL_RETURN_VALUE; } - /* The walk of the parse tree is where we actually execute the method */ + return_ACPI_STATUS (status); +} - status = acpi_ps_parse_aml (walk_state); - goto cleanup2; /* Walk state already deleted */ +/******************************************************************************* + * + * FUNCTION: acpi_ps_update_parameter_list + * + * PARAMETERS: Info - See struct acpi_parameter_info + * (Used: parameter_type and Parameters) + * Action - Add or Remove reference + * + * RETURN: Status + * + * DESCRIPTION: Update reference count on all method parameter objects + * + ******************************************************************************/ -cleanup3: - acpi_ds_delete_walk_state (walk_state); +static void +acpi_ps_update_parameter_list ( + struct acpi_parameter_info *info, + u16 action) +{ + acpi_native_uint i; -cleanup2: - acpi_ps_delete_parse_tree (op); -cleanup1: if ((info->parameter_type == ACPI_PARAM_ARGS) && (info->parameters)) { - /* Take away the extra reference that we gave the parameters above */ + /* Update reference count for each parameter */ for (i = 0; info->parameters[i]; i++) { /* Ignore errors, just do them all */ - (void) acpi_ut_update_object_reference ( - info->parameters[i], REF_DECREMENT); + (void) acpi_ut_update_object_reference (info->parameters[i], action); } } +} - if (ACPI_FAILURE (status)) { - return_ACPI_STATUS (status); + +/******************************************************************************* + * + * FUNCTION: acpi_ps_execute_pass + * + * PARAMETERS: Info - See struct acpi_parameter_info + * (Used: pass_number, Node, and obj_desc) + * + * RETURN: Status + * + * DESCRIPTION: Single AML pass: Parse or Execute a control method + * + ******************************************************************************/ + +static acpi_status +acpi_ps_execute_pass ( + struct acpi_parameter_info *info) +{ + acpi_status status; + union acpi_parse_object *op; + struct acpi_walk_state *walk_state; + + + ACPI_FUNCTION_TRACE ("ps_execute_pass"); + + + /* Create and init a Root Node */ + + op = acpi_ps_create_scope_op (); + if (!op) { + return_ACPI_STATUS (AE_NO_MEMORY); } - /* - * If the method has returned an object, signal this to the caller with - * a control exception code - */ - if (info->return_object) { - ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "Method returned obj_desc=%p\n", - info->return_object)); - ACPI_DUMP_STACK_ENTRY (info->return_object); + /* Create and initialize a new walk state */ - status = AE_CTRL_RETURN_VALUE; + walk_state = acpi_ds_create_walk_state ( + info->obj_desc->method.owner_id, NULL, NULL, NULL); + if (!walk_state) { + status = AE_NO_MEMORY; + goto cleanup; + } + + status = acpi_ds_init_aml_walk (walk_state, op, info->node, + info->obj_desc->method.aml_start, + info->obj_desc->method.aml_length, + info->pass_number == 1 ? NULL : info, + info->pass_number); + if (ACPI_FAILURE (status)) { + acpi_ds_delete_walk_state (walk_state); + goto cleanup; } + /* Parse the AML */ + + status = acpi_ps_parse_aml (walk_state); + + /* Walk state was deleted by parse_aml */ + +cleanup: + acpi_ps_delete_parse_tree (op); return_ACPI_STATUS (status); } diff --git a/drivers/acpi/resources/rsdump.c b/drivers/acpi/resources/rsdump.c index 1935dab2ab5..2c3bb8c3574 100644 --- a/drivers/acpi/resources/rsdump.c +++ b/drivers/acpi/resources/rsdump.c @@ -48,6 +48,9 @@ #define _COMPONENT ACPI_RESOURCES ACPI_MODULE_NAME ("rsdump") + +#if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER) + /* Local prototypes */ static void @@ -103,7 +106,6 @@ acpi_rs_dump_vendor_specific ( union acpi_resource_data *data); -#if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER) /******************************************************************************* * * FUNCTION: acpi_rs_dump_irq diff --git a/drivers/acpi/tables/tbconvrt.c b/drivers/acpi/tables/tbconvrt.c index 92e0c31539b..d4ff71f5fe5 100644 --- a/drivers/acpi/tables/tbconvrt.c +++ b/drivers/acpi/tables/tbconvrt.c @@ -97,7 +97,9 @@ acpi_tb_get_table_count ( ACPI_FUNCTION_ENTRY (); - if (RSDP->revision < 2) { + /* RSDT pointers are 32 bits, XSDT pointers are 64 bits */ + + if (acpi_gbl_root_table_type == ACPI_TABLE_TYPE_RSDT) { pointer_size = sizeof (u32); } else { @@ -158,7 +160,9 @@ acpi_tb_convert_to_xsdt ( /* Copy the table pointers */ for (i = 0; i < acpi_gbl_rsdt_table_count; i++) { - if (acpi_gbl_RSDP->revision < 2) { + /* RSDT pointers are 32 bits, XSDT pointers are 64 bits */ + + if (acpi_gbl_root_table_type == ACPI_TABLE_TYPE_RSDT) { ACPI_STORE_ADDRESS (new_table->table_offset_entry[i], (ACPI_CAST_PTR (struct rsdt_descriptor_rev1, table_info->pointer))->table_offset_entry[i]); diff --git a/drivers/acpi/tables/tbinstal.c b/drivers/acpi/tables/tbinstal.c index 629b64c8193..698799901f5 100644 --- a/drivers/acpi/tables/tbinstal.c +++ b/drivers/acpi/tables/tbinstal.c @@ -124,9 +124,7 @@ acpi_tb_match_signature ( * * RETURN: Status * - * DESCRIPTION: Load and validate all tables other than the RSDT. The RSDT must - * already be loaded and validated. - * Install the table into the global data structs. + * DESCRIPTION: Install the table into the global data structures. * ******************************************************************************/ @@ -136,6 +134,7 @@ acpi_tb_install_table ( { acpi_status status; + ACPI_FUNCTION_TRACE ("tb_install_table"); @@ -143,22 +142,33 @@ acpi_tb_install_table ( status = acpi_ut_acquire_mutex (ACPI_MTX_TABLES); if (ACPI_FAILURE (status)) { - ACPI_REPORT_ERROR (("Could not acquire table mutex for [%4.4s], %s\n", - table_info->pointer->signature, acpi_format_exception (status))); + ACPI_REPORT_ERROR (("Could not acquire table mutex, %s\n", + acpi_format_exception (status))); return_ACPI_STATUS (status); } + /* + * Ignore a table that is already installed. For example, some BIOS + * ASL code will repeatedly attempt to load the same SSDT. + */ + status = acpi_tb_is_table_installed (table_info); + if (ACPI_FAILURE (status)) { + goto unlock_and_exit; + } + /* Install the table into the global data structure */ status = acpi_tb_init_table_descriptor (table_info->type, table_info); if (ACPI_FAILURE (status)) { - ACPI_REPORT_ERROR (("Could not install ACPI table [%4.4s], %s\n", + ACPI_REPORT_ERROR (("Could not install table [%4.4s], %s\n", table_info->pointer->signature, acpi_format_exception (status))); } ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "%s located at %p\n", acpi_gbl_table_data[table_info->type].name, table_info->pointer)); + +unlock_and_exit: (void) acpi_ut_release_mutex (ACPI_MTX_TABLES); return_ACPI_STATUS (status); } @@ -251,6 +261,7 @@ acpi_tb_init_table_descriptor ( { struct acpi_table_list *list_head; struct acpi_table_desc *table_desc; + acpi_status status; ACPI_FUNCTION_TRACE_U32 ("tb_init_table_descriptor", table_type); @@ -263,6 +274,13 @@ acpi_tb_init_table_descriptor ( return_ACPI_STATUS (AE_NO_MEMORY); } + /* Get a new owner ID for the table */ + + status = acpi_ut_allocate_owner_id (&table_desc->owner_id); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } + /* Install the table into the global data structure */ list_head = &acpi_gbl_table_lists[table_type]; @@ -325,8 +343,6 @@ acpi_tb_init_table_descriptor ( table_desc->aml_start = (u8 *) (table_desc->pointer + 1), table_desc->aml_length = (u32) (table_desc->length - (u32) sizeof (struct acpi_table_header)); - table_desc->table_id = acpi_ut_allocate_owner_id ( - ACPI_OWNER_TYPE_TABLE); table_desc->loaded_into_namespace = FALSE; /* @@ -339,7 +355,7 @@ acpi_tb_init_table_descriptor ( /* Return Data */ - table_info->table_id = table_desc->table_id; + table_info->owner_id = table_desc->owner_id; table_info->installed_desc = table_desc; return_ACPI_STATUS (AE_OK); diff --git a/drivers/acpi/tables/tbrsdt.c b/drivers/acpi/tables/tbrsdt.c index b7ffe39c362..069d498465d 100644 --- a/drivers/acpi/tables/tbrsdt.c +++ b/drivers/acpi/tables/tbrsdt.c @@ -96,32 +96,13 @@ acpi_tb_verify_rsdp ( return_ACPI_STATUS (AE_BAD_PARAMETER); } - /* - * The signature and checksum must both be correct - */ - if (ACPI_STRNCMP ((char *) rsdp, RSDP_SIG, sizeof (RSDP_SIG)-1) != 0) { - /* Nope, BAD Signature */ - - status = AE_BAD_SIGNATURE; - goto cleanup; - } - - /* Check the standard checksum */ + /* Verify RSDP signature and checksum */ - if (acpi_tb_checksum (rsdp, ACPI_RSDP_CHECKSUM_LENGTH) != 0) { - status = AE_BAD_CHECKSUM; + status = acpi_tb_validate_rsdp (rsdp); + if (ACPI_FAILURE (status)) { goto cleanup; } - /* Check extended checksum if table version >= 2 */ - - if (rsdp->revision >= 2) { - if (acpi_tb_checksum (rsdp, ACPI_RSDP_XCHECKSUM_LENGTH) != 0) { - status = AE_BAD_CHECKSUM; - goto cleanup; - } - } - /* The RSDP supplied is OK */ table_info.pointer = ACPI_CAST_PTR (struct acpi_table_header, rsdp); @@ -159,8 +140,8 @@ cleanup: * * RETURN: None, Address * - * DESCRIPTION: Extract the address of the RSDT or XSDT, depending on the - * version of the RSDP + * DESCRIPTION: Extract the address of either the RSDT or XSDT, depending on the + * version of the RSDP and whether the XSDT pointer is valid * ******************************************************************************/ @@ -174,16 +155,19 @@ acpi_tb_get_rsdt_address ( out_address->pointer_type = acpi_gbl_table_flags | ACPI_LOGICAL_ADDRESSING; - /* - * For RSDP revision 0 or 1, we use the RSDT. - * For RSDP revision 2 (and above), we use the XSDT - */ - if (acpi_gbl_RSDP->revision < 2) { - out_address->pointer.value = acpi_gbl_RSDP->rsdt_physical_address; - } - else { + /* Use XSDT if it is present */ + + if ((acpi_gbl_RSDP->revision >= 2) && + acpi_gbl_RSDP->xsdt_physical_address) { out_address->pointer.value = acpi_gbl_RSDP->xsdt_physical_address; + acpi_gbl_root_table_type = ACPI_TABLE_TYPE_XSDT; + } + else { + /* No XSDT, use the RSDT */ + + out_address->pointer.value = acpi_gbl_RSDP->rsdt_physical_address; + acpi_gbl_root_table_type = ACPI_TABLE_TYPE_RSDT; } } @@ -211,10 +195,9 @@ acpi_tb_validate_rsdt ( /* - * For RSDP revision 0 or 1, we use the RSDT. - * For RSDP revision 2 and above, we use the XSDT + * Search for appropriate signature, RSDT or XSDT */ - if (acpi_gbl_RSDP->revision < 2) { + if (acpi_gbl_root_table_type == ACPI_TABLE_TYPE_RSDT) { no_match = ACPI_STRNCMP ((char *) table_ptr, RSDT_SIG, sizeof (RSDT_SIG) -1); } @@ -236,11 +219,11 @@ acpi_tb_validate_rsdt ( acpi_gbl_RSDP->rsdt_physical_address, (void *) (acpi_native_uint) acpi_gbl_RSDP->rsdt_physical_address)); - if (acpi_gbl_RSDP->revision < 2) { - ACPI_REPORT_ERROR (("Looking for RSDT (RSDP->Rev < 2)\n")) + if (acpi_gbl_root_table_type == ACPI_TABLE_TYPE_RSDT) { + ACPI_REPORT_ERROR (("Looking for RSDT\n")) } else { - ACPI_REPORT_ERROR (("Looking for XSDT (RSDP->Rev >= 2)\n")) + ACPI_REPORT_ERROR (("Looking for XSDT\n")) } ACPI_DUMP_BUFFER ((char *) table_ptr, 48); diff --git a/drivers/acpi/tables/tbutils.c b/drivers/acpi/tables/tbutils.c index e69d01d443d..6fc1e36e604 100644 --- a/drivers/acpi/tables/tbutils.c +++ b/drivers/acpi/tables/tbutils.c @@ -61,6 +61,67 @@ acpi_tb_handle_to_object ( /******************************************************************************* * + * FUNCTION: acpi_tb_is_table_installed + * + * PARAMETERS: new_table_desc - Descriptor for new table being installed + * + * RETURN: Status - AE_ALREADY_EXISTS if the table is already installed + * + * DESCRIPTION: Determine if an ACPI table is already installed + * + * MUTEX: Table data structures should be locked + * + ******************************************************************************/ + +acpi_status +acpi_tb_is_table_installed ( + struct acpi_table_desc *new_table_desc) +{ + struct acpi_table_desc *table_desc; + + + ACPI_FUNCTION_TRACE ("tb_is_table_installed"); + + + /* Get the list descriptor and first table descriptor */ + + table_desc = acpi_gbl_table_lists[new_table_desc->type].next; + + /* Examine all installed tables of this type */ + + while (table_desc) { + /* Compare Revision and oem_table_id */ + + if ((table_desc->loaded_into_namespace) && + (table_desc->pointer->revision == + new_table_desc->pointer->revision) && + (!ACPI_MEMCMP (table_desc->pointer->oem_table_id, + new_table_desc->pointer->oem_table_id, 8))) { + /* This table is already installed */ + + ACPI_DEBUG_PRINT ((ACPI_DB_TABLES, + "Table [%4.4s] already installed: Rev %X oem_table_id [%8.8s]\n", + new_table_desc->pointer->signature, + new_table_desc->pointer->revision, + new_table_desc->pointer->oem_table_id)); + + new_table_desc->owner_id = table_desc->owner_id; + new_table_desc->installed_desc = table_desc; + + return_ACPI_STATUS (AE_ALREADY_EXISTS); + } + + /* Get next table on the list */ + + table_desc = table_desc->next; + } + + return_ACPI_STATUS (AE_OK); +} + + +/******************************************************************************* + * * FUNCTION: acpi_tb_validate_table_header * * PARAMETERS: table_header - Logical pointer to the table @@ -157,7 +218,7 @@ acpi_tb_verify_table_checksum ( /* Compute the checksum on the table */ - checksum = acpi_tb_checksum (table_header, table_header->length); + checksum = acpi_tb_generate_checksum (table_header, table_header->length); /* Return the appropriate exception */ @@ -175,7 +236,7 @@ acpi_tb_verify_table_checksum ( /******************************************************************************* * - * FUNCTION: acpi_tb_checksum + * FUNCTION: acpi_tb_generate_checksum * * PARAMETERS: Buffer - Buffer to checksum * Length - Size of the buffer @@ -187,7 +248,7 @@ acpi_tb_verify_table_checksum ( ******************************************************************************/ u8 -acpi_tb_checksum ( +acpi_tb_generate_checksum ( void *buffer, u32 length) { diff --git a/drivers/acpi/tables/tbxface.c b/drivers/acpi/tables/tbxface.c index 0c0b9085dbe..e18a05d1b9b 100644 --- a/drivers/acpi/tables/tbxface.c +++ b/drivers/acpi/tables/tbxface.c @@ -182,10 +182,23 @@ acpi_load_table ( return_ACPI_STATUS (status); } + /* Check signature for a valid table type */ + + status = acpi_tb_recognize_table (&table_info, ACPI_TABLE_ALL); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } + /* Install the new table into the local data structures */ status = acpi_tb_install_table (&table_info); if (ACPI_FAILURE (status)) { + if (status == AE_ALREADY_EXISTS) { + /* Table already exists, no error */ + + status = AE_OK; + } + /* Free table allocated by acpi_tb_get_table_body */ acpi_tb_delete_single_table (&table_info); @@ -260,8 +273,8 @@ acpi_unload_table ( * "Scope" operator. Thus, we need to track ownership by an ID, not * simply a position within the hierarchy */ - acpi_ns_delete_namespace_by_owner (table_desc->table_id); - + acpi_ns_delete_namespace_by_owner (table_desc->owner_id); + acpi_ut_release_owner_id (&table_desc->owner_id); table_desc = table_desc->next; } diff --git a/drivers/acpi/tables/tbxfroot.c b/drivers/acpi/tables/tbxfroot.c index dc3c3f6a9f6..87dccdda9ae 100644 --- a/drivers/acpi/tables/tbxfroot.c +++ b/drivers/acpi/tables/tbxfroot.c @@ -65,6 +65,51 @@ acpi_tb_scan_memory_for_rsdp ( /******************************************************************************* * + * FUNCTION: acpi_tb_validate_rsdp + * + * PARAMETERS: Rsdp - Pointer to unvalidated RSDP + * + * RETURN: Status + * + * DESCRIPTION: Validate the RSDP (ptr) + * + ******************************************************************************/ + +acpi_status +acpi_tb_validate_rsdp ( + struct rsdp_descriptor *rsdp) +{ + ACPI_FUNCTION_ENTRY (); + + + /* + * The signature and checksum must both be correct + */ + if (ACPI_STRNCMP ((char *) rsdp, RSDP_SIG, sizeof (RSDP_SIG)-1) != 0) { + /* Nope, BAD Signature */ + + return (AE_BAD_SIGNATURE); + } + + /* Check the standard checksum */ + + if (acpi_tb_generate_checksum (rsdp, ACPI_RSDP_CHECKSUM_LENGTH) != 0) { + return (AE_BAD_CHECKSUM); + } + + /* Check extended checksum if table version >= 2 */ + + if ((rsdp->revision >= 2) && + (acpi_tb_generate_checksum (rsdp, ACPI_RSDP_XCHECKSUM_LENGTH) != 0)) { + return (AE_BAD_CHECKSUM); + } + + return (AE_OK); +} + + +/******************************************************************************* + * * FUNCTION: acpi_tb_find_table * * PARAMETERS: Signature - String with ACPI table signature @@ -218,19 +263,11 @@ acpi_get_firmware_table ( acpi_gbl_RSDP = address.pointer.logical; } - /* The signature and checksum must both be correct */ - - if (ACPI_STRNCMP ((char *) acpi_gbl_RSDP, RSDP_SIG, - sizeof (RSDP_SIG)-1) != 0) { - /* Nope, BAD Signature */ - - return_ACPI_STATUS (AE_BAD_SIGNATURE); - } - - if (acpi_tb_checksum (acpi_gbl_RSDP, ACPI_RSDP_CHECKSUM_LENGTH) != 0) { - /* Nope, BAD Checksum */ + /* The RDSP signature and checksum must both be correct */ - return_ACPI_STATUS (AE_BAD_CHECKSUM); + status = acpi_tb_validate_rsdp (acpi_gbl_RSDP); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); } } @@ -287,9 +324,11 @@ acpi_get_firmware_table ( * requested table */ for (i = 0, j = 0; i < table_count; i++) { - /* Get the next table pointer, handle RSDT vs. XSDT */ - - if (acpi_gbl_RSDP->revision < 2) { + /* + * Get the next table pointer, handle RSDT vs. XSDT + * RSDT pointers are 32 bits, XSDT pointers are 64 bits + */ + if (acpi_gbl_root_table_type == ACPI_TABLE_TYPE_RSDT) { address.pointer.value = (ACPI_CAST_PTR ( RSDT_DESCRIPTOR, rsdt_info->pointer))->table_offset_entry[i]; } @@ -331,8 +370,10 @@ acpi_get_firmware_table ( cleanup: - acpi_os_unmap_memory (rsdt_info->pointer, - (acpi_size) rsdt_info->pointer->length); + if (rsdt_info->pointer) { + acpi_os_unmap_memory (rsdt_info->pointer, + (acpi_size) rsdt_info->pointer->length); + } ACPI_MEM_FREE (rsdt_info); if (header) { @@ -410,9 +451,9 @@ acpi_tb_scan_memory_for_rsdp ( u8 *start_address, u32 length) { + acpi_status status; u8 *mem_rover; u8 *end_address; - u8 checksum; ACPI_FUNCTION_TRACE ("tb_scan_memory_for_rsdp"); @@ -424,45 +465,25 @@ acpi_tb_scan_memory_for_rsdp ( for (mem_rover = start_address; mem_rover < end_address; mem_rover += ACPI_RSDP_SCAN_STEP) { - /* The signature and checksum must both be correct */ - - if (ACPI_STRNCMP ((char *) mem_rover, - RSDP_SIG, sizeof (RSDP_SIG) - 1) != 0) { - /* No signature match, keep looking */ - - continue; - } - - /* Signature matches, check the appropriate checksum */ - - if ((ACPI_CAST_PTR (struct rsdp_descriptor, mem_rover))->revision < 2) { - /* ACPI version 1.0 */ + /* The RSDP signature and checksum must both be correct */ - checksum = acpi_tb_checksum (mem_rover, ACPI_RSDP_CHECKSUM_LENGTH); - } - else { - /* Post ACPI 1.0, use extended_checksum */ - - checksum = acpi_tb_checksum (mem_rover, ACPI_RSDP_XCHECKSUM_LENGTH); - } - - if (checksum == 0) { - /* Checksum valid, we have found a valid RSDP */ + status = acpi_tb_validate_rsdp (ACPI_CAST_PTR (struct rsdp_descriptor, mem_rover)); + if (ACPI_SUCCESS (status)) { + /* Sig and checksum valid, we have found a real RSDP */ ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "RSDP located at physical address %p\n", mem_rover)); return_PTR (mem_rover); } - ACPI_DEBUG_PRINT ((ACPI_DB_INFO, - "Found an RSDP at physical address %p, but it has a bad checksum\n", - mem_rover)); + /* No sig match or bad checksum, keep searching */ } /* Searched entire block, no RSDP was found */ ACPI_DEBUG_PRINT ((ACPI_DB_INFO, - "Searched entire block, no valid RSDP was found.\n")); + "Searched entire block from %p, valid RSDP was not found\n", + start_address)); return_PTR (NULL); } @@ -550,7 +571,7 @@ acpi_tb_find_rsdp ( acpi_os_unmap_memory (table_ptr, ACPI_EBDA_WINDOW_SIZE); if (mem_rover) { - /* Found it, return the physical address */ + /* Return the physical address */ physical_address += ACPI_PTR_DIFF (mem_rover, table_ptr); @@ -579,7 +600,7 @@ acpi_tb_find_rsdp ( acpi_os_unmap_memory (table_ptr, ACPI_HI_RSDP_WINDOW_SIZE); if (mem_rover) { - /* Found it, return the physical address */ + /* Return the physical address */ physical_address = ACPI_HI_RSDP_WINDOW_BASE + ACPI_PTR_DIFF (mem_rover, table_ptr); @@ -610,7 +631,7 @@ acpi_tb_find_rsdp ( ACPI_PHYSADDR_TO_PTR (physical_address), ACPI_EBDA_WINDOW_SIZE); if (mem_rover) { - /* Found it, return the physical address */ + /* Return the physical address */ table_info->physical_address = ACPI_TO_INTEGER (mem_rover); return_ACPI_STATUS (AE_OK); @@ -630,8 +651,9 @@ acpi_tb_find_rsdp ( } } - /* RSDP signature was not found */ + /* A valid RSDP was not found */ + ACPI_REPORT_ERROR (("No valid RSDP was found\n")); return_ACPI_STATUS (AE_NOT_FOUND); } diff --git a/drivers/acpi/utilities/Makefile b/drivers/acpi/utilities/Makefile index 939c447dd52..e87108b7338 100644 --- a/drivers/acpi/utilities/Makefile +++ b/drivers/acpi/utilities/Makefile @@ -3,6 +3,6 @@ # obj-y := utalloc.o utdebug.o uteval.o utinit.o utmisc.o utxface.o \ - utcopy.o utdelete.o utglobal.o utmath.o utobject.o + utcopy.o utdelete.o utglobal.o utmath.o utobject.o utstate.o utmutex.o utobject.o utcache.o EXTRA_CFLAGS += $(ACPI_CFLAGS) diff --git a/drivers/acpi/utilities/utalloc.c b/drivers/acpi/utilities/utalloc.c index c4e7f989a2b..78270f50e62 100644 --- a/drivers/acpi/utilities/utalloc.c +++ b/drivers/acpi/utilities/utalloc.c @@ -1,6 +1,6 @@ /****************************************************************************** * - * Module Name: utalloc - local cache and memory allocation routines + * Module Name: utalloc - local memory allocation routines * *****************************************************************************/ @@ -52,12 +52,10 @@ #ifdef ACPI_DBG_TRACK_ALLOCATIONS static struct acpi_debug_mem_block * acpi_ut_find_allocation ( - u32 list_id, void *allocation); static acpi_status acpi_ut_track_allocation ( - u32 list_id, struct acpi_debug_mem_block *address, acpi_size size, u8 alloc_type, @@ -67,206 +65,118 @@ acpi_ut_track_allocation ( static acpi_status acpi_ut_remove_allocation ( - u32 list_id, struct acpi_debug_mem_block *address, u32 component, char *module, u32 line); #endif /* ACPI_DBG_TRACK_ALLOCATIONS */ - -/******************************************************************************* - * - * FUNCTION: acpi_ut_release_to_cache - * - * PARAMETERS: list_id - Memory list/cache ID - * Object - The object to be released - * - * RETURN: None - * - * DESCRIPTION: Release an object to the specified cache. If cache is full, - * the object is deleted. - * - ******************************************************************************/ - -void -acpi_ut_release_to_cache ( - u32 list_id, - void *object) -{ - struct acpi_memory_list *cache_info; - - - ACPI_FUNCTION_ENTRY (); - - - cache_info = &acpi_gbl_memory_lists[list_id]; - -#ifdef ACPI_ENABLE_OBJECT_CACHE - - /* If walk cache is full, just free this wallkstate object */ - - if (cache_info->cache_depth >= cache_info->max_cache_depth) { - ACPI_MEM_FREE (object); - ACPI_MEM_TRACKING (cache_info->total_freed++); - } - - /* Otherwise put this object back into the cache */ - - else { - if (ACPI_FAILURE (acpi_ut_acquire_mutex (ACPI_MTX_CACHES))) { - return; - } - - /* Mark the object as cached */ - - ACPI_MEMSET (object, 0xCA, cache_info->object_size); - ACPI_SET_DESCRIPTOR_TYPE (object, ACPI_DESC_TYPE_CACHED); - - /* Put the object at the head of the cache list */ - - * (ACPI_CAST_INDIRECT_PTR (char, - &(((char *) object)[cache_info->link_offset]))) = cache_info->list_head; - cache_info->list_head = object; - cache_info->cache_depth++; - - (void) acpi_ut_release_mutex (ACPI_MTX_CACHES); - } - -#else - - /* Object cache is disabled; just free the object */ - - ACPI_MEM_FREE (object); - ACPI_MEM_TRACKING (cache_info->total_freed++); +#ifdef ACPI_DBG_TRACK_ALLOCATIONS +static acpi_status +acpi_ut_create_list ( + char *list_name, + u16 object_size, + struct acpi_memory_list **return_cache); #endif -} /******************************************************************************* * - * FUNCTION: acpi_ut_acquire_from_cache + * FUNCTION: acpi_ut_create_caches * - * PARAMETERS: list_id - Memory list ID + * PARAMETERS: None * - * RETURN: A requested object. NULL if the object could not be - * allocated. + * RETURN: Status * - * DESCRIPTION: Get an object from the specified cache. If cache is empty, - * the object is allocated. + * DESCRIPTION: Create all local caches * ******************************************************************************/ -void * -acpi_ut_acquire_from_cache ( - u32 list_id) +acpi_status +acpi_ut_create_caches ( + void) { - struct acpi_memory_list *cache_info; - void *object; - - - ACPI_FUNCTION_NAME ("ut_acquire_from_cache"); + acpi_status status; - cache_info = &acpi_gbl_memory_lists[list_id]; +#ifdef ACPI_DBG_TRACK_ALLOCATIONS -#ifdef ACPI_ENABLE_OBJECT_CACHE + /* Memory allocation lists */ - if (ACPI_FAILURE (acpi_ut_acquire_mutex (ACPI_MTX_CACHES))) { - return (NULL); + status = acpi_ut_create_list ("Acpi-Global", 0, + &acpi_gbl_global_list); + if (ACPI_FAILURE (status)) { + return (status); } - ACPI_MEM_TRACKING (cache_info->cache_requests++); - - /* Check the cache first */ - - if (cache_info->list_head) { - /* There is an object available, use it */ - - object = cache_info->list_head; - cache_info->list_head = *(ACPI_CAST_INDIRECT_PTR (char, - &(((char *) object)[cache_info->link_offset]))); - - ACPI_MEM_TRACKING (cache_info->cache_hits++); - cache_info->cache_depth--; - -#ifdef ACPI_DBG_TRACK_ALLOCATIONS - ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Object %p from %s\n", - object, acpi_gbl_memory_lists[list_id].list_name)); + status = acpi_ut_create_list ("Acpi-Namespace", sizeof (struct acpi_namespace_node), + &acpi_gbl_ns_node_list); + if (ACPI_FAILURE (status)) { + return (status); + } #endif - if (ACPI_FAILURE (acpi_ut_release_mutex (ACPI_MTX_CACHES))) { - return (NULL); - } - - /* Clear (zero) the previously used Object */ + /* Object Caches, for frequently used objects */ - ACPI_MEMSET (object, 0, cache_info->object_size); + status = acpi_os_create_cache ("acpi_state", sizeof (union acpi_generic_state), + ACPI_MAX_STATE_CACHE_DEPTH, &acpi_gbl_state_cache); + if (ACPI_FAILURE (status)) { + return (status); } - else { - /* The cache is empty, create a new object */ - - /* Avoid deadlock with ACPI_MEM_CALLOCATE */ - - if (ACPI_FAILURE (acpi_ut_release_mutex (ACPI_MTX_CACHES))) { - return (NULL); - } - - object = ACPI_MEM_CALLOCATE (cache_info->object_size); - ACPI_MEM_TRACKING (cache_info->total_allocated++); + status = acpi_os_create_cache ("acpi_parse", sizeof (struct acpi_parse_obj_common), + ACPI_MAX_PARSE_CACHE_DEPTH, &acpi_gbl_ps_node_cache); + if (ACPI_FAILURE (status)) { + return (status); } -#else - - /* Object cache is disabled; just allocate the object */ + status = acpi_os_create_cache ("acpi_parse_ext", sizeof (struct acpi_parse_obj_named), + ACPI_MAX_EXTPARSE_CACHE_DEPTH, &acpi_gbl_ps_node_ext_cache); + if (ACPI_FAILURE (status)) { + return (status); + } - object = ACPI_MEM_CALLOCATE (cache_info->object_size); - ACPI_MEM_TRACKING (cache_info->total_allocated++); -#endif + status = acpi_os_create_cache ("acpi_operand", sizeof (union acpi_operand_object), + ACPI_MAX_OBJECT_CACHE_DEPTH, &acpi_gbl_operand_cache); + if (ACPI_FAILURE (status)) { + return (status); + } - return (object); + return (AE_OK); } -#ifdef ACPI_ENABLE_OBJECT_CACHE /******************************************************************************* * - * FUNCTION: acpi_ut_delete_generic_cache + * FUNCTION: acpi_ut_delete_caches * - * PARAMETERS: list_id - Memory list ID + * PARAMETERS: None * - * RETURN: None + * RETURN: Status * - * DESCRIPTION: Free all objects within the requested cache. + * DESCRIPTION: Purge and delete all local caches * ******************************************************************************/ -void -acpi_ut_delete_generic_cache ( - u32 list_id) +acpi_status +acpi_ut_delete_caches ( + void) { - struct acpi_memory_list *cache_info; - char *next; + (void) acpi_os_delete_cache (acpi_gbl_state_cache); + acpi_gbl_state_cache = NULL; - ACPI_FUNCTION_ENTRY (); - + (void) acpi_os_delete_cache (acpi_gbl_operand_cache); + acpi_gbl_operand_cache = NULL; - cache_info = &acpi_gbl_memory_lists[list_id]; - while (cache_info->list_head) { - /* Delete one cached state object */ + (void) acpi_os_delete_cache (acpi_gbl_ps_node_cache); + acpi_gbl_ps_node_cache = NULL; - next = *(ACPI_CAST_INDIRECT_PTR (char, - &(((char *) cache_info->list_head)[cache_info->link_offset]))); - ACPI_MEM_FREE (cache_info->list_head); + (void) acpi_os_delete_cache (acpi_gbl_ps_node_ext_cache); + acpi_gbl_ps_node_ext_cache = NULL; - cache_info->list_head = next; - cache_info->cache_depth--; - } + return (AE_OK); } -#endif - /******************************************************************************* * @@ -500,6 +410,43 @@ acpi_ut_callocate ( * occurs in the body of acpi_ut_free. */ +/******************************************************************************* + * + * FUNCTION: acpi_ut_create_list + * + * PARAMETERS: cache_name - Ascii name for the cache + * object_size - Size of each cached object + * return_cache - Where the new cache object is returned + * + * RETURN: Status + * + * DESCRIPTION: Create a local memory list for tracking purposed + * + ******************************************************************************/ + +static acpi_status +acpi_ut_create_list ( + char *list_name, + u16 object_size, + struct acpi_memory_list **return_cache) +{ + struct acpi_memory_list *cache; + + + cache = acpi_os_allocate (sizeof (struct acpi_memory_list)); + if (!cache) { + return (AE_NO_MEMORY); + } + + ACPI_MEMSET (cache, 0, sizeof (struct acpi_memory_list)); + + cache->list_name = list_name; + cache->object_size = object_size; + + *return_cache = cache; + return (AE_OK); +} + /******************************************************************************* * @@ -533,15 +480,15 @@ acpi_ut_allocate_and_track ( return (NULL); } - status = acpi_ut_track_allocation (ACPI_MEM_LIST_GLOBAL, allocation, size, + status = acpi_ut_track_allocation (allocation, size, ACPI_MEM_MALLOC, component, module, line); if (ACPI_FAILURE (status)) { acpi_os_free (allocation); return (NULL); } - acpi_gbl_memory_lists[ACPI_MEM_LIST_GLOBAL].total_allocated++; - acpi_gbl_memory_lists[ACPI_MEM_LIST_GLOBAL].current_total_size += (u32) size; + acpi_gbl_global_list->total_allocated++; + acpi_gbl_global_list->current_total_size += (u32) size; return ((void *) &allocation->user_space); } @@ -583,15 +530,15 @@ acpi_ut_callocate_and_track ( return (NULL); } - status = acpi_ut_track_allocation (ACPI_MEM_LIST_GLOBAL, allocation, size, + status = acpi_ut_track_allocation (allocation, size, ACPI_MEM_CALLOC, component, module, line); if (ACPI_FAILURE (status)) { acpi_os_free (allocation); return (NULL); } - acpi_gbl_memory_lists[ACPI_MEM_LIST_GLOBAL].total_allocated++; - acpi_gbl_memory_lists[ACPI_MEM_LIST_GLOBAL].current_total_size += (u32) size; + acpi_gbl_global_list->total_allocated++; + acpi_gbl_global_list->current_total_size += (u32) size; return ((void *) &allocation->user_space); } @@ -636,10 +583,10 @@ acpi_ut_free_and_track ( debug_block = ACPI_CAST_PTR (struct acpi_debug_mem_block, (((char *) allocation) - sizeof (struct acpi_debug_mem_header))); - acpi_gbl_memory_lists[ACPI_MEM_LIST_GLOBAL].total_freed++; - acpi_gbl_memory_lists[ACPI_MEM_LIST_GLOBAL].current_total_size -= debug_block->size; + acpi_gbl_global_list->total_freed++; + acpi_gbl_global_list->current_total_size -= debug_block->size; - status = acpi_ut_remove_allocation (ACPI_MEM_LIST_GLOBAL, debug_block, + status = acpi_ut_remove_allocation (debug_block, component, module, line); if (ACPI_FAILURE (status)) { ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Could not free memory, %s\n", @@ -658,8 +605,7 @@ acpi_ut_free_and_track ( * * FUNCTION: acpi_ut_find_allocation * - * PARAMETERS: list_id - Memory list to search - * Allocation - Address of allocated memory + * PARAMETERS: Allocation - Address of allocated memory * * RETURN: A list element if found; NULL otherwise. * @@ -669,7 +615,6 @@ acpi_ut_free_and_track ( static struct acpi_debug_mem_block * acpi_ut_find_allocation ( - u32 list_id, void *allocation) { struct acpi_debug_mem_block *element; @@ -678,11 +623,7 @@ acpi_ut_find_allocation ( ACPI_FUNCTION_ENTRY (); - if (list_id > ACPI_MEM_LIST_MAX) { - return (NULL); - } - - element = acpi_gbl_memory_lists[list_id].list_head; + element = acpi_gbl_global_list->list_head; /* Search for the address. */ @@ -702,8 +643,7 @@ acpi_ut_find_allocation ( * * FUNCTION: acpi_ut_track_allocation * - * PARAMETERS: list_id - Memory list to search - * Allocation - Address of allocated memory + * PARAMETERS: Allocation - Address of allocated memory * Size - Size of the allocation * alloc_type - MEM_MALLOC or MEM_CALLOC * Component - Component type of caller @@ -718,7 +658,6 @@ acpi_ut_find_allocation ( static acpi_status acpi_ut_track_allocation ( - u32 list_id, struct acpi_debug_mem_block *allocation, acpi_size size, u8 alloc_type, @@ -734,11 +673,7 @@ acpi_ut_track_allocation ( ACPI_FUNCTION_TRACE_PTR ("ut_track_allocation", allocation); - if (list_id > ACPI_MEM_LIST_MAX) { - return_ACPI_STATUS (AE_BAD_PARAMETER); - } - - mem_list = &acpi_gbl_memory_lists[list_id]; + mem_list = acpi_gbl_global_list; status = acpi_ut_acquire_mutex (ACPI_MTX_MEMORY); if (ACPI_FAILURE (status)) { return_ACPI_STATUS (status); @@ -748,8 +683,7 @@ acpi_ut_track_allocation ( * Search list for this address to make sure it is not already on the list. * This will catch several kinds of problems. */ - - element = acpi_ut_find_allocation (list_id, allocation); + element = acpi_ut_find_allocation (allocation); if (element) { ACPI_REPORT_ERROR (( "ut_track_allocation: Allocation already present in list! (%p)\n", @@ -793,8 +727,7 @@ unlock_and_exit: * * FUNCTION: acpi_ut_remove_allocation * - * PARAMETERS: list_id - Memory list to search - * Allocation - Address of allocated memory + * PARAMETERS: Allocation - Address of allocated memory * Component - Component type of caller * Module - Source file name of caller * Line - Line number of caller @@ -807,7 +740,6 @@ unlock_and_exit: static acpi_status acpi_ut_remove_allocation ( - u32 list_id, struct acpi_debug_mem_block *allocation, u32 component, char *module, @@ -820,11 +752,7 @@ acpi_ut_remove_allocation ( ACPI_FUNCTION_TRACE ("ut_remove_allocation"); - if (list_id > ACPI_MEM_LIST_MAX) { - return_ACPI_STATUS (AE_BAD_PARAMETER); - } - - mem_list = &acpi_gbl_memory_lists[list_id]; + mem_list = acpi_gbl_global_list; if (NULL == mem_list->list_head) { /* No allocations! */ @@ -959,7 +887,7 @@ acpi_ut_dump_allocations ( return; } - element = acpi_gbl_memory_lists[0].list_head; + element = acpi_gbl_global_list->list_head; while (element) { if ((element->component & component) && ((module == NULL) || (0 == ACPI_STRCMP (module, element->module)))) { diff --git a/drivers/acpi/utilities/utcache.c b/drivers/acpi/utilities/utcache.c new file mode 100644 index 00000000000..c0df0585c68 --- /dev/null +++ b/drivers/acpi/utilities/utcache.c @@ -0,0 +1,328 @@ +/****************************************************************************** + * + * Module Name: utcache - local cache allocation routines + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2005, R. Byron Moore + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + + +#include <acpi/acpi.h> + +#define _COMPONENT ACPI_UTILITIES + ACPI_MODULE_NAME ("utcache") + + +#ifdef ACPI_USE_LOCAL_CACHE +/******************************************************************************* + * + * FUNCTION: acpi_os_create_cache + * + * PARAMETERS: cache_name - Ascii name for the cache + * object_size - Size of each cached object + * max_depth - Maximum depth of the cache (in objects) + * return_cache - Where the new cache object is returned + * + * RETURN: Status + * + * DESCRIPTION: Create a cache object + * + ******************************************************************************/ + +acpi_status +acpi_os_create_cache ( + char *cache_name, + u16 object_size, + u16 max_depth, + struct acpi_memory_list **return_cache) +{ + struct acpi_memory_list *cache; + + + ACPI_FUNCTION_ENTRY (); + + + if (!cache_name || !return_cache || (object_size < 16)) { + return (AE_BAD_PARAMETER); + } + + /* Create the cache object */ + + cache = acpi_os_allocate (sizeof (struct acpi_memory_list)); + if (!cache) { + return (AE_NO_MEMORY); + } + + /* Populate the cache object and return it */ + + ACPI_MEMSET (cache, 0, sizeof (struct acpi_memory_list)); + cache->link_offset = 8; + cache->list_name = cache_name; + cache->object_size = object_size; + cache->max_depth = max_depth; + + *return_cache = cache; + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: acpi_os_purge_cache + * + * PARAMETERS: Cache - Handle to cache object + * + * RETURN: Status + * + * DESCRIPTION: Free all objects within the requested cache. + * + ******************************************************************************/ + +acpi_status +acpi_os_purge_cache ( + struct acpi_memory_list *cache) +{ + char *next; + + + ACPI_FUNCTION_ENTRY (); + + + if (!cache) { + return (AE_BAD_PARAMETER); + } + + /* Walk the list of objects in this cache */ + + while (cache->list_head) { + /* Delete and unlink one cached state object */ + + next = *(ACPI_CAST_INDIRECT_PTR (char, + &(((char *) cache->list_head)[cache->link_offset]))); + ACPI_MEM_FREE (cache->list_head); + + cache->list_head = next; + cache->current_depth--; + } + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: acpi_os_delete_cache + * + * PARAMETERS: Cache - Handle to cache object + * + * RETURN: Status + * + * DESCRIPTION: Free all objects within the requested cache and delete the + * cache object. + * + ******************************************************************************/ + +acpi_status +acpi_os_delete_cache ( + struct acpi_memory_list *cache) +{ + acpi_status status; + + + ACPI_FUNCTION_ENTRY (); + + + /* Purge all objects in the cache */ + + status = acpi_os_purge_cache (cache); + if (ACPI_FAILURE (status)) { + return (status); + } + + /* Now we can delete the cache object */ + + acpi_os_free (cache); + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: acpi_os_release_object + * + * PARAMETERS: Cache - Handle to cache object + * Object - The object to be released + * + * RETURN: None + * + * DESCRIPTION: Release an object to the specified cache. If cache is full, + * the object is deleted. + * + ******************************************************************************/ + +acpi_status +acpi_os_release_object ( + struct acpi_memory_list *cache, + void *object) +{ + acpi_status status; + + + ACPI_FUNCTION_ENTRY (); + + + if (!cache || !object) { + return (AE_BAD_PARAMETER); + } + + /* If cache is full, just free this object */ + + if (cache->current_depth >= cache->max_depth) { + ACPI_MEM_FREE (object); + ACPI_MEM_TRACKING (cache->total_freed++); + } + + /* Otherwise put this object back into the cache */ + + else { + status = acpi_ut_acquire_mutex (ACPI_MTX_CACHES); + if (ACPI_FAILURE (status)) { + return (status); + } + + /* Mark the object as cached */ + + ACPI_MEMSET (object, 0xCA, cache->object_size); + ACPI_SET_DESCRIPTOR_TYPE (object, ACPI_DESC_TYPE_CACHED); + + /* Put the object at the head of the cache list */ + + * (ACPI_CAST_INDIRECT_PTR (char, + &(((char *) object)[cache->link_offset]))) = cache->list_head; + cache->list_head = object; + cache->current_depth++; + + (void) acpi_ut_release_mutex (ACPI_MTX_CACHES); + } + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: acpi_os_acquire_object + * + * PARAMETERS: Cache - Handle to cache object + * + * RETURN: the acquired object. NULL on error + * + * DESCRIPTION: Get an object from the specified cache. If cache is empty, + * the object is allocated. + * + ******************************************************************************/ + +void * +acpi_os_acquire_object ( + struct acpi_memory_list *cache) +{ + acpi_status status; + void *object; + + + ACPI_FUNCTION_NAME ("os_acquire_object"); + + + if (!cache) { + return (NULL); + } + + status = acpi_ut_acquire_mutex (ACPI_MTX_CACHES); + if (ACPI_FAILURE (status)) { + return (NULL); + } + + ACPI_MEM_TRACKING (cache->requests++); + + /* Check the cache first */ + + if (cache->list_head) { + /* There is an object available, use it */ + + object = cache->list_head; + cache->list_head = *(ACPI_CAST_INDIRECT_PTR (char, + &(((char *) object)[cache->link_offset]))); + + cache->current_depth--; + + ACPI_MEM_TRACKING (cache->hits++); + ACPI_MEM_TRACKING (ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, + "Object %p from %s cache\n", object, cache->list_name))); + + status = acpi_ut_release_mutex (ACPI_MTX_CACHES); + if (ACPI_FAILURE (status)) { + return (NULL); + } + + /* Clear (zero) the previously used Object */ + + ACPI_MEMSET (object, 0, cache->object_size); + } + else { + /* The cache is empty, create a new object */ + + ACPI_MEM_TRACKING (cache->total_allocated++); + + /* Avoid deadlock with ACPI_MEM_CALLOCATE */ + + status = acpi_ut_release_mutex (ACPI_MTX_CACHES); + if (ACPI_FAILURE (status)) { + return (NULL); + } + + object = ACPI_MEM_CALLOCATE (cache->object_size); + if (!object) { + return (NULL); + } + } + + return (object); +} +#endif /* ACPI_USE_LOCAL_CACHE */ + + diff --git a/drivers/acpi/utilities/utcopy.c b/drivers/acpi/utilities/utcopy.c index 11e88495716..31c30a32e5c 100644 --- a/drivers/acpi/utilities/utcopy.c +++ b/drivers/acpi/utilities/utcopy.c @@ -694,58 +694,50 @@ acpi_ut_copy_simple_object ( dest_desc->common.reference_count = reference_count; dest_desc->common.next_object = next_object; + /* New object is not static, regardless of source */ + + dest_desc->common.flags &= ~AOPOBJ_STATIC_POINTER; + /* Handle the objects with extra data */ switch (ACPI_GET_OBJECT_TYPE (dest_desc)) { case ACPI_TYPE_BUFFER: - - dest_desc->buffer.node = NULL; - dest_desc->common.flags = source_desc->common.flags; - /* * Allocate and copy the actual buffer if and only if: * 1) There is a valid buffer pointer - * 2) The buffer is not static (not in an ACPI table) (in this case, - * the actual pointer was already copied above) + * 2) The buffer has a length > 0 */ if ((source_desc->buffer.pointer) && - (!(source_desc->common.flags & AOPOBJ_STATIC_POINTER))) { - dest_desc->buffer.pointer = NULL; - - /* Create an actual buffer only if length > 0 */ - - if (source_desc->buffer.length) { - dest_desc->buffer.pointer = - ACPI_MEM_ALLOCATE (source_desc->buffer.length); - if (!dest_desc->buffer.pointer) { - return (AE_NO_MEMORY); - } + (source_desc->buffer.length)) { + dest_desc->buffer.pointer = + ACPI_MEM_ALLOCATE (source_desc->buffer.length); + if (!dest_desc->buffer.pointer) { + return (AE_NO_MEMORY); + } - /* Copy the actual buffer data */ + /* Copy the actual buffer data */ - ACPI_MEMCPY (dest_desc->buffer.pointer, - source_desc->buffer.pointer, - source_desc->buffer.length); - } + ACPI_MEMCPY (dest_desc->buffer.pointer, + source_desc->buffer.pointer, + source_desc->buffer.length); } break; case ACPI_TYPE_STRING: - /* * Allocate and copy the actual string if and only if: * 1) There is a valid string pointer - * 2) The string is not static (not in an ACPI table) (in this case, - * the actual pointer was already copied above) + * (Pointer to a NULL string is allowed) */ - if ((source_desc->string.pointer) && - (!(source_desc->common.flags & AOPOBJ_STATIC_POINTER))) { + if (source_desc->string.pointer) { dest_desc->string.pointer = ACPI_MEM_ALLOCATE ((acpi_size) source_desc->string.length + 1); if (!dest_desc->string.pointer) { return (AE_NO_MEMORY); } + /* Copy the actual string data */ + ACPI_MEMCPY (dest_desc->string.pointer, source_desc->string.pointer, (acpi_size) source_desc->string.length + 1); } diff --git a/drivers/acpi/utilities/utdebug.c b/drivers/acpi/utilities/utdebug.c index 794c7df3f2a..c27cbb7f5c5 100644 --- a/drivers/acpi/utilities/utdebug.c +++ b/drivers/acpi/utilities/utdebug.c @@ -55,6 +55,12 @@ static u32 acpi_gbl_prev_thread_id = 0xFFFFFFFF; static char *acpi_gbl_fn_entry_str = "----Entry"; static char *acpi_gbl_fn_exit_str = "----Exit-"; +/* Local prototypes */ + +static const char * +acpi_ut_trim_function_name ( + const char *function_name); + /******************************************************************************* * @@ -72,7 +78,7 @@ void acpi_ut_init_stack_ptr_trace ( void) { - u32 current_sp; + u32 current_sp; acpi_gbl_entry_stack_pointer = ACPI_PTR_DIFF (¤t_sp, NULL); @@ -95,7 +101,7 @@ void acpi_ut_track_stack_ptr ( void) { - acpi_size current_sp; + acpi_size current_sp; current_sp = ACPI_PTR_DIFF (¤t_sp, NULL); @@ -112,14 +118,50 @@ acpi_ut_track_stack_ptr ( /******************************************************************************* * + * FUNCTION: acpi_ut_trim_function_name + * + * PARAMETERS: function_name - Ascii string containing a procedure name + * + * RETURN: Updated pointer to the function name + * + * DESCRIPTION: Remove the "Acpi" prefix from the function name, if present. + * This allows compiler macros such as __FUNCTION__ to be used + * with no change to the debug output. + * + ******************************************************************************/ + +static const char * +acpi_ut_trim_function_name ( + const char *function_name) +{ + + /* All Function names are longer than 4 chars, check is safe */ + + if (*(ACPI_CAST_PTR (u32, function_name)) == ACPI_FUNCTION_PREFIX1) { + /* This is the case where the original source has not been modified */ + + return (function_name + 4); + } + + if (*(ACPI_CAST_PTR (u32, function_name)) == ACPI_FUNCTION_PREFIX2) { + /* This is the case where the source has been 'linuxized' */ + + return (function_name + 5); + } + + return (function_name); +} + + +/******************************************************************************* + * * FUNCTION: acpi_ut_debug_print * * PARAMETERS: requested_debug_level - Requested debug print level * line_number - Caller's line number (for error output) - * dbg_info - Contains: - * proc_name - Caller's procedure name - * module_name - Caller's module name - * component_id - Caller's component ID + * function_name - Caller's procedure name + * module_name - Caller's module name + * component_id - Caller's component ID * Format - Printf format field * ... - Optional printf arguments * @@ -134,7 +176,9 @@ void ACPI_INTERNAL_VAR_XFACE acpi_ut_debug_print ( u32 requested_debug_level, u32 line_number, - struct acpi_debug_print_info *dbg_info, + const char *function_name, + char *module_name, + u32 component_id, char *format, ...) { @@ -146,7 +190,7 @@ acpi_ut_debug_print ( * Stay silent if the debug level or component ID is disabled */ if (!(requested_debug_level & acpi_dbg_level) || - !(dbg_info->component_id & acpi_dbg_layer)) { + !(component_id & acpi_dbg_layer)) { return; } @@ -169,14 +213,14 @@ acpi_ut_debug_print ( * Display the module name, current line number, thread ID (if requested), * current procedure nesting level, and the current procedure name */ - acpi_os_printf ("%8s-%04ld ", dbg_info->module_name, line_number); + acpi_os_printf ("%8s-%04ld ", module_name, line_number); if (ACPI_LV_THREADS & acpi_dbg_level) { acpi_os_printf ("[%04lX] ", thread_id); } acpi_os_printf ("[%02ld] %-22.22s: ", - acpi_gbl_nesting_level, dbg_info->proc_name); + acpi_gbl_nesting_level, acpi_ut_trim_function_name (function_name)); va_start (args, format); acpi_os_vprintf (format, args); @@ -190,10 +234,9 @@ EXPORT_SYMBOL(acpi_ut_debug_print); * * PARAMETERS: requested_debug_level - Requested debug print level * line_number - Caller's line number - * dbg_info - Contains: - * proc_name - Caller's procedure name - * module_name - Caller's module name - * component_id - Caller's component ID + * function_name - Caller's procedure name + * module_name - Caller's module name + * component_id - Caller's component ID * Format - Printf format field * ... - Optional printf arguments * @@ -208,7 +251,9 @@ void ACPI_INTERNAL_VAR_XFACE acpi_ut_debug_print_raw ( u32 requested_debug_level, u32 line_number, - struct acpi_debug_print_info *dbg_info, + const char *function_name, + char *module_name, + u32 component_id, char *format, ...) { @@ -216,7 +261,7 @@ acpi_ut_debug_print_raw ( if (!(requested_debug_level & acpi_dbg_level) || - !(dbg_info->component_id & acpi_dbg_layer)) { + !(component_id & acpi_dbg_layer)) { return; } @@ -231,10 +276,9 @@ EXPORT_SYMBOL(acpi_ut_debug_print_raw); * FUNCTION: acpi_ut_trace * * PARAMETERS: line_number - Caller's line number - * dbg_info - Contains: - * proc_name - Caller's procedure name - * module_name - Caller's module name - * component_id - Caller's component ID + * function_name - Caller's procedure name + * module_name - Caller's module name + * component_id - Caller's component ID * * RETURN: None * @@ -246,14 +290,17 @@ EXPORT_SYMBOL(acpi_ut_debug_print_raw); void acpi_ut_trace ( u32 line_number, - struct acpi_debug_print_info *dbg_info) + const char *function_name, + char *module_name, + u32 component_id) { acpi_gbl_nesting_level++; acpi_ut_track_stack_ptr (); - acpi_ut_debug_print (ACPI_LV_FUNCTIONS, line_number, dbg_info, - "%s\n", acpi_gbl_fn_entry_str); + acpi_ut_debug_print (ACPI_LV_FUNCTIONS, + line_number, function_name, module_name, component_id, + "%s\n", acpi_gbl_fn_entry_str); } EXPORT_SYMBOL(acpi_ut_trace); @@ -263,10 +310,9 @@ EXPORT_SYMBOL(acpi_ut_trace); * FUNCTION: acpi_ut_trace_ptr * * PARAMETERS: line_number - Caller's line number - * dbg_info - Contains: - * proc_name - Caller's procedure name - * module_name - Caller's module name - * component_id - Caller's component ID + * function_name - Caller's procedure name + * module_name - Caller's module name + * component_id - Caller's component ID * Pointer - Pointer to display * * RETURN: None @@ -279,14 +325,17 @@ EXPORT_SYMBOL(acpi_ut_trace); void acpi_ut_trace_ptr ( u32 line_number, - struct acpi_debug_print_info *dbg_info, + const char *function_name, + char *module_name, + u32 component_id, void *pointer) { acpi_gbl_nesting_level++; acpi_ut_track_stack_ptr (); - acpi_ut_debug_print (ACPI_LV_FUNCTIONS, line_number, dbg_info, - "%s %p\n", acpi_gbl_fn_entry_str, pointer); + acpi_ut_debug_print (ACPI_LV_FUNCTIONS, + line_number, function_name, module_name, component_id, + "%s %p\n", acpi_gbl_fn_entry_str, pointer); } @@ -295,10 +344,9 @@ acpi_ut_trace_ptr ( * FUNCTION: acpi_ut_trace_str * * PARAMETERS: line_number - Caller's line number - * dbg_info - Contains: - * proc_name - Caller's procedure name - * module_name - Caller's module name - * component_id - Caller's component ID + * function_name - Caller's procedure name + * module_name - Caller's module name + * component_id - Caller's component ID * String - Additional string to display * * RETURN: None @@ -311,15 +359,18 @@ acpi_ut_trace_ptr ( void acpi_ut_trace_str ( u32 line_number, - struct acpi_debug_print_info *dbg_info, + const char *function_name, + char *module_name, + u32 component_id, char *string) { acpi_gbl_nesting_level++; acpi_ut_track_stack_ptr (); - acpi_ut_debug_print (ACPI_LV_FUNCTIONS, line_number, dbg_info, - "%s %s\n", acpi_gbl_fn_entry_str, string); + acpi_ut_debug_print (ACPI_LV_FUNCTIONS, + line_number, function_name, module_name, component_id, + "%s %s\n", acpi_gbl_fn_entry_str, string); } @@ -328,10 +379,9 @@ acpi_ut_trace_str ( * FUNCTION: acpi_ut_trace_u32 * * PARAMETERS: line_number - Caller's line number - * dbg_info - Contains: - * proc_name - Caller's procedure name - * module_name - Caller's module name - * component_id - Caller's component ID + * function_name - Caller's procedure name + * module_name - Caller's module name + * component_id - Caller's component ID * Integer - Integer to display * * RETURN: None @@ -344,15 +394,18 @@ acpi_ut_trace_str ( void acpi_ut_trace_u32 ( u32 line_number, - struct acpi_debug_print_info *dbg_info, + const char *function_name, + char *module_name, + u32 component_id, u32 integer) { acpi_gbl_nesting_level++; acpi_ut_track_stack_ptr (); - acpi_ut_debug_print (ACPI_LV_FUNCTIONS, line_number, dbg_info, - "%s %08X\n", acpi_gbl_fn_entry_str, integer); + acpi_ut_debug_print (ACPI_LV_FUNCTIONS, + line_number, function_name, module_name, component_id, + "%s %08X\n", acpi_gbl_fn_entry_str, integer); } @@ -361,10 +414,9 @@ acpi_ut_trace_u32 ( * FUNCTION: acpi_ut_exit * * PARAMETERS: line_number - Caller's line number - * dbg_info - Contains: - * proc_name - Caller's procedure name - * module_name - Caller's module name - * component_id - Caller's component ID + * function_name - Caller's procedure name + * module_name - Caller's module name + * component_id - Caller's component ID * * RETURN: None * @@ -376,11 +428,14 @@ acpi_ut_trace_u32 ( void acpi_ut_exit ( u32 line_number, - struct acpi_debug_print_info *dbg_info) + const char *function_name, + char *module_name, + u32 component_id) { - acpi_ut_debug_print (ACPI_LV_FUNCTIONS, line_number, dbg_info, - "%s\n", acpi_gbl_fn_exit_str); + acpi_ut_debug_print (ACPI_LV_FUNCTIONS, + line_number, function_name, module_name, component_id, + "%s\n", acpi_gbl_fn_exit_str); acpi_gbl_nesting_level--; } @@ -392,10 +447,9 @@ EXPORT_SYMBOL(acpi_ut_exit); * FUNCTION: acpi_ut_status_exit * * PARAMETERS: line_number - Caller's line number - * dbg_info - Contains: - * proc_name - Caller's procedure name - * module_name - Caller's module name - * component_id - Caller's component ID + * function_name - Caller's procedure name + * module_name - Caller's module name + * component_id - Caller's component ID * Status - Exit status code * * RETURN: None @@ -408,19 +462,23 @@ EXPORT_SYMBOL(acpi_ut_exit); void acpi_ut_status_exit ( u32 line_number, - struct acpi_debug_print_info *dbg_info, + const char *function_name, + char *module_name, + u32 component_id, acpi_status status) { if (ACPI_SUCCESS (status)) { - acpi_ut_debug_print (ACPI_LV_FUNCTIONS, line_number, dbg_info, - "%s %s\n", acpi_gbl_fn_exit_str, - acpi_format_exception (status)); + acpi_ut_debug_print (ACPI_LV_FUNCTIONS, + line_number, function_name, module_name, component_id, + "%s %s\n", acpi_gbl_fn_exit_str, + acpi_format_exception (status)); } else { - acpi_ut_debug_print (ACPI_LV_FUNCTIONS, line_number, dbg_info, - "%s ****Exception****: %s\n", acpi_gbl_fn_exit_str, - acpi_format_exception (status)); + acpi_ut_debug_print (ACPI_LV_FUNCTIONS, + line_number, function_name, module_name, component_id, + "%s ****Exception****: %s\n", acpi_gbl_fn_exit_str, + acpi_format_exception (status)); } acpi_gbl_nesting_level--; @@ -433,10 +491,9 @@ EXPORT_SYMBOL(acpi_ut_status_exit); * FUNCTION: acpi_ut_value_exit * * PARAMETERS: line_number - Caller's line number - * dbg_info - Contains: - * proc_name - Caller's procedure name - * module_name - Caller's module name - * component_id - Caller's component ID + * function_name - Caller's procedure name + * module_name - Caller's module name + * component_id - Caller's component ID * Value - Value to be printed with exit msg * * RETURN: None @@ -449,13 +506,16 @@ EXPORT_SYMBOL(acpi_ut_status_exit); void acpi_ut_value_exit ( u32 line_number, - struct acpi_debug_print_info *dbg_info, + const char *function_name, + char *module_name, + u32 component_id, acpi_integer value) { - acpi_ut_debug_print (ACPI_LV_FUNCTIONS, line_number, dbg_info, - "%s %8.8X%8.8X\n", acpi_gbl_fn_exit_str, - ACPI_FORMAT_UINT64 (value)); + acpi_ut_debug_print (ACPI_LV_FUNCTIONS, + line_number, function_name, module_name, component_id, + "%s %8.8X%8.8X\n", acpi_gbl_fn_exit_str, + ACPI_FORMAT_UINT64 (value)); acpi_gbl_nesting_level--; } @@ -467,10 +527,9 @@ EXPORT_SYMBOL(acpi_ut_value_exit); * FUNCTION: acpi_ut_ptr_exit * * PARAMETERS: line_number - Caller's line number - * dbg_info - Contains: - * proc_name - Caller's procedure name - * module_name - Caller's module name - * component_id - Caller's component ID + * function_name - Caller's procedure name + * module_name - Caller's module name + * component_id - Caller's component ID * Ptr - Pointer to display * * RETURN: None @@ -483,12 +542,15 @@ EXPORT_SYMBOL(acpi_ut_value_exit); void acpi_ut_ptr_exit ( u32 line_number, - struct acpi_debug_print_info *dbg_info, + const char *function_name, + char *module_name, + u32 component_id, u8 *ptr) { - acpi_ut_debug_print (ACPI_LV_FUNCTIONS, line_number, dbg_info, - "%s %p\n", acpi_gbl_fn_exit_str, ptr); + acpi_ut_debug_print (ACPI_LV_FUNCTIONS, + line_number, function_name, module_name, component_id, + "%s %p\n", acpi_gbl_fn_exit_str, ptr); acpi_gbl_nesting_level--; } @@ -549,7 +611,7 @@ acpi_ut_dump_buffer ( /* Dump fill spaces */ acpi_os_printf ("%*s", ((display * 2) + 1), " "); - j += display; + j += (acpi_native_uint) display; continue; } @@ -584,12 +646,12 @@ acpi_ut_dump_buffer ( break; } - j += display; + j += (acpi_native_uint) display; } /* - * Print the ASCII equivalent characters - * But watch out for the bad unprintable ones... + * Print the ASCII equivalent characters but watch out for the bad + * unprintable ones (printable chars are 0x20 through 0x7E) */ acpi_os_printf (" "); for (j = 0; j < 16; j++) { @@ -599,9 +661,7 @@ acpi_ut_dump_buffer ( } buf_char = buffer[i + j]; - if ((buf_char > 0x1F && buf_char < 0x2E) || - (buf_char > 0x2F && buf_char < 0x61) || - (buf_char > 0x60 && buf_char < 0x7F)) { + if (ACPI_IS_PRINT (buf_char)) { acpi_os_printf ("%c", buf_char); } else { diff --git a/drivers/acpi/utilities/utdelete.c b/drivers/acpi/utilities/utdelete.c index bc540302268..eeafb324c50 100644 --- a/drivers/acpi/utilities/utdelete.c +++ b/drivers/acpi/utilities/utdelete.c @@ -435,35 +435,24 @@ acpi_ut_update_object_reference ( union acpi_operand_object *object, u16 action) { - acpi_status status; - u32 i; - union acpi_generic_state *state_list = NULL; - union acpi_generic_state *state; - union acpi_operand_object *tmp; - - ACPI_FUNCTION_TRACE_PTR ("ut_update_object_reference", object); + acpi_status status = AE_OK; + union acpi_generic_state *state_list = NULL; + union acpi_operand_object *next_object = NULL; + union acpi_generic_state *state; + acpi_native_uint i; - /* Ignore a null object ptr */ - - if (!object) { - return_ACPI_STATUS (AE_OK); - } + ACPI_FUNCTION_TRACE_PTR ("ut_update_object_reference", object); - /* Make sure that this isn't a namespace handle */ - if (ACPI_GET_DESCRIPTOR_TYPE (object) == ACPI_DESC_TYPE_NAMED) { - ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, - "Object %p is NS handle\n", object)); - return_ACPI_STATUS (AE_OK); - } + while (object) { + /* Make sure that this isn't a namespace handle */ - state = acpi_ut_create_update_state (object, action); - - while (state) { - object = state->update.object; - action = state->update.value; - acpi_ut_delete_generic_state (state); + if (ACPI_GET_DESCRIPTOR_TYPE (object) == ACPI_DESC_TYPE_NAMED) { + ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, + "Object %p is NS handle\n", object)); + return_ACPI_STATUS (AE_OK); + } /* * All sub-objects must have their reference count incremented also. @@ -472,24 +461,14 @@ acpi_ut_update_object_reference ( switch (ACPI_GET_OBJECT_TYPE (object)) { case ACPI_TYPE_DEVICE: - tmp = object->device.system_notify; - if (tmp && (tmp->common.reference_count <= 1) && action == REF_DECREMENT) - object->device.system_notify = NULL; - acpi_ut_update_ref_count (tmp, action); - - tmp = object->device.device_notify; - if (tmp && (tmp->common.reference_count <= 1) && action == REF_DECREMENT) - object->device.device_notify = NULL; - acpi_ut_update_ref_count (tmp, action); - + acpi_ut_update_ref_count (object->device.system_notify, action); + acpi_ut_update_ref_count (object->device.device_notify, action); break; - case ACPI_TYPE_PACKAGE: - /* - * We must update all the sub-objects of the package - * (Each of whom may have their own sub-objects, etc. + * We must update all the sub-objects of the package, + * each of whom may have their own sub-objects. */ for (i = 0; i < object->package.count; i++) { /* @@ -502,111 +481,52 @@ acpi_ut_update_object_reference ( if (ACPI_FAILURE (status)) { goto error_exit; } - - tmp = object->package.elements[i]; - if (tmp && (tmp->common.reference_count <= 1) && action == REF_DECREMENT) - object->package.elements[i] = NULL; } break; - case ACPI_TYPE_BUFFER_FIELD: - status = acpi_ut_create_update_state_and_push ( - object->buffer_field.buffer_obj, action, &state_list); - if (ACPI_FAILURE (status)) { - goto error_exit; - } - - tmp = object->buffer_field.buffer_obj; - if ( tmp && (tmp->common.reference_count <= 1) && action == REF_DECREMENT) - object->buffer_field.buffer_obj = NULL; + next_object = object->buffer_field.buffer_obj; break; - case ACPI_TYPE_LOCAL_REGION_FIELD: - status = acpi_ut_create_update_state_and_push ( - object->field.region_obj, action, &state_list); - if (ACPI_FAILURE (status)) { - goto error_exit; - } - - tmp = object->field.region_obj; - if ( tmp && (tmp->common.reference_count <= 1) && action == REF_DECREMENT) - object->field.region_obj = NULL; - break; - + next_object = object->field.region_obj; + break; case ACPI_TYPE_LOCAL_BANK_FIELD: - status = acpi_ut_create_update_state_and_push ( - object->bank_field.bank_obj, action, &state_list); - if (ACPI_FAILURE (status)) { - goto error_exit; - } - - tmp = object->bank_field.bank_obj; - if ( tmp && (tmp->common.reference_count <= 1) && action == REF_DECREMENT) - object->bank_field.bank_obj = NULL; - + next_object = object->bank_field.bank_obj; status = acpi_ut_create_update_state_and_push ( object->bank_field.region_obj, action, &state_list); if (ACPI_FAILURE (status)) { goto error_exit; } - - tmp = object->bank_field.region_obj; - if ( tmp && (tmp->common.reference_count <= 1) && action == REF_DECREMENT) - object->bank_field.region_obj = NULL; break; - case ACPI_TYPE_LOCAL_INDEX_FIELD: - status = acpi_ut_create_update_state_and_push ( - object->index_field.index_obj, action, &state_list); - if (ACPI_FAILURE (status)) { - goto error_exit; - } - - tmp = object->index_field.index_obj; - if ( tmp && (tmp->common.reference_count <= 1) && action == REF_DECREMENT) - object->index_field.index_obj = NULL; - + next_object = object->index_field.index_obj; status = acpi_ut_create_update_state_and_push ( object->index_field.data_obj, action, &state_list); if (ACPI_FAILURE (status)) { goto error_exit; } - - tmp = object->index_field.data_obj; - if ( tmp && (tmp->common.reference_count <= 1) && action == REF_DECREMENT) - object->index_field.data_obj = NULL; break; - case ACPI_TYPE_LOCAL_REFERENCE: - /* * The target of an Index (a package, string, or buffer) must track * changes to the ref count of the index. */ if (object->reference.opcode == AML_INDEX_OP) { - status = acpi_ut_create_update_state_and_push ( - object->reference.object, action, &state_list); - if (ACPI_FAILURE (status)) { - goto error_exit; - } + next_object = object->reference.object; } break; - case ACPI_TYPE_REGION: default: - - /* No subobjects */ - break; + break;/* No subobjects */ } /* @@ -615,15 +535,23 @@ acpi_ut_update_object_reference ( * main object to be deleted. */ acpi_ut_update_ref_count (object, action); + object = NULL; /* Move on to the next object to be updated */ - state = acpi_ut_pop_generic_state (&state_list); + if (next_object) { + object = next_object; + next_object = NULL; + } + else if (state_list) { + state = acpi_ut_pop_generic_state (&state_list); + object = state->update.object; + acpi_ut_delete_generic_state (state); + } } return_ACPI_STATUS (AE_OK); - error_exit: ACPI_REPORT_ERROR (("Could not update object reference count, %s\n", diff --git a/drivers/acpi/utilities/utglobal.c b/drivers/acpi/utilities/utglobal.c index 4146019b543..0e4161c8107 100644 --- a/drivers/acpi/utilities/utglobal.c +++ b/drivers/acpi/utilities/utglobal.c @@ -738,73 +738,6 @@ acpi_ut_valid_object_type ( /******************************************************************************* * - * FUNCTION: acpi_ut_allocate_owner_id - * - * PARAMETERS: id_type - Type of ID (method or table) - * - * DESCRIPTION: Allocate a table or method owner id - * - * NOTE: this algorithm has a wraparound problem at 64_k method invocations, and - * should be revisited (TBD) - * - ******************************************************************************/ - -acpi_owner_id -acpi_ut_allocate_owner_id ( - u32 id_type) -{ - acpi_owner_id owner_id = 0xFFFF; - - - ACPI_FUNCTION_TRACE ("ut_allocate_owner_id"); - - - if (ACPI_FAILURE (acpi_ut_acquire_mutex (ACPI_MTX_CACHES))) - { - return (0); - } - - switch (id_type) - { - case ACPI_OWNER_TYPE_TABLE: - - owner_id = acpi_gbl_next_table_owner_id; - acpi_gbl_next_table_owner_id++; - - /* Check for wraparound */ - - if (acpi_gbl_next_table_owner_id == ACPI_FIRST_METHOD_ID) - { - acpi_gbl_next_table_owner_id = ACPI_FIRST_TABLE_ID; - ACPI_REPORT_WARNING (("Table owner ID wraparound\n")); - } - break; - - - case ACPI_OWNER_TYPE_METHOD: - - owner_id = acpi_gbl_next_method_owner_id; - acpi_gbl_next_method_owner_id++; - - if (acpi_gbl_next_method_owner_id == ACPI_FIRST_TABLE_ID) - { - /* Check for wraparound */ - - acpi_gbl_next_method_owner_id = ACPI_FIRST_METHOD_ID; - } - break; - - default: - break; - } - - (void) acpi_ut_release_mutex (ACPI_MTX_CACHES); - return_VALUE (owner_id); -} - - -/******************************************************************************* - * * FUNCTION: acpi_ut_init_globals * * PARAMETERS: None @@ -820,42 +753,20 @@ void acpi_ut_init_globals ( void) { + acpi_status status; u32 i; ACPI_FUNCTION_TRACE ("ut_init_globals"); - /* Memory allocation and cache lists */ - - ACPI_MEMSET (acpi_gbl_memory_lists, 0, sizeof (struct acpi_memory_list) * ACPI_NUM_MEM_LISTS); + /* Create all memory caches */ - acpi_gbl_memory_lists[ACPI_MEM_LIST_STATE].link_offset = (u16) ACPI_PTR_DIFF (&(((union acpi_generic_state *) NULL)->common.next), NULL); - acpi_gbl_memory_lists[ACPI_MEM_LIST_PSNODE].link_offset = (u16) ACPI_PTR_DIFF (&(((union acpi_parse_object *) NULL)->common.next), NULL); - acpi_gbl_memory_lists[ACPI_MEM_LIST_PSNODE_EXT].link_offset = (u16) ACPI_PTR_DIFF (&(((union acpi_parse_object *) NULL)->common.next), NULL); - acpi_gbl_memory_lists[ACPI_MEM_LIST_OPERAND].link_offset = (u16) ACPI_PTR_DIFF (&(((union acpi_operand_object *) NULL)->cache.next), NULL); - acpi_gbl_memory_lists[ACPI_MEM_LIST_WALK].link_offset = (u16) ACPI_PTR_DIFF (&(((struct acpi_walk_state *) NULL)->next), NULL); - - acpi_gbl_memory_lists[ACPI_MEM_LIST_NSNODE].object_size = sizeof (struct acpi_namespace_node); - acpi_gbl_memory_lists[ACPI_MEM_LIST_STATE].object_size = sizeof (union acpi_generic_state); - acpi_gbl_memory_lists[ACPI_MEM_LIST_PSNODE].object_size = sizeof (struct acpi_parse_obj_common); - acpi_gbl_memory_lists[ACPI_MEM_LIST_PSNODE_EXT].object_size = sizeof (struct acpi_parse_obj_named); - acpi_gbl_memory_lists[ACPI_MEM_LIST_OPERAND].object_size = sizeof (union acpi_operand_object); - acpi_gbl_memory_lists[ACPI_MEM_LIST_WALK].object_size = sizeof (struct acpi_walk_state); - - acpi_gbl_memory_lists[ACPI_MEM_LIST_STATE].max_cache_depth = ACPI_MAX_STATE_CACHE_DEPTH; - acpi_gbl_memory_lists[ACPI_MEM_LIST_PSNODE].max_cache_depth = ACPI_MAX_PARSE_CACHE_DEPTH; - acpi_gbl_memory_lists[ACPI_MEM_LIST_PSNODE_EXT].max_cache_depth = ACPI_MAX_EXTPARSE_CACHE_DEPTH; - acpi_gbl_memory_lists[ACPI_MEM_LIST_OPERAND].max_cache_depth = ACPI_MAX_OBJECT_CACHE_DEPTH; - acpi_gbl_memory_lists[ACPI_MEM_LIST_WALK].max_cache_depth = ACPI_MAX_WALK_CACHE_DEPTH; - - ACPI_MEM_TRACKING (acpi_gbl_memory_lists[ACPI_MEM_LIST_GLOBAL].list_name = "Global Memory Allocation"); - ACPI_MEM_TRACKING (acpi_gbl_memory_lists[ACPI_MEM_LIST_NSNODE].list_name = "Namespace Nodes"); - ACPI_MEM_TRACKING (acpi_gbl_memory_lists[ACPI_MEM_LIST_STATE].list_name = "State Object Cache"); - ACPI_MEM_TRACKING (acpi_gbl_memory_lists[ACPI_MEM_LIST_PSNODE].list_name = "Parse Node Cache"); - ACPI_MEM_TRACKING (acpi_gbl_memory_lists[ACPI_MEM_LIST_PSNODE_EXT].list_name = "Extended Parse Node Cache"); - ACPI_MEM_TRACKING (acpi_gbl_memory_lists[ACPI_MEM_LIST_OPERAND].list_name = "Operand Object Cache"); - ACPI_MEM_TRACKING (acpi_gbl_memory_lists[ACPI_MEM_LIST_WALK].list_name = "Tree Walk Node Cache"); + status = acpi_ut_create_caches (); + if (ACPI_FAILURE (status)) + { + return; + } /* ACPI table structure */ @@ -870,7 +781,7 @@ acpi_ut_init_globals ( for (i = 0; i < NUM_MUTEX; i++) { acpi_gbl_mutex_info[i].mutex = NULL; - acpi_gbl_mutex_info[i].owner_id = ACPI_MUTEX_NOT_ACQUIRED; + acpi_gbl_mutex_info[i].thread_id = ACPI_MUTEX_NOT_ACQUIRED; acpi_gbl_mutex_info[i].use_count = 0; } @@ -911,8 +822,7 @@ acpi_ut_init_globals ( acpi_gbl_ns_lookup_count = 0; acpi_gbl_ps_find_count = 0; acpi_gbl_acpi_hardware_present = TRUE; - acpi_gbl_next_table_owner_id = ACPI_FIRST_TABLE_ID; - acpi_gbl_next_method_owner_id = ACPI_FIRST_METHOD_ID; + acpi_gbl_owner_id_mask = 0; acpi_gbl_debugger_configuration = DEBUGGER_THREADING; acpi_gbl_db_output_flags = ACPI_DB_CONSOLE_OUTPUT; diff --git a/drivers/acpi/utilities/utinit.c b/drivers/acpi/utilities/utinit.c index 7f3713889ff..fd7ceba8322 100644 --- a/drivers/acpi/utilities/utinit.c +++ b/drivers/acpi/utilities/utinit.c @@ -264,7 +264,7 @@ acpi_ut_subsystem_shutdown ( /* Purge the local caches */ - (void) acpi_purge_cached_objects (); + (void) acpi_ut_delete_caches (); /* Debug only - display leftover memory allocation, if any */ diff --git a/drivers/acpi/utilities/utmisc.c b/drivers/acpi/utilities/utmisc.c index f6de4ed3d52..1d350b302a3 100644 --- a/drivers/acpi/utilities/utmisc.c +++ b/drivers/acpi/utilities/utmisc.c @@ -49,15 +49,121 @@ #define _COMPONENT ACPI_UTILITIES ACPI_MODULE_NAME ("utmisc") -/* Local prototypes */ -static acpi_status -acpi_ut_create_mutex ( - acpi_mutex_handle mutex_id); +/******************************************************************************* + * + * FUNCTION: acpi_ut_allocate_owner_id + * + * PARAMETERS: owner_id - Where the new owner ID is returned + * + * RETURN: Status + * + * DESCRIPTION: Allocate a table or method owner ID. The owner ID is used to + * track objects created by the table or method, to be deleted + * when the method exits or the table is unloaded. + * + ******************************************************************************/ + +acpi_status +acpi_ut_allocate_owner_id ( + acpi_owner_id *owner_id) +{ + acpi_native_uint i; + acpi_status status; + + + ACPI_FUNCTION_TRACE ("ut_allocate_owner_id"); -static acpi_status -acpi_ut_delete_mutex ( - acpi_mutex_handle mutex_id); + + /* Mutex for the global ID mask */ + + status = acpi_ut_acquire_mutex (ACPI_MTX_CACHES); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } + + /* Find a free owner ID */ + + for (i = 0; i < 32; i++) { + if (!(acpi_gbl_owner_id_mask & (1 << i))) { + acpi_gbl_owner_id_mask |= (1 << i); + *owner_id = (acpi_owner_id) (i + 1); + goto exit; + } + } + + /* + * If we are here, all owner_ids have been allocated. This probably should + * not happen since the IDs are reused after deallocation. The IDs are + * allocated upon table load (one per table) and method execution, and + * they are released when a table is unloaded or a method completes + * execution. + */ + *owner_id = 0; + status = AE_OWNER_ID_LIMIT; + ACPI_REPORT_ERROR (( + "Could not allocate new owner_id (32 max), AE_OWNER_ID_LIMIT\n")); + +exit: + (void) acpi_ut_release_mutex (ACPI_MTX_CACHES); + return_ACPI_STATUS (status); +} + + +/******************************************************************************* + * + * FUNCTION: acpi_ut_release_owner_id + * + * PARAMETERS: owner_id_ptr - Pointer to a previously allocated owner_iD + * + * RETURN: None. No error is returned because we are either exiting a + * control method or unloading a table. Either way, we would + * ignore any error anyway. + * + * DESCRIPTION: Release a table or method owner ID. Valid IDs are 1 - 32 + * + ******************************************************************************/ + +void +acpi_ut_release_owner_id ( + acpi_owner_id *owner_id_ptr) +{ + acpi_owner_id owner_id = *owner_id_ptr; + acpi_status status; + + + ACPI_FUNCTION_TRACE ("ut_release_owner_id"); + + + /* Always clear the input owner_id (zero is an invalid ID) */ + + *owner_id_ptr = 0; + + /* Zero is not a valid owner_iD */ + + if ((owner_id == 0) || (owner_id > 32)) { + ACPI_REPORT_ERROR (("Invalid owner_id: %2.2X\n", owner_id)); + return_VOID; + } + + /* Mutex for the global ID mask */ + + status = acpi_ut_acquire_mutex (ACPI_MTX_CACHES); + if (ACPI_FAILURE (status)) { + return_VOID; + } + + owner_id--; /* Normalize to zero */ + + /* Free the owner ID only if it is valid */ + + if (acpi_gbl_owner_id_mask & (1 << owner_id)) { + acpi_gbl_owner_id_mask ^= (1 << owner_id); + } + + (void) acpi_ut_release_mutex (ACPI_MTX_CACHES); + return_VOID; +} /******************************************************************************* @@ -66,7 +172,7 @@ acpi_ut_delete_mutex ( * * PARAMETERS: src_string - The source string to convert * - * RETURN: Converted src_string (same as input pointer) + * RETURN: None * * DESCRIPTION: Convert string to uppercase * @@ -74,7 +180,7 @@ acpi_ut_delete_mutex ( * ******************************************************************************/ -char * +void acpi_ut_strupr ( char *src_string) { @@ -84,13 +190,17 @@ acpi_ut_strupr ( ACPI_FUNCTION_ENTRY (); + if (!src_string) { + return; + } + /* Walk entire string, uppercasing the letters */ for (string = src_string; *string; string++) { *string = (char) ACPI_TOUPPER (*string); } - return (src_string); + return; } @@ -543,320 +653,6 @@ error_exit: /******************************************************************************* * - * FUNCTION: acpi_ut_mutex_initialize - * - * PARAMETERS: None. - * - * RETURN: Status - * - * DESCRIPTION: Create the system mutex objects. - * - ******************************************************************************/ - -acpi_status -acpi_ut_mutex_initialize ( - void) -{ - u32 i; - acpi_status status; - - - ACPI_FUNCTION_TRACE ("ut_mutex_initialize"); - - - /* - * Create each of the predefined mutex objects - */ - for (i = 0; i < NUM_MUTEX; i++) { - status = acpi_ut_create_mutex (i); - if (ACPI_FAILURE (status)) { - return_ACPI_STATUS (status); - } - } - - status = acpi_os_create_lock (&acpi_gbl_gpe_lock); - return_ACPI_STATUS (status); -} - - -/******************************************************************************* - * - * FUNCTION: acpi_ut_mutex_terminate - * - * PARAMETERS: None. - * - * RETURN: None. - * - * DESCRIPTION: Delete all of the system mutex objects. - * - ******************************************************************************/ - -void -acpi_ut_mutex_terminate ( - void) -{ - u32 i; - - - ACPI_FUNCTION_TRACE ("ut_mutex_terminate"); - - - /* - * Delete each predefined mutex object - */ - for (i = 0; i < NUM_MUTEX; i++) { - (void) acpi_ut_delete_mutex (i); - } - - acpi_os_delete_lock (acpi_gbl_gpe_lock); - return_VOID; -} - - -/******************************************************************************* - * - * FUNCTION: acpi_ut_create_mutex - * - * PARAMETERS: mutex_iD - ID of the mutex to be created - * - * RETURN: Status - * - * DESCRIPTION: Create a mutex object. - * - ******************************************************************************/ - -static acpi_status -acpi_ut_create_mutex ( - acpi_mutex_handle mutex_id) -{ - acpi_status status = AE_OK; - - - ACPI_FUNCTION_TRACE_U32 ("ut_create_mutex", mutex_id); - - - if (mutex_id > MAX_MUTEX) { - return_ACPI_STATUS (AE_BAD_PARAMETER); - } - - if (!acpi_gbl_mutex_info[mutex_id].mutex) { - status = acpi_os_create_semaphore (1, 1, - &acpi_gbl_mutex_info[mutex_id].mutex); - acpi_gbl_mutex_info[mutex_id].owner_id = ACPI_MUTEX_NOT_ACQUIRED; - acpi_gbl_mutex_info[mutex_id].use_count = 0; - } - - return_ACPI_STATUS (status); -} - - -/******************************************************************************* - * - * FUNCTION: acpi_ut_delete_mutex - * - * PARAMETERS: mutex_iD - ID of the mutex to be deleted - * - * RETURN: Status - * - * DESCRIPTION: Delete a mutex object. - * - ******************************************************************************/ - -static acpi_status -acpi_ut_delete_mutex ( - acpi_mutex_handle mutex_id) -{ - acpi_status status; - - - ACPI_FUNCTION_TRACE_U32 ("ut_delete_mutex", mutex_id); - - - if (mutex_id > MAX_MUTEX) { - return_ACPI_STATUS (AE_BAD_PARAMETER); - } - - status = acpi_os_delete_semaphore (acpi_gbl_mutex_info[mutex_id].mutex); - - acpi_gbl_mutex_info[mutex_id].mutex = NULL; - acpi_gbl_mutex_info[mutex_id].owner_id = ACPI_MUTEX_NOT_ACQUIRED; - - return_ACPI_STATUS (status); -} - - -/******************************************************************************* - * - * FUNCTION: acpi_ut_acquire_mutex - * - * PARAMETERS: mutex_iD - ID of the mutex to be acquired - * - * RETURN: Status - * - * DESCRIPTION: Acquire a mutex object. - * - ******************************************************************************/ - -acpi_status -acpi_ut_acquire_mutex ( - acpi_mutex_handle mutex_id) -{ - acpi_status status; - u32 this_thread_id; - - - ACPI_FUNCTION_NAME ("ut_acquire_mutex"); - - - if (mutex_id > MAX_MUTEX) { - return (AE_BAD_PARAMETER); - } - - this_thread_id = acpi_os_get_thread_id (); - -#ifdef ACPI_MUTEX_DEBUG - { - u32 i; - /* - * Mutex debug code, for internal debugging only. - * - * Deadlock prevention. Check if this thread owns any mutexes of value - * greater than or equal to this one. If so, the thread has violated - * the mutex ordering rule. This indicates a coding error somewhere in - * the ACPI subsystem code. - */ - for (i = mutex_id; i < MAX_MUTEX; i++) { - if (acpi_gbl_mutex_info[i].owner_id == this_thread_id) { - if (i == mutex_id) { - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, - "Mutex [%s] already acquired by this thread [%X]\n", - acpi_ut_get_mutex_name (mutex_id), this_thread_id)); - - return (AE_ALREADY_ACQUIRED); - } - - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, - "Invalid acquire order: Thread %X owns [%s], wants [%s]\n", - this_thread_id, acpi_ut_get_mutex_name (i), - acpi_ut_get_mutex_name (mutex_id))); - - return (AE_ACQUIRE_DEADLOCK); - } - } - } -#endif - - ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, - "Thread %X attempting to acquire Mutex [%s]\n", - this_thread_id, acpi_ut_get_mutex_name (mutex_id))); - - status = acpi_os_wait_semaphore (acpi_gbl_mutex_info[mutex_id].mutex, - 1, ACPI_WAIT_FOREVER); - if (ACPI_SUCCESS (status)) { - ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, "Thread %X acquired Mutex [%s]\n", - this_thread_id, acpi_ut_get_mutex_name (mutex_id))); - - acpi_gbl_mutex_info[mutex_id].use_count++; - acpi_gbl_mutex_info[mutex_id].owner_id = this_thread_id; - } - else { - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, - "Thread %X could not acquire Mutex [%s] %s\n", - this_thread_id, acpi_ut_get_mutex_name (mutex_id), - acpi_format_exception (status))); - } - - return (status); -} - - -/******************************************************************************* - * - * FUNCTION: acpi_ut_release_mutex - * - * PARAMETERS: mutex_iD - ID of the mutex to be released - * - * RETURN: Status - * - * DESCRIPTION: Release a mutex object. - * - ******************************************************************************/ - -acpi_status -acpi_ut_release_mutex ( - acpi_mutex_handle mutex_id) -{ - acpi_status status; - u32 i; - u32 this_thread_id; - - - ACPI_FUNCTION_NAME ("ut_release_mutex"); - - - this_thread_id = acpi_os_get_thread_id (); - ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, - "Thread %X releasing Mutex [%s]\n", this_thread_id, - acpi_ut_get_mutex_name (mutex_id))); - - if (mutex_id > MAX_MUTEX) { - return (AE_BAD_PARAMETER); - } - - /* - * Mutex must be acquired in order to release it! - */ - if (acpi_gbl_mutex_info[mutex_id].owner_id == ACPI_MUTEX_NOT_ACQUIRED) { - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, - "Mutex [%s] is not acquired, cannot release\n", - acpi_ut_get_mutex_name (mutex_id))); - - return (AE_NOT_ACQUIRED); - } - - /* - * Deadlock prevention. Check if this thread owns any mutexes of value - * greater than this one. If so, the thread has violated the mutex - * ordering rule. This indicates a coding error somewhere in - * the ACPI subsystem code. - */ - for (i = mutex_id; i < MAX_MUTEX; i++) { - if (acpi_gbl_mutex_info[i].owner_id == this_thread_id) { - if (i == mutex_id) { - continue; - } - - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, - "Invalid release order: owns [%s], releasing [%s]\n", - acpi_ut_get_mutex_name (i), acpi_ut_get_mutex_name (mutex_id))); - - return (AE_RELEASE_DEADLOCK); - } - } - - /* Mark unlocked FIRST */ - - acpi_gbl_mutex_info[mutex_id].owner_id = ACPI_MUTEX_NOT_ACQUIRED; - - status = acpi_os_signal_semaphore (acpi_gbl_mutex_info[mutex_id].mutex, 1); - - if (ACPI_FAILURE (status)) { - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, - "Thread %X could not release Mutex [%s] %s\n", - this_thread_id, acpi_ut_get_mutex_name (mutex_id), - acpi_format_exception (status))); - } - else { - ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, "Thread %X released Mutex [%s]\n", - this_thread_id, acpi_ut_get_mutex_name (mutex_id))); - } - - return (status); -} - - -/******************************************************************************* - * * FUNCTION: acpi_ut_create_update_state_and_push * * PARAMETERS: Object - Object to be added to the new state @@ -899,361 +695,6 @@ acpi_ut_create_update_state_and_push ( /******************************************************************************* * - * FUNCTION: acpi_ut_create_pkg_state_and_push - * - * PARAMETERS: Object - Object to be added to the new state - * Action - Increment/Decrement - * state_list - List the state will be added to - * - * RETURN: Status - * - * DESCRIPTION: Create a new state and push it - * - ******************************************************************************/ - -#ifdef ACPI_FUTURE_USAGE -acpi_status -acpi_ut_create_pkg_state_and_push ( - void *internal_object, - void *external_object, - u16 index, - union acpi_generic_state **state_list) -{ - union acpi_generic_state *state; - - - ACPI_FUNCTION_ENTRY (); - - - state = acpi_ut_create_pkg_state (internal_object, external_object, index); - if (!state) { - return (AE_NO_MEMORY); - } - - acpi_ut_push_generic_state (state_list, state); - return (AE_OK); -} -#endif /* ACPI_FUTURE_USAGE */ - -/******************************************************************************* - * - * FUNCTION: acpi_ut_push_generic_state - * - * PARAMETERS: list_head - Head of the state stack - * State - State object to push - * - * RETURN: None - * - * DESCRIPTION: Push a state object onto a state stack - * - ******************************************************************************/ - -void -acpi_ut_push_generic_state ( - union acpi_generic_state **list_head, - union acpi_generic_state *state) -{ - ACPI_FUNCTION_TRACE ("ut_push_generic_state"); - - - /* Push the state object onto the front of the list (stack) */ - - state->common.next = *list_head; - *list_head = state; - - return_VOID; -} - - -/******************************************************************************* - * - * FUNCTION: acpi_ut_pop_generic_state - * - * PARAMETERS: list_head - Head of the state stack - * - * RETURN: The popped state object - * - * DESCRIPTION: Pop a state object from a state stack - * - ******************************************************************************/ - -union acpi_generic_state * -acpi_ut_pop_generic_state ( - union acpi_generic_state **list_head) -{ - union acpi_generic_state *state; - - - ACPI_FUNCTION_TRACE ("ut_pop_generic_state"); - - - /* Remove the state object at the head of the list (stack) */ - - state = *list_head; - if (state) { - /* Update the list head */ - - *list_head = state->common.next; - } - - return_PTR (state); -} - - -/******************************************************************************* - * - * FUNCTION: acpi_ut_create_generic_state - * - * PARAMETERS: None - * - * RETURN: The new state object. NULL on failure. - * - * DESCRIPTION: Create a generic state object. Attempt to obtain one from - * the global state cache; If none available, create a new one. - * - ******************************************************************************/ - -union acpi_generic_state * -acpi_ut_create_generic_state ( - void) -{ - union acpi_generic_state *state; - - - ACPI_FUNCTION_ENTRY (); - - - state = acpi_ut_acquire_from_cache (ACPI_MEM_LIST_STATE); - - /* Initialize */ - - if (state) { - state->common.data_type = ACPI_DESC_TYPE_STATE; - } - - return (state); -} - - -/******************************************************************************* - * - * FUNCTION: acpi_ut_create_thread_state - * - * PARAMETERS: None - * - * RETURN: New Thread State. NULL on failure - * - * DESCRIPTION: Create a "Thread State" - a flavor of the generic state used - * to track per-thread info during method execution - * - ******************************************************************************/ - -struct acpi_thread_state * -acpi_ut_create_thread_state ( - void) -{ - union acpi_generic_state *state; - - - ACPI_FUNCTION_TRACE ("ut_create_thread_state"); - - - /* Create the generic state object */ - - state = acpi_ut_create_generic_state (); - if (!state) { - return_PTR (NULL); - } - - /* Init fields specific to the update struct */ - - state->common.data_type = ACPI_DESC_TYPE_STATE_THREAD; - state->thread.thread_id = acpi_os_get_thread_id (); - - return_PTR ((struct acpi_thread_state *) state); -} - - -/******************************************************************************* - * - * FUNCTION: acpi_ut_create_update_state - * - * PARAMETERS: Object - Initial Object to be installed in the state - * Action - Update action to be performed - * - * RETURN: New state object, null on failure - * - * DESCRIPTION: Create an "Update State" - a flavor of the generic state used - * to update reference counts and delete complex objects such - * as packages. - * - ******************************************************************************/ - -union acpi_generic_state * -acpi_ut_create_update_state ( - union acpi_operand_object *object, - u16 action) -{ - union acpi_generic_state *state; - - - ACPI_FUNCTION_TRACE_PTR ("ut_create_update_state", object); - - - /* Create the generic state object */ - - state = acpi_ut_create_generic_state (); - if (!state) { - return_PTR (NULL); - } - - /* Init fields specific to the update struct */ - - state->common.data_type = ACPI_DESC_TYPE_STATE_UPDATE; - state->update.object = object; - state->update.value = action; - - return_PTR (state); -} - - -/******************************************************************************* - * - * FUNCTION: acpi_ut_create_pkg_state - * - * PARAMETERS: Object - Initial Object to be installed in the state - * Action - Update action to be performed - * - * RETURN: New state object, null on failure - * - * DESCRIPTION: Create a "Package State" - * - ******************************************************************************/ - -union acpi_generic_state * -acpi_ut_create_pkg_state ( - void *internal_object, - void *external_object, - u16 index) -{ - union acpi_generic_state *state; - - - ACPI_FUNCTION_TRACE_PTR ("ut_create_pkg_state", internal_object); - - - /* Create the generic state object */ - - state = acpi_ut_create_generic_state (); - if (!state) { - return_PTR (NULL); - } - - /* Init fields specific to the update struct */ - - state->common.data_type = ACPI_DESC_TYPE_STATE_PACKAGE; - state->pkg.source_object = (union acpi_operand_object *) internal_object; - state->pkg.dest_object = external_object; - state->pkg.index = index; - state->pkg.num_packages = 1; - - return_PTR (state); -} - - -/******************************************************************************* - * - * FUNCTION: acpi_ut_create_control_state - * - * PARAMETERS: None - * - * RETURN: New state object, null on failure - * - * DESCRIPTION: Create a "Control State" - a flavor of the generic state used - * to support nested IF/WHILE constructs in the AML. - * - ******************************************************************************/ - -union acpi_generic_state * -acpi_ut_create_control_state ( - void) -{ - union acpi_generic_state *state; - - - ACPI_FUNCTION_TRACE ("ut_create_control_state"); - - - /* Create the generic state object */ - - state = acpi_ut_create_generic_state (); - if (!state) { - return_PTR (NULL); - } - - /* Init fields specific to the control struct */ - - state->common.data_type = ACPI_DESC_TYPE_STATE_CONTROL; - state->common.state = ACPI_CONTROL_CONDITIONAL_EXECUTING; - - return_PTR (state); -} - - -/******************************************************************************* - * - * FUNCTION: acpi_ut_delete_generic_state - * - * PARAMETERS: State - The state object to be deleted - * - * RETURN: None - * - * DESCRIPTION: Put a state object back into the global state cache. The object - * is not actually freed at this time. - * - ******************************************************************************/ - -void -acpi_ut_delete_generic_state ( - union acpi_generic_state *state) -{ - ACPI_FUNCTION_TRACE ("ut_delete_generic_state"); - - - acpi_ut_release_to_cache (ACPI_MEM_LIST_STATE, state); - return_VOID; -} - - -#ifdef ACPI_ENABLE_OBJECT_CACHE -/******************************************************************************* - * - * FUNCTION: acpi_ut_delete_generic_state_cache - * - * PARAMETERS: None - * - * RETURN: None - * - * DESCRIPTION: Purge the global state object cache. Used during subsystem - * termination. - * - ******************************************************************************/ - -void -acpi_ut_delete_generic_state_cache ( - void) -{ - ACPI_FUNCTION_TRACE ("ut_delete_generic_state_cache"); - - - acpi_ut_delete_generic_cache (ACPI_MEM_LIST_STATE); - return_VOID; -} -#endif - - -/******************************************************************************* - * * FUNCTION: acpi_ut_walk_package_tree * * PARAMETERS: source_object - The package to walk diff --git a/drivers/acpi/utilities/utmutex.c b/drivers/acpi/utilities/utmutex.c new file mode 100644 index 00000000000..0699b6be62b --- /dev/null +++ b/drivers/acpi/utilities/utmutex.c @@ -0,0 +1,380 @@ +/******************************************************************************* + * + * Module Name: utmutex - local mutex support + * + ******************************************************************************/ + +/* + * Copyright (C) 2000 - 2005, R. Byron Moore + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + + +#include <acpi/acpi.h> + +#define _COMPONENT ACPI_UTILITIES + ACPI_MODULE_NAME ("utmutex") + +/* Local prototypes */ + +static acpi_status +acpi_ut_create_mutex ( + acpi_mutex_handle mutex_id); + +static acpi_status +acpi_ut_delete_mutex ( + acpi_mutex_handle mutex_id); + + +/******************************************************************************* + * + * FUNCTION: acpi_ut_mutex_initialize + * + * PARAMETERS: None. + * + * RETURN: Status + * + * DESCRIPTION: Create the system mutex objects. + * + ******************************************************************************/ + +acpi_status +acpi_ut_mutex_initialize ( + void) +{ + u32 i; + acpi_status status; + + + ACPI_FUNCTION_TRACE ("ut_mutex_initialize"); + + + /* + * Create each of the predefined mutex objects + */ + for (i = 0; i < NUM_MUTEX; i++) { + status = acpi_ut_create_mutex (i); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } + } + + status = acpi_os_create_lock (&acpi_gbl_gpe_lock); + return_ACPI_STATUS (status); +} + + +/******************************************************************************* + * + * FUNCTION: acpi_ut_mutex_terminate + * + * PARAMETERS: None. + * + * RETURN: None. + * + * DESCRIPTION: Delete all of the system mutex objects. + * + ******************************************************************************/ + +void +acpi_ut_mutex_terminate ( + void) +{ + u32 i; + + + ACPI_FUNCTION_TRACE ("ut_mutex_terminate"); + + + /* + * Delete each predefined mutex object + */ + for (i = 0; i < NUM_MUTEX; i++) { + (void) acpi_ut_delete_mutex (i); + } + + acpi_os_delete_lock (acpi_gbl_gpe_lock); + return_VOID; +} + + +/******************************************************************************* + * + * FUNCTION: acpi_ut_create_mutex + * + * PARAMETERS: mutex_iD - ID of the mutex to be created + * + * RETURN: Status + * + * DESCRIPTION: Create a mutex object. + * + ******************************************************************************/ + +static acpi_status +acpi_ut_create_mutex ( + acpi_mutex_handle mutex_id) +{ + acpi_status status = AE_OK; + + + ACPI_FUNCTION_TRACE_U32 ("ut_create_mutex", mutex_id); + + + if (mutex_id > MAX_MUTEX) { + return_ACPI_STATUS (AE_BAD_PARAMETER); + } + + if (!acpi_gbl_mutex_info[mutex_id].mutex) { + status = acpi_os_create_semaphore (1, 1, + &acpi_gbl_mutex_info[mutex_id].mutex); + acpi_gbl_mutex_info[mutex_id].thread_id = ACPI_MUTEX_NOT_ACQUIRED; + acpi_gbl_mutex_info[mutex_id].use_count = 0; + } + + return_ACPI_STATUS (status); +} + + +/******************************************************************************* + * + * FUNCTION: acpi_ut_delete_mutex + * + * PARAMETERS: mutex_iD - ID of the mutex to be deleted + * + * RETURN: Status + * + * DESCRIPTION: Delete a mutex object. + * + ******************************************************************************/ + +static acpi_status +acpi_ut_delete_mutex ( + acpi_mutex_handle mutex_id) +{ + acpi_status status; + + + ACPI_FUNCTION_TRACE_U32 ("ut_delete_mutex", mutex_id); + + + if (mutex_id > MAX_MUTEX) { + return_ACPI_STATUS (AE_BAD_PARAMETER); + } + + status = acpi_os_delete_semaphore (acpi_gbl_mutex_info[mutex_id].mutex); + + acpi_gbl_mutex_info[mutex_id].mutex = NULL; + acpi_gbl_mutex_info[mutex_id].thread_id = ACPI_MUTEX_NOT_ACQUIRED; + + return_ACPI_STATUS (status); +} + + +/******************************************************************************* + * + * FUNCTION: acpi_ut_acquire_mutex + * + * PARAMETERS: mutex_iD - ID of the mutex to be acquired + * + * RETURN: Status + * + * DESCRIPTION: Acquire a mutex object. + * + ******************************************************************************/ + +acpi_status +acpi_ut_acquire_mutex ( + acpi_mutex_handle mutex_id) +{ + acpi_status status; + u32 this_thread_id; + + + ACPI_FUNCTION_NAME ("ut_acquire_mutex"); + + + if (mutex_id > MAX_MUTEX) { + return (AE_BAD_PARAMETER); + } + + this_thread_id = acpi_os_get_thread_id (); + +#ifdef ACPI_MUTEX_DEBUG + { + u32 i; + /* + * Mutex debug code, for internal debugging only. + * + * Deadlock prevention. Check if this thread owns any mutexes of value + * greater than or equal to this one. If so, the thread has violated + * the mutex ordering rule. This indicates a coding error somewhere in + * the ACPI subsystem code. + */ + for (i = mutex_id; i < MAX_MUTEX; i++) { + if (acpi_gbl_mutex_info[i].owner_id == this_thread_id) { + if (i == mutex_id) { + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, + "Mutex [%s] already acquired by this thread [%X]\n", + acpi_ut_get_mutex_name (mutex_id), this_thread_id)); + + return (AE_ALREADY_ACQUIRED); + } + + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, + "Invalid acquire order: Thread %X owns [%s], wants [%s]\n", + this_thread_id, acpi_ut_get_mutex_name (i), + acpi_ut_get_mutex_name (mutex_id))); + + return (AE_ACQUIRE_DEADLOCK); + } + } + } +#endif + + ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, + "Thread %X attempting to acquire Mutex [%s]\n", + this_thread_id, acpi_ut_get_mutex_name (mutex_id))); + + status = acpi_os_wait_semaphore (acpi_gbl_mutex_info[mutex_id].mutex, + 1, ACPI_WAIT_FOREVER); + if (ACPI_SUCCESS (status)) { + ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, "Thread %X acquired Mutex [%s]\n", + this_thread_id, acpi_ut_get_mutex_name (mutex_id))); + + acpi_gbl_mutex_info[mutex_id].use_count++; + acpi_gbl_mutex_info[mutex_id].thread_id = this_thread_id; + } + else { + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, + "Thread %X could not acquire Mutex [%s] %s\n", + this_thread_id, acpi_ut_get_mutex_name (mutex_id), + acpi_format_exception (status))); + } + + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: acpi_ut_release_mutex + * + * PARAMETERS: mutex_iD - ID of the mutex to be released + * + * RETURN: Status + * + * DESCRIPTION: Release a mutex object. + * + ******************************************************************************/ + +acpi_status +acpi_ut_release_mutex ( + acpi_mutex_handle mutex_id) +{ + acpi_status status; + u32 this_thread_id; + + + ACPI_FUNCTION_NAME ("ut_release_mutex"); + + + this_thread_id = acpi_os_get_thread_id (); + ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, + "Thread %X releasing Mutex [%s]\n", this_thread_id, + acpi_ut_get_mutex_name (mutex_id))); + + if (mutex_id > MAX_MUTEX) { + return (AE_BAD_PARAMETER); + } + + /* + * Mutex must be acquired in order to release it! + */ + if (acpi_gbl_mutex_info[mutex_id].thread_id == ACPI_MUTEX_NOT_ACQUIRED) { + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, + "Mutex [%s] is not acquired, cannot release\n", + acpi_ut_get_mutex_name (mutex_id))); + + return (AE_NOT_ACQUIRED); + } + +#ifdef ACPI_MUTEX_DEBUG + { + u32 i; + /* + * Mutex debug code, for internal debugging only. + * + * Deadlock prevention. Check if this thread owns any mutexes of value + * greater than this one. If so, the thread has violated the mutex + * ordering rule. This indicates a coding error somewhere in + * the ACPI subsystem code. + */ + for (i = mutex_id; i < MAX_MUTEX; i++) { + if (acpi_gbl_mutex_info[i].owner_id == this_thread_id) { + if (i == mutex_id) { + continue; + } + + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, + "Invalid release order: owns [%s], releasing [%s]\n", + acpi_ut_get_mutex_name (i), acpi_ut_get_mutex_name (mutex_id))); + + return (AE_RELEASE_DEADLOCK); + } + } + } +#endif + + /* Mark unlocked FIRST */ + + acpi_gbl_mutex_info[mutex_id].thread_id = ACPI_MUTEX_NOT_ACQUIRED; + + status = acpi_os_signal_semaphore (acpi_gbl_mutex_info[mutex_id].mutex, 1); + + if (ACPI_FAILURE (status)) { + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, + "Thread %X could not release Mutex [%s] %s\n", + this_thread_id, acpi_ut_get_mutex_name (mutex_id), + acpi_format_exception (status))); + } + else { + ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, "Thread %X released Mutex [%s]\n", + this_thread_id, acpi_ut_get_mutex_name (mutex_id))); + } + + return (status); +} + + diff --git a/drivers/acpi/utilities/utobject.c b/drivers/acpi/utilities/utobject.c index cd3899b9cc5..19178e14295 100644 --- a/drivers/acpi/utilities/utobject.c +++ b/drivers/acpi/utilities/utobject.c @@ -338,7 +338,7 @@ acpi_ut_allocate_object_desc_dbg ( ACPI_FUNCTION_TRACE ("ut_allocate_object_desc_dbg"); - object = acpi_ut_acquire_from_cache (ACPI_MEM_LIST_OPERAND); + object = acpi_os_acquire_object (acpi_gbl_operand_cache); if (!object) { _ACPI_REPORT_ERROR (module_name, line_number, component_id, ("Could not allocate an object descriptor\n")); @@ -347,7 +347,7 @@ acpi_ut_allocate_object_desc_dbg ( } /* Mark the descriptor type */ - + memset(object, 0, sizeof(union acpi_operand_object)); ACPI_SET_DESCRIPTOR_TYPE (object, ACPI_DESC_TYPE_OPERAND); ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "%p Size %X\n", @@ -385,37 +385,9 @@ acpi_ut_delete_object_desc ( return_VOID; } - acpi_ut_release_to_cache (ACPI_MEM_LIST_OPERAND, object); - - return_VOID; -} - - -#ifdef ACPI_ENABLE_OBJECT_CACHE -/******************************************************************************* - * - * FUNCTION: acpi_ut_delete_object_cache - * - * PARAMETERS: None - * - * RETURN: None - * - * DESCRIPTION: Purge the global state object cache. Used during subsystem - * termination. - * - ******************************************************************************/ - -void -acpi_ut_delete_object_cache ( - void) -{ - ACPI_FUNCTION_TRACE ("ut_delete_object_cache"); - - - acpi_ut_delete_generic_cache (ACPI_MEM_LIST_OPERAND); + (void) acpi_os_release_object (acpi_gbl_operand_cache, object); return_VOID; } -#endif /******************************************************************************* diff --git a/drivers/acpi/utilities/utstate.c b/drivers/acpi/utilities/utstate.c new file mode 100644 index 00000000000..192e7ac9569 --- /dev/null +++ b/drivers/acpi/utilities/utstate.c @@ -0,0 +1,376 @@ +/******************************************************************************* + * + * Module Name: utstate - state object support procedures + * + ******************************************************************************/ + +/* + * Copyright (C) 2000 - 2005, R. Byron Moore + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + + +#include <acpi/acpi.h> + +#define _COMPONENT ACPI_UTILITIES + ACPI_MODULE_NAME ("utstate") + + +/******************************************************************************* + * + * FUNCTION: acpi_ut_create_pkg_state_and_push + * + * PARAMETERS: Object - Object to be added to the new state + * Action - Increment/Decrement + * state_list - List the state will be added to + * + * RETURN: Status + * + * DESCRIPTION: Create a new state and push it + * + ******************************************************************************/ + +acpi_status +acpi_ut_create_pkg_state_and_push ( + void *internal_object, + void *external_object, + u16 index, + union acpi_generic_state **state_list) +{ + union acpi_generic_state *state; + + + ACPI_FUNCTION_ENTRY (); + + + state = acpi_ut_create_pkg_state (internal_object, external_object, index); + if (!state) { + return (AE_NO_MEMORY); + } + + acpi_ut_push_generic_state (state_list, state); + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: acpi_ut_push_generic_state + * + * PARAMETERS: list_head - Head of the state stack + * State - State object to push + * + * RETURN: None + * + * DESCRIPTION: Push a state object onto a state stack + * + ******************************************************************************/ + +void +acpi_ut_push_generic_state ( + union acpi_generic_state **list_head, + union acpi_generic_state *state) +{ + ACPI_FUNCTION_TRACE ("ut_push_generic_state"); + + + /* Push the state object onto the front of the list (stack) */ + + state->common.next = *list_head; + *list_head = state; + + return_VOID; +} + + +/******************************************************************************* + * + * FUNCTION: acpi_ut_pop_generic_state + * + * PARAMETERS: list_head - Head of the state stack + * + * RETURN: The popped state object + * + * DESCRIPTION: Pop a state object from a state stack + * + ******************************************************************************/ + +union acpi_generic_state * +acpi_ut_pop_generic_state ( + union acpi_generic_state **list_head) +{ + union acpi_generic_state *state; + + + ACPI_FUNCTION_TRACE ("ut_pop_generic_state"); + + + /* Remove the state object at the head of the list (stack) */ + + state = *list_head; + if (state) { + /* Update the list head */ + + *list_head = state->common.next; + } + + return_PTR (state); +} + + +/******************************************************************************* + * + * FUNCTION: acpi_ut_create_generic_state + * + * PARAMETERS: None + * + * RETURN: The new state object. NULL on failure. + * + * DESCRIPTION: Create a generic state object. Attempt to obtain one from + * the global state cache; If none available, create a new one. + * + ******************************************************************************/ + +union acpi_generic_state * +acpi_ut_create_generic_state ( + void) +{ + union acpi_generic_state *state; + + + ACPI_FUNCTION_ENTRY (); + + + state = acpi_os_acquire_object (acpi_gbl_state_cache); + if (state) { + /* Initialize */ + memset(state, 0, sizeof(union acpi_generic_state)); + state->common.data_type = ACPI_DESC_TYPE_STATE; + } + + return (state); +} + + +/******************************************************************************* + * + * FUNCTION: acpi_ut_create_thread_state + * + * PARAMETERS: None + * + * RETURN: New Thread State. NULL on failure + * + * DESCRIPTION: Create a "Thread State" - a flavor of the generic state used + * to track per-thread info during method execution + * + ******************************************************************************/ + +struct acpi_thread_state * +acpi_ut_create_thread_state ( + void) +{ + union acpi_generic_state *state; + + + ACPI_FUNCTION_TRACE ("ut_create_thread_state"); + + + /* Create the generic state object */ + + state = acpi_ut_create_generic_state (); + if (!state) { + return_PTR (NULL); + } + + /* Init fields specific to the update struct */ + + state->common.data_type = ACPI_DESC_TYPE_STATE_THREAD; + state->thread.thread_id = acpi_os_get_thread_id (); + + return_PTR ((struct acpi_thread_state *) state); +} + + +/******************************************************************************* + * + * FUNCTION: acpi_ut_create_update_state + * + * PARAMETERS: Object - Initial Object to be installed in the state + * Action - Update action to be performed + * + * RETURN: New state object, null on failure + * + * DESCRIPTION: Create an "Update State" - a flavor of the generic state used + * to update reference counts and delete complex objects such + * as packages. + * + ******************************************************************************/ + +union acpi_generic_state * +acpi_ut_create_update_state ( + union acpi_operand_object *object, + u16 action) +{ + union acpi_generic_state *state; + + + ACPI_FUNCTION_TRACE_PTR ("ut_create_update_state", object); + + + /* Create the generic state object */ + + state = acpi_ut_create_generic_state (); + if (!state) { + return_PTR (NULL); + } + + /* Init fields specific to the update struct */ + + state->common.data_type = ACPI_DESC_TYPE_STATE_UPDATE; + state->update.object = object; + state->update.value = action; + + return_PTR (state); +} + + +/******************************************************************************* + * + * FUNCTION: acpi_ut_create_pkg_state + * + * PARAMETERS: Object - Initial Object to be installed in the state + * Action - Update action to be performed + * + * RETURN: New state object, null on failure + * + * DESCRIPTION: Create a "Package State" + * + ******************************************************************************/ + +union acpi_generic_state * +acpi_ut_create_pkg_state ( + void *internal_object, + void *external_object, + u16 index) +{ + union acpi_generic_state *state; + + + ACPI_FUNCTION_TRACE_PTR ("ut_create_pkg_state", internal_object); + + + /* Create the generic state object */ + + state = acpi_ut_create_generic_state (); + if (!state) { + return_PTR (NULL); + } + + /* Init fields specific to the update struct */ + + state->common.data_type = ACPI_DESC_TYPE_STATE_PACKAGE; + state->pkg.source_object = (union acpi_operand_object *) internal_object; + state->pkg.dest_object = external_object; + state->pkg.index = index; + state->pkg.num_packages = 1; + + return_PTR (state); +} + + +/******************************************************************************* + * + * FUNCTION: acpi_ut_create_control_state + * + * PARAMETERS: None + * + * RETURN: New state object, null on failure + * + * DESCRIPTION: Create a "Control State" - a flavor of the generic state used + * to support nested IF/WHILE constructs in the AML. + * + ******************************************************************************/ + +union acpi_generic_state * +acpi_ut_create_control_state ( + void) +{ + union acpi_generic_state *state; + + + ACPI_FUNCTION_TRACE ("ut_create_control_state"); + + + /* Create the generic state object */ + + state = acpi_ut_create_generic_state (); + if (!state) { + return_PTR (NULL); + } + + /* Init fields specific to the control struct */ + + state->common.data_type = ACPI_DESC_TYPE_STATE_CONTROL; + state->common.state = ACPI_CONTROL_CONDITIONAL_EXECUTING; + + return_PTR (state); +} + + +/******************************************************************************* + * + * FUNCTION: acpi_ut_delete_generic_state + * + * PARAMETERS: State - The state object to be deleted + * + * RETURN: None + * + * DESCRIPTION: Put a state object back into the global state cache. The object + * is not actually freed at this time. + * + ******************************************************************************/ + +void +acpi_ut_delete_generic_state ( + union acpi_generic_state *state) +{ + ACPI_FUNCTION_TRACE ("ut_delete_generic_state"); + + + (void) acpi_os_release_object (acpi_gbl_state_cache, state); + return_VOID; +} + + diff --git a/drivers/acpi/utilities/utxface.c b/drivers/acpi/utilities/utxface.c index e8803d81065..850da681742 100644 --- a/drivers/acpi/utilities/utxface.c +++ b/drivers/acpi/utilities/utxface.c @@ -46,8 +46,6 @@ #include <acpi/acpi.h> #include <acpi/acevents.h> #include <acpi/acnamesp.h> -#include <acpi/acparser.h> -#include <acpi/acdispat.h> #include <acpi/acdebug.h> #define _COMPONENT ACPI_UTILITIES @@ -79,11 +77,6 @@ acpi_initialize_subsystem ( ACPI_DEBUG_EXEC (acpi_ut_init_stack_ptr_trace ()); - - /* Initialize all globals used by the subsystem */ - - acpi_ut_init_globals (); - /* Initialize the OS-Dependent layer */ status = acpi_os_initialize (); @@ -93,6 +86,10 @@ acpi_initialize_subsystem ( return_ACPI_STATUS (status); } + /* Initialize all globals used by the subsystem */ + + acpi_ut_init_globals (); + /* Create the default mutex objects */ status = acpi_ut_mutex_initialize (); @@ -522,13 +519,9 @@ acpi_purge_cached_objects ( { ACPI_FUNCTION_TRACE ("acpi_purge_cached_objects"); - -#ifdef ACPI_ENABLE_OBJECT_CACHE - acpi_ut_delete_generic_state_cache (); - acpi_ut_delete_object_cache (); - acpi_ds_delete_walk_state_cache (); - acpi_ps_delete_parse_cache (); -#endif - + (void) acpi_os_purge_cache (acpi_gbl_state_cache); + (void) acpi_os_purge_cache (acpi_gbl_operand_cache); + (void) acpi_os_purge_cache (acpi_gbl_ps_node_cache); + (void) acpi_os_purge_cache (acpi_gbl_ps_node_ext_cache); return_ACPI_STATUS (AE_OK); } |