Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3c59f960 authored by Bob Moore's avatar Bob Moore Committed by Len Brown
Browse files

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: default avatarBob Moore <robert.moore@intel.com>
Signed-off-by: default avatarLin Ming <ming.m.lin@intel.com>
Signed-off-by: default avatarLen Brown <len.brown@intel.com>
parent b2f7ddcf
Loading
Loading
Loading
Loading
+78 −18
Original line number Diff line number Diff line
@@ -47,6 +47,7 @@
#include "acnamesp.h"
#include "actables.h"
#include "acdispat.h"
#include "acevents.h"

#define _COMPONENT          ACPI_EXECUTER
ACPI_MODULE_NAME("exconfig")
@@ -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
@@ -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
@@ -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 */

@@ -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 */
@@ -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;