aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/acpi/acpica/exconfig.c96
1 files changed, 78 insertions, 18 deletions
diff --git a/drivers/acpi/acpica/exconfig.c b/drivers/acpi/acpica/exconfig.c
index 0731fd6bad63..eca6f63a53fd 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
@@ -257,6 +262,48 @@ acpi_ex_load_table_op(struct acpi_walk_state *walk_state,
257 262
258/******************************************************************************* 263/*******************************************************************************
259 * 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 acpi_physical_address address;
284 u32 i;
285
286 address = obj_desc->region.address;
287
288 /* Bytewise reads */
289
290 for (i = 0; i < length; i++) {
291 status = acpi_ev_address_space_dispatch(obj_desc, ACPI_READ,
292 address, 8, &value);
293 if (ACPI_FAILURE(status)) {
294 return status;
295 }
296
297 *buffer = (u8)value;
298 buffer++;
299 address++;
300 }
301
302 return AE_OK;
303}
304
305/*******************************************************************************
306 *
260 * FUNCTION: acpi_ex_load_op 307 * FUNCTION: acpi_ex_load_op
261 * 308 *
262 * PARAMETERS: obj_desc - Region or Buffer/Field where the table will be 309 * PARAMETERS: obj_desc - Region or Buffer/Field where the table will be
@@ -317,18 +364,23 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc,
317 } 364 }
318 } 365 }
319 366
320 /* 367 /* Get the table header first so we can get the table length */
321 * Map the table header and get the actual table length. The region 368
322 * length is not guaranteed to be the same as the table length. 369 table = ACPI_ALLOCATE(sizeof(struct acpi_table_header));
323 */
324 table = acpi_os_map_memory(obj_desc->region.address,
325 sizeof(struct acpi_table_header));
326 if (!table) { 370 if (!table) {
327 return_ACPI_STATUS(AE_NO_MEMORY); 371 return_ACPI_STATUS(AE_NO_MEMORY);
328 } 372 }
329 373
374 status =
375 acpi_ex_region_read(obj_desc,
376 sizeof(struct acpi_table_header),
377 ACPI_CAST_PTR(u8, table));
330 length = table->length; 378 length = table->length;
331 acpi_os_unmap_memory(table, sizeof(struct acpi_table_header)); 379 ACPI_FREE(table);
380
381 if (ACPI_FAILURE(status)) {
382 return_ACPI_STATUS(status);
383 }
332 384
333 /* Must have at least an ACPI table header */ 385 /* Must have at least an ACPI table header */
334 386
@@ -337,10 +389,19 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc,
337 } 389 }
338 390
339 /* 391 /*
340 * The memory region is not guaranteed to remain stable and we must 392 * The original implementation simply mapped the table, with no copy.
341 * copy the table to a local buffer. For example, the memory region 393 * However, the memory region is not guaranteed to remain stable and
342 * is corrupted after suspend on some machines. Dynamically loaded 394 * we must copy the table to a local buffer. For example, the memory
343 * tables are usually small, so this overhead is minimal. 395 * region is corrupted after suspend on some machines. Dynamically
396 * loaded tables are usually small, so this overhead is minimal.
397 *
398 * The latest implementation (5/2009) does not use a mapping at all.
399 * We use the low-level operation region interface to read the table
400 * instead of the obvious optimization of using a direct mapping.
401 * This maintains a consistent use of operation regions across the
402 * entire subsystem. This is important if additional processing must
403 * be performed in the (possibly user-installed) operation region
404 * handler. For example, acpi_exec and ASLTS depend on this.
344 */ 405 */
345 406
346 /* Allocate a buffer for the table */ 407 /* Allocate a buffer for the table */
@@ -350,17 +411,16 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc,
350 return_ACPI_STATUS(AE_NO_MEMORY); 411 return_ACPI_STATUS(AE_NO_MEMORY);
351 } 412 }
352 413
353 /* Map the entire table and copy it */ 414 /* Read the entire table */
354 415
355 table = acpi_os_map_memory(obj_desc->region.address, length); 416 status = acpi_ex_region_read(obj_desc, length,
356 if (!table) { 417 ACPI_CAST_PTR(u8,
418 table_desc.pointer));
419 if (ACPI_FAILURE(status)) {
357 ACPI_FREE(table_desc.pointer); 420 ACPI_FREE(table_desc.pointer);
358 return_ACPI_STATUS(AE_NO_MEMORY); 421 return_ACPI_STATUS(status);
359 } 422 }
360 423
361 ACPI_MEMCPY(table_desc.pointer, table, length);
362 acpi_os_unmap_memory(table, length);
363
364 table_desc.address = obj_desc->region.address; 424 table_desc.address = obj_desc->region.address;
365 break; 425 break;
366 426