summaryrefslogtreecommitdiff
path: root/drivers/acpi/acpica
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/acpi/acpica')
-rw-r--r--drivers/acpi/acpica/evrgnini.c14
-rw-r--r--drivers/acpi/acpica/exprep.c4
-rw-r--r--drivers/acpi/acpica/exregion.c64
-rw-r--r--drivers/acpi/acpica/utdelete.c6
-rw-r--r--drivers/acpi/acpica/utids.c3
5 files changed, 56 insertions, 35 deletions
diff --git a/drivers/acpi/acpica/evrgnini.c b/drivers/acpi/acpica/evrgnini.c
index aefc0145e583..89be3ccdad53 100644
--- a/drivers/acpi/acpica/evrgnini.c
+++ b/drivers/acpi/acpica/evrgnini.c
@@ -38,6 +38,7 @@ acpi_ev_system_memory_region_setup(acpi_handle handle,
union acpi_operand_object *region_desc =
(union acpi_operand_object *)handle;
struct acpi_mem_space_context *local_region_context;
+ struct acpi_mem_mapping *mm;
ACPI_FUNCTION_TRACE(ev_system_memory_region_setup);
@@ -46,13 +47,14 @@ acpi_ev_system_memory_region_setup(acpi_handle handle,
local_region_context =
(struct acpi_mem_space_context *)*region_context;
- /* Delete a cached mapping if present */
+ /* Delete memory mappings if present */
- if (local_region_context->mapped_length) {
- acpi_os_unmap_memory(local_region_context->
- mapped_logical_address,
- local_region_context->
- mapped_length);
+ while (local_region_context->first_mm) {
+ mm = local_region_context->first_mm;
+ local_region_context->first_mm = mm->next_mm;
+ acpi_os_unmap_memory(mm->logical_address,
+ mm->length);
+ ACPI_FREE(mm);
}
ACPI_FREE(local_region_context);
*region_context = NULL;
diff --git a/drivers/acpi/acpica/exprep.c b/drivers/acpi/acpica/exprep.c
index a4e306690a21..4a0f03157e08 100644
--- a/drivers/acpi/acpica/exprep.c
+++ b/drivers/acpi/acpica/exprep.c
@@ -473,10 +473,6 @@ acpi_status acpi_ex_prep_field_value(struct acpi_create_field_info *info)
(u8)access_byte_width;
}
}
- /* An additional reference for the container */
-
- acpi_ut_add_reference(obj_desc->field.region_obj);
-
ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
"RegionField: BitOff %X, Off %X, Gran %X, Region %p\n",
obj_desc->field.start_field_bit_offset,
diff --git a/drivers/acpi/acpica/exregion.c b/drivers/acpi/acpica/exregion.c
index d15a66de26c0..4914dbc44517 100644
--- a/drivers/acpi/acpica/exregion.c
+++ b/drivers/acpi/acpica/exregion.c
@@ -41,6 +41,7 @@ acpi_ex_system_memory_space_handler(u32 function,
acpi_status status = AE_OK;
void *logical_addr_ptr = NULL;
struct acpi_mem_space_context *mem_info = region_context;
+ struct acpi_mem_mapping *mm = mem_info->cur_mm;
u32 length;
acpi_size map_length;
acpi_size page_boundary_map_length;
@@ -96,20 +97,37 @@ acpi_ex_system_memory_space_handler(u32 function,
* Is 1) Address below the current mapping? OR
* 2) Address beyond the current mapping?
*/
- if ((address < mem_info->mapped_physical_address) ||
- (((u64) address + length) > ((u64)
- mem_info->mapped_physical_address +
- mem_info->mapped_length))) {
+ if (!mm || (address < mm->physical_address) ||
+ ((u64) address + length > (u64) mm->physical_address + mm->length)) {
/*
- * The request cannot be resolved by the current memory mapping;
- * Delete the existing mapping and create a new one.
+ * The request cannot be resolved by the current memory mapping.
+ *
+ * Look for an existing saved mapping covering the address range
+ * at hand. If found, save it as the current one and carry out
+ * the access.
*/
- if (mem_info->mapped_length) {
+ for (mm = mem_info->first_mm; mm; mm = mm->next_mm) {
+ if (mm == mem_info->cur_mm)
+ continue;
+
+ if (address < mm->physical_address)
+ continue;
- /* Valid mapping, delete it */
+ if ((u64) address + length >
+ (u64) mm->physical_address + mm->length)
+ continue;
- acpi_os_unmap_memory(mem_info->mapped_logical_address,
- mem_info->mapped_length);
+ mem_info->cur_mm = mm;
+ goto access;
+ }
+
+ /* Create a new mappings list entry */
+ mm = ACPI_ALLOCATE_ZEROED(sizeof(*mm));
+ if (!mm) {
+ ACPI_ERROR((AE_INFO,
+ "Unable to save memory mapping at 0x%8.8X%8.8X, size %u",
+ ACPI_FORMAT_UINT64(address), length));
+ return_ACPI_STATUS(AE_NO_MEMORY);
}
/*
@@ -143,29 +161,39 @@ acpi_ex_system_memory_space_handler(u32 function,
/* Create a new mapping starting at the address given */
- mem_info->mapped_logical_address =
- acpi_os_map_memory(address, map_length);
- if (!mem_info->mapped_logical_address) {
+ logical_addr_ptr = acpi_os_map_memory(address, map_length);
+ if (!logical_addr_ptr) {
ACPI_ERROR((AE_INFO,
"Could not map memory at 0x%8.8X%8.8X, size %u",
ACPI_FORMAT_UINT64(address),
(u32)map_length));
- mem_info->mapped_length = 0;
+ ACPI_FREE(mm);
return_ACPI_STATUS(AE_NO_MEMORY);
}
/* Save the physical address and mapping size */
- mem_info->mapped_physical_address = address;
- mem_info->mapped_length = map_length;
+ mm->logical_address = logical_addr_ptr;
+ mm->physical_address = address;
+ mm->length = map_length;
+
+ /*
+ * Add the new entry to the mappigs list and save it as the
+ * current mapping.
+ */
+ mm->next_mm = mem_info->first_mm;
+ mem_info->first_mm = mm;
+
+ mem_info->cur_mm = mm;
}
+access:
/*
* Generate a logical pointer corresponding to the address we want to
* access
*/
- logical_addr_ptr = mem_info->mapped_logical_address +
- ((u64) address - (u64) mem_info->mapped_physical_address);
+ logical_addr_ptr = mm->logical_address +
+ ((u64) address - (u64) mm->physical_address);
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"System-Memory (width %u) R/W %u Address=%8.8X%8.8X\n",
diff --git a/drivers/acpi/acpica/utdelete.c b/drivers/acpi/acpica/utdelete.c
index c365faf4e6cd..4c0d4e434196 100644
--- a/drivers/acpi/acpica/utdelete.c
+++ b/drivers/acpi/acpica/utdelete.c
@@ -568,11 +568,6 @@ acpi_ut_update_object_reference(union acpi_operand_object *object, u16 action)
next_object = object->buffer_field.buffer_obj;
break;
- case ACPI_TYPE_LOCAL_REGION_FIELD:
-
- next_object = object->field.region_obj;
- break;
-
case ACPI_TYPE_LOCAL_BANK_FIELD:
next_object = object->bank_field.bank_obj;
@@ -613,6 +608,7 @@ acpi_ut_update_object_reference(union acpi_operand_object *object, u16 action)
}
break;
+ case ACPI_TYPE_LOCAL_REGION_FIELD:
case ACPI_TYPE_REGION:
default:
diff --git a/drivers/acpi/acpica/utids.c b/drivers/acpi/acpica/utids.c
index 3bb06935a2ad..3e68864ef242 100644
--- a/drivers/acpi/acpica/utids.c
+++ b/drivers/acpi/acpica/utids.c
@@ -263,8 +263,7 @@ acpi_ut_execute_CID(struct acpi_namespace_node *device_node,
* 3) Size of the actual CID strings
*/
cid_list_size = sizeof(struct acpi_pnp_device_id_list) +
- ((count - 1) * sizeof(struct acpi_pnp_device_id)) +
- string_area_size;
+ (count * sizeof(struct acpi_pnp_device_id)) + string_area_size;
cid_list = ACPI_ALLOCATE_ZEROED(cid_list_size);
if (!cid_list) {