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: Zhang Rui <rui.zhang@intel.com> Signed-off-by: Bob Moore <robert.moore@intel.com> Signed-off-by: Lv Zheng <lv.zheng@intel.com> Acked-by: Len Brown <len.brown@intel.com> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
This commit is contained in:
parent
d835e7f4f8
commit
8f4f5e7815
@ -54,7 +54,8 @@ extern u8 acpi_gbl_default_address_spaces[];
|
|||||||
|
|
||||||
/* Local prototypes */
|
/* 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
|
static acpi_status
|
||||||
acpi_ev_reg_run(acpi_handle obj_handle,
|
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 */
|
/* Special case for EC: handle "orphan" _REG methods with no region */
|
||||||
|
|
||||||
if (space_id == ACPI_ADR_SPACE_EC) {
|
if (space_id == ACPI_ADR_SPACE_EC) {
|
||||||
acpi_ev_orphan_ec_reg_method();
|
acpi_ev_orphan_ec_reg_method(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
return_ACPI_STATUS(status);
|
return_ACPI_STATUS(status);
|
||||||
@ -681,7 +682,7 @@ acpi_ev_reg_run(acpi_handle obj_handle,
|
|||||||
*
|
*
|
||||||
* FUNCTION: acpi_ev_orphan_ec_reg_method
|
* FUNCTION: acpi_ev_orphan_ec_reg_method
|
||||||
*
|
*
|
||||||
* PARAMETERS: None
|
* PARAMETERS: ec_device_node - Namespace node for an EC device
|
||||||
*
|
*
|
||||||
* RETURN: None
|
* RETURN: None
|
||||||
*
|
*
|
||||||
@ -693,37 +694,27 @@ acpi_ev_reg_run(acpi_handle obj_handle,
|
|||||||
* detected by providing a _REG method object underneath the
|
* detected by providing a _REG method object underneath the
|
||||||
* Embedded Controller device."
|
* Embedded Controller device."
|
||||||
*
|
*
|
||||||
* To quickly access the EC device, we use the EC_ID that appears
|
* To quickly access the EC device, we use the ec_device_node used
|
||||||
* within the ECDT. Otherwise, we would need to perform a time-
|
* during EC handler installation. Otherwise, we would need to
|
||||||
* consuming namespace walk, executing _HID methods to find the
|
* perform a time consuming namespace walk, executing _HID
|
||||||
* EC device.
|
* 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;
|
acpi_status status;
|
||||||
struct acpi_object_list args;
|
struct acpi_object_list args;
|
||||||
union acpi_object objects[2];
|
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);
|
ACPI_FUNCTION_TRACE(ev_orphan_ec_reg_method);
|
||||||
|
|
||||||
/* Get the ECDT (if present in system) */
|
if (!ec_device_node) {
|
||||||
|
|
||||||
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)) {
|
|
||||||
return_VOID;
|
return_VOID;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -731,22 +722,11 @@ static void acpi_ev_orphan_ec_reg_method(void)
|
|||||||
|
|
||||||
(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
|
(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 */
|
/* Get a handle to a _REG method immediately under the EC device */
|
||||||
|
|
||||||
status = acpi_get_handle(ec_device_node,
|
status = acpi_get_handle(ec_device_node, METHOD_NAME__REG, ®_method);
|
||||||
METHOD_NAME__REG, ACPI_CAST_PTR(acpi_handle,
|
|
||||||
®_method));
|
|
||||||
if (ACPI_FAILURE(status)) {
|
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
|
* this scope with the Embedded Controller space ID. Otherwise, it
|
||||||
* will already have been executed. Note, this allows for Regions
|
* will already have been executed. Note, this allows for Regions
|
||||||
* with other space IDs to be present; but the code below will then
|
* 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);
|
next_node = acpi_ns_get_next_node(ec_device_node, NULL);
|
||||||
while (next_node) {
|
while (next_node) {
|
||||||
if ((next_node->type == ACPI_TYPE_REGION) &&
|
if ((next_node->type == ACPI_TYPE_REGION) &&
|
||||||
(next_node->object) &&
|
(next_node->object) &&
|
||||||
(next_node->object->region.space_id == ACPI_ADR_SPACE_EC)) {
|
(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);
|
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.count = 2;
|
||||||
args.pointer = objects;
|
args.pointer = objects;
|
||||||
|
Loading…
Reference in New Issue
Block a user