Commit 8f4f5e78 authored by Zhang Rui's avatar Zhang Rui Committed by Rafael J. Wysocki
Browse files

ACPICA: Update for "orphan" embedded controller _REG method support



This refers to _REG methods under the EC device that have no
corresponding operation region. This is allowed by the ACPI
specification. This update removes a dependency on having an
ECDT table, and will execute an orphan _REG method as long as
the handler for the EC is installed at the EC device node (not
the namespace root).  Rui Zhang (original update), Bob Moore
(update/integrate).

Signed-off-by: default avatarZhang Rui <rui.zhang@intel.com>
Signed-off-by: default avatarBob Moore <robert.moore@intel.com>
Signed-off-by: default avatarLv Zheng <lv.zheng@intel.com>
Acked-by: default avatarLen Brown <len.brown@intel.com>
Signed-off-by: default avatarRafael J. Wysocki <rafael.j.wysocki@intel.com>
parent d835e7f4
Loading
Loading
Loading
Loading
+21 −40
Original line number Diff line number Diff line
@@ -54,7 +54,8 @@ extern u8 acpi_gbl_default_address_spaces[];

/* Local prototypes */

static void acpi_ev_orphan_ec_reg_method(void);
static void
acpi_ev_orphan_ec_reg_method(struct acpi_namespace_node *ec_device_node);

static acpi_status
acpi_ev_reg_run(acpi_handle obj_handle,
@@ -612,7 +613,7 @@ acpi_ev_execute_reg_methods(struct acpi_namespace_node *node,
	/* Special case for EC: handle "orphan" _REG methods with no region */

	if (space_id == ACPI_ADR_SPACE_EC) {
		acpi_ev_orphan_ec_reg_method();
		acpi_ev_orphan_ec_reg_method(node);
	}

	return_ACPI_STATUS(status);
@@ -681,7 +682,7 @@ acpi_ev_reg_run(acpi_handle obj_handle,
 *
 * FUNCTION:    acpi_ev_orphan_ec_reg_method
 *
 * PARAMETERS:  None
 * PARAMETERS:  ec_device_node      - Namespace node for an EC device
 *
 * RETURN:      None
 *
@@ -693,37 +694,27 @@ acpi_ev_reg_run(acpi_handle obj_handle,
 *              detected by providing a _REG method object underneath the
 *              Embedded Controller device."
 *
 *              To quickly access the EC device, we use the EC_ID that appears
 *              within the ECDT. Otherwise, we would need to perform a time-
 *              consuming namespace walk, executing _HID methods to find the
 *              EC device.
 *              To quickly access the EC device, we use the ec_device_node used
 *              during EC handler installation. Otherwise, we would need to
 *              perform a time consuming namespace walk, executing _HID
 *              methods to find the EC device.
 *
 *  MUTEX:      Assumes the namespace is locked
 *
 ******************************************************************************/

static void acpi_ev_orphan_ec_reg_method(void)
static void
acpi_ev_orphan_ec_reg_method(struct acpi_namespace_node *ec_device_node)
{
	struct acpi_table_ecdt *table;
	acpi_handle reg_method;
	struct acpi_namespace_node *next_node;
	acpi_status status;
	struct acpi_object_list args;
	union acpi_object objects[2];
	struct acpi_namespace_node *ec_device_node;
	struct acpi_namespace_node *reg_method;
	struct acpi_namespace_node *next_node;

	ACPI_FUNCTION_TRACE(ev_orphan_ec_reg_method);

	/* Get the ECDT (if present in system) */

	status = acpi_get_table(ACPI_SIG_ECDT, 0,
				ACPI_CAST_INDIRECT_PTR(struct acpi_table_header,
						       &table));
	if (ACPI_FAILURE(status)) {
		return_VOID;
	}

	/* We need a valid EC_ID string */

	if (!(*table->id)) {
	if (!ec_device_node) {
		return_VOID;
	}

@@ -731,22 +722,11 @@ static void acpi_ev_orphan_ec_reg_method(void)

	(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);

	/* Get a handle to the EC device referenced in the ECDT */

	status = acpi_get_handle(NULL,
				 ACPI_CAST_PTR(char, table->id),
				 ACPI_CAST_PTR(acpi_handle, &ec_device_node));
	if (ACPI_FAILURE(status)) {
		goto exit;
	}

	/* Get a handle to a _REG method immediately under the EC device */

	status = acpi_get_handle(ec_device_node,
				 METHOD_NAME__REG, ACPI_CAST_PTR(acpi_handle,
								 &reg_method));
	status = acpi_get_handle(ec_device_node, METHOD_NAME__REG, &reg_method);
	if (ACPI_FAILURE(status)) {
		goto exit;
		goto exit;	/* There is no _REG method present */
	}

	/*
@@ -754,19 +734,20 @@ static void acpi_ev_orphan_ec_reg_method(void)
	 * this scope with the Embedded Controller space ID. Otherwise, it
	 * will already have been executed. Note, this allows for Regions
	 * with other space IDs to be present; but the code below will then
	 * execute the _REG method with the EC space ID argument.
	 * execute the _REG method with the embedded_control space_ID argument.
	 */
	next_node = acpi_ns_get_next_node(ec_device_node, NULL);
	while (next_node) {
		if ((next_node->type == ACPI_TYPE_REGION) &&
		    (next_node->object) &&
		    (next_node->object->region.space_id == ACPI_ADR_SPACE_EC)) {
			goto exit;	/* Do not execute _REG */
			goto exit;	/* Do not execute the _REG */
		}

		next_node = acpi_ns_get_next_node(ec_device_node, next_node);
	}

	/* Evaluate the _REG(EC,Connect) method */
	/* Evaluate the _REG(embedded_control,Connect) method */

	args.count = 2;
	args.pointer = objects;