aboutsummaryrefslogtreecommitdiff
path: root/drivers/acpi/acpica/exprep.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/acpi/acpica/exprep.c')
-rw-r--r--drivers/acpi/acpica/exprep.c110
1 files changed, 74 insertions, 36 deletions
diff --git a/drivers/acpi/acpica/exprep.c b/drivers/acpi/acpica/exprep.c
index edf62bf5b26..ee3f872870b 100644
--- a/drivers/acpi/acpica/exprep.c
+++ b/drivers/acpi/acpica/exprep.c
@@ -1,4 +1,3 @@
-
/******************************************************************************
*
* Module Name: exprep - ACPI AML (p-code) execution - field prep utilities
@@ -6,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2010, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -47,6 +46,7 @@
#include "acinterp.h"
#include "amlcode.h"
#include "acnamesp.h"
+#include "acdispat.h"
#define _COMPONENT ACPI_EXECUTER
ACPI_MODULE_NAME("exprep")
@@ -77,8 +77,8 @@ acpi_ex_generate_access(u32 field_bit_offset,
* any_acc keyword.
*
* NOTE: Need to have the region_length in order to check for boundary
- * conditions (end-of-region). However, the region_length is a deferred
- * operation. Therefore, to complete this implementation, the generation
+ * conditions (end-of-region). However, the region_length is a deferred
+ * operation. Therefore, to complete this implementation, the generation
* of this access width must be deferred until the region length has
* been evaluated.
*
@@ -108,11 +108,11 @@ acpi_ex_generate_access(u32 field_bit_offset,
field_byte_length = field_byte_end_offset - field_byte_offset;
ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
- "Bit length %d, Bit offset %d\n",
+ "Bit length %u, Bit offset %u\n",
field_bit_length, field_bit_offset));
ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
- "Byte Length %d, Byte Offset %d, End Offset %d\n",
+ "Byte Length %u, Byte Offset %u, End Offset %u\n",
field_byte_length, field_byte_offset,
field_byte_end_offset));
@@ -147,11 +147,11 @@ acpi_ex_generate_access(u32 field_bit_offset,
accesses = field_end_offset - field_start_offset;
ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
- "AccessWidth %d end is within region\n",
+ "AccessWidth %u end is within region\n",
access_byte_width));
ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
- "Field Start %d, Field End %d -- requires %d accesses\n",
+ "Field Start %u, Field End %u -- requires %u accesses\n",
field_start_offset, field_end_offset,
accesses));
@@ -159,7 +159,7 @@ acpi_ex_generate_access(u32 field_bit_offset,
if (accesses <= 1) {
ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
- "Entire field can be accessed with one operation of size %d\n",
+ "Entire field can be accessed with one operation of size %u\n",
access_byte_width));
return_VALUE(access_byte_width);
}
@@ -174,7 +174,7 @@ acpi_ex_generate_access(u32 field_bit_offset,
}
} else {
ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
- "AccessWidth %d end is NOT within region\n",
+ "AccessWidth %u end is NOT within region\n",
access_byte_width));
if (access_byte_width == 1) {
ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
@@ -190,7 +190,7 @@ acpi_ex_generate_access(u32 field_bit_offset,
* previous access
*/
ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
- "Backing off to previous optimal access width of %d\n",
+ "Backing off to previous optimal access width of %u\n",
minimum_access_width));
return_VALUE(minimum_access_width);
}
@@ -253,29 +253,34 @@ acpi_ex_decode_field_access(union acpi_operand_object *obj_desc,
case AML_FIELD_ACCESS_BYTE:
case AML_FIELD_ACCESS_BUFFER: /* ACPI 2.0 (SMBus Buffer) */
+
byte_alignment = 1;
bit_length = 8;
break;
case AML_FIELD_ACCESS_WORD:
+
byte_alignment = 2;
bit_length = 16;
break;
case AML_FIELD_ACCESS_DWORD:
+
byte_alignment = 4;
bit_length = 32;
break;
case AML_FIELD_ACCESS_QWORD: /* ACPI 2.0 */
+
byte_alignment = 8;
bit_length = 64;
break;
default:
+
/* Invalid field access type */
- ACPI_ERROR((AE_INFO, "Unknown field access type %X", access));
+ ACPI_ERROR((AE_INFO, "Unknown field access type 0x%X", access));
return_UINT32(0);
}
@@ -307,7 +312,7 @@ acpi_ex_decode_field_access(union acpi_operand_object *obj_desc,
* RETURN: Status
*
* DESCRIPTION: Initialize the areas of the field object that are common
- * to the various types of fields. Note: This is very "sensitive"
+ * to the various types of fields. Note: This is very "sensitive"
* code because we are solving the general case for field
* alignment.
*
@@ -335,13 +340,13 @@ acpi_ex_prep_common_field_object(union acpi_operand_object *obj_desc,
obj_desc->common_field.bit_length = field_bit_length;
/*
- * Decode the access type so we can compute offsets. The access type gives
+ * Decode the access type so we can compute offsets. The access type gives
* two pieces of information - the width of each field access and the
* necessary byte_alignment (address granularity) of the access.
*
* For any_acc, the access_bit_width is the largest width that is both
* necessary and possible in an attempt to access the whole field in one
- * I/O operation. However, for any_acc, the byte_alignment is always one
+ * I/O operation. However, for any_acc, the byte_alignment is always one
* byte.
*
* For all Buffer Fields, the byte_alignment is always one byte.
@@ -355,16 +360,14 @@ acpi_ex_prep_common_field_object(union acpi_operand_object *obj_desc,
return_ACPI_STATUS(AE_AML_OPERAND_VALUE);
}
- /* Setup width (access granularity) fields */
+ /* Setup width (access granularity) fields (values are: 1, 2, 4, 8) */
obj_desc->common_field.access_byte_width = (u8)
- ACPI_DIV_8(access_bit_width); /* 1, 2, 4, 8 */
-
- obj_desc->common_field.access_bit_width = (u8) access_bit_width;
+ ACPI_DIV_8(access_bit_width);
/*
* base_byte_offset is the address of the start of the field within the
- * region. It is the byte address of the first *datum* (field-width data
+ * region. It is the byte address of the first *datum* (field-width data
* unit) of the field. (i.e., the first datum that contains at least the
* first *bit* of the field.)
*
@@ -385,15 +388,6 @@ acpi_ex_prep_common_field_object(union acpi_operand_object *obj_desc,
(field_bit_position -
ACPI_MUL_8(obj_desc->common_field.base_byte_offset));
- /*
- * Does the entire field fit within a single field access element? (datum)
- * (i.e., without crossing a datum boundary)
- */
- if ((obj_desc->common_field.start_field_bit_offset +
- field_bit_length) <= (u16) access_bit_width) {
- obj_desc->common.flags |= AOPOBJ_SINGLE_DATUM;
- }
-
return_ACPI_STATUS(AE_OK);
}
@@ -401,12 +395,12 @@ acpi_ex_prep_common_field_object(union acpi_operand_object *obj_desc,
*
* FUNCTION: acpi_ex_prep_field_value
*
- * PARAMETERS: Info - Contains all field creation info
+ * PARAMETERS: info - Contains all field creation info
*
* RETURN: Status
*
- * DESCRIPTION: Construct a union acpi_operand_object of type def_field and
- * connect it to the parent Node.
+ * DESCRIPTION: Construct an object of type union acpi_operand_object with a
+ * subtype of def_field and connect it to the parent Node.
*
******************************************************************************/
@@ -414,8 +408,9 @@ acpi_status acpi_ex_prep_field_value(struct acpi_create_field_info *info)
{
union acpi_operand_object *obj_desc;
union acpi_operand_object *second_desc = NULL;
- u32 type;
acpi_status status;
+ u32 access_byte_width;
+ u32 type;
ACPI_FUNCTION_TRACE(ex_prep_field_value);
@@ -430,8 +425,8 @@ acpi_status acpi_ex_prep_field_value(struct acpi_create_field_info *info)
type = acpi_ns_get_type(info->region_node);
if (type != ACPI_TYPE_REGION) {
ACPI_ERROR((AE_INFO,
- "Needed Region, found type %X (%s)",
- type, acpi_ut_get_type_name(type)));
+ "Needed Region, found type 0x%X (%s)", type,
+ acpi_ut_get_type_name(type)));
return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
}
@@ -447,7 +442,8 @@ acpi_status acpi_ex_prep_field_value(struct acpi_create_field_info *info)
/* Initialize areas of the object that are common to all fields */
obj_desc->common_field.node = info->field_node;
- status = acpi_ex_prep_common_field_object(obj_desc, info->field_flags,
+ status = acpi_ex_prep_common_field_object(obj_desc,
+ info->field_flags,
info->attribute,
info->field_bit_position,
info->field_bit_length);
@@ -464,6 +460,46 @@ acpi_status acpi_ex_prep_field_value(struct acpi_create_field_info *info)
obj_desc->field.region_obj =
acpi_ns_get_attached_object(info->region_node);
+ /* Fields specific to generic_serial_bus fields */
+
+ obj_desc->field.access_length = info->access_length;
+
+ if (info->connection_node) {
+ second_desc = info->connection_node->object;
+ if (!(second_desc->common.flags & AOPOBJ_DATA_VALID)) {
+ status =
+ acpi_ds_get_buffer_arguments(second_desc);
+ if (ACPI_FAILURE(status)) {
+ acpi_ut_delete_object_desc(obj_desc);
+ return_ACPI_STATUS(status);
+ }
+ }
+
+ obj_desc->field.resource_buffer =
+ second_desc->buffer.pointer;
+ obj_desc->field.resource_length =
+ (u16)second_desc->buffer.length;
+ } else if (info->resource_buffer) {
+ obj_desc->field.resource_buffer = info->resource_buffer;
+ obj_desc->field.resource_length = info->resource_length;
+ }
+
+ /* Allow full data read from EC address space */
+
+ if ((obj_desc->field.region_obj->region.space_id ==
+ ACPI_ADR_SPACE_EC)
+ && (obj_desc->common_field.bit_length > 8)) {
+ access_byte_width =
+ ACPI_ROUND_BITS_UP_TO_BYTES(obj_desc->common_field.
+ bit_length);
+
+ /* Maximum byte width supported is 255 */
+
+ if (access_byte_width < 256) {
+ obj_desc->common_field.access_byte_width =
+ (u8)access_byte_width;
+ }
+ }
/* An additional reference for the container */
acpi_ut_add_reference(obj_desc->field.region_obj);
@@ -567,7 +603,9 @@ acpi_status acpi_ex_prep_field_value(struct acpi_create_field_info *info)
break;
default:
+
/* No other types should get here */
+
break;
}