diff options
Diffstat (limited to 'drivers/acpi/executer')
23 files changed, 592 insertions, 410 deletions
diff --git a/drivers/acpi/executer/exconfig.c b/drivers/acpi/executer/exconfig.c index 25802f302ff..24da921d13e 100644 --- a/drivers/acpi/executer/exconfig.c +++ b/drivers/acpi/executer/exconfig.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -45,7 +45,6 @@ #include <acpi/acinterp.h> #include <acpi/amlcode.h> #include <acpi/acnamesp.h> -#include <acpi/acevents.h> #include <acpi/actables.h> #include <acpi/acdispat.h> @@ -138,6 +137,14 @@ acpi_ex_load_table_op(struct acpi_walk_state *walk_state, ACPI_FUNCTION_TRACE(ex_load_table_op); + /* Validate lengths for the signature_string, OEMIDString, OEMtable_iD */ + + if ((operand[0]->string.length > ACPI_NAME_SIZE) || + (operand[1]->string.length > ACPI_OEM_ID_SIZE) || + (operand[2]->string.length > ACPI_OEM_TABLE_ID_SIZE)) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + /* Find the ACPI table in the RSDT/XSDT */ status = acpi_tb_find_table(operand[0]->string.pointer, @@ -229,11 +236,18 @@ acpi_ex_load_table_op(struct acpi_walk_state *walk_state, status = acpi_get_table_by_index(table_index, &table); if (ACPI_SUCCESS(status)) { ACPI_INFO((AE_INFO, - "Dynamic OEM Table Load - [%4.4s] OemId [%6.6s] OemTableId [%8.8s]", + "Dynamic OEM Table Load - [%.4s] OemId [%.6s] OemTableId [%.8s]", table->signature, table->oem_id, table->oem_table_id)); } + /* Invoke table handler if present */ + + if (acpi_gbl_table_handler) { + (void)acpi_gbl_table_handler(ACPI_TABLE_EVENT_LOAD, table, + acpi_gbl_table_handler_context); + } + *return_desc = ddb_handle; return_ACPI_STATUS(status); } @@ -268,6 +282,7 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc, struct acpi_table_desc table_desc; acpi_native_uint table_index; acpi_status status; + u32 length; ACPI_FUNCTION_TRACE(ex_load_op); @@ -278,16 +293,16 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc, switch (ACPI_GET_OBJECT_TYPE(obj_desc)) { case ACPI_TYPE_REGION: + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Load from Region %p %s\n", + obj_desc, + acpi_ut_get_object_type_name(obj_desc))); + /* Region must be system_memory (from ACPI spec) */ if (obj_desc->region.space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY) { return_ACPI_STATUS(AE_AML_OPERAND_TYPE); } - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Load from Region %p %s\n", - obj_desc, - acpi_ut_get_object_type_name(obj_desc))); - /* * If the Region Address and Length have not been previously evaluated, * evaluate them now and save the results. @@ -299,6 +314,11 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc, } } + /* + * We will simply map the memory region for the table. However, the + * memory region is technically not guaranteed to remain stable and + * we may eventually have to copy the table to a local buffer. + */ table_desc.address = obj_desc->region.address; table_desc.length = obj_desc->region.length; table_desc.flags = ACPI_TABLE_ORIGIN_MAPPED; @@ -306,18 +326,41 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc, case ACPI_TYPE_BUFFER: /* Buffer or resolved region_field */ - /* Simply extract the buffer from the buffer object */ - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Load from Buffer or Field %p %s\n", obj_desc, acpi_ut_get_object_type_name(obj_desc))); - table_desc.pointer = ACPI_CAST_PTR(struct acpi_table_header, - obj_desc->buffer.pointer); - table_desc.length = table_desc.pointer->length; - table_desc.flags = ACPI_TABLE_ORIGIN_ALLOCATED; + length = obj_desc->buffer.length; + + /* Must have at least an ACPI table header */ + + if (length < sizeof(struct acpi_table_header)) { + return_ACPI_STATUS(AE_INVALID_TABLE_LENGTH); + } + + /* Validate checksum here. It won't get validated in tb_add_table */ - obj_desc->buffer.pointer = NULL; + status = + acpi_tb_verify_checksum(ACPI_CAST_PTR + (struct acpi_table_header, + obj_desc->buffer.pointer), length); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* + * We need to copy the buffer since the original buffer could be + * changed or deleted in the future + */ + table_desc.pointer = ACPI_ALLOCATE(length); + if (!table_desc.pointer) { + return_ACPI_STATUS(AE_NO_MEMORY); + } + + ACPI_MEMCPY(table_desc.pointer, obj_desc->buffer.pointer, + length); + table_desc.length = length; + table_desc.flags = ACPI_TABLE_ORIGIN_ALLOCATED; break; default: @@ -333,7 +376,8 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc, } status = - acpi_ex_add_table(table_index, acpi_gbl_root_node, &ddb_handle); + acpi_ex_add_table(table_index, walk_state->scope_info->scope.node, + &ddb_handle); if (ACPI_FAILURE(status)) { /* On error, table_ptr was deallocated above */ @@ -349,11 +393,23 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc, /* table_ptr was deallocated above */ + acpi_ut_remove_reference(ddb_handle); return_ACPI_STATUS(status); } + /* Invoke table handler if present */ + + if (acpi_gbl_table_handler) { + (void)acpi_gbl_table_handler(ACPI_TABLE_EVENT_LOAD, + table_desc.pointer, + acpi_gbl_table_handler_context); + } + cleanup: if (ACPI_FAILURE(status)) { + + /* Delete allocated buffer or mapping */ + acpi_tb_delete_table(&table_desc); } return_ACPI_STATUS(status); @@ -376,6 +432,7 @@ acpi_status acpi_ex_unload_table(union acpi_operand_object *ddb_handle) acpi_status status = AE_OK; union acpi_operand_object *table_desc = ddb_handle; acpi_native_uint table_index; + struct acpi_table_header *table; ACPI_FUNCTION_TRACE(ex_unload_table); @@ -395,17 +452,25 @@ acpi_status acpi_ex_unload_table(union acpi_operand_object *ddb_handle) table_index = (acpi_native_uint) table_desc->reference.object; + /* Invoke table handler if present */ + + if (acpi_gbl_table_handler) { + status = acpi_get_table_by_index(table_index, &table); + if (ACPI_SUCCESS(status)) { + (void)acpi_gbl_table_handler(ACPI_TABLE_EVENT_UNLOAD, + table, + acpi_gbl_table_handler_context); + } + } + /* * Delete the entire namespace under this table Node * (Offset contains the table_id) */ acpi_tb_delete_namespace_by_owner(table_index); - acpi_tb_release_owner_id(table_index); + (void)acpi_tb_release_owner_id(table_index); acpi_tb_set_table_loaded_flag(table_index, FALSE); - /* Delete the table descriptor (ddb_handle) */ - - acpi_ut_remove_reference(table_desc); - return_ACPI_STATUS(status); + return_ACPI_STATUS(AE_OK); } diff --git a/drivers/acpi/executer/exconvrt.c b/drivers/acpi/executer/exconvrt.c index 79f2c0d42c0..fd954b4ed83 100644 --- a/drivers/acpi/executer/exconvrt.c +++ b/drivers/acpi/executer/exconvrt.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/executer/excreate.c b/drivers/acpi/executer/excreate.c index 6e9a23e47fe..60e62c4f057 100644 --- a/drivers/acpi/executer/excreate.c +++ b/drivers/acpi/executer/excreate.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -96,6 +96,9 @@ acpi_status acpi_ex_create_alias(struct acpi_walk_state *walk_state) * to the original Node. */ switch (target_node->type) { + + /* For these types, the sub-object can change dynamically via a Store */ + case ACPI_TYPE_INTEGER: case ACPI_TYPE_STRING: case ACPI_TYPE_BUFFER: @@ -103,9 +106,18 @@ acpi_status acpi_ex_create_alias(struct acpi_walk_state *walk_state) case ACPI_TYPE_BUFFER_FIELD: /* + * These types open a new scope, so we need the NS node in order to access + * any children. + */ + case ACPI_TYPE_DEVICE: + case ACPI_TYPE_POWER: + case ACPI_TYPE_PROCESSOR: + case ACPI_TYPE_THERMAL: + case ACPI_TYPE_LOCAL_SCOPE: + + /* * The new alias has the type ALIAS and points to the original - * NS node, not the object itself. This is because for these - * types, the object can change dynamically via a Store. + * NS node, not the object itself. */ alias_node->type = ACPI_TYPE_LOCAL_ALIAS; alias_node->object = @@ -115,9 +127,7 @@ acpi_status acpi_ex_create_alias(struct acpi_walk_state *walk_state) case ACPI_TYPE_METHOD: /* - * The new alias has the type ALIAS and points to the original - * NS node, not the object itself. This is because for these - * types, the object can change dynamically via a Store. + * Control method aliases need to be differentiated */ alias_node->type = ACPI_TYPE_LOCAL_METHOD_ALIAS; alias_node->object = @@ -342,101 +352,6 @@ acpi_ex_create_region(u8 * aml_start, /******************************************************************************* * - * FUNCTION: acpi_ex_create_table_region - * - * PARAMETERS: walk_state - Current state - * - * RETURN: Status - * - * DESCRIPTION: Create a new data_table_region object - * - ******************************************************************************/ - -acpi_status acpi_ex_create_table_region(struct acpi_walk_state *walk_state) -{ - acpi_status status; - union acpi_operand_object **operand = &walk_state->operands[0]; - union acpi_operand_object *obj_desc; - struct acpi_namespace_node *node; - union acpi_operand_object *region_obj2; - acpi_native_uint table_index; - struct acpi_table_header *table; - - ACPI_FUNCTION_TRACE(ex_create_table_region); - - /* Get the Node from the object stack */ - - node = walk_state->op->common.node; - - /* - * If the region object is already attached to this node, - * just return - */ - if (acpi_ns_get_attached_object(node)) { - return_ACPI_STATUS(AE_OK); - } - - /* Find the ACPI table */ - - status = acpi_tb_find_table(operand[1]->string.pointer, - operand[2]->string.pointer, - operand[3]->string.pointer, &table_index); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - /* Create the region descriptor */ - - obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_REGION); - if (!obj_desc) { - return_ACPI_STATUS(AE_NO_MEMORY); - } - - region_obj2 = obj_desc->common.next_object; - region_obj2->extra.region_context = NULL; - - status = acpi_get_table_by_index(table_index, &table); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - /* Init the region from the operands */ - - obj_desc->region.space_id = REGION_DATA_TABLE; - obj_desc->region.address = - (acpi_physical_address) ACPI_TO_INTEGER(table); - obj_desc->region.length = table->length; - obj_desc->region.node = node; - obj_desc->region.flags = AOPOBJ_DATA_VALID; - - /* Install the new region object in the parent Node */ - - status = acpi_ns_attach_object(node, obj_desc, ACPI_TYPE_REGION); - if (ACPI_FAILURE(status)) { - goto cleanup; - } - - status = acpi_ev_initialize_region(obj_desc, FALSE); - if (ACPI_FAILURE(status)) { - if (status == AE_NOT_EXIST) { - status = AE_OK; - } else { - goto cleanup; - } - } - - obj_desc->region.flags |= AOPOBJ_SETUP_COMPLETE; - - cleanup: - - /* Remove local reference to the object */ - - acpi_ut_remove_reference(obj_desc); - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * * FUNCTION: acpi_ex_create_processor * * PARAMETERS: walk_state - Current state diff --git a/drivers/acpi/executer/exdump.c b/drivers/acpi/executer/exdump.c index 51c9c29987c..74f1b22601b 100644 --- a/drivers/acpi/executer/exdump.c +++ b/drivers/acpi/executer/exdump.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -500,25 +500,28 @@ void acpi_ex_dump_operand(union acpi_operand_object *obj_desc, u32 depth) acpi_os_printf("Reference: Debug\n"); break; - case AML_NAME_OP: + case AML_INDEX_OP: - ACPI_DUMP_PATHNAME(obj_desc->reference.object, - "Reference: Name: ", ACPI_LV_INFO, - _COMPONENT); - ACPI_DUMP_ENTRY(obj_desc->reference.object, - ACPI_LV_INFO); + acpi_os_printf("Reference: Index %p\n", + obj_desc->reference.object); break; - case AML_INDEX_OP: + case AML_LOAD_OP: - acpi_os_printf("Reference: Index %p\n", + acpi_os_printf("Reference: [DdbHandle] TableIndex %p\n", obj_desc->reference.object); break; case AML_REF_OF_OP: - acpi_os_printf("Reference: (RefOf) %p\n", - obj_desc->reference.object); + acpi_os_printf("Reference: (RefOf) %p [%s]\n", + obj_desc->reference.object, + acpi_ut_get_type_name(((union + acpi_operand_object + *)obj_desc-> + reference. + object)->common. + type)); break; case AML_ARG_OP: @@ -559,8 +562,9 @@ void acpi_ex_dump_operand(union acpi_operand_object *obj_desc, u32 depth) case AML_INT_NAMEPATH_OP: - acpi_os_printf("Reference.Node->Name %X\n", - obj_desc->reference.node->name.integer); + acpi_os_printf("Reference: Namepath %X [%4.4s]\n", + obj_desc->reference.node->name.integer, + obj_desc->reference.node->name.ascii); break; default: @@ -640,8 +644,8 @@ void acpi_ex_dump_operand(union acpi_operand_object *obj_desc, u32 depth) acpi_os_printf("\n"); } else { acpi_os_printf(" base %8.8X%8.8X Length %X\n", - ACPI_FORMAT_UINT64(obj_desc->region. - address), + ACPI_FORMAT_NATIVE_UINT(obj_desc->region. + address), obj_desc->region.length); } break; @@ -877,20 +881,43 @@ static void acpi_ex_dump_reference_obj(union acpi_operand_object *obj_desc) ret_buf.length = ACPI_ALLOCATE_LOCAL_BUFFER; if (obj_desc->reference.opcode == AML_INT_NAMEPATH_OP) { - acpi_os_printf("Named Object %p ", obj_desc->reference.node); + acpi_os_printf(" Named Object %p ", obj_desc->reference.node); 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"); + acpi_os_printf(" Could not convert name to pathname\n"); } else { acpi_os_printf("%s\n", (char *)ret_buf.pointer); ACPI_FREE(ret_buf.pointer); } } else if (obj_desc->reference.object) { - acpi_os_printf("\nReferenced Object: %p\n", - obj_desc->reference.object); + if (ACPI_GET_DESCRIPTOR_TYPE(obj_desc) == + ACPI_DESC_TYPE_OPERAND) { + acpi_os_printf(" Target: %p", + obj_desc->reference.object); + if (obj_desc->reference.opcode == AML_LOAD_OP) { + /* + * For DDBHandle reference, + * obj_desc->Reference.Object is the table index + */ + acpi_os_printf(" [DDBHandle]\n"); + } else { + acpi_os_printf(" [%s]\n", + acpi_ut_get_type_name(((union + acpi_operand_object + *) + obj_desc-> + reference. + object)-> + common. + type)); + } + } else { + acpi_os_printf(" Target: %p\n", + obj_desc->reference.object); + } } } @@ -976,7 +1003,9 @@ acpi_ex_dump_package_obj(union acpi_operand_object *obj_desc, case ACPI_TYPE_LOCAL_REFERENCE: - acpi_os_printf("[Object Reference] "); + acpi_os_printf("[Object Reference] %s", + (acpi_ps_get_opcode_info + (obj_desc->reference.opcode))->name); acpi_ex_dump_reference_obj(obj_desc); break; diff --git a/drivers/acpi/executer/exfield.c b/drivers/acpi/executer/exfield.c index 2d88a3d8d1a..3e440d84226 100644 --- a/drivers/acpi/executer/exfield.c +++ b/drivers/acpi/executer/exfield.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -71,7 +71,6 @@ acpi_ex_read_data_from_field(struct acpi_walk_state *walk_state, union acpi_operand_object *buffer_desc; acpi_size length; void *buffer; - u8 locked; ACPI_FUNCTION_TRACE_PTR(ex_read_data_from_field, obj_desc); @@ -111,9 +110,7 @@ acpi_ex_read_data_from_field(struct acpi_walk_state *walk_state, /* Lock entire transaction if requested */ - locked = - acpi_ex_acquire_global_lock(obj_desc->common_field. - field_flags); + acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags); /* * Perform the read. @@ -125,7 +122,7 @@ acpi_ex_read_data_from_field(struct acpi_walk_state *walk_state, buffer.pointer), ACPI_READ | (obj_desc->field. attribute << 16)); - acpi_ex_release_global_lock(locked); + acpi_ex_release_global_lock(obj_desc->common_field.field_flags); goto exit; } @@ -175,13 +172,12 @@ acpi_ex_read_data_from_field(struct acpi_walk_state *walk_state, /* Lock entire transaction if requested */ - locked = - acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags); + acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags); /* Read from the field */ status = acpi_ex_extract_from_field(obj_desc, buffer, (u32) length); - acpi_ex_release_global_lock(locked); + acpi_ex_release_global_lock(obj_desc->common_field.field_flags); exit: if (ACPI_FAILURE(status)) { @@ -214,10 +210,7 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_desc, { acpi_status status; u32 length; - u32 required_length; void *buffer; - void *new_buffer; - u8 locked; union acpi_operand_object *buffer_desc; ACPI_FUNCTION_TRACE_PTR(ex_write_data_to_field, obj_desc); @@ -278,9 +271,7 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_desc, /* Lock entire transaction if requested */ - locked = - acpi_ex_acquire_global_lock(obj_desc->common_field. - field_flags); + acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags); /* * Perform the write (returns status and perhaps data in the @@ -291,7 +282,7 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_desc, (acpi_integer *) buffer, ACPI_WRITE | (obj_desc->field. attribute << 16)); - acpi_ex_release_global_lock(locked); + acpi_ex_release_global_lock(obj_desc->common_field.field_flags); *result_desc = buffer_desc; return_ACPI_STATUS(status); @@ -319,35 +310,6 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_desc, return_ACPI_STATUS(AE_AML_OPERAND_TYPE); } - /* - * We must have a buffer that is at least as long as the field - * we are writing to. This is because individual fields are - * indivisible and partial writes are not supported -- as per - * the ACPI specification. - */ - new_buffer = NULL; - required_length = - ACPI_ROUND_BITS_UP_TO_BYTES(obj_desc->common_field.bit_length); - - if (length < required_length) { - - /* We need to create a new buffer */ - - new_buffer = ACPI_ALLOCATE_ZEROED(required_length); - if (!new_buffer) { - return_ACPI_STATUS(AE_NO_MEMORY); - } - - /* - * Copy the original data to the new buffer, starting - * at Byte zero. All unused (upper) bytes of the - * buffer will be 0. - */ - ACPI_MEMCPY((char *)new_buffer, (char *)buffer, length); - buffer = new_buffer; - length = required_length; - } - ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, "FieldWrite [FROM]: Obj %p (%s:%X), Buf %p, ByteLen %X\n", source_desc, @@ -366,19 +328,12 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_desc, /* Lock entire transaction if requested */ - locked = - acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags); + acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags); /* Write to the field */ status = acpi_ex_insert_into_field(obj_desc, buffer, length); - acpi_ex_release_global_lock(locked); - - /* Free temporary buffer if we used one */ - - if (new_buffer) { - ACPI_FREE(new_buffer); - } + acpi_ex_release_global_lock(obj_desc->common_field.field_flags); return_ACPI_STATUS(status); } diff --git a/drivers/acpi/executer/exfldio.c b/drivers/acpi/executer/exfldio.c index 65a48b6170e..e336b5dc7a5 100644 --- a/drivers/acpi/executer/exfldio.c +++ b/drivers/acpi/executer/exfldio.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -263,7 +263,8 @@ acpi_ex_access_region(union acpi_operand_object *obj_desc, rgn_desc->region.space_id, obj_desc->common_field.access_byte_width, obj_desc->common_field.base_byte_offset, - field_datum_byte_offset, (void *)address)); + field_datum_byte_offset, ACPI_CAST_PTR(void, + address))); /* Invoke the appropriate address_space/op_region handler */ @@ -805,18 +806,39 @@ acpi_ex_insert_into_field(union acpi_operand_object *obj_desc, u32 datum_count; u32 field_datum_count; u32 i; + u32 required_length; + void *new_buffer; ACPI_FUNCTION_TRACE(ex_insert_into_field); /* Validate input buffer */ - if (buffer_length < - ACPI_ROUND_BITS_UP_TO_BYTES(obj_desc->common_field.bit_length)) { - ACPI_ERROR((AE_INFO, - "Field size %X (bits) is too large for buffer (%X)", - obj_desc->common_field.bit_length, buffer_length)); + new_buffer = NULL; + required_length = + ACPI_ROUND_BITS_UP_TO_BYTES(obj_desc->common_field.bit_length); + /* + * We must have a buffer that is at least as long as the field + * we are writing to. This is because individual fields are + * indivisible and partial writes are not supported -- as per + * the ACPI specification. + */ + if (buffer_length < required_length) { - return_ACPI_STATUS(AE_BUFFER_OVERFLOW); + /* We need to create a new buffer */ + + new_buffer = ACPI_ALLOCATE_ZEROED(required_length); + if (!new_buffer) { + return_ACPI_STATUS(AE_NO_MEMORY); + } + + /* + * Copy the original data to the new buffer, starting + * at Byte zero. All unused (upper) bytes of the + * buffer will be 0. + */ + ACPI_MEMCPY((char *)new_buffer, (char *)buffer, buffer_length); + buffer = new_buffer; + buffer_length = required_length; } /* @@ -866,7 +888,7 @@ acpi_ex_insert_into_field(union acpi_operand_object *obj_desc, merged_datum, field_offset); if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); + goto exit; } field_offset += obj_desc->common_field.access_byte_width; @@ -924,5 +946,11 @@ acpi_ex_insert_into_field(union acpi_operand_object *obj_desc, mask, merged_datum, field_offset); + exit: + /* Free temporary buffer if we used one */ + + if (new_buffer) { + ACPI_FREE(new_buffer); + } return_ACPI_STATUS(status); } diff --git a/drivers/acpi/executer/exmisc.c b/drivers/acpi/executer/exmisc.c index f13d1cec2d6..cc956a5b526 100644 --- a/drivers/acpi/executer/exmisc.c +++ b/drivers/acpi/executer/exmisc.c @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/executer/exmutex.c b/drivers/acpi/executer/exmutex.c index 6748e3ef099..c873ab40cd0 100644 --- a/drivers/acpi/executer/exmutex.c +++ b/drivers/acpi/executer/exmutex.c @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -126,6 +126,79 @@ acpi_ex_link_mutex(union acpi_operand_object *obj_desc, /******************************************************************************* * + * FUNCTION: acpi_ex_acquire_mutex_object + * + * PARAMETERS: time_desc - Timeout in milliseconds + * obj_desc - Mutex object + * Thread - Current thread state + * + * RETURN: Status + * + * DESCRIPTION: Acquire an AML mutex, low-level interface. Provides a common + * path that supports multiple acquires by the same thread. + * + * MUTEX: Interpreter must be locked + * + * NOTE: This interface is called from three places: + * 1) From acpi_ex_acquire_mutex, via an AML Acquire() operator + * 2) From acpi_ex_acquire_global_lock when an AML Field access requires the + * global lock + * 3) From the external interface, acpi_acquire_global_lock + * + ******************************************************************************/ + +acpi_status +acpi_ex_acquire_mutex_object(u16 timeout, + union acpi_operand_object *obj_desc, + acpi_thread_id thread_id) +{ + acpi_status status; + + ACPI_FUNCTION_TRACE_PTR(ex_acquire_mutex_object, obj_desc); + + if (!obj_desc) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + /* Support for multiple acquires by the owning thread */ + + if (obj_desc->mutex.thread_id == thread_id) { + /* + * The mutex is already owned by this thread, just increment the + * acquisition depth + */ + obj_desc->mutex.acquisition_depth++; + return_ACPI_STATUS(AE_OK); + } + + /* Acquire the mutex, wait if necessary. Special case for Global Lock */ + + if (obj_desc == acpi_gbl_global_lock_mutex) { + status = acpi_ev_acquire_global_lock(timeout); + } else { + status = acpi_ex_system_wait_mutex(obj_desc->mutex.os_mutex, + timeout); + } + + if (ACPI_FAILURE(status)) { + + /* Includes failure from a timeout on time_desc */ + + return_ACPI_STATUS(status); + } + + /* Acquired the mutex: update mutex object */ + + obj_desc->mutex.thread_id = thread_id; + obj_desc->mutex.acquisition_depth = 1; + obj_desc->mutex.original_sync_level = 0; + obj_desc->mutex.owner_thread = NULL; /* Used only for AML Acquire() */ + + return_ACPI_STATUS(AE_OK); +} + +/******************************************************************************* + * * FUNCTION: acpi_ex_acquire_mutex * * PARAMETERS: time_desc - Timeout integer @@ -151,7 +224,7 @@ acpi_ex_acquire_mutex(union acpi_operand_object *time_desc, return_ACPI_STATUS(AE_BAD_PARAMETER); } - /* Sanity check: we must have a valid thread ID */ + /* Must have a valid thread ID */ if (!walk_state->thread) { ACPI_ERROR((AE_INFO, @@ -161,7 +234,7 @@ acpi_ex_acquire_mutex(union acpi_operand_object *time_desc, } /* - * Current Sync must be less than or equal to the sync level of the + * Current sync level must be less than or equal to the sync level of the * mutex. This mechanism provides some deadlock prevention */ if (walk_state->thread->current_sync_level > obj_desc->mutex.sync_level) { @@ -172,51 +245,89 @@ acpi_ex_acquire_mutex(union acpi_operand_object *time_desc, return_ACPI_STATUS(AE_AML_MUTEX_ORDER); } - /* Support for multiple acquires by the owning thread */ + status = acpi_ex_acquire_mutex_object((u16) time_desc->integer.value, + obj_desc, + walk_state->thread->thread_id); + if (ACPI_SUCCESS(status) && obj_desc->mutex.acquisition_depth == 1) { - if (obj_desc->mutex.owner_thread) { - if (obj_desc->mutex.owner_thread->thread_id == - walk_state->thread->thread_id) { - /* - * The mutex is already owned by this thread, just increment the - * acquisition depth - */ - obj_desc->mutex.acquisition_depth++; - return_ACPI_STATUS(AE_OK); - } + /* Save Thread object, original/current sync levels */ + + obj_desc->mutex.owner_thread = walk_state->thread; + obj_desc->mutex.original_sync_level = + walk_state->thread->current_sync_level; + walk_state->thread->current_sync_level = + obj_desc->mutex.sync_level; + + /* Link the mutex to the current thread for force-unlock at method exit */ + + acpi_ex_link_mutex(obj_desc, walk_state->thread); } - /* Acquire the mutex, wait if necessary. Special case for Global Lock */ + return_ACPI_STATUS(status); +} - if (obj_desc->mutex.os_mutex == acpi_gbl_global_lock_mutex) { - status = - acpi_ev_acquire_global_lock((u16) time_desc->integer.value); - } else { - status = acpi_ex_system_wait_mutex(obj_desc->mutex.os_mutex, - (u16) time_desc->integer. - value); +/******************************************************************************* + * + * FUNCTION: acpi_ex_release_mutex_object + * + * PARAMETERS: obj_desc - The object descriptor for this op + * + * RETURN: Status + * + * DESCRIPTION: Release a previously acquired Mutex, low level interface. + * Provides a common path that supports multiple releases (after + * previous multiple acquires) by the same thread. + * + * MUTEX: Interpreter must be locked + * + * NOTE: This interface is called from three places: + * 1) From acpi_ex_release_mutex, via an AML Acquire() operator + * 2) From acpi_ex_release_global_lock when an AML Field access requires the + * global lock + * 3) From the external interface, acpi_release_global_lock + * + ******************************************************************************/ + +acpi_status acpi_ex_release_mutex_object(union acpi_operand_object *obj_desc) +{ + acpi_status status = AE_OK; + + ACPI_FUNCTION_TRACE(ex_release_mutex_object); + + if (obj_desc->mutex.acquisition_depth == 0) { + return (AE_NOT_ACQUIRED); } - if (ACPI_FAILURE(status)) { + /* Match multiple Acquires with multiple Releases */ - /* Includes failure from a timeout on time_desc */ + obj_desc->mutex.acquisition_depth--; + if (obj_desc->mutex.acquisition_depth != 0) { - return_ACPI_STATUS(status); + /* Just decrement the depth and return */ + + return_ACPI_STATUS(AE_OK); } - /* Have the mutex: update mutex and walk info and save the sync_level */ + if (obj_desc->mutex.owner_thread) { - obj_desc->mutex.owner_thread = walk_state->thread; - obj_desc->mutex.acquisition_depth = 1; - obj_desc->mutex.original_sync_level = - walk_state->thread->current_sync_level; + /* Unlink the mutex from the owner's list */ - walk_state->thread->current_sync_level = obj_desc->mutex.sync_level; + acpi_ex_unlink_mutex(obj_desc); + obj_desc->mutex.owner_thread = NULL; + } - /* Link the mutex to the current thread for force-unlock at method exit */ + /* Release the mutex, special case for Global Lock */ - acpi_ex_link_mutex(obj_desc, walk_state->thread); - return_ACPI_STATUS(AE_OK); + if (obj_desc == acpi_gbl_global_lock_mutex) { + status = acpi_ev_release_global_lock(); + } else { + acpi_os_release_mutex(obj_desc->mutex.os_mutex); + } + + /* Clear mutex info */ + + obj_desc->mutex.thread_id = 0; + return_ACPI_STATUS(status); } /******************************************************************************* @@ -253,22 +364,13 @@ acpi_ex_release_mutex(union acpi_operand_object *obj_desc, return_ACPI_STATUS(AE_AML_MUTEX_NOT_ACQUIRED); } - /* Sanity check: we must have a valid thread ID */ - - if (!walk_state->thread) { - ACPI_ERROR((AE_INFO, - "Cannot release Mutex [%4.4s], null thread info", - acpi_ut_get_node_name(obj_desc->mutex.node))); - return_ACPI_STATUS(AE_AML_INTERNAL); - } - /* * The Mutex is owned, but this thread must be the owner. * Special case for Global Lock, any thread can release */ if ((obj_desc->mutex.owner_thread->thread_id != walk_state->thread->thread_id) - && (obj_desc->mutex.os_mutex != acpi_gbl_global_lock_mutex)) { + && (obj_desc != acpi_gbl_global_lock_mutex)) { ACPI_ERROR((AE_INFO, "Thread %lX cannot release Mutex [%4.4s] acquired by thread %lX", (unsigned long)walk_state->thread->thread_id, @@ -278,45 +380,37 @@ acpi_ex_release_mutex(union acpi_operand_object *obj_desc, return_ACPI_STATUS(AE_AML_NOT_OWNER); } + /* Must have a valid thread ID */ + + if (!walk_state->thread) { + ACPI_ERROR((AE_INFO, + "Cannot release Mutex [%4.4s], null thread info", + acpi_ut_get_node_name(obj_desc->mutex.node))); + return_ACPI_STATUS(AE_AML_INTERNAL); + } + /* * The sync level of the mutex must be less than or equal to the current * sync level */ if (obj_desc->mutex.sync_level > walk_state->thread->current_sync_level) { ACPI_ERROR((AE_INFO, - "Cannot release Mutex [%4.4s], incorrect SyncLevel", - acpi_ut_get_node_name(obj_desc->mutex.node))); + "Cannot release Mutex [%4.4s], SyncLevel mismatch: mutex %d current %d", + acpi_ut_get_node_name(obj_desc->mutex.node), + obj_desc->mutex.sync_level, + walk_state->thread->current_sync_level)); return_ACPI_STATUS(AE_AML_MUTEX_ORDER); } - /* Match multiple Acquires with multiple Releases */ - - obj_desc->mutex.acquisition_depth--; - if (obj_desc->mutex.acquisition_depth != 0) { - - /* Just decrement the depth and return */ - - return_ACPI_STATUS(AE_OK); - } - - /* Unlink the mutex from the owner's list */ + status = acpi_ex_release_mutex_object(obj_desc); - acpi_ex_unlink_mutex(obj_desc); + if (obj_desc->mutex.acquisition_depth == 0) { - /* Release the mutex, special case for Global Lock */ + /* Restore the original sync_level */ - if (obj_desc->mutex.os_mutex == acpi_gbl_global_lock_mutex) { - status = acpi_ev_release_global_lock(); - } else { - acpi_os_release_mutex(obj_desc->mutex.os_mutex); + walk_state->thread->current_sync_level = + obj_desc->mutex.original_sync_level; } - - /* Update the mutex and restore sync_level */ - - obj_desc->mutex.owner_thread = NULL; - walk_state->thread->current_sync_level = - obj_desc->mutex.original_sync_level; - return_ACPI_STATUS(status); } @@ -357,7 +451,7 @@ void acpi_ex_release_all_mutexes(struct acpi_thread_state *thread) /* Release the mutex, special case for Global Lock */ - if (obj_desc->mutex.os_mutex == acpi_gbl_global_lock_mutex) { + if (obj_desc == acpi_gbl_global_lock_mutex) { /* Ignore errors */ @@ -369,6 +463,7 @@ void acpi_ex_release_all_mutexes(struct acpi_thread_state *thread) /* Mark mutex unowned */ obj_desc->mutex.owner_thread = NULL; + obj_desc->mutex.thread_id = 0; /* Update Thread sync_level (Last mutex is the important one) */ diff --git a/drivers/acpi/executer/exnames.c b/drivers/acpi/executer/exnames.c index 308eae52dc0..817e67be369 100644 --- a/drivers/acpi/executer/exnames.c +++ b/drivers/acpi/executer/exnames.c @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/executer/exoparg1.c b/drivers/acpi/executer/exoparg1.c index 252f10acbbc..7c3bea575e0 100644 --- a/drivers/acpi/executer/exoparg1.c +++ b/drivers/acpi/executer/exoparg1.c @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -121,6 +121,7 @@ acpi_status acpi_ex_opcode_0A_0T_1R(struct acpi_walk_state *walk_state) if ((ACPI_FAILURE(status)) || walk_state->result_obj) { acpi_ut_remove_reference(return_desc); + walk_state->result_obj = NULL; } else { /* Save the return value */ @@ -739,26 +740,38 @@ acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state) value = acpi_gbl_integer_byte_width; break; - case ACPI_TYPE_BUFFER: - value = temp_desc->buffer.length; - break; - case ACPI_TYPE_STRING: value = temp_desc->string.length; break; + case ACPI_TYPE_BUFFER: + + /* Buffer arguments may not be evaluated at this point */ + + status = acpi_ds_get_buffer_arguments(temp_desc); + value = temp_desc->buffer.length; + break; + case ACPI_TYPE_PACKAGE: + + /* Package arguments may not be evaluated at this point */ + + status = acpi_ds_get_package_arguments(temp_desc); value = temp_desc->package.count; break; default: ACPI_ERROR((AE_INFO, - "Operand is not Buf/Int/Str/Pkg - found type %s", + "Operand must be Buffer/Integer/String/Package - found type %s", acpi_ut_get_type_name(type))); status = AE_AML_OPERAND_TYPE; goto cleanup; } + if (ACPI_FAILURE(status)) { + goto cleanup; + } + /* * Now that we have the size of the object, create a result * object to hold the value diff --git a/drivers/acpi/executer/exoparg2.c b/drivers/acpi/executer/exoparg2.c index 17e652e6537..8e8bbb6cceb 100644 --- a/drivers/acpi/executer/exoparg2.c +++ b/drivers/acpi/executer/exoparg2.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -241,10 +241,6 @@ acpi_status acpi_ex_opcode_2A_2T_1R(struct acpi_walk_state *walk_state) goto cleanup; } - /* Return the remainder */ - - walk_state->result_obj = return_desc1; - cleanup: /* * Since the remainder is not returned indirectly, remove a reference to @@ -259,6 +255,12 @@ acpi_status acpi_ex_opcode_2A_2T_1R(struct acpi_walk_state *walk_state) acpi_ut_remove_reference(return_desc1); } + /* Save return object (the remainder) on success */ + + else { + walk_state->result_obj = return_desc1; + } + return_ACPI_STATUS(status); } @@ -490,6 +492,7 @@ acpi_status acpi_ex_opcode_2A_1T_1R(struct acpi_walk_state *walk_state) if (ACPI_FAILURE(status)) { acpi_ut_remove_reference(return_desc); + walk_state->result_obj = NULL; } return_ACPI_STATUS(status); @@ -583,8 +586,6 @@ acpi_status acpi_ex_opcode_2A_0T_1R(struct acpi_walk_state *walk_state) return_desc->integer.value = ACPI_INTEGER_MAX; } - walk_state->result_obj = return_desc; - cleanup: /* Delete return object on error */ @@ -593,5 +594,11 @@ acpi_status acpi_ex_opcode_2A_0T_1R(struct acpi_walk_state *walk_state) acpi_ut_remove_reference(return_desc); } + /* Save return object on success */ + + else { + walk_state->result_obj = return_desc; + } + return_ACPI_STATUS(status); } diff --git a/drivers/acpi/executer/exoparg3.c b/drivers/acpi/executer/exoparg3.c index 7fe67cf82ce..9cb4197681a 100644 --- a/drivers/acpi/executer/exoparg3.c +++ b/drivers/acpi/executer/exoparg3.c @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -260,6 +260,7 @@ acpi_status acpi_ex_opcode_3A_1T_1R(struct acpi_walk_state *walk_state) if (ACPI_FAILURE(status) || walk_state->result_obj) { acpi_ut_remove_reference(return_desc); + walk_state->result_obj = NULL; } /* Set the return object and exit */ diff --git a/drivers/acpi/executer/exoparg6.c b/drivers/acpi/executer/exoparg6.c index bd80a9cb3d6..67d48737af5 100644 --- a/drivers/acpi/executer/exoparg6.c +++ b/drivers/acpi/executer/exoparg6.c @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -322,8 +322,6 @@ acpi_status acpi_ex_opcode_6A_0T_1R(struct acpi_walk_state * walk_state) goto cleanup; } - walk_state->result_obj = return_desc; - cleanup: /* Delete return object on error */ @@ -332,5 +330,11 @@ acpi_status acpi_ex_opcode_6A_0T_1R(struct acpi_walk_state * walk_state) acpi_ut_remove_reference(return_desc); } + /* Save return object on success */ + + else { + walk_state->result_obj = return_desc; + } + return_ACPI_STATUS(status); } diff --git a/drivers/acpi/executer/exprep.c b/drivers/acpi/executer/exprep.c index efe5d4b461a..3a2f8cd4c62 100644 --- a/drivers/acpi/executer/exprep.c +++ b/drivers/acpi/executer/exprep.c @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -412,6 +412,7 @@ acpi_ex_prep_common_field_object(union acpi_operand_object *obj_desc, acpi_status acpi_ex_prep_field_value(struct acpi_create_field_info *info) { union acpi_operand_object *obj_desc; + union acpi_operand_object *second_desc = NULL; u32 type; acpi_status status; @@ -494,6 +495,20 @@ acpi_status acpi_ex_prep_field_value(struct acpi_create_field_info *info) obj_desc->field.access_byte_width, obj_desc->bank_field.region_obj, obj_desc->bank_field.bank_obj)); + + /* + * Remember location in AML stream of the field unit + * opcode and operands -- since the bank_value + * operands must be evaluated. + */ + second_desc = obj_desc->common.next_object; + second_desc->extra.aml_start = + ((union acpi_parse_object *)(info->data_register_node))-> + named.data; + second_desc->extra.aml_length = + ((union acpi_parse_object *)(info->data_register_node))-> + named.length; + break; case ACPI_TYPE_LOCAL_INDEX_FIELD: diff --git a/drivers/acpi/executer/exregion.c b/drivers/acpi/executer/exregion.c index 3f51b7e84a1..7cd8bb54fa0 100644 --- a/drivers/acpi/executer/exregion.c +++ b/drivers/acpi/executer/exregion.c @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -160,7 +160,7 @@ acpi_ex_system_memory_space_handler(u32 function, if (!mem_info->mapped_logical_address) { ACPI_ERROR((AE_INFO, "Could not map memory at %8.8X%8.8X, size %X", - ACPI_FORMAT_UINT64(address), + ACPI_FORMAT_NATIVE_UINT(address), (u32) window_size)); mem_info->mapped_length = 0; return_ACPI_STATUS(AE_NO_MEMORY); @@ -182,7 +182,8 @@ acpi_ex_system_memory_space_handler(u32 function, ACPI_DEBUG_PRINT((ACPI_DB_INFO, "System-Memory (width %d) R/W %d Address=%8.8X%8.8X\n", - bit_width, function, ACPI_FORMAT_UINT64(address))); + bit_width, function, + ACPI_FORMAT_NATIVE_UINT(address))); /* * Perform the memory read or write @@ -284,7 +285,8 @@ acpi_ex_system_io_space_handler(u32 function, ACPI_DEBUG_PRINT((ACPI_DB_INFO, "System-IO (width %d) R/W %d Address=%8.8X%8.8X\n", - bit_width, function, ACPI_FORMAT_UINT64(address))); + bit_width, function, + ACPI_FORMAT_NATIVE_UINT(address))); /* Decode the function parameter */ diff --git a/drivers/acpi/executer/exresnte.c b/drivers/acpi/executer/exresnte.c index 2b3a01cc492..5596f42c967 100644 --- a/drivers/acpi/executer/exresnte.c +++ b/drivers/acpi/executer/exresnte.c @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -116,9 +116,11 @@ acpi_ex_resolve_node_to_value(struct acpi_namespace_node **object_ptr, * Several object types require no further processing: * 1) Device/Thermal objects don't have a "real" subobject, return the Node * 2) Method locals and arguments have a pseudo-Node + * 3) 10/2007: Added method type to assist with Package construction. */ if ((entry_type == ACPI_TYPE_DEVICE) || (entry_type == ACPI_TYPE_THERMAL) || + (entry_type == ACPI_TYPE_METHOD) || (node->flags & (ANOBJ_METHOD_ARG | ANOBJ_METHOD_LOCAL))) { return_ACPI_STATUS(AE_OK); } @@ -214,7 +216,6 @@ acpi_ex_resolve_node_to_value(struct acpi_namespace_node **object_ptr, /* For these objects, just return the object attached to the Node */ case ACPI_TYPE_MUTEX: - case ACPI_TYPE_METHOD: case ACPI_TYPE_POWER: case ACPI_TYPE_PROCESSOR: case ACPI_TYPE_EVENT: @@ -238,13 +239,12 @@ acpi_ex_resolve_node_to_value(struct acpi_namespace_node **object_ptr, case ACPI_TYPE_LOCAL_REFERENCE: switch (source_desc->reference.opcode) { - case AML_LOAD_OP: + case AML_LOAD_OP: /* This is a ddb_handle */ + case AML_REF_OF_OP: + case AML_INDEX_OP: - /* This is a ddb_handle */ /* Return an additional reference to the object */ - case AML_REF_OF_OP: - obj_desc = source_desc; acpi_ut_add_reference(obj_desc); break; diff --git a/drivers/acpi/executer/exresolv.c b/drivers/acpi/executer/exresolv.c index 6c64e55dab0..b35f7c817ac 100644 --- a/drivers/acpi/executer/exresolv.c +++ b/drivers/acpi/executer/exresolv.c @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -140,7 +140,6 @@ acpi_ex_resolve_object_to_value(union acpi_operand_object **stack_ptr, { acpi_status status = AE_OK; union acpi_operand_object *stack_desc; - void *temp_node; union acpi_operand_object *obj_desc = NULL; u16 opcode; @@ -156,23 +155,6 @@ acpi_ex_resolve_object_to_value(union acpi_operand_object **stack_ptr, opcode = stack_desc->reference.opcode; switch (opcode) { - case AML_NAME_OP: - - /* - * Convert name reference to a namespace node - * Then, acpi_ex_resolve_node_to_value can be used to get the value - */ - temp_node = stack_desc->reference.object; - - /* Delete the Reference Object */ - - acpi_ut_remove_reference(stack_desc); - - /* Return the namespace node */ - - (*stack_ptr) = temp_node; - break; - case AML_LOCAL_OP: case AML_ARG_OP: @@ -207,15 +189,25 @@ acpi_ex_resolve_object_to_value(union acpi_operand_object **stack_ptr, switch (stack_desc->reference.target_type) { case ACPI_TYPE_BUFFER_FIELD: - /* Just return - leave the Reference on the stack */ + /* Just return - do not dereference */ break; case ACPI_TYPE_PACKAGE: + /* If method call or copy_object - do not dereference */ + + if ((walk_state->opcode == + AML_INT_METHODCALL_OP) + || (walk_state->opcode == AML_COPY_OP)) { + break; + } + + /* Otherwise, dereference the package_index to a package element */ + obj_desc = *stack_desc->reference.where; if (obj_desc) { /* - * Valid obj descriptor, copy pointer to return value + * Valid object descriptor, copy pointer to return value * (i.e., dereference the package index) * Delete the ref object, increment the returned object */ @@ -224,11 +216,11 @@ acpi_ex_resolve_object_to_value(union acpi_operand_object **stack_ptr, *stack_ptr = obj_desc; } else { /* - * A NULL object descriptor means an unitialized element of + * A NULL object descriptor means an uninitialized element of * the package, can't dereference it */ ACPI_ERROR((AE_INFO, - "Attempt to deref an Index to NULL pkg element Idx=%p", + "Attempt to dereference an Index to NULL package element Idx=%p", stack_desc)); status = AE_AML_UNINITIALIZED_ELEMENT; } @@ -239,7 +231,7 @@ acpi_ex_resolve_object_to_value(union acpi_operand_object **stack_ptr, /* Invalid reference object */ ACPI_ERROR((AE_INFO, - "Unknown TargetType %X in Index/Reference obj %p", + "Unknown TargetType %X in Index/Reference object %p", stack_desc->reference.target_type, stack_desc)); status = AE_AML_INTERNAL; @@ -251,7 +243,7 @@ acpi_ex_resolve_object_to_value(union acpi_operand_object **stack_ptr, case AML_DEBUG_OP: case AML_LOAD_OP: - /* Just leave the object as-is */ + /* Just leave the object as-is, do not dereference */ break; @@ -390,10 +382,10 @@ acpi_ex_resolve_multiple(struct acpi_walk_state *walk_state, } /* - * For reference objects created via the ref_of or Index operators, - * we need to get to the base object (as per the ACPI specification - * of the object_type and size_of operators). This means traversing - * the list of possibly many nested references. + * For reference objects created via the ref_of, Index, or Load/load_table + * operators, we need to get to the base object (as per the ACPI + * specification of the object_type and size_of operators). This means + * traversing the list of possibly many nested references. */ while (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_LOCAL_REFERENCE) { switch (obj_desc->reference.opcode) { @@ -463,6 +455,11 @@ acpi_ex_resolve_multiple(struct acpi_walk_state *walk_state, } break; + case AML_LOAD_OP: + + type = ACPI_TYPE_DDB_HANDLE; + goto exit; + case AML_LOCAL_OP: case AML_ARG_OP: diff --git a/drivers/acpi/executer/exresop.c b/drivers/acpi/executer/exresop.c index 09d897b3f6d..73e29e566a7 100644 --- a/drivers/acpi/executer/exresop.c +++ b/drivers/acpi/executer/exresop.c @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -137,7 +137,6 @@ acpi_ex_resolve_operands(u16 opcode, union acpi_operand_object *obj_desc; acpi_status status = AE_OK; u8 object_type; - void *temp_node; u32 arg_types; const struct acpi_opcode_info *op_info; u32 this_arg_type; @@ -239,7 +238,6 @@ acpi_ex_resolve_operands(u16 opcode, /*lint -fallthrough */ - case AML_NAME_OP: case AML_INDEX_OP: case AML_REF_OF_OP: case AML_ARG_OP: @@ -332,15 +330,6 @@ acpi_ex_resolve_operands(u16 opcode, if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } - - if (obj_desc->reference.opcode == AML_NAME_OP) { - - /* Convert a named reference to the actual named object */ - - temp_node = obj_desc->reference.object; - acpi_ut_remove_reference(obj_desc); - (*stack_ptr) = temp_node; - } goto next_operand; case ARGI_DATAREFOBJ: /* Store operator only */ diff --git a/drivers/acpi/executer/exstore.c b/drivers/acpi/executer/exstore.c index f4b69a63782..76c875bc315 100644 --- a/drivers/acpi/executer/exstore.c +++ b/drivers/acpi/executer/exstore.c @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -84,8 +84,12 @@ acpi_ex_do_debug_object(union acpi_operand_object *source_desc, ACPI_FUNCTION_TRACE_PTR(ex_do_debug_object, source_desc); - ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "[ACPI Debug] %*s", - level, " ")); + /* Print line header as long as we are not in the middle of an object display */ + + if (!((level > 0) && index == 0)) { + ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "[ACPI Debug] %*s", + level, " ")); + } /* Display index for package output only */ @@ -95,12 +99,12 @@ acpi_ex_do_debug_object(union acpi_operand_object *source_desc, } if (!source_desc) { - ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "<Null Object>\n")); + ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "[Null Object]\n")); return_VOID; } if (ACPI_GET_DESCRIPTOR_TYPE(source_desc) == ACPI_DESC_TYPE_OPERAND) { - ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "%s: ", + ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "%s ", acpi_ut_get_object_type_name (source_desc))); @@ -123,6 +127,8 @@ acpi_ex_do_debug_object(union acpi_operand_object *source_desc, return_VOID; } + /* source_desc is of type ACPI_DESC_TYPE_OPERAND */ + switch (ACPI_GET_OBJECT_TYPE(source_desc)) { case ACPI_TYPE_INTEGER: @@ -147,7 +153,7 @@ acpi_ex_do_debug_object(union acpi_operand_object *source_desc, (u32) source_desc->buffer.length)); ACPI_DUMP_BUFFER(source_desc->buffer.pointer, (source_desc->buffer.length < - 32) ? source_desc->buffer.length : 32); + 256) ? source_desc->buffer.length : 256); break; case ACPI_TYPE_STRING: @@ -160,7 +166,7 @@ acpi_ex_do_debug_object(union acpi_operand_object *source_desc, case ACPI_TYPE_PACKAGE: ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, - "[0x%.2X Elements]\n", + "[Contains 0x%.2X Elements]\n", source_desc->package.count)); /* Output the entire contents of the package */ @@ -180,12 +186,59 @@ acpi_ex_do_debug_object(union acpi_operand_object *source_desc, (source_desc->reference.opcode), source_desc->reference.offset)); } else { - ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "[%s]\n", + ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "[%s]", acpi_ps_get_opcode_name (source_desc->reference.opcode))); } - if (source_desc->reference.object) { + if (source_desc->reference.opcode == AML_LOAD_OP) { /* Load and load_table */ + ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, + " Table OwnerId %p\n", + source_desc->reference.object)); + break; + } + + ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, " ")); + + /* Check for valid node first, then valid object */ + + if (source_desc->reference.node) { + if (ACPI_GET_DESCRIPTOR_TYPE + (source_desc->reference.node) != + ACPI_DESC_TYPE_NAMED) { + ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, + " %p - Not a valid namespace node\n", + source_desc->reference. + node)); + } else { + ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, + "Node %p [%4.4s] ", + source_desc->reference. + node, + (source_desc->reference. + node)->name.ascii)); + + switch ((source_desc->reference.node)->type) { + + /* These types have no attached object */ + + case ACPI_TYPE_DEVICE: + acpi_os_printf("Device\n"); + break; + + case ACPI_TYPE_THERMAL: + acpi_os_printf("Thermal Zone\n"); + break; + + default: + acpi_ex_do_debug_object((source_desc-> + reference. + node)->object, + level + 4, 0); + break; + } + } + } else if (source_desc->reference.object) { if (ACPI_GET_DESCRIPTOR_TYPE (source_desc->reference.object) == ACPI_DESC_TYPE_NAMED) { @@ -198,18 +251,13 @@ acpi_ex_do_debug_object(union acpi_operand_object *source_desc, acpi_ex_do_debug_object(source_desc->reference. object, level + 4, 0); } - } else if (source_desc->reference.node) { - acpi_ex_do_debug_object((source_desc->reference.node)-> - object, level + 4, 0); } break; default: - ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "%p %s\n", - source_desc, - acpi_ut_get_object_type_name - (source_desc))); + ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "%p\n", + source_desc)); break; } @@ -313,7 +361,6 @@ acpi_ex_store(union acpi_operand_object *source_desc, * 4) Store to the debug object */ switch (ref_desc->reference.opcode) { - case AML_NAME_OP: case AML_REF_OF_OP: /* Storing an object into a Name "container" */ @@ -415,11 +462,24 @@ acpi_ex_store_object_to_index(union acpi_operand_object *source_desc, */ obj_desc = *(index_desc->reference.where); - status = - acpi_ut_copy_iobject_to_iobject(source_desc, &new_desc, - walk_state); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); + if (ACPI_GET_OBJECT_TYPE(source_desc) == + ACPI_TYPE_LOCAL_REFERENCE + && source_desc->reference.opcode == AML_LOAD_OP) { + + /* This is a DDBHandle, just add a reference to it */ + + acpi_ut_add_reference(source_desc); + new_desc = source_desc; + } else { + /* Normal object, copy it */ + + status = + acpi_ut_copy_iobject_to_iobject(source_desc, + &new_desc, + walk_state); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } } if (obj_desc) { @@ -571,10 +631,17 @@ acpi_ex_store_object_to_node(union acpi_operand_object *source_desc, /* If no implicit conversion, drop into the default case below */ - if ((!implicit_conversion) || (walk_state->opcode == AML_COPY_OP)) { - - /* Force execution of default (no implicit conversion) */ - + if ((!implicit_conversion) || + ((walk_state->opcode == AML_COPY_OP) && + (target_type != ACPI_TYPE_LOCAL_REGION_FIELD) && + (target_type != ACPI_TYPE_LOCAL_BANK_FIELD) && + (target_type != ACPI_TYPE_LOCAL_INDEX_FIELD))) { + /* + * Force execution of default (no implicit conversion). Note: + * copy_object does not perform an implicit conversion, as per the ACPI + * spec -- except in case of region/bank/index fields -- because these + * objects must retain their original type permanently. + */ target_type = ACPI_TYPE_ANY; } diff --git a/drivers/acpi/executer/exstoren.c b/drivers/acpi/executer/exstoren.c index 1d622c625c6..a6d2168b81f 100644 --- a/drivers/acpi/executer/exstoren.c +++ b/drivers/acpi/executer/exstoren.c @@ -7,7 +7,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/executer/exstorob.c b/drivers/acpi/executer/exstorob.c index 8233d40178e..9a75ff09fb0 100644 --- a/drivers/acpi/executer/exstorob.c +++ b/drivers/acpi/executer/exstorob.c @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/executer/exsystem.c b/drivers/acpi/executer/exsystem.c index 9460baff303..68990f1df37 100644 --- a/drivers/acpi/executer/exsystem.c +++ b/drivers/acpi/executer/exsystem.c @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -44,7 +44,6 @@ #include <acpi/acpi.h> #include <acpi/acinterp.h> -#include <acpi/acevents.h> #define _COMPONENT ACPI_EXECUTER ACPI_MODULE_NAME("exsystem") diff --git a/drivers/acpi/executer/exutils.c b/drivers/acpi/executer/exutils.c index 6b0aeccbb69..86c03880b52 100644 --- a/drivers/acpi/executer/exutils.c +++ b/drivers/acpi/executer/exutils.c @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -61,7 +61,6 @@ #include <acpi/acpi.h> #include <acpi/acinterp.h> #include <acpi/amlcode.h> -#include <acpi/acevents.h> #define _COMPONENT ACPI_EXECUTER ACPI_MODULE_NAME("exutils") @@ -217,9 +216,10 @@ void acpi_ex_truncate_for32bit_table(union acpi_operand_object *obj_desc) /* * Object must be a valid number and we must be executing - * a control method + * a control method. NS node could be there for AML_INT_NAMEPATH_OP. */ if ((!obj_desc) || + (ACPI_GET_DESCRIPTOR_TYPE(obj_desc) != ACPI_DESC_TYPE_OPERAND) || (ACPI_GET_OBJECT_TYPE(obj_desc) != ACPI_TYPE_INTEGER)) { return; } @@ -240,72 +240,73 @@ void acpi_ex_truncate_for32bit_table(union acpi_operand_object *obj_desc) * PARAMETERS: field_flags - Flags with Lock rule: * always_lock or never_lock * - * RETURN: TRUE/FALSE indicating whether the lock was actually acquired + * RETURN: None * - * DESCRIPTION: Obtain the global lock and keep track of this fact via two - * methods. A global variable keeps the state of the lock, and - * the state is returned to the caller. + * DESCRIPTION: Obtain the ACPI hardware Global Lock, only if the field + * flags specifiy that it is to be obtained before field access. * ******************************************************************************/ -u8 acpi_ex_acquire_global_lock(u32 field_flags) +void acpi_ex_acquire_global_lock(u32 field_flags) { - u8 locked = FALSE; acpi_status status; ACPI_FUNCTION_TRACE(ex_acquire_global_lock); - /* Only attempt lock if the always_lock bit is set */ + /* Only use the lock if the always_lock bit is set */ + + if (!(field_flags & AML_FIELD_LOCK_RULE_MASK)) { + return_VOID; + } - if (field_flags & AML_FIELD_LOCK_RULE_MASK) { + /* Attempt to get the global lock, wait forever */ - /* We should attempt to get the lock, wait forever */ + status = acpi_ex_acquire_mutex_object(ACPI_WAIT_FOREVER, + acpi_gbl_global_lock_mutex, + acpi_os_get_thread_id()); - status = acpi_ev_acquire_global_lock(ACPI_WAIT_FOREVER); - if (ACPI_SUCCESS(status)) { - locked = TRUE; - } else { - ACPI_EXCEPTION((AE_INFO, status, - "Could not acquire Global Lock")); - } + if (ACPI_FAILURE(status)) { + ACPI_EXCEPTION((AE_INFO, status, + "Could not acquire Global Lock")); } - return_UINT8(locked); + return_VOID; } /******************************************************************************* * * FUNCTION: acpi_ex_release_global_lock * - * PARAMETERS: locked_by_me - Return value from corresponding call to - * acquire_global_lock. + * PARAMETERS: field_flags - Flags with Lock rule: + * always_lock or never_lock * * RETURN: None * - * DESCRIPTION: Release the global lock if it is locked. + * DESCRIPTION: Release the ACPI hardware Global Lock * ******************************************************************************/ -void acpi_ex_release_global_lock(u8 locked_by_me) +void acpi_ex_release_global_lock(u32 field_flags) { acpi_status status; ACPI_FUNCTION_TRACE(ex_release_global_lock); - /* Only attempt unlock if the caller locked it */ + /* Only use the lock if the always_lock bit is set */ - if (locked_by_me) { + if (!(field_flags & AML_FIELD_LOCK_RULE_MASK)) { + return_VOID; + } - /* OK, now release the lock */ + /* Release the global lock */ - status = acpi_ev_release_global_lock(); - if (ACPI_FAILURE(status)) { + status = acpi_ex_release_mutex_object(acpi_gbl_global_lock_mutex); + if (ACPI_FAILURE(status)) { - /* Report the error, but there isn't much else we can do */ + /* Report the error, but there isn't much else we can do */ - ACPI_EXCEPTION((AE_INFO, status, - "Could not release ACPI Global Lock")); - } + ACPI_EXCEPTION((AE_INFO, status, + "Could not release Global Lock")); } return_VOID; |