ACPICA: Update Load() to use operation region interfaces
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>
This commit is contained in:
@@ -47,6 +47,7 @@
|
|||||||
#include "acnamesp.h"
|
#include "acnamesp.h"
|
||||||
#include "actables.h"
|
#include "actables.h"
|
||||||
#include "acdispat.h"
|
#include "acdispat.h"
|
||||||
|
#include "acevents.h"
|
||||||
|
|
||||||
#define _COMPONENT ACPI_EXECUTER
|
#define _COMPONENT ACPI_EXECUTER
|
||||||
ACPI_MODULE_NAME("exconfig")
|
ACPI_MODULE_NAME("exconfig")
|
||||||
@@ -57,6 +58,10 @@ acpi_ex_add_table(u32 table_index,
|
|||||||
struct acpi_namespace_node *parent_node,
|
struct acpi_namespace_node *parent_node,
|
||||||
union acpi_operand_object **ddb_handle);
|
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
|
* FUNCTION: acpi_ex_add_table
|
||||||
@@ -255,6 +260,48 @@ acpi_ex_load_table_op(struct acpi_walk_state *walk_state,
|
|||||||
return_ACPI_STATUS(status);
|
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
|
* FUNCTION: acpi_ex_load_op
|
||||||
@@ -317,18 +364,23 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/* Get the table header first so we can get the table length */
|
||||||
* 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_ALLOCATE(sizeof(struct acpi_table_header));
|
||||||
*/
|
|
||||||
table = acpi_os_map_memory(obj_desc->region.address,
|
|
||||||
sizeof(struct acpi_table_header));
|
|
||||||
if (!table) {
|
if (!table) {
|
||||||
return_ACPI_STATUS(AE_NO_MEMORY);
|
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;
|
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 */
|
/* Must have at least an ACPI table header */
|
||||||
|
|
||||||
@@ -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
|
* The original implementation simply mapped the table, with no copy.
|
||||||
* copy the table to a local buffer. For example, the memory region
|
* However, the memory region is not guaranteed to remain stable and
|
||||||
* is corrupted after suspend on some machines. Dynamically loaded
|
* we must copy the table to a local buffer. For example, the memory
|
||||||
* tables are usually small, so this overhead is minimal.
|
* 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 */
|
/* Allocate a buffer for the table */
|
||||||
@@ -350,17 +411,16 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc,
|
|||||||
return_ACPI_STATUS(AE_NO_MEMORY);
|
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);
|
status = acpi_ex_region_read(obj_desc, length,
|
||||||
if (!table) {
|
ACPI_CAST_PTR(u8,
|
||||||
|
table_desc.pointer));
|
||||||
|
if (ACPI_FAILURE(status)) {
|
||||||
ACPI_FREE(table_desc.pointer);
|
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;
|
table_desc.address = obj_desc->region.address;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user