Skip to content

Commit

Permalink
ACPICA: Integrate package handling with module-level code
Browse files Browse the repository at this point in the history
ACPICA commit 8faf6fca445eb7219963d80543fb802302a7a8c7

This change completes the integration of the recent changes to
package object handling with the module-level code support.

For acpi_exec, the -ep flag is removed.

This change allows table load to behave as if it were a method
invocation. Before this, the definition block definition below would
have loaded all named objects at the root scope. After loading, it
would execute the if statements at the root scope.

DefinitionBlock (...)
{
  Name(OBJ1, 0)

  if (1)
  {
    Device (DEV1)
    {
      Name (_HID,0x0)
    }
  }
  Scope (DEV1)
  {
    Name (OBJ2)
  }
}

The above code would load OBJ1 to the namespace, defer the execution
of the if statement and attempt to add OBJ2 within the scope of DEV1.
Since DEV1 is not in scope, this would incur an AE_NOT_FOUND error.
After this error is emitted, the if block is invoked and DEV1 and its
_HID is added to the namespace.

This commit changes the behavior to execute the if block in place
rather than deferring it until all tables are loaded. The new
behavior is as follows: insert OBJ1 in the namespace, invoke the if
statement and add DEV1 and its _HID to the namespace, add OBJ2 to the
scope of DEV1.

Bug report links:
Link: https://bugs.acpica.org/show_bug.cgi?id=963
Link: https://bugzilla.kernel.org/show_bug.cgi?id=153541
Link: https://bugzilla.kernel.org/show_bug.cgi?id=196165
Link: https://bugzilla.kernel.org/show_bug.cgi?id=192621
Link: https://bugzilla.kernel.org/show_bug.cgi?id=197207
Link: https://bugzilla.kernel.org/show_bug.cgi?id=198051
Link: https://bugzilla.kernel.org/show_bug.cgi?id=198515

ACPICA repo:
Link: https://github.com/acpica/acpica/commit/8faf6fca

Tested-by: Kai-Heng Feng <kai.heng.feng@canonical.com>
Signed-off-by: Bob Moore <robert.moore@intel.com>
Signed-off-by: Erik Schmauss <erik.schmauss@intel.com>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
  • Loading branch information
Schmauss, Erik authored and Rafael J. Wysocki committed Feb 21, 2018
1 parent 7decc66 commit 5a8361f
Show file tree
Hide file tree
Showing 5 changed files with 85 additions and 63 deletions.
128 changes: 71 additions & 57 deletions drivers/acpi/acpica/dspkginit.c
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
#include "amlcode.h"
#include "acdispat.h"
#include "acinterp.h"
#include "acparser.h"

#define _COMPONENT ACPI_NAMESPACE
ACPI_MODULE_NAME("dspkginit")
Expand Down Expand Up @@ -94,12 +95,19 @@ acpi_ds_build_internal_package_obj(struct acpi_walk_state *walk_state,
union acpi_parse_object *parent;
union acpi_operand_object *obj_desc = NULL;
acpi_status status = AE_OK;
u8 module_level_code = FALSE;
u16 reference_count;
u32 index;
u32 i;

ACPI_FUNCTION_TRACE(ds_build_internal_package_obj);

/* Check if we are executing module level code */

if (walk_state->parse_flags & ACPI_PARSE_MODULE_LEVEL) {
module_level_code = TRUE;
}

/* Find the parent of a possibly nested package */

parent = op->common.parent;
Expand Down Expand Up @@ -130,24 +138,44 @@ acpi_ds_build_internal_package_obj(struct acpi_walk_state *walk_state,

/*
* Allocate the element array (array of pointers to the individual
* objects) based on the num_elements parameter. Add an extra pointer slot
* so that the list is always null terminated.
* objects) if necessary. the count is based on the num_elements
* parameter. Add an extra pointer slot so that the list is always
* null terminated.
*/
obj_desc->package.elements = ACPI_ALLOCATE_ZEROED(((acpi_size)
element_count +
1) * sizeof(void *));

if (!obj_desc->package.elements) {
acpi_ut_delete_object_desc(obj_desc);
return_ACPI_STATUS(AE_NO_MEMORY);
obj_desc->package.elements = ACPI_ALLOCATE_ZEROED(((acpi_size)
element_count
+
1) *
sizeof(void
*));

if (!obj_desc->package.elements) {
acpi_ut_delete_object_desc(obj_desc);
return_ACPI_STATUS(AE_NO_MEMORY);
}

obj_desc->package.count = element_count;
}

obj_desc->package.count = element_count;
/* First arg is element count. Second arg begins the initializer list */

arg = op->common.value.arg;
arg = arg->common.next;

if (arg) {
obj_desc->package.flags |= AOPOBJ_DATA_VALID;
/*
* If we are executing module-level code, we will defer the
* full resolution of the package elements in order to support
* forward references from the elements. This provides
* compatibility with other ACPI implementations.
*/
if (module_level_code) {
obj_desc->package.aml_start = walk_state->aml;
obj_desc->package.aml_length = 0;

ACPI_DEBUG_PRINT_RAW((ACPI_DB_PARSE,
"%s: Deferring resolution of Package elements\n",
ACPI_GET_FUNCTION_NAME));
}

/*
Expand Down Expand Up @@ -187,15 +215,19 @@ acpi_ds_build_internal_package_obj(struct acpi_walk_state *walk_state,
"****DS namepath not found"));
}

/*
* Initialize this package element. This function handles the
* resolution of named references within the package.
*/
acpi_ds_init_package_element(0,
obj_desc->package.
elements[i], NULL,
&obj_desc->package.
elements[i]);
if (!module_level_code) {
/*
* Initialize this package element. This function handles the
* resolution of named references within the package.
* Forward references from module-level code are deferred
* until all ACPI tables are loaded.
*/
acpi_ds_init_package_element(0,
obj_desc->package.
elements[i], NULL,
&obj_desc->package.
elements[i]);
}
}

if (*obj_desc_ptr) {
Expand Down Expand Up @@ -265,15 +297,21 @@ acpi_ds_build_internal_package_obj(struct acpi_walk_state *walk_state,
* num_elements count.
*
* Note: this is not an error, the package is padded out
* with NULLs.
* with NULLs as per the ACPI specification.
*/
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"Package List length (%u) smaller than NumElements "
"count (%u), padded with null elements\n",
i, element_count));
ACPI_DEBUG_PRINT_RAW((ACPI_DB_INFO,
"%s: Package List length (%u) smaller than NumElements "
"count (%u), padded with null elements\n",
ACPI_GET_FUNCTION_NAME, i,
element_count));
}

/* Module-level packages will be resolved later */

if (!module_level_code) {
obj_desc->package.flags |= AOPOBJ_DATA_VALID;
}

obj_desc->package.flags |= AOPOBJ_DATA_VALID;
op->common.node = ACPI_CAST_PTR(struct acpi_namespace_node, obj_desc);
return_ACPI_STATUS(status);
}
Expand Down Expand Up @@ -363,6 +401,10 @@ acpi_ds_resolve_package_element(union acpi_operand_object **element_ptr)
/* Check if reference element is already resolved */

if (element->reference.resolved) {
ACPI_DEBUG_PRINT_RAW((ACPI_DB_PARSE,
"%s: Package element is already resolved\n",
ACPI_GET_FUNCTION_NAME));

return_VOID;
}

Expand All @@ -383,7 +425,10 @@ acpi_ds_resolve_package_element(union acpi_operand_object **element_ptr)
"Could not find/resolve named package element: %s",
external_path));

/* Not found, set the element to NULL */

ACPI_FREE(external_path);
acpi_ut_remove_reference(*element_ptr);
*element_ptr = NULL;
return_VOID;
} else if (resolved_node->type == ACPI_TYPE_ANY) {
Expand All @@ -397,23 +442,6 @@ acpi_ds_resolve_package_element(union acpi_operand_object **element_ptr)
*element_ptr = NULL;
return_VOID;
}
#if 0
else if (resolved_node->flags & ANOBJ_TEMPORARY) {
/*
* A temporary node found here indicates that the reference is
* to a node that was created within this method. We are not
* going to allow it (especially if the package is returned
* from the method) -- the temporary node will be deleted out
* from under the method. (05/2017).
*/
ACPI_ERROR((AE_INFO,
"Package element refers to a temporary name [%4.4s], "
"inserting a NULL element",
resolved_node->name.ascii));
*element_ptr = NULL;
return_VOID;
}
#endif

/*
* Special handling for Alias objects. We need resolved_node to point
Expand Down Expand Up @@ -449,20 +477,6 @@ acpi_ds_resolve_package_element(union acpi_operand_object **element_ptr)
if (ACPI_FAILURE(status)) {
return_VOID;
}
#if 0
/* TBD - alias support */
/*
* Special handling for Alias objects. We need to setup the type
* and the Op->Common.Node to point to the Alias target. Note,
* Alias has at most one level of indirection internally.
*/
type = op->common.node->type;
if (type == ACPI_TYPE_LOCAL_ALIAS) {
type = obj_desc->common.type;
op->common.node = ACPI_CAST_PTR(struct acpi_namespace_node,
op->common.node->object);
}
#endif

switch (type) {
/*
Expand Down
6 changes: 4 additions & 2 deletions drivers/acpi/acpica/dswexec.c
Original file line number Diff line number Diff line change
Expand Up @@ -576,8 +576,10 @@ acpi_status acpi_ds_exec_end_op(struct acpi_walk_state *walk_state)
case AML_TYPE_CREATE_OBJECT:

ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
"Executing CreateObject (Buffer/Package) Op=%p AMLPtr=%p\n",
op, op->named.data));
"Executing CreateObject (Buffer/Package) Op=%p Child=%p ParentOpcode=%4.4X\n",
op, op->named.value.arg,
op->common.parent->common.
aml_opcode));

switch (op->common.parent->common.aml_opcode) {
case AML_NAME_OP:
Expand Down
5 changes: 3 additions & 2 deletions drivers/acpi/acpica/nsparse.c
Original file line number Diff line number Diff line change
Expand Up @@ -267,8 +267,9 @@ acpi_ns_parse_table(u32 table_index, struct acpi_namespace_node *start_node)
ACPI_FUNCTION_TRACE(ns_parse_table);

if (acpi_gbl_parse_table_as_term_list) {
ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
"**** Start table execution pass\n"));
ACPI_DEBUG_PRINT_RAW((ACPI_DB_PARSE,
"%s: **** Start table execution pass\n",
ACPI_GET_FUNCTION_NAME));

status = acpi_ns_execute_table(table_index, start_node);
if (ACPI_FAILURE(status)) {
Expand Down
1 change: 1 addition & 0 deletions drivers/acpi/acpica/pstree.c
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,7 @@ union acpi_parse_object *acpi_ps_get_child(union acpi_parse_object *op)

case AML_BUFFER_OP:
case AML_PACKAGE_OP:
case AML_VARIABLE_PACKAGE_OP:
case AML_METHOD_OP:
case AML_IF_OP:
case AML_WHILE_OP:
Expand Down
8 changes: 6 additions & 2 deletions include/acpi/acpixf.h
Original file line number Diff line number Diff line change
Expand Up @@ -192,15 +192,19 @@ ACPI_INIT_GLOBAL(u8, acpi_gbl_do_not_use_xsdt, FALSE);

/*
* Optionally support group module level code.
* NOTE, this is essentially obsolete and will be removed soon
* (01/2018).
*/
ACPI_INIT_GLOBAL(u8, acpi_gbl_group_module_level_code, TRUE);
ACPI_INIT_GLOBAL(u8, acpi_gbl_group_module_level_code, FALSE);

/*
* Optionally support module level code by parsing the entire table as
* a term_list. Default is FALSE, do not execute entire table until some
* lock order issues are fixed.
* NOTE, this is essentially obsolete and will be removed soon
* (01/2018).
*/
ACPI_INIT_GLOBAL(u8, acpi_gbl_parse_table_as_term_list, FALSE);
ACPI_INIT_GLOBAL(u8, acpi_gbl_parse_table_as_term_list, TRUE);

/*
* Optionally use 32-bit FADT addresses if and when there is a conflict
Expand Down

0 comments on commit 5a8361f

Please sign in to comment.