diff options
Diffstat (limited to 'drivers')
40 files changed, 2469 insertions, 1941 deletions
diff --git a/drivers/acpi/dispatcher/dsmthdat.c b/drivers/acpi/dispatcher/dsmthdat.c index f7998306f756..c83d53fd6398 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/dswload.c b/drivers/acpi/dispatcher/dswload.c index e2e0a855be2c..d2c603f54fd6 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 @@ -176,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: @@ -569,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; } diff --git a/drivers/acpi/dispatcher/dswstate.c b/drivers/acpi/dispatcher/dswstate.c index cc45d52225d6..d360d8e89544 100644 --- a/drivers/acpi/dispatcher/dswstate.c +++ b/drivers/acpi/dispatcher/dswstate.c @@ -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); } @@ -900,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 081120b109ba..ede834df4f69 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 ee5419b8f1b1..dfc54692b127 100644 --- a/drivers/acpi/events/evgpeblk.c +++ b/drivers/acpi/events/evgpeblk.c @@ -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 */ @@ -500,6 +499,7 @@ acpi_ev_get_gpe_xrupt_block ( 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"); @@ -527,7 +527,7 @@ acpi_ev_get_gpe_xrupt_block ( /* 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,7 +540,7 @@ 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 */ @@ -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"); @@ -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 */ @@ -637,6 +638,7 @@ acpi_ev_install_gpe_block ( 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"); @@ -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 */ diff --git a/drivers/acpi/events/evmisc.c b/drivers/acpi/events/evmisc.c index 659e90956112..38d7ab8aef3a 100644 --- a/drivers/acpi/events/evmisc.c +++ b/drivers/acpi/events/evmisc.c @@ -589,7 +589,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 +602,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/evxface.c b/drivers/acpi/events/evxface.c index 4092d47f6758..4c1c25e316a8 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/executer/exconvrt.c b/drivers/acpi/executer/exconvrt.c index 97856c48bd74..21331625e66e 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 ae6cad85e015..7007abb6051e 100644 --- a/drivers/acpi/executer/exdump.c +++ b/drivers/acpi/executer/exdump.c @@ -80,6 +80,16 @@ acpi_ex_out_address ( acpi_physical_address value); #endif /* ACPI_FUTURE_USAGE */ +static void +acpi_ex_dump_reference ( + union acpi_operand_object *obj_desc); + +static void +acpi_ex_dump_package ( + union acpi_operand_object *obj_desc, + u32 level, + u32 index); + /******************************************************************************* * @@ -508,7 +518,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 +575,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", 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 +724,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 +790,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; @@ -790,10 +923,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/exmisc.c b/drivers/acpi/executer/exmisc.c index 022f281345b8..237ef28c8132 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/exoparg1.c b/drivers/acpi/executer/exoparg1.c index ffc61ddeb659..131f49acb1df 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 */ diff --git a/drivers/acpi/executer/exoparg3.c b/drivers/acpi/executer/exoparg3.c index 23b068adbf58..197890f443b5 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/exstore.c b/drivers/acpi/executer/exstore.c index 763ffeea8503..59dbfeaa54c0 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); diff --git a/drivers/acpi/executer/exutils.c b/drivers/acpi/executer/exutils.c index 5c7ec0c04177..d00b0dcba96a 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 8daeabb2fc7a..3536bbb990c3 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 6d9e4eb84836..04a058565d8d 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 415d342aeab5..cedee0c43b5f 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 ece7a9dedd5c..9df0a64ba9e9 100644 --- a/drivers/acpi/namespace/nsaccess.c +++ b/drivers/acpi/namespace/nsaccess.c @@ -159,7 +159,7 @@ 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) || defined (ACPI_DUMP_App) /* * i_aSL Compiler cheats by putting parameter count diff --git a/drivers/acpi/namespace/nsalloc.c b/drivers/acpi/namespace/nsalloc.c index 5653a19d7172..3f94b0806ecf 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 @@ -362,7 +362,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)); diff --git a/drivers/acpi/namespace/nsdump.c b/drivers/acpi/namespace/nsdump.c index 05af95322a62..c9f35dd7a431 100644 --- a/drivers/acpi/namespace/nsdump.c +++ b/drivers/acpi/namespace/nsdump.c @@ -208,33 +208,37 @@ acpi_ns_dump_one_object ( 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) { @@ -646,7 +650,7 @@ acpi_ns_dump_entry ( } -#ifdef _ACPI_ASL_COMPILER +#ifdef ACPI_ASL_COMPILER /******************************************************************************* * * FUNCTION: acpi_ns_dump_tables diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index bdd9f37f8101..56e7cedba919 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c @@ -778,54 +778,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, @@ -1172,3 +1124,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 bbdd286c660d..db24ee09cf11 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 000000000000..decb2e9a049d --- /dev/null +++ b/drivers/acpi/parser/psloop.c @@ -0,0 +1,775 @@ +/****************************************************************************** + * + * 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> +#include <acpi/acnamesp.h> +#include <acpi/acinterp.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 */ + + 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: + + /* Skip body of if/else/while in pass 1 */ + + parser_state->aml = parser_state->pkg_end; + walk_state->arg_count = 0; + break; + + default: + break; + } + } + + 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 95ef5e8947a8..6f7594a516d2 100644 --- a/drivers/acpi/parser/psopcode.c +++ b/drivers/acpi/parser/psopcode.c @@ -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 bdbe0d99486f..16b84a3d0436 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 acpi_status -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)); @@ -158,7 +138,7 @@ acpi_ps_peek_opcode ( * ******************************************************************************/ -static acpi_status +acpi_status acpi_ps_complete_this_op ( struct acpi_walk_state *walk_state, union acpi_parse_object *op) @@ -331,7 +311,7 @@ allocate_error: * ******************************************************************************/ -static acpi_status +acpi_status acpi_ps_next_parse_state ( struct acpi_walk_state *walk_state, union acpi_parse_object *op, @@ -441,706 +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; - 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 */ - - if (walk_state->pass_number <= ACPI_IMODE_LOAD_PASS1) { - switch (op->common.aml_opcode) { - case AML_IF_OP: - case AML_ELSE_OP: - case AML_WHILE_OP: - - /* Skip body of if/else/while in pass 1 */ - - parser_state->aml = parser_state->pkg_end; - walk_state->arg_count = 0; - break; - - default: - break; - } - } - - 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); -} - - -/******************************************************************************* - * * 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 a10f88715d43..19a27020eeef 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); + acpi_os_release_object (acpi_gbl_ps_node_cache, op); } else { - acpi_ut_release_to_cache (ACPI_MEM_LIST_PSNODE_EXT, op); + 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/tables/tbconvrt.c b/drivers/acpi/tables/tbconvrt.c index 92e0c31539be..d4ff71f5fe5d 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/tbrsdt.c b/drivers/acpi/tables/tbrsdt.c index b7ffe39c3626..13c6ddb2f546 100644 --- a/drivers/acpi/tables/tbrsdt.c +++ b/drivers/acpi/tables/tbrsdt.c @@ -159,8 +159,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 +174,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 +214,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 +238,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/tbxfroot.c b/drivers/acpi/tables/tbxfroot.c index 198997aa7fbe..fe9c8317df46 100644 --- a/drivers/acpi/tables/tbxfroot.c +++ b/drivers/acpi/tables/tbxfroot.c @@ -287,9 +287,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]; } diff --git a/drivers/acpi/utilities/Makefile b/drivers/acpi/utilities/Makefile index 939c447dd52a..e87108b7338a 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 c4e7f989a2bd..5061c6f0ee66 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, + acpi_handle *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, + acpi_handle *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 000000000000..07588812e72d --- /dev/null +++ b/drivers/acpi/utilities/utcache.c @@ -0,0 +1,322 @@ +/****************************************************************************** + * + * 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; + + + 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; + + + /* 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 ("ut_acquire_from_cache"); + + + 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\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/utdebug.c b/drivers/acpi/utilities/utdebug.c index 794c7df3f2ad..08362f686ec1 100644 --- a/drivers/acpi/utilities/utdebug.c +++ b/drivers/acpi/utilities/utdebug.c @@ -549,7 +549,7 @@ acpi_ut_dump_buffer ( /* Dump fill spaces */ acpi_os_printf ("%*s", ((display * 2) + 1), " "); - j += display; + j += (acpi_native_uint) display; continue; } @@ -584,7 +584,7 @@ acpi_ut_dump_buffer ( break; } - j += display; + j += (acpi_native_uint) display; } /* diff --git a/drivers/acpi/utilities/utglobal.c b/drivers/acpi/utilities/utglobal.c index 4146019b543f..8653dda4f813 100644 --- a/drivers/acpi/utilities/utglobal.c +++ b/drivers/acpi/utilities/utglobal.c @@ -820,42 +820,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); - - 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"); + /* Create all memory caches */ + + status = acpi_ut_create_caches (); + if (ACPI_FAILURE (status)) + { + return; + } /* ACPI table structure */ diff --git a/drivers/acpi/utilities/utinit.c b/drivers/acpi/utilities/utinit.c index 7f3713889ff0..fd7ceba83229 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 bb658777fa88..207c836aec64 100644 --- a/drivers/acpi/utilities/utmisc.c +++ b/drivers/acpi/utilities/utmisc.c @@ -49,16 +49,6 @@ #define _COMPONENT ACPI_UTILITIES ACPI_MODULE_NAME ("utmisc") -/* 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); - /******************************************************************************* * @@ -84,6 +74,10 @@ acpi_ut_strupr ( ACPI_FUNCTION_ENTRY (); + if (!src_string) { + return (NULL); + } + /* Walk entire string, uppercasing the letters */ for (string = src_string; *string; string++) { @@ -543,326 +537,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 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); - } - -#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].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 @@ -905,361 +579,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 000000000000..a80b97cb2e56 --- /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].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 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); + } + +#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].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); +} + + diff --git a/drivers/acpi/utilities/utobject.c b/drivers/acpi/utilities/utobject.c index cd3899b9cc5a..19178e142951 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 000000000000..192e7ac95690 --- /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 e8803d810656..850da6817423 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); } |