diff options
Diffstat (limited to 'drivers/acpi/acpica/nsparse.c')
-rw-r--r-- | drivers/acpi/acpica/nsparse.c | 165 |
1 files changed, 134 insertions, 31 deletions
diff --git a/drivers/acpi/acpica/nsparse.c b/drivers/acpi/acpica/nsparse.c index f631a47724f0..4f14e9205bff 100644 --- a/drivers/acpi/acpica/nsparse.c +++ b/drivers/acpi/acpica/nsparse.c | |||
@@ -47,12 +47,103 @@ | |||
47 | #include "acparser.h" | 47 | #include "acparser.h" |
48 | #include "acdispat.h" | 48 | #include "acdispat.h" |
49 | #include "actables.h" | 49 | #include "actables.h" |
50 | #include "acinterp.h" | ||
50 | 51 | ||
51 | #define _COMPONENT ACPI_NAMESPACE | 52 | #define _COMPONENT ACPI_NAMESPACE |
52 | ACPI_MODULE_NAME("nsparse") | 53 | ACPI_MODULE_NAME("nsparse") |
53 | 54 | ||
54 | /******************************************************************************* | 55 | /******************************************************************************* |
55 | * | 56 | * |
57 | * FUNCTION: ns_execute_table | ||
58 | * | ||
59 | * PARAMETERS: table_desc - An ACPI table descriptor for table to parse | ||
60 | * start_node - Where to enter the table into the namespace | ||
61 | * | ||
62 | * RETURN: Status | ||
63 | * | ||
64 | * DESCRIPTION: Load ACPI/AML table by executing the entire table as a | ||
65 | * term_list. | ||
66 | * | ||
67 | ******************************************************************************/ | ||
68 | acpi_status | ||
69 | acpi_ns_execute_table(u32 table_index, struct acpi_namespace_node *start_node) | ||
70 | { | ||
71 | acpi_status status; | ||
72 | struct acpi_table_header *table; | ||
73 | acpi_owner_id owner_id; | ||
74 | struct acpi_evaluate_info *info = NULL; | ||
75 | u32 aml_length; | ||
76 | u8 *aml_start; | ||
77 | union acpi_operand_object *method_obj = NULL; | ||
78 | |||
79 | ACPI_FUNCTION_TRACE(ns_execute_table); | ||
80 | |||
81 | status = acpi_get_table_by_index(table_index, &table); | ||
82 | if (ACPI_FAILURE(status)) { | ||
83 | return_ACPI_STATUS(status); | ||
84 | } | ||
85 | |||
86 | /* Table must consist of at least a complete header */ | ||
87 | |||
88 | if (table->length < sizeof(struct acpi_table_header)) { | ||
89 | return_ACPI_STATUS(AE_BAD_HEADER); | ||
90 | } | ||
91 | |||
92 | aml_start = (u8 *)table + sizeof(struct acpi_table_header); | ||
93 | aml_length = table->length - sizeof(struct acpi_table_header); | ||
94 | |||
95 | status = acpi_tb_get_owner_id(table_index, &owner_id); | ||
96 | if (ACPI_FAILURE(status)) { | ||
97 | return_ACPI_STATUS(status); | ||
98 | } | ||
99 | |||
100 | /* Create, initialize, and link a new temporary method object */ | ||
101 | |||
102 | method_obj = acpi_ut_create_internal_object(ACPI_TYPE_METHOD); | ||
103 | if (!method_obj) { | ||
104 | return_ACPI_STATUS(AE_NO_MEMORY); | ||
105 | } | ||
106 | |||
107 | /* Allocate the evaluation information block */ | ||
108 | |||
109 | info = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_evaluate_info)); | ||
110 | if (!info) { | ||
111 | status = AE_NO_MEMORY; | ||
112 | goto cleanup; | ||
113 | } | ||
114 | |||
115 | ACPI_DEBUG_PRINT((ACPI_DB_PARSE, | ||
116 | "Create table code block: %p\n", method_obj)); | ||
117 | |||
118 | method_obj->method.aml_start = aml_start; | ||
119 | method_obj->method.aml_length = aml_length; | ||
120 | method_obj->method.owner_id = owner_id; | ||
121 | method_obj->method.info_flags |= ACPI_METHOD_MODULE_LEVEL; | ||
122 | |||
123 | info->pass_number = ACPI_IMODE_EXECUTE; | ||
124 | info->node = start_node; | ||
125 | info->obj_desc = method_obj; | ||
126 | info->node_flags = info->node->flags; | ||
127 | info->full_pathname = acpi_ns_get_normalized_pathname(info->node, TRUE); | ||
128 | if (!info->full_pathname) { | ||
129 | status = AE_NO_MEMORY; | ||
130 | goto cleanup; | ||
131 | } | ||
132 | |||
133 | status = acpi_ps_execute_table(info); | ||
134 | |||
135 | cleanup: | ||
136 | if (info) { | ||
137 | ACPI_FREE(info->full_pathname); | ||
138 | info->full_pathname = NULL; | ||
139 | } | ||
140 | ACPI_FREE(info); | ||
141 | acpi_ut_remove_reference(method_obj); | ||
142 | return_ACPI_STATUS(status); | ||
143 | } | ||
144 | |||
145 | /******************************************************************************* | ||
146 | * | ||
56 | * FUNCTION: ns_one_complete_parse | 147 | * FUNCTION: ns_one_complete_parse |
57 | * | 148 | * |
58 | * PARAMETERS: pass_number - 1 or 2 | 149 | * PARAMETERS: pass_number - 1 or 2 |
@@ -63,6 +154,7 @@ ACPI_MODULE_NAME("nsparse") | |||
63 | * DESCRIPTION: Perform one complete parse of an ACPI/AML table. | 154 | * DESCRIPTION: Perform one complete parse of an ACPI/AML table. |
64 | * | 155 | * |
65 | ******************************************************************************/ | 156 | ******************************************************************************/ |
157 | |||
66 | acpi_status | 158 | acpi_status |
67 | acpi_ns_one_complete_parse(u32 pass_number, | 159 | acpi_ns_one_complete_parse(u32 pass_number, |
68 | u32 table_index, | 160 | u32 table_index, |
@@ -143,7 +235,9 @@ acpi_ns_one_complete_parse(u32 pass_number, | |||
143 | 235 | ||
144 | ACPI_DEBUG_PRINT((ACPI_DB_PARSE, | 236 | ACPI_DEBUG_PRINT((ACPI_DB_PARSE, |
145 | "*PARSE* pass %u parse\n", pass_number)); | 237 | "*PARSE* pass %u parse\n", pass_number)); |
238 | acpi_ex_enter_interpreter(); | ||
146 | status = acpi_ps_parse_aml(walk_state); | 239 | status = acpi_ps_parse_aml(walk_state); |
240 | acpi_ex_exit_interpreter(); | ||
147 | 241 | ||
148 | cleanup: | 242 | cleanup: |
149 | acpi_ps_delete_parse_tree(parse_root); | 243 | acpi_ps_delete_parse_tree(parse_root); |
@@ -170,38 +264,47 @@ acpi_ns_parse_table(u32 table_index, struct acpi_namespace_node *start_node) | |||
170 | 264 | ||
171 | ACPI_FUNCTION_TRACE(ns_parse_table); | 265 | ACPI_FUNCTION_TRACE(ns_parse_table); |
172 | 266 | ||
173 | /* | 267 | if (acpi_gbl_parse_table_as_term_list) { |
174 | * AML Parse, pass 1 | 268 | ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "**** Start load pass\n")); |
175 | * | ||
176 | * In this pass, we load most of the namespace. Control methods | ||
177 | * are not parsed until later. A parse tree is not created. Instead, | ||
178 | * each Parser Op subtree is deleted when it is finished. This saves | ||
179 | * a great deal of memory, and allows a small cache of parse objects | ||
180 | * to service the entire parse. The second pass of the parse then | ||
181 | * performs another complete parse of the AML. | ||
182 | */ | ||
183 | ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "**** Start pass 1\n")); | ||
184 | |||
185 | status = acpi_ns_one_complete_parse(ACPI_IMODE_LOAD_PASS1, | ||
186 | table_index, start_node); | ||
187 | if (ACPI_FAILURE(status)) { | ||
188 | return_ACPI_STATUS(status); | ||
189 | } | ||
190 | 269 | ||
191 | /* | 270 | status = acpi_ns_execute_table(table_index, start_node); |
192 | * AML Parse, pass 2 | 271 | if (ACPI_FAILURE(status)) { |
193 | * | 272 | return_ACPI_STATUS(status); |
194 | * In this pass, we resolve forward references and other things | 273 | } |
195 | * that could not be completed during the first pass. | 274 | } else { |
196 | * Another complete parse of the AML is performed, but the | 275 | /* |
197 | * overhead of this is compensated for by the fact that the | 276 | * AML Parse, pass 1 |
198 | * parse objects are all cached. | 277 | * |
199 | */ | 278 | * In this pass, we load most of the namespace. Control methods |
200 | ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "**** Start pass 2\n")); | 279 | * are not parsed until later. A parse tree is not created. |
201 | status = acpi_ns_one_complete_parse(ACPI_IMODE_LOAD_PASS2, | 280 | * Instead, each Parser Op subtree is deleted when it is finished. |
202 | table_index, start_node); | 281 | * This saves a great deal of memory, and allows a small cache of |
203 | if (ACPI_FAILURE(status)) { | 282 | * parse objects to service the entire parse. The second pass of |
204 | return_ACPI_STATUS(status); | 283 | * the parse then performs another complete parse of the AML. |
284 | */ | ||
285 | ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "**** Start pass 1\n")); | ||
286 | |||
287 | status = acpi_ns_one_complete_parse(ACPI_IMODE_LOAD_PASS1, | ||
288 | table_index, start_node); | ||
289 | if (ACPI_FAILURE(status)) { | ||
290 | return_ACPI_STATUS(status); | ||
291 | } | ||
292 | |||
293 | /* | ||
294 | * AML Parse, pass 2 | ||
295 | * | ||
296 | * In this pass, we resolve forward references and other things | ||
297 | * that could not be completed during the first pass. | ||
298 | * Another complete parse of the AML is performed, but the | ||
299 | * overhead of this is compensated for by the fact that the | ||
300 | * parse objects are all cached. | ||
301 | */ | ||
302 | ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "**** Start pass 2\n")); | ||
303 | status = acpi_ns_one_complete_parse(ACPI_IMODE_LOAD_PASS2, | ||
304 | table_index, start_node); | ||
305 | if (ACPI_FAILURE(status)) { | ||
306 | return_ACPI_STATUS(status); | ||
307 | } | ||
205 | } | 308 | } |
206 | 309 | ||
207 | return_ACPI_STATUS(status); | 310 | return_ACPI_STATUS(status); |