Source
x
// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
/******************************************************************************
*
* Module Name: dsmethod - Parser/Interpreter interface - control method parsing
*
* Copyright (C) 2000 - 2019, Intel Corp.
*
*****************************************************************************/
ACPI_MODULE_NAME("dsmethod")
/* Local prototypes */
static acpi_status
acpi_ds_detect_named_opcodes(struct acpi_walk_state *walk_state,
union acpi_parse_object **out_op);
static acpi_status
acpi_ds_create_method_mutex(union acpi_operand_object *method_desc);
/*******************************************************************************
*
* FUNCTION: acpi_ds_auto_serialize_method
*
* PARAMETERS: node - Namespace Node of the method
* obj_desc - Method object attached to node
*
* RETURN: Status
*
* DESCRIPTION: Parse a control method AML to scan for control methods that
* need serialization due to the creation of named objects.
*
* NOTE: It is a bit of overkill to mark all such methods serialized, since
* there is only a problem if the method actually blocks during execution.
* A blocking operation is, for example, a Sleep() operation, or any access
* to an operation region. However, it is probably not possible to easily
* detect whether a method will block or not, so we simply mark all suspicious
* methods as serialized.
*
* NOTE2: This code is essentially a generic routine for parsing a single
* control method.
*
******************************************************************************/
acpi_status
acpi_ds_auto_serialize_method(struct acpi_namespace_node *node,
union acpi_operand_object *obj_desc)
{
acpi_status status;
union acpi_parse_object *op = NULL;
struct acpi_walk_state *walk_state;
ACPI_FUNCTION_TRACE_PTR(ds_auto_serialize_method, node);
ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
"Method auto-serialization parse [%4.4s] %p\n",
acpi_ut_get_node_name(node), node));
/* Create/Init a root op for the method parse tree */
op = acpi_ps_alloc_op(AML_METHOD_OP, obj_desc->method.aml_start);
if (!op) {
return_ACPI_STATUS(AE_NO_MEMORY);
}
acpi_ps_set_name(op, node->name.integer);
op->common.node = node;
/* Create and initialize a new walk state */
walk_state =
acpi_ds_create_walk_state(node->owner_id, NULL, NULL, NULL);
if (!walk_state) {
acpi_ps_free_op(op);
return_ACPI_STATUS(AE_NO_MEMORY);
}
status = acpi_ds_init_aml_walk(walk_state, op, node,
obj_desc->method.aml_start,
obj_desc->method.aml_length, NULL, 0);
if (ACPI_FAILURE(status)) {
acpi_ds_delete_walk_state(walk_state);
acpi_ps_free_op(op);