aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/acpica/exconfig.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/acpi/acpica/exconfig.c')
-rw-r--r--drivers/acpi/acpica/exconfig.c125
1 files changed, 102 insertions, 23 deletions
diff --git a/drivers/acpi/acpica/exconfig.c b/drivers/acpi/acpica/exconfig.c
index 3deb20a126b..277fd609611 100644
--- a/drivers/acpi/acpica/exconfig.c
+++ b/drivers/acpi/acpica/exconfig.c
@@ -47,6 +47,7 @@
47#include "acnamesp.h" 47#include "acnamesp.h"
48#include "actables.h" 48#include "actables.h"
49#include "acdispat.h" 49#include "acdispat.h"
50#include "acevents.h"
50 51
51#define _COMPONENT ACPI_EXECUTER 52#define _COMPONENT ACPI_EXECUTER
52ACPI_MODULE_NAME("exconfig") 53ACPI_MODULE_NAME("exconfig")
@@ -57,6 +58,10 @@ acpi_ex_add_table(u32 table_index,
57 struct acpi_namespace_node *parent_node, 58 struct acpi_namespace_node *parent_node,
58 union acpi_operand_object **ddb_handle); 59 union acpi_operand_object **ddb_handle);
59 60
61static acpi_status
62acpi_ex_region_read(union acpi_operand_object *obj_desc,
63 u32 length, u8 *buffer);
64
60/******************************************************************************* 65/*******************************************************************************
61 * 66 *
62 * FUNCTION: acpi_ex_add_table 67 * FUNCTION: acpi_ex_add_table
@@ -91,6 +96,7 @@ acpi_ex_add_table(u32 table_index,
91 96
92 /* Init the table handle */ 97 /* Init the table handle */
93 98
99 obj_desc->common.flags |= AOPOBJ_DATA_VALID;
94 obj_desc->reference.class = ACPI_REFCLASS_TABLE; 100 obj_desc->reference.class = ACPI_REFCLASS_TABLE;
95 *ddb_handle = obj_desc; 101 *ddb_handle = obj_desc;
96 102
@@ -229,6 +235,8 @@ acpi_ex_load_table_op(struct acpi_walk_state *walk_state,
229 walk_state); 235 walk_state);
230 if (ACPI_FAILURE(status)) { 236 if (ACPI_FAILURE(status)) {
231 (void)acpi_ex_unload_table(ddb_handle); 237 (void)acpi_ex_unload_table(ddb_handle);
238
239 acpi_ut_remove_reference(ddb_handle);
232 return_ACPI_STATUS(status); 240 return_ACPI_STATUS(status);
233 } 241 }
234 } 242 }
@@ -254,6 +262,47 @@ acpi_ex_load_table_op(struct acpi_walk_state *walk_state,
254 262
255/******************************************************************************* 263/*******************************************************************************
256 * 264 *
265 * FUNCTION: acpi_ex_region_read
266 *
267 * PARAMETERS: obj_desc - Region descriptor
268 * Length - Number of bytes to read
269 * Buffer - Pointer to where to put the data
270 *
271 * RETURN: Status
272 *
273 * DESCRIPTION: Read data from an operation region. The read starts from the
274 * beginning of the region.
275 *
276 ******************************************************************************/
277
278static acpi_status
279acpi_ex_region_read(union acpi_operand_object *obj_desc, u32 length, u8 *buffer)
280{
281 acpi_status status;
282 acpi_integer value;
283 u32 region_offset = 0;
284 u32 i;
285
286 /* Bytewise reads */
287
288 for (i = 0; i < length; i++) {
289 status = acpi_ev_address_space_dispatch(obj_desc, ACPI_READ,
290 region_offset, 8,
291 &value);
292 if (ACPI_FAILURE(status)) {
293 return status;
294 }
295
296 *buffer = (u8)value;
297 buffer++;
298 region_offset++;
299 }
300
301 return AE_OK;
302}
303
304/*******************************************************************************
305 *
257 * FUNCTION: acpi_ex_load_op 306 * FUNCTION: acpi_ex_load_op
258 * 307 *
259 * PARAMETERS: obj_desc - Region or Buffer/Field where the table will be 308 * PARAMETERS: obj_desc - Region or Buffer/Field where the table will be
@@ -314,18 +363,23 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc,
314 } 363 }
315 } 364 }
316 365
317 /* 366 /* Get the table header first so we can get the table length */
318 * Map the table header and get the actual table length. The region 367
319 * length is not guaranteed to be the same as the table length. 368 table = ACPI_ALLOCATE(sizeof(struct acpi_table_header));
320 */
321 table = acpi_os_map_memory(obj_desc->region.address,
322 sizeof(struct acpi_table_header));
323 if (!table) { 369 if (!table) {
324 return_ACPI_STATUS(AE_NO_MEMORY); 370 return_ACPI_STATUS(AE_NO_MEMORY);
325 } 371 }
326 372
373 status =
374 acpi_ex_region_read(obj_desc,
375 sizeof(struct acpi_table_header),
376 ACPI_CAST_PTR(u8, table));
327 length = table->length; 377 length = table->length;
328 acpi_os_unmap_memory(table, sizeof(struct acpi_table_header)); 378 ACPI_FREE(table);
379
380 if (ACPI_FAILURE(status)) {
381 return_ACPI_STATUS(status);
382 }
329 383
330 /* Must have at least an ACPI table header */ 384 /* Must have at least an ACPI table header */
331 385
@@ -334,10 +388,19 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc,
334 } 388 }
335 389
336 /* 390 /*
337 * The memory region is not guaranteed to remain stable and we must 391 * The original implementation simply mapped the table, with no copy.
338 * copy the table to a local buffer. For example, the memory region 392 * However, the memory region is not guaranteed to remain stable and
339 * is corrupted after suspend on some machines. Dynamically loaded 393 * we must copy the table to a local buffer. For example, the memory
340 * tables are usually small, so this overhead is minimal. 394 * region is corrupted after suspend on some machines. Dynamically
395 * loaded tables are usually small, so this overhead is minimal.
396 *
397 * The latest implementation (5/2009) does not use a mapping at all.
398 * We use the low-level operation region interface to read the table
399 * instead of the obvious optimization of using a direct mapping.
400 * This maintains a consistent use of operation regions across the
401 * entire subsystem. This is important if additional processing must
402 * be performed in the (possibly user-installed) operation region
403 * handler. For example, acpi_exec and ASLTS depend on this.
341 */ 404 */
342 405
343 /* Allocate a buffer for the table */ 406 /* Allocate a buffer for the table */
@@ -347,17 +410,16 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc,
347 return_ACPI_STATUS(AE_NO_MEMORY); 410 return_ACPI_STATUS(AE_NO_MEMORY);
348 } 411 }
349 412
350 /* Map the entire table and copy it */ 413 /* Read the entire table */
351 414
352 table = acpi_os_map_memory(obj_desc->region.address, length); 415 status = acpi_ex_region_read(obj_desc, length,
353 if (!table) { 416 ACPI_CAST_PTR(u8,
417 table_desc.pointer));
418 if (ACPI_FAILURE(status)) {
354 ACPI_FREE(table_desc.pointer); 419 ACPI_FREE(table_desc.pointer);
355 return_ACPI_STATUS(AE_NO_MEMORY); 420 return_ACPI_STATUS(status);
356 } 421 }
357 422
358 ACPI_MEMCPY(table_desc.pointer, table, length);
359 acpi_os_unmap_memory(table, length);
360
361 table_desc.address = obj_desc->region.address; 423 table_desc.address = obj_desc->region.address;
362 break; 424 break;
363 425
@@ -454,6 +516,10 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc,
454 return_ACPI_STATUS(status); 516 return_ACPI_STATUS(status);
455 } 517 }
456 518
519 /* Remove the reference by added by acpi_ex_store above */
520
521 acpi_ut_remove_reference(ddb_handle);
522
457 /* Invoke table handler if present */ 523 /* Invoke table handler if present */
458 524
459 if (acpi_gbl_table_handler) { 525 if (acpi_gbl_table_handler) {
@@ -495,13 +561,18 @@ acpi_status acpi_ex_unload_table(union acpi_operand_object *ddb_handle)
495 561
496 /* 562 /*
497 * Validate the handle 563 * Validate the handle
498 * Although the handle is partially validated in acpi_ex_reconfiguration(), 564 * Although the handle is partially validated in acpi_ex_reconfiguration()
499 * when it calls acpi_ex_resolve_operands(), the handle is more completely 565 * when it calls acpi_ex_resolve_operands(), the handle is more completely
500 * validated here. 566 * validated here.
567 *
568 * Handle must be a valid operand object of type reference. Also, the
569 * ddb_handle must still be marked valid (table has not been previously
570 * unloaded)
501 */ 571 */
502 if ((!ddb_handle) || 572 if ((!ddb_handle) ||
503 (ACPI_GET_DESCRIPTOR_TYPE(ddb_handle) != ACPI_DESC_TYPE_OPERAND) || 573 (ACPI_GET_DESCRIPTOR_TYPE(ddb_handle) != ACPI_DESC_TYPE_OPERAND) ||
504 (ddb_handle->common.type != ACPI_TYPE_LOCAL_REFERENCE)) { 574 (ddb_handle->common.type != ACPI_TYPE_LOCAL_REFERENCE) ||
575 (!(ddb_handle->common.flags & AOPOBJ_DATA_VALID))) {
505 return_ACPI_STATUS(AE_BAD_PARAMETER); 576 return_ACPI_STATUS(AE_BAD_PARAMETER);
506 } 577 }
507 578
@@ -509,6 +580,12 @@ acpi_status acpi_ex_unload_table(union acpi_operand_object *ddb_handle)
509 580
510 table_index = table_desc->reference.value; 581 table_index = table_desc->reference.value;
511 582
583 /* Ensure the table is still loaded */
584
585 if (!acpi_tb_is_table_loaded(table_index)) {
586 return_ACPI_STATUS(AE_NOT_EXIST);
587 }
588
512 /* Invoke table handler if present */ 589 /* Invoke table handler if present */
513 590
514 if (acpi_gbl_table_handler) { 591 if (acpi_gbl_table_handler) {
@@ -530,8 +607,10 @@ acpi_status acpi_ex_unload_table(union acpi_operand_object *ddb_handle)
530 (void)acpi_tb_release_owner_id(table_index); 607 (void)acpi_tb_release_owner_id(table_index);
531 acpi_tb_set_table_loaded_flag(table_index, FALSE); 608 acpi_tb_set_table_loaded_flag(table_index, FALSE);
532 609
533 /* Table unloaded, remove a reference to the ddb_handle object */ 610 /*
534 611 * Invalidate the handle. We do this because the handle may be stored
535 acpi_ut_remove_reference(ddb_handle); 612 * in a named object and may not be actually deleted until much later.
613 */
614 ddb_handle->common.flags &= ~AOPOBJ_DATA_VALID;
536 return_ACPI_STATUS(AE_OK); 615 return_ACPI_STATUS(AE_OK);
537} 616}