diff options
author | Alexey Starikovskiy <alexey.y.starikovskiy@intel.com> | 2007-02-02 11:48:22 -0500 |
---|---|---|
committer | Len Brown <len.brown@intel.com> | 2007-02-02 21:14:29 -0500 |
commit | a6823e12ca3f79a8c0f8b2d14976ab2152d117e5 (patch) | |
tree | b09c1cfca1332b9bf878827900f86a768ba2da9c /drivers/acpi/executer/exconfig.c | |
parent | 428f211297bc95fd41f23830eab4180339020dd0 (diff) |
ACPICA: Fixes for load() operator.
Optimized the Load operator in the case where the source operand is an
operation region. Simply map the operation region memory, instead of
performing a bytewise read.
Signed-off-by: Bob Moore <robert.moore@intel.com>
Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers/acpi/executer/exconfig.c')
-rw-r--r-- | drivers/acpi/executer/exconfig.c | 160 |
1 files changed, 34 insertions, 126 deletions
diff --git a/drivers/acpi/executer/exconfig.c b/drivers/acpi/executer/exconfig.c index 7aa18f93f95d..61ec855b5d61 100644 --- a/drivers/acpi/executer/exconfig.c +++ b/drivers/acpi/executer/exconfig.c | |||
@@ -119,7 +119,7 @@ acpi_ex_add_table(acpi_native_uint table_index, | |||
119 | * | 119 | * |
120 | * RETURN: Status | 120 | * RETURN: Status |
121 | * | 121 | * |
122 | * DESCRIPTION: Load an ACPI table | 122 | * DESCRIPTION: Load an ACPI table from the RSDT/XSDT |
123 | * | 123 | * |
124 | ******************************************************************************/ | 124 | ******************************************************************************/ |
125 | 125 | ||
@@ -138,21 +138,7 @@ acpi_ex_load_table_op(struct acpi_walk_state *walk_state, | |||
138 | 138 | ||
139 | ACPI_FUNCTION_TRACE(ex_load_table_op); | 139 | ACPI_FUNCTION_TRACE(ex_load_table_op); |
140 | 140 | ||
141 | #if 0 | 141 | /* Find the ACPI table in the RSDT/XSDT */ |
142 | /* | ||
143 | * Make sure that the signature does not match one of the tables that | ||
144 | * is already loaded. | ||
145 | */ | ||
146 | status = acpi_tb_match_signature(operand[0]->string.pointer, NULL); | ||
147 | if (status == AE_OK) { | ||
148 | |||
149 | /* Signature matched -- don't allow override */ | ||
150 | |||
151 | return_ACPI_STATUS(AE_ALREADY_EXISTS); | ||
152 | } | ||
153 | #endif | ||
154 | |||
155 | /* Find the ACPI table */ | ||
156 | 142 | ||
157 | status = acpi_tb_find_table(operand[0]->string.pointer, | 143 | status = acpi_tb_find_table(operand[0]->string.pointer, |
158 | operand[1]->string.pointer, | 144 | operand[1]->string.pointer, |
@@ -256,7 +242,7 @@ acpi_ex_load_table_op(struct acpi_walk_state *walk_state, | |||
256 | * | 242 | * |
257 | * FUNCTION: acpi_ex_load_op | 243 | * FUNCTION: acpi_ex_load_op |
258 | * | 244 | * |
259 | * PARAMETERS: obj_desc - Region or Field where the table will be | 245 | * PARAMETERS: obj_desc - Region or Buffer/Field where the table will be |
260 | * obtained | 246 | * obtained |
261 | * Target - Where a handle to the table will be stored | 247 | * Target - Where a handle to the table will be stored |
262 | * walk_state - Current state | 248 | * walk_state - Current state |
@@ -265,6 +251,12 @@ acpi_ex_load_table_op(struct acpi_walk_state *walk_state, | |||
265 | * | 251 | * |
266 | * DESCRIPTION: Load an ACPI table from a field or operation region | 252 | * DESCRIPTION: Load an ACPI table from a field or operation region |
267 | * | 253 | * |
254 | * NOTE: Region Fields (Field, bank_field, index_fields) are resolved to buffer | ||
255 | * objects before this code is reached. | ||
256 | * | ||
257 | * If source is an operation region, it must refer to system_memory, as | ||
258 | * per the ACPI specification. | ||
259 | * | ||
268 | ******************************************************************************/ | 260 | ******************************************************************************/ |
269 | 261 | ||
270 | acpi_status | 262 | acpi_status |
@@ -272,24 +264,26 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc, | |||
272 | union acpi_operand_object *target, | 264 | union acpi_operand_object *target, |
273 | struct acpi_walk_state *walk_state) | 265 | struct acpi_walk_state *walk_state) |
274 | { | 266 | { |
275 | acpi_status status; | ||
276 | union acpi_operand_object *ddb_handle; | 267 | union acpi_operand_object *ddb_handle; |
277 | union acpi_operand_object *buffer_desc = NULL; | ||
278 | struct acpi_table_header *table_ptr = NULL; | ||
279 | acpi_native_uint table_index; | ||
280 | acpi_physical_address address; | ||
281 | struct acpi_table_header table_header; | ||
282 | struct acpi_table_desc table_desc; | 268 | struct acpi_table_desc table_desc; |
283 | acpi_integer temp; | 269 | acpi_native_uint table_index; |
284 | u32 i; | 270 | acpi_status status; |
285 | 271 | ||
286 | ACPI_FUNCTION_TRACE(ex_load_op); | 272 | ACPI_FUNCTION_TRACE(ex_load_op); |
287 | 273 | ||
288 | /* Object can be either an op_region or a Field */ | ||
289 | ACPI_MEMSET(&table_desc, 0, sizeof(struct acpi_table_desc)); | 274 | ACPI_MEMSET(&table_desc, 0, sizeof(struct acpi_table_desc)); |
275 | |||
276 | /* Source Object can be either an op_region or a Buffer/Field */ | ||
277 | |||
290 | switch (ACPI_GET_OBJECT_TYPE(obj_desc)) { | 278 | switch (ACPI_GET_OBJECT_TYPE(obj_desc)) { |
291 | case ACPI_TYPE_REGION: | 279 | case ACPI_TYPE_REGION: |
292 | 280 | ||
281 | /* Region must be system_memory (from ACPI spec) */ | ||
282 | |||
283 | if (obj_desc->region.space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY) { | ||
284 | return_ACPI_STATUS(AE_AML_OPERAND_TYPE); | ||
285 | } | ||
286 | |||
293 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Load from Region %p %s\n", | 287 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Load from Region %p %s\n", |
294 | obj_desc, | 288 | obj_desc, |
295 | acpi_ut_get_object_type_name(obj_desc))); | 289 | acpi_ut_get_object_type_name(obj_desc))); |
@@ -305,113 +299,31 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc, | |||
305 | } | 299 | } |
306 | } | 300 | } |
307 | 301 | ||
308 | /* Get the base physical address of the region */ | 302 | table_desc.address = obj_desc->region.address; |
309 | 303 | table_desc.length = obj_desc->region.length; | |
310 | address = obj_desc->region.address; | 304 | table_desc.flags = ACPI_TABLE_ORIGIN_MAPPED; |
311 | |||
312 | /* Get part of the table header to get the table length */ | ||
313 | |||
314 | table_header.length = 0; | ||
315 | for (i = 0; i < 8; i++) { | ||
316 | status = | ||
317 | acpi_ev_address_space_dispatch(obj_desc, ACPI_READ, | ||
318 | (acpi_physical_address) | ||
319 | (i + address), 8, | ||
320 | &temp); | ||
321 | if (ACPI_FAILURE(status)) { | ||
322 | return_ACPI_STATUS(status); | ||
323 | } | ||
324 | |||
325 | /* Get the one valid byte of the returned 64-bit value */ | ||
326 | |||
327 | ACPI_CAST_PTR(u8, &table_header)[i] = (u8) temp; | ||
328 | } | ||
329 | |||
330 | /* Sanity check the table length */ | ||
331 | |||
332 | if (table_header.length < sizeof(struct acpi_table_header)) { | ||
333 | return_ACPI_STATUS(AE_BAD_HEADER); | ||
334 | } | ||
335 | |||
336 | /* Allocate a buffer for the entire table */ | ||
337 | |||
338 | table_ptr = ACPI_ALLOCATE(table_header.length); | ||
339 | if (!table_ptr) { | ||
340 | return_ACPI_STATUS(AE_NO_MEMORY); | ||
341 | } | ||
342 | |||
343 | /* Get the entire table from the op region */ | ||
344 | |||
345 | for (i = 0; i < table_header.length; i++) { | ||
346 | status = | ||
347 | acpi_ev_address_space_dispatch(obj_desc, ACPI_READ, | ||
348 | (acpi_physical_address) | ||
349 | (i + address), 8, | ||
350 | &temp); | ||
351 | if (ACPI_FAILURE(status)) { | ||
352 | goto cleanup; | ||
353 | } | ||
354 | |||
355 | /* Get the one valid byte of the returned 64-bit value */ | ||
356 | |||
357 | ACPI_CAST_PTR(u8, table_ptr)[i] = (u8) temp; | ||
358 | } | ||
359 | break; | 305 | break; |
360 | 306 | ||
361 | case ACPI_TYPE_LOCAL_REGION_FIELD: | 307 | case ACPI_TYPE_BUFFER: /* Buffer or resolved region_field */ |
362 | case ACPI_TYPE_LOCAL_BANK_FIELD: | ||
363 | case ACPI_TYPE_LOCAL_INDEX_FIELD: | ||
364 | 308 | ||
365 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Load from Field %p %s\n", | 309 | /* Simply extract the buffer from the buffer object */ |
366 | obj_desc, | ||
367 | acpi_ut_get_object_type_name(obj_desc))); | ||
368 | 310 | ||
369 | /* | 311 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, |
370 | * The length of the field must be at least as large as the table. | 312 | "Load from Buffer or Field %p %s\n", obj_desc, |
371 | * Read the entire field and thus the entire table. Buffer is | 313 | acpi_ut_get_object_type_name(obj_desc))); |
372 | * allocated during the read. | ||
373 | */ | ||
374 | status = | ||
375 | acpi_ex_read_data_from_field(walk_state, obj_desc, | ||
376 | &buffer_desc); | ||
377 | if (ACPI_FAILURE(status)) { | ||
378 | return_ACPI_STATUS(status); | ||
379 | } | ||
380 | |||
381 | table_ptr = ACPI_CAST_PTR(struct acpi_table_header, | ||
382 | buffer_desc->buffer.pointer); | ||
383 | |||
384 | /* All done with the buffer_desc, delete it */ | ||
385 | |||
386 | buffer_desc->buffer.pointer = NULL; | ||
387 | acpi_ut_remove_reference(buffer_desc); | ||
388 | 314 | ||
389 | /* Sanity check the table length */ | 315 | table_desc.pointer = ACPI_CAST_PTR(struct acpi_table_header, |
316 | obj_desc->buffer.pointer); | ||
317 | table_desc.length = table_desc.pointer->length; | ||
318 | table_desc.flags = ACPI_TABLE_ORIGIN_ALLOCATED; | ||
390 | 319 | ||
391 | if (table_ptr->length < sizeof(struct acpi_table_header)) { | 320 | obj_desc->buffer.pointer = NULL; |
392 | status = AE_BAD_HEADER; | ||
393 | goto cleanup; | ||
394 | } | ||
395 | break; | 321 | break; |
396 | 322 | ||
397 | default: | 323 | default: |
398 | return_ACPI_STATUS(AE_AML_OPERAND_TYPE); | 324 | return_ACPI_STATUS(AE_AML_OPERAND_TYPE); |
399 | } | 325 | } |
400 | 326 | ||
401 | /* The table must be either an SSDT or a PSDT */ | ||
402 | |||
403 | if ((!ACPI_COMPARE_NAME(table_ptr->signature, ACPI_SIG_PSDT)) && | ||
404 | (!ACPI_COMPARE_NAME(table_ptr->signature, ACPI_SIG_SSDT))) { | ||
405 | ACPI_ERROR((AE_INFO, | ||
406 | "Table has invalid signature [%4.4s], must be SSDT or PSDT", | ||
407 | table_ptr->signature)); | ||
408 | status = AE_BAD_SIGNATURE; | ||
409 | goto cleanup; | ||
410 | } | ||
411 | |||
412 | table_desc.pointer = table_ptr; | ||
413 | table_desc.length = table_ptr->length; | ||
414 | table_desc.flags = ACPI_TABLE_ORIGIN_ALLOCATED; | ||
415 | /* | 327 | /* |
416 | * Install the new table into the local data structures | 328 | * Install the new table into the local data structures |
417 | */ | 329 | */ |
@@ -440,13 +352,9 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc, | |||
440 | return_ACPI_STATUS(status); | 352 | return_ACPI_STATUS(status); |
441 | } | 353 | } |
442 | 354 | ||
443 | ACPI_INFO((AE_INFO, | ||
444 | "Dynamic SSDT Load - OemId [%6.6s] OemTableId [%8.8s]", | ||
445 | table_ptr->oem_id, table_ptr->oem_table_id)); | ||
446 | |||
447 | cleanup: | 355 | cleanup: |
448 | if (ACPI_FAILURE(status)) { | 356 | if (ACPI_FAILURE(status)) { |
449 | ACPI_FREE(table_ptr); | 357 | acpi_tb_delete_table(&table_desc); |
450 | } | 358 | } |
451 | return_ACPI_STATUS(status); | 359 | return_ACPI_STATUS(status); |
452 | } | 360 | } |