aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/executer/exconfig.c
diff options
context:
space:
mode:
authorAlexey Starikovskiy <alexey.y.starikovskiy@intel.com>2007-02-02 11:48:22 -0500
committerLen Brown <len.brown@intel.com>2007-02-02 21:14:29 -0500
commita6823e12ca3f79a8c0f8b2d14976ab2152d117e5 (patch)
treeb09c1cfca1332b9bf878827900f86a768ba2da9c /drivers/acpi/executer/exconfig.c
parent428f211297bc95fd41f23830eab4180339020dd0 (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.c160
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
270acpi_status 262acpi_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}