aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/acpica/dsmethod.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/acpi/acpica/dsmethod.c')
-rw-r--r--drivers/acpi/acpica/dsmethod.c156
1 files changed, 151 insertions, 5 deletions
diff --git a/drivers/acpi/acpica/dsmethod.c b/drivers/acpi/acpica/dsmethod.c
index 2c6d42c2bc01..3c7f7378b94d 100644
--- a/drivers/acpi/acpica/dsmethod.c
+++ b/drivers/acpi/acpica/dsmethod.c
@@ -49,16 +49,155 @@
49#ifdef ACPI_DISASSEMBLER 49#ifdef ACPI_DISASSEMBLER
50#include "acdisasm.h" 50#include "acdisasm.h"
51#endif 51#endif
52#include "acparser.h"
53#include "amlcode.h"
52 54
53#define _COMPONENT ACPI_DISPATCHER 55#define _COMPONENT ACPI_DISPATCHER
54ACPI_MODULE_NAME("dsmethod") 56ACPI_MODULE_NAME("dsmethod")
55 57
56/* Local prototypes */ 58/* Local prototypes */
57static acpi_status 59static acpi_status
60acpi_ds_detect_named_opcodes(struct acpi_walk_state *walk_state,
61 union acpi_parse_object **out_op);
62
63static acpi_status
58acpi_ds_create_method_mutex(union acpi_operand_object *method_desc); 64acpi_ds_create_method_mutex(union acpi_operand_object *method_desc);
59 65
60/******************************************************************************* 66/*******************************************************************************
61 * 67 *
68 * FUNCTION: acpi_ds_auto_serialize_method
69 *
70 * PARAMETERS: node - Namespace Node of the method
71 * obj_desc - Method object attached to node
72 *
73 * RETURN: Status
74 *
75 * DESCRIPTION: Parse a control method AML to scan for control methods that
76 * need serialization due to the creation of named objects.
77 *
78 * NOTE: It is a bit of overkill to mark all such methods serialized, since
79 * there is only a problem if the method actually blocks during execution.
80 * A blocking operation is, for example, a Sleep() operation, or any access
81 * to an operation region. However, it is probably not possible to easily
82 * detect whether a method will block or not, so we simply mark all suspicious
83 * methods as serialized.
84 *
85 * NOTE2: This code is essentially a generic routine for parsing a single
86 * control method.
87 *
88 ******************************************************************************/
89
90acpi_status
91acpi_ds_auto_serialize_method(struct acpi_namespace_node *node,
92 union acpi_operand_object *obj_desc)
93{
94 acpi_status status;
95 union acpi_parse_object *op = NULL;
96 struct acpi_walk_state *walk_state;
97
98 ACPI_FUNCTION_TRACE_PTR(ds_auto_serialize_method, node);
99
100 ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
101 "Method auto-serialization parse [%4.4s] %p\n",
102 acpi_ut_get_node_name(node), node));
103
104 /* Create/Init a root op for the method parse tree */
105
106 op = acpi_ps_alloc_op(AML_METHOD_OP);
107 if (!op) {
108 return_ACPI_STATUS(AE_NO_MEMORY);
109 }
110
111 acpi_ps_set_name(op, node->name.integer);
112 op->common.node = node;
113
114 /* Create and initialize a new walk state */
115
116 walk_state =
117 acpi_ds_create_walk_state(node->owner_id, NULL, NULL, NULL);
118 if (!walk_state) {
119 return_ACPI_STATUS(AE_NO_MEMORY);
120 }
121
122 status =
123 acpi_ds_init_aml_walk(walk_state, op, node,
124 obj_desc->method.aml_start,
125 obj_desc->method.aml_length, NULL, 0);
126 if (ACPI_FAILURE(status)) {
127 acpi_ds_delete_walk_state(walk_state);
128 return_ACPI_STATUS(status);
129 }
130
131 walk_state->descending_callback = acpi_ds_detect_named_opcodes;
132
133 /* Parse the method, scan for creation of named objects */
134
135 status = acpi_ps_parse_aml(walk_state);
136 if (ACPI_FAILURE(status)) {
137 return_ACPI_STATUS(status);
138 }
139
140 acpi_ps_delete_parse_tree(op);
141 return_ACPI_STATUS(status);
142}
143
144/*******************************************************************************
145 *
146 * FUNCTION: acpi_ds_detect_named_opcodes
147 *
148 * PARAMETERS: walk_state - Current state of the parse tree walk
149 * out_op - Unused, required for parser interface
150 *
151 * RETURN: Status
152 *
153 * DESCRIPTION: Descending callback used during the loading of ACPI tables.
154 * Currently used to detect methods that must be marked serialized
155 * in order to avoid problems with the creation of named objects.
156 *
157 ******************************************************************************/
158
159static acpi_status
160acpi_ds_detect_named_opcodes(struct acpi_walk_state *walk_state,
161 union acpi_parse_object **out_op)
162{
163
164 ACPI_FUNCTION_NAME(acpi_ds_detect_named_opcodes);
165
166 /* We are only interested in opcodes that create a new name */
167
168 if (!
169 (walk_state->op_info->
170 flags & (AML_NAMED | AML_CREATE | AML_FIELD))) {
171 return (AE_OK);
172 }
173
174 /*
175 * At this point, we know we have a Named object opcode.
176 * Mark the method as serialized. Later code will create a mutex for
177 * this method to enforce serialization.
178 *
179 * Note, ACPI_METHOD_IGNORE_SYNC_LEVEL flag means that we will ignore the
180 * Sync Level mechanism for this method, even though it is now serialized.
181 * Otherwise, there can be conflicts with existing ASL code that actually
182 * uses sync levels.
183 */
184 walk_state->method_desc->method.sync_level = 0;
185 walk_state->method_desc->method.info_flags |=
186 (ACPI_METHOD_SERIALIZED | ACPI_METHOD_IGNORE_SYNC_LEVEL);
187
188 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
189 "Method serialized [%4.4s] %p - [%s] (%4.4X)\n",
190 walk_state->method_node->name.ascii,
191 walk_state->method_node, walk_state->op_info->name,
192 walk_state->opcode));
193
194 /* Abort the parse, no need to examine this method any further */
195
196 return (AE_CTRL_TERMINATE);
197}
198
199/*******************************************************************************
200 *
62 * FUNCTION: acpi_ds_method_error 201 * FUNCTION: acpi_ds_method_error
63 * 202 *
64 * PARAMETERS: status - Execution status 203 * PARAMETERS: status - Execution status
@@ -74,7 +213,7 @@ acpi_ds_create_method_mutex(union acpi_operand_object *method_desc);
74 ******************************************************************************/ 213 ******************************************************************************/
75 214
76acpi_status 215acpi_status
77acpi_ds_method_error(acpi_status status, struct acpi_walk_state *walk_state) 216acpi_ds_method_error(acpi_status status, struct acpi_walk_state * walk_state)
78{ 217{
79 ACPI_FUNCTION_ENTRY(); 218 ACPI_FUNCTION_ENTRY();
80 219
@@ -217,13 +356,19 @@ acpi_ds_begin_method_execution(struct acpi_namespace_node *method_node,
217 /* 356 /*
218 * The current_sync_level (per-thread) must be less than or equal to 357 * The current_sync_level (per-thread) must be less than or equal to
219 * the sync level of the method. This mechanism provides some 358 * the sync level of the method. This mechanism provides some
220 * deadlock prevention 359 * deadlock prevention.
360 *
361 * If the method was auto-serialized, we just ignore the sync level
362 * mechanism, because auto-serialization of methods can interfere
363 * with ASL code that actually uses sync levels.
221 * 364 *
222 * Top-level method invocation has no walk state at this point 365 * Top-level method invocation has no walk state at this point
223 */ 366 */
224 if (walk_state && 367 if (walk_state &&
225 (walk_state->thread->current_sync_level > 368 (!(obj_desc->method.
226 obj_desc->method.mutex->mutex.sync_level)) { 369 info_flags & ACPI_METHOD_IGNORE_SYNC_LEVEL))
370 && (walk_state->thread->current_sync_level >
371 obj_desc->method.mutex->mutex.sync_level)) {
227 ACPI_ERROR((AE_INFO, 372 ACPI_ERROR((AE_INFO,
228 "Cannot acquire Mutex for method [%4.4s], current SyncLevel is too large (%u)", 373 "Cannot acquire Mutex for method [%4.4s], current SyncLevel is too large (%u)",
229 acpi_ut_get_node_name(method_node), 374 acpi_ut_get_node_name(method_node),
@@ -668,7 +813,8 @@ acpi_ds_terminate_control_method(union acpi_operand_object *method_desc,
668 method_desc->method.info_flags &= 813 method_desc->method.info_flags &=
669 ~ACPI_METHOD_SERIALIZED_PENDING; 814 ~ACPI_METHOD_SERIALIZED_PENDING;
670 method_desc->method.info_flags |= 815 method_desc->method.info_flags |=
671 ACPI_METHOD_SERIALIZED; 816 (ACPI_METHOD_SERIALIZED |
817 ACPI_METHOD_IGNORE_SYNC_LEVEL);
672 method_desc->method.sync_level = 0; 818 method_desc->method.sync_level = 0;
673 } 819 }
674 820