Skip to content

Commit

Permalink
ACPICA: Implemented full support for deferred execution for the TermA…
Browse files Browse the repository at this point in the history
…rg string arguments for DataTableRegion

This enables forward references and full operand resolution for
the three string arguments. Similar to OperationRegion deferred
argument execution.)

http://www.acpica.org/bugzilla/show_bug.cgi?id=430

Signed-off-by: Lin Ming <ming.m.lin@intel.com>
Signed-off-by: Bob Moore <robert.moore@intel.com>
Signed-off-by: Alexey Starikovskiy <astarikovskiy@suse.de>
Signed-off-by: Len Brown <len.brown@intel.com>
  • Loading branch information
Lin Ming authored and Len Brown committed Apr 22, 2008
1 parent 9aa6169 commit 941f48b
Show file tree
Hide file tree
Showing 9 changed files with 160 additions and 110 deletions.
103 changes: 103 additions & 0 deletions drivers/acpi/dispatcher/dsopcode.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
#include <acpi/acinterp.h>
#include <acpi/acnamesp.h>
#include <acpi/acevents.h>
#include <acpi/actables.h>

#define _COMPONENT ACPI_DISPATCHER
ACPI_MODULE_NAME("dsopcode")
Expand Down Expand Up @@ -780,6 +781,108 @@ acpi_ds_eval_region_operands(struct acpi_walk_state *walk_state,
return_ACPI_STATUS(status);
}

/*******************************************************************************
*
* FUNCTION: acpi_ds_eval_table_region_operands
*
* PARAMETERS: walk_state - Current walk
* Op - A valid region Op object
*
* RETURN: Status
*
* DESCRIPTION: Get region address and length
* Called from acpi_ds_exec_end_op during data_table_region parse tree walk
*
******************************************************************************/

acpi_status
acpi_ds_eval_table_region_operands(struct acpi_walk_state *walk_state,
union acpi_parse_object *op)
{
acpi_status status;
union acpi_operand_object *obj_desc;
union acpi_operand_object **operand;
struct acpi_namespace_node *node;
union acpi_parse_object *next_op;
acpi_native_uint table_index;
struct acpi_table_header *table;

ACPI_FUNCTION_TRACE_PTR(ds_eval_table_region_operands, op);

/*
* This is where we evaluate the signature_string and oem_iDString
* and oem_table_iDString of the data_table_region declaration
*/
node = op->common.node;

/* next_op points to signature_string op */

next_op = op->common.value.arg;

/*
* Evaluate/create the signature_string and oem_iDString
* and oem_table_iDString operands
*/
status = acpi_ds_create_operands(walk_state, next_op);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}

/*
* Resolve the signature_string and oem_iDString
* and oem_table_iDString operands
*/
status = acpi_ex_resolve_operands(op->common.aml_opcode,
ACPI_WALK_OPERANDS, walk_state);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}

ACPI_DUMP_OPERANDS(ACPI_WALK_OPERANDS, ACPI_IMODE_EXECUTE,
acpi_ps_get_opcode_name(op->common.aml_opcode),
1, "after AcpiExResolveOperands");

operand = &walk_state->operands[0];

/* Find the ACPI table */

status = acpi_tb_find_table(operand[0]->string.pointer,
operand[1]->string.pointer,
operand[2]->string.pointer, &table_index);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}

acpi_ut_remove_reference(operand[0]);
acpi_ut_remove_reference(operand[1]);
acpi_ut_remove_reference(operand[2]);

status = acpi_get_table_by_index(table_index, &table);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}

obj_desc = acpi_ns_get_attached_object(node);
if (!obj_desc) {
return_ACPI_STATUS(AE_NOT_EXIST);
}

obj_desc->region.address =
(acpi_physical_address) ACPI_TO_INTEGER(table);
obj_desc->region.length = table->length;

ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "RgnObj %p Addr %8.8X%8.8X Len %X\n",
obj_desc,
ACPI_FORMAT_NATIVE_UINT(obj_desc->region.address),
obj_desc->region.length));

/* Now the address and length are valid for this opregion */

obj_desc->region.flags |= AOPOBJ_DATA_VALID;

return_ACPI_STATUS(status);
}

/*******************************************************************************
*
* FUNCTION: acpi_ds_eval_data_object_operands
Expand Down
11 changes: 11 additions & 0 deletions drivers/acpi/dispatcher/dswexec.c
Original file line number Diff line number Diff line change
Expand Up @@ -641,6 +641,17 @@ acpi_status acpi_ds_exec_end_op(struct acpi_walk_state *walk_state)
if (ACPI_FAILURE(status)) {
break;
}
} else if (op->common.aml_opcode == AML_DATA_REGION_OP) {
ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
"Executing DataTableRegion Strings Op=%p\n",
op));

status =
acpi_ds_eval_table_region_operands
(walk_state, op);
if (ACPI_FAILURE(status)) {
break;
}
}
break;

Expand Down
29 changes: 20 additions & 9 deletions drivers/acpi/dispatcher/dswload.c
Original file line number Diff line number Diff line change
Expand Up @@ -443,6 +443,15 @@ acpi_status acpi_ds_load1_end_op(struct acpi_walk_state *walk_state)
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
} else if (op->common.aml_opcode == AML_DATA_REGION_OP) {
status =
acpi_ex_create_region(op->named.data,
op->named.length,
REGION_DATA_TABLE,
walk_state);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
}
}
#endif
Expand Down Expand Up @@ -823,6 +832,7 @@ acpi_status acpi_ds_load2_end_op(struct acpi_walk_state *walk_state)
struct acpi_namespace_node *new_node;
#ifndef ACPI_NO_METHOD_EXECUTION
u32 i;
u8 region_space;
#endif

ACPI_FUNCTION_TRACE(ds_load2_end_op);
Expand Down Expand Up @@ -1003,11 +1013,6 @@ acpi_status acpi_ds_load2_end_op(struct acpi_walk_state *walk_state)
status = acpi_ex_create_event(walk_state);
break;

case AML_DATA_REGION_OP:

status = acpi_ex_create_table_region(walk_state);
break;

case AML_ALIAS_OP:

status = acpi_ex_create_alias(walk_state);
Expand Down Expand Up @@ -1035,6 +1040,15 @@ acpi_status acpi_ds_load2_end_op(struct acpi_walk_state *walk_state)
switch (op->common.aml_opcode) {
#ifndef ACPI_NO_METHOD_EXECUTION
case AML_REGION_OP:
case AML_DATA_REGION_OP:

if (op->common.aml_opcode == AML_REGION_OP) {
region_space = (acpi_adr_space_type)
((op->common.value.arg)->common.value.
integer);
} else {
region_space = REGION_DATA_TABLE;
}

/*
* If we are executing a method, initialize the region
Expand All @@ -1043,10 +1057,7 @@ acpi_status acpi_ds_load2_end_op(struct acpi_walk_state *walk_state)
status =
acpi_ex_create_region(op->named.data,
op->named.length,
(acpi_adr_space_type)
((op->common.value.
arg)->common.value.
integer),
region_space,
walk_state);
if (ACPI_FAILURE(status)) {
return (status);
Expand Down
95 changes: 0 additions & 95 deletions drivers/acpi/executer/excreate.c
Original file line number Diff line number Diff line change
Expand Up @@ -350,101 +350,6 @@ acpi_ex_create_region(u8 * aml_start,
return_ACPI_STATUS(status);
}

/*******************************************************************************
*
* 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
Expand Down
16 changes: 16 additions & 0 deletions drivers/acpi/executer/exmutex.c
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ void acpi_ex_unlink_mutex(union acpi_operand_object *obj_desc)
} else {
thread->acquired_mutex_list = obj_desc->mutex.next;
}
return;
}

/*******************************************************************************
Expand Down Expand Up @@ -298,6 +299,17 @@ acpi_status acpi_ex_release_mutex_object(union acpi_operand_object *obj_desc)
return (AE_NOT_ACQUIRED);
}

/* No obj_desc->Mutex.owner_thread for Global Lock */

/*
* Mutex to be released must be at the head of acquired list to prevent
* deadlock. (The head of the list is the last mutex acquired.)
*/
if (obj_desc->mutex.owner_thread &&
(obj_desc != obj_desc->mutex.owner_thread->acquired_mutex_list)) {
return (AE_AML_MUTEX_ORDER);
}

/* Match multiple Acquires with multiple Releases */

obj_desc->mutex.acquisition_depth--;
Expand Down Expand Up @@ -403,6 +415,9 @@ acpi_ex_release_mutex(union acpi_operand_object *obj_desc,
}

status = acpi_ex_release_mutex_object(obj_desc);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}

if (obj_desc->mutex.acquisition_depth == 0) {

Expand All @@ -411,6 +426,7 @@ acpi_ex_release_mutex(union acpi_operand_object *obj_desc,
walk_state->thread->current_sync_level =
obj_desc->mutex.original_sync_level;
}

return_ACPI_STATUS(status);
}

Expand Down
6 changes: 4 additions & 2 deletions drivers/acpi/parser/psloop.c
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,8 @@ acpi_ps_build_named_op(struct acpi_walk_state *walk_state,
acpi_ps_append_arg(*op, unnamed_op->common.value.arg);
acpi_gbl_depth++;

if ((*op)->common.aml_opcode == AML_REGION_OP) {
if ((*op)->common.aml_opcode == AML_REGION_OP ||
(*op)->common.aml_opcode == AML_DATA_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.,
Expand Down Expand Up @@ -1013,7 +1014,8 @@ acpi_status acpi_ps_parse_loop(struct acpi_walk_state *walk_state)
acpi_gbl_depth--;
}

if (op->common.aml_opcode == AML_REGION_OP) {
if (op->common.aml_opcode == AML_REGION_OP ||
op->common.aml_opcode == AML_DATA_REGION_OP) {
/*
* Skip parsing of control method or opregion body,
* because we don't have enough info in the first pass
Expand Down
4 changes: 2 additions & 2 deletions drivers/acpi/parser/psopcode.c
Original file line number Diff line number Diff line change
Expand Up @@ -624,9 +624,9 @@ const struct acpi_opcode_info acpi_gbl_aml_op_info[AML_NUM_OPCODES] = {
AML_TYPE_EXEC_6A_0T_1R, AML_FLAGS_EXEC_6A_0T_1R),
/* 7C */ ACPI_OP("DataTableRegion", ARGP_DATA_REGION_OP,
ARGI_DATA_REGION_OP, ACPI_TYPE_REGION,
AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_SIMPLE,
AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_COMPLEX,
AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE |
AML_NSNODE | AML_NAMED),
AML_NSNODE | AML_NAMED | AML_DEFER),
/* 7D */ ACPI_OP("[EvalSubTree]", ARGP_SCOPE_OP, ARGI_SCOPE_OP,
ACPI_TYPE_ANY, AML_CLASS_NAMED_OBJECT,
AML_TYPE_NAMED_NO_OBJ,
Expand Down
4 changes: 4 additions & 0 deletions include/acpi/acdispat.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,10 @@ acpi_status
acpi_ds_eval_region_operands(struct acpi_walk_state *walk_state,
union acpi_parse_object *op);

acpi_status
acpi_ds_eval_table_region_operands(struct acpi_walk_state *walk_state,
union acpi_parse_object *op);

acpi_status
acpi_ds_eval_data_object_operands(struct acpi_walk_state *walk_state,
union acpi_parse_object *op,
Expand Down
2 changes: 0 additions & 2 deletions include/acpi/acinterp.h
Original file line number Diff line number Diff line change
Expand Up @@ -215,8 +215,6 @@ acpi_ex_create_region(u8 * aml_start,
u32 aml_length,
u8 region_space, struct acpi_walk_state *walk_state);

acpi_status acpi_ex_create_table_region(struct acpi_walk_state *walk_state);

acpi_status acpi_ex_create_event(struct acpi_walk_state *walk_state);

acpi_status acpi_ex_create_alias(struct acpi_walk_state *walk_state);
Expand Down

0 comments on commit 941f48b

Please sign in to comment.