Skip to content

Commit

Permalink
ACPICA: Update Load() to use operation region interfaces
Browse files Browse the repository at this point in the history
Replace memory mapping with region access calls. Now, all region
accesses go through the region handler as they should.

Signed-off-by: Bob Moore <robert.moore@intel.com>
Signed-off-by: Lin Ming <ming.m.lin@intel.com>
Signed-off-by: Len Brown <len.brown@intel.com>
  • Loading branch information
Bob Moore authored and Len Brown committed May 27, 2009
1 parent b2f7ddc commit 3c59f96
Showing 1 changed file with 78 additions and 18 deletions.
96 changes: 78 additions & 18 deletions drivers/acpi/acpica/exconfig.c
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
#include "acnamesp.h"
#include "actables.h"
#include "acdispat.h"
#include "acevents.h"

#define _COMPONENT ACPI_EXECUTER
ACPI_MODULE_NAME("exconfig")
Expand All @@ -57,6 +58,10 @@ acpi_ex_add_table(u32 table_index,
struct acpi_namespace_node *parent_node,
union acpi_operand_object **ddb_handle);

static acpi_status
acpi_ex_region_read(union acpi_operand_object *obj_desc,
u32 length, u8 *buffer);

/*******************************************************************************
*
* FUNCTION: acpi_ex_add_table
Expand Down Expand Up @@ -255,6 +260,48 @@ acpi_ex_load_table_op(struct acpi_walk_state *walk_state,
return_ACPI_STATUS(status);
}

/*******************************************************************************
*
* FUNCTION: acpi_ex_region_read
*
* PARAMETERS: obj_desc - Region descriptor
* Length - Number of bytes to read
* Buffer - Pointer to where to put the data
*
* RETURN: Status
*
* DESCRIPTION: Read data from an operation region. The read starts from the
* beginning of the region.
*
******************************************************************************/

static acpi_status
acpi_ex_region_read(union acpi_operand_object *obj_desc, u32 length, u8 *buffer)
{
acpi_status status;
acpi_integer value;
acpi_physical_address address;
u32 i;

address = obj_desc->region.address;

/* Bytewise reads */

for (i = 0; i < length; i++) {
status = acpi_ev_address_space_dispatch(obj_desc, ACPI_READ,
address, 8, &value);
if (ACPI_FAILURE(status)) {
return status;
}

*buffer = (u8)value;
buffer++;
address++;
}

return AE_OK;
}

/*******************************************************************************
*
* FUNCTION: acpi_ex_load_op
Expand Down Expand Up @@ -317,18 +364,23 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc,
}
}

/*
* Map the table header and get the actual table length. The region
* length is not guaranteed to be the same as the table length.
*/
table = acpi_os_map_memory(obj_desc->region.address,
sizeof(struct acpi_table_header));
/* Get the table header first so we can get the table length */

table = ACPI_ALLOCATE(sizeof(struct acpi_table_header));
if (!table) {
return_ACPI_STATUS(AE_NO_MEMORY);
}

status =
acpi_ex_region_read(obj_desc,
sizeof(struct acpi_table_header),
ACPI_CAST_PTR(u8, table));
length = table->length;
acpi_os_unmap_memory(table, sizeof(struct acpi_table_header));
ACPI_FREE(table);

if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}

/* Must have at least an ACPI table header */

Expand All @@ -337,10 +389,19 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc,
}

/*
* The memory region is not guaranteed to remain stable and we must
* copy the table to a local buffer. For example, the memory region
* is corrupted after suspend on some machines. Dynamically loaded
* tables are usually small, so this overhead is minimal.
* The original implementation simply mapped the table, with no copy.
* However, the memory region is not guaranteed to remain stable and
* we must copy the table to a local buffer. For example, the memory
* region is corrupted after suspend on some machines. Dynamically
* loaded tables are usually small, so this overhead is minimal.
*
* The latest implementation (5/2009) does not use a mapping at all.
* We use the low-level operation region interface to read the table
* instead of the obvious optimization of using a direct mapping.
* This maintains a consistent use of operation regions across the
* entire subsystem. This is important if additional processing must
* be performed in the (possibly user-installed) operation region
* handler. For example, acpi_exec and ASLTS depend on this.
*/

/* Allocate a buffer for the table */
Expand All @@ -350,17 +411,16 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc,
return_ACPI_STATUS(AE_NO_MEMORY);
}

/* Map the entire table and copy it */
/* Read the entire table */

table = acpi_os_map_memory(obj_desc->region.address, length);
if (!table) {
status = acpi_ex_region_read(obj_desc, length,
ACPI_CAST_PTR(u8,
table_desc.pointer));
if (ACPI_FAILURE(status)) {
ACPI_FREE(table_desc.pointer);
return_ACPI_STATUS(AE_NO_MEMORY);
return_ACPI_STATUS(status);
}

ACPI_MEMCPY(table_desc.pointer, table, length);
acpi_os_unmap_memory(table, length);

table_desc.address = obj_desc->region.address;
break;

Expand Down

0 comments on commit 3c59f96

Please sign in to comment.