Commit bc7a36ab authored by Lin Ming's avatar Lin Ming Committed by Len Brown
Browse files

ACPICA: Fixes for Unload and DDBHandles

Implemented support for the use of DDBHandles as an Indexed
Reference, as per the ACPI spec.

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

Implemented support for UserTerm (Method invocation) for the Unload operator
as per the ACPI spec.

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



Signed-off-by: default avatarBob Moore <robert.moore@intel.com>
Signed-off-by: default avatarAlexey Starikovskiy <astarikovskiy@suse.de>
Signed-off-by: default avatarLen Brown <len.brown@intel.com>
parent a6f4a451
Loading
Loading
Loading
Loading
+19 −8
Original line number Diff line number Diff line
@@ -895,14 +895,25 @@ static void acpi_ex_dump_reference_obj(union acpi_operand_object *obj_desc)
	} else if (obj_desc->reference.object) {
		if (ACPI_GET_DESCRIPTOR_TYPE(obj_desc) ==
		    ACPI_DESC_TYPE_OPERAND) {
			acpi_os_printf(" Target: %p [%s]\n",
				       obj_desc->reference.object,
			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->
								       *)
								      obj_desc->
								      reference.
							      object)->common.
								      object)->
								     common.
								     type));
			}
		} else {
			acpi_os_printf(" Target: %p\n",
				       obj_desc->reference.object);
+9 −4
Original line number Diff line number Diff line
@@ -382,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) {
@@ -455,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:

+18 −5
Original line number Diff line number Diff line
@@ -434,12 +434,25 @@ acpi_ex_store_object_to_index(union acpi_operand_object *source_desc,
		 */
		obj_desc = *(index_desc->reference.where);

		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,
			    acpi_ut_copy_iobject_to_iobject(source_desc,
							    &new_desc,
							    walk_state);
			if (ACPI_FAILURE(status)) {
				return_ACPI_STATUS(status);
			}
		}

		if (obj_desc) {

+34 −3
Original line number Diff line number Diff line
@@ -235,6 +235,7 @@ acpi_ps_get_next_namepath(struct acpi_walk_state *walk_state,
	union acpi_parse_object *name_op;
	union acpi_operand_object *method_desc;
	struct acpi_namespace_node *node;
	u8 *start = parser_state->aml;

	ACPI_FUNCTION_TRACE(ps_get_next_namepath);

@@ -267,6 +268,16 @@ acpi_ps_get_next_namepath(struct acpi_walk_state *walk_state,
	 */
	if (ACPI_SUCCESS(status) &&
	    possible_method_call && (node->type == ACPI_TYPE_METHOD)) {
		if (walk_state->op->common.aml_opcode == AML_UNLOAD_OP) {
			/*
			 * acpi_ps_get_next_namestring has increased the AML pointer,
			 * so we need to restore the saved AML pointer for method call.
			 */
			walk_state->parser_state.aml = start;
			walk_state->arg_count = 1;
			acpi_ps_init_op(arg, AML_INT_METHODCALL_OP);
			return_ACPI_STATUS(AE_OK);
		}

		/* This name is actually a control method invocation */

@@ -678,9 +689,29 @@ acpi_ps_get_next_arg(struct acpi_walk_state *walk_state,
				return_ACPI_STATUS(AE_NO_MEMORY);
			}

			/* To support super_name arg of Unload */

			if (walk_state->op->common.aml_opcode == AML_UNLOAD_OP) {
				status =
			    acpi_ps_get_next_namepath(walk_state, parser_state,
						      arg, 0);
				    acpi_ps_get_next_namepath(walk_state,
							      parser_state, arg,
							      1);

				/*
				 * If the super_name arg of Unload is a method call,
				 * we have restored the AML pointer, just free this Arg
				 */
				if (arg->common.aml_opcode ==
				    AML_INT_METHODCALL_OP) {
					acpi_ps_free_op(arg);
					arg = NULL;
				}
			} else {
				status =
				    acpi_ps_get_next_namepath(walk_state,
							      parser_state, arg,
							      0);
			}
		} else {
			/* Single complex argument, nothing returned */

+8 −0
Original line number Diff line number Diff line
@@ -709,7 +709,15 @@ acpi_ut_copy_simple_object(union acpi_operand_object *source_desc,
		/*
		 * We copied the reference object, so we now must add a reference
		 * to the object pointed to by the reference
		 *
		 * DDBHandle reference (from Load/load_table is a special reference,
		 * it's Reference.Object is the table index, so does not need to
		 * increase the reference count
		 */
		if (source_desc->reference.opcode == AML_LOAD_OP) {
			break;
		}

		acpi_ut_add_reference(source_desc->reference.object);
		break;