Commit 09387b43 authored by Bob Moore's avatar Bob Moore Committed by Len Brown

ACPICA: Revert "Revert "Enable multi-byte EC transfers

This reverts commit f23b9c7(http://git.moblin.org/cgit.cgi/acpica/commit/?id=f23b9c7)
The problem with this change was determined to be a problem with
the FreeBSD host OSL (OS services layer), not with this patch
itself. Therefore, re-introducing this change into the main ACPICA
code. See ACPICA bugzilla 863.

http://www.acpica.org/bugzilla/show_bug.cgi?id=863Signed-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 c5f0231e
...@@ -248,7 +248,7 @@ ACPI_OBJECT_COMMON_HEADER ACPI_COMMON_NOTIFY_INFO}; ...@@ -248,7 +248,7 @@ ACPI_OBJECT_COMMON_HEADER ACPI_COMMON_NOTIFY_INFO};
u32 base_byte_offset; /* Byte offset within containing object */\ u32 base_byte_offset; /* Byte offset within containing object */\
u32 value; /* Value to store into the Bank or Index register */\ u32 value; /* Value to store into the Bank or Index register */\
u8 start_field_bit_offset;/* Bit offset within first field datum (0-63) */\ u8 start_field_bit_offset;/* Bit offset within first field datum (0-63) */\
u8 access_bit_width; /* Read/Write size in bits (8-64) */
struct acpi_object_field_common { /* COMMON FIELD (for BUFFER, REGION, BANK, and INDEX fields) */ struct acpi_object_field_common { /* COMMON FIELD (for BUFFER, REGION, BANK, and INDEX fields) */
ACPI_OBJECT_COMMON_HEADER ACPI_COMMON_FIELD_INFO union acpi_operand_object *region_obj; /* Parent Operation Region object (REGION/BANK fields only) */ ACPI_OBJECT_COMMON_HEADER ACPI_COMMON_FIELD_INFO union acpi_operand_object *region_obj; /* Parent Operation Region object (REGION/BANK fields only) */
......
...@@ -119,8 +119,8 @@ acpi_ex_setup_region(union acpi_operand_object *obj_desc, ...@@ -119,8 +119,8 @@ acpi_ex_setup_region(union acpi_operand_object *obj_desc,
} }
/* /*
* Exit now for SMBus or IPMI address space, it has a non-linear address space * Exit now for SMBus or IPMI address space, it has a non-linear
* and the request cannot be directly validated * address space and the request cannot be directly validated
*/ */
if (rgn_desc->region.space_id == ACPI_ADR_SPACE_SMBUS || if (rgn_desc->region.space_id == ACPI_ADR_SPACE_SMBUS ||
rgn_desc->region.space_id == ACPI_ADR_SPACE_IPMI) { rgn_desc->region.space_id == ACPI_ADR_SPACE_IPMI) {
...@@ -147,8 +147,7 @@ acpi_ex_setup_region(union acpi_operand_object *obj_desc, ...@@ -147,8 +147,7 @@ acpi_ex_setup_region(union acpi_operand_object *obj_desc,
* (Region length is specified in bytes) * (Region length is specified in bytes)
*/ */
if (rgn_desc->region.length < if (rgn_desc->region.length <
(obj_desc->common_field.base_byte_offset + (obj_desc->common_field.base_byte_offset + field_datum_byte_offset +
field_datum_byte_offset +
obj_desc->common_field.access_byte_width)) { obj_desc->common_field.access_byte_width)) {
if (acpi_gbl_enable_interpreter_slack) { if (acpi_gbl_enable_interpreter_slack) {
/* /*
...@@ -680,6 +679,7 @@ acpi_ex_extract_from_field(union acpi_operand_object *obj_desc, ...@@ -680,6 +679,7 @@ acpi_ex_extract_from_field(union acpi_operand_object *obj_desc,
u32 buffer_tail_bits; u32 buffer_tail_bits;
u32 datum_count; u32 datum_count;
u32 field_datum_count; u32 field_datum_count;
u32 access_bit_width;
u32 i; u32 i;
ACPI_FUNCTION_TRACE(ex_extract_from_field); ACPI_FUNCTION_TRACE(ex_extract_from_field);
...@@ -694,16 +694,36 @@ acpi_ex_extract_from_field(union acpi_operand_object *obj_desc, ...@@ -694,16 +694,36 @@ acpi_ex_extract_from_field(union acpi_operand_object *obj_desc,
return_ACPI_STATUS(AE_BUFFER_OVERFLOW); return_ACPI_STATUS(AE_BUFFER_OVERFLOW);
} }
ACPI_MEMSET(buffer, 0, buffer_length); ACPI_MEMSET(buffer, 0, buffer_length);
access_bit_width = ACPI_MUL_8(obj_desc->common_field.access_byte_width);
/* Handle the simple case here */
if ((obj_desc->common_field.start_field_bit_offset == 0) &&
(obj_desc->common_field.bit_length == access_bit_width)) {
status = acpi_ex_field_datum_io(obj_desc, 0, buffer, ACPI_READ);
return_ACPI_STATUS(status);
}
/* TBD: Move to common setup code */
/* Field algorithm is limited to sizeof(u64), truncate if needed */
if (obj_desc->common_field.access_byte_width > sizeof(u64)) {
obj_desc->common_field.access_byte_width = sizeof(u64);
access_bit_width = sizeof(u64) * 8;
}
/* Compute the number of datums (access width data items) */ /* Compute the number of datums (access width data items) */
datum_count = ACPI_ROUND_UP_TO(obj_desc->common_field.bit_length, datum_count =
obj_desc->common_field.access_bit_width); ACPI_ROUND_UP_TO(obj_desc->common_field.bit_length,
access_bit_width);
field_datum_count = ACPI_ROUND_UP_TO(obj_desc->common_field.bit_length + field_datum_count = ACPI_ROUND_UP_TO(obj_desc->common_field.bit_length +
obj_desc->common_field. obj_desc->common_field.
start_field_bit_offset, start_field_bit_offset,
obj_desc->common_field.
access_bit_width); access_bit_width);
/* Priming read from the field */ /* Priming read from the field */
...@@ -738,12 +758,11 @@ acpi_ex_extract_from_field(union acpi_operand_object *obj_desc, ...@@ -738,12 +758,11 @@ acpi_ex_extract_from_field(union acpi_operand_object *obj_desc,
* This avoids the differences in behavior between different compilers * This avoids the differences in behavior between different compilers
* concerning shift values larger than the target data width. * concerning shift values larger than the target data width.
*/ */
if ((obj_desc->common_field.access_bit_width - if (access_bit_width -
obj_desc->common_field.start_field_bit_offset) < obj_desc->common_field.start_field_bit_offset <
ACPI_INTEGER_BIT_SIZE) { ACPI_INTEGER_BIT_SIZE) {
merged_datum |= merged_datum |=
raw_datum << (obj_desc->common_field. raw_datum << (access_bit_width -
access_bit_width -
obj_desc->common_field. obj_desc->common_field.
start_field_bit_offset); start_field_bit_offset);
} }
...@@ -765,8 +784,7 @@ acpi_ex_extract_from_field(union acpi_operand_object *obj_desc, ...@@ -765,8 +784,7 @@ acpi_ex_extract_from_field(union acpi_operand_object *obj_desc,
/* Mask off any extra bits in the last datum */ /* Mask off any extra bits in the last datum */
buffer_tail_bits = obj_desc->common_field.bit_length % buffer_tail_bits = obj_desc->common_field.bit_length % access_bit_width;
obj_desc->common_field.access_bit_width;
if (buffer_tail_bits) { if (buffer_tail_bits) {
merged_datum &= ACPI_MASK_BITS_ABOVE(buffer_tail_bits); merged_datum &= ACPI_MASK_BITS_ABOVE(buffer_tail_bits);
} }
...@@ -798,6 +816,7 @@ acpi_status ...@@ -798,6 +816,7 @@ acpi_status
acpi_ex_insert_into_field(union acpi_operand_object *obj_desc, acpi_ex_insert_into_field(union acpi_operand_object *obj_desc,
void *buffer, u32 buffer_length) void *buffer, u32 buffer_length)
{ {
void *new_buffer;
acpi_status status; acpi_status status;
u64 mask; u64 mask;
u64 width_mask; u64 width_mask;
...@@ -808,9 +827,9 @@ acpi_ex_insert_into_field(union acpi_operand_object *obj_desc, ...@@ -808,9 +827,9 @@ acpi_ex_insert_into_field(union acpi_operand_object *obj_desc,
u32 buffer_tail_bits; u32 buffer_tail_bits;
u32 datum_count; u32 datum_count;
u32 field_datum_count; u32 field_datum_count;
u32 i; u32 access_bit_width;
u32 required_length; u32 required_length;
void *new_buffer; u32 i;
ACPI_FUNCTION_TRACE(ex_insert_into_field); ACPI_FUNCTION_TRACE(ex_insert_into_field);
...@@ -844,17 +863,24 @@ acpi_ex_insert_into_field(union acpi_operand_object *obj_desc, ...@@ -844,17 +863,24 @@ acpi_ex_insert_into_field(union acpi_operand_object *obj_desc,
buffer_length = required_length; buffer_length = required_length;
} }
/* TBD: Move to common setup code */
/* Algo is limited to sizeof(u64), so cut the access_byte_width */
if (obj_desc->common_field.access_byte_width > sizeof(u64)) {
obj_desc->common_field.access_byte_width = sizeof(u64);
}
access_bit_width = ACPI_MUL_8(obj_desc->common_field.access_byte_width);
/* /*
* Create the bitmasks used for bit insertion. * Create the bitmasks used for bit insertion.
* Note: This if/else is used to bypass compiler differences with the * Note: This if/else is used to bypass compiler differences with the
* shift operator * shift operator
*/ */
if (obj_desc->common_field.access_bit_width == ACPI_INTEGER_BIT_SIZE) { if (access_bit_width == ACPI_INTEGER_BIT_SIZE) {
width_mask = ACPI_UINT64_MAX; width_mask = ACPI_UINT64_MAX;
} else { } else {
width_mask = width_mask = ACPI_MASK_BITS_ABOVE(access_bit_width);
ACPI_MASK_BITS_ABOVE(obj_desc->common_field.
access_bit_width);
} }
mask = width_mask & mask = width_mask &
...@@ -863,12 +889,11 @@ acpi_ex_insert_into_field(union acpi_operand_object *obj_desc, ...@@ -863,12 +889,11 @@ acpi_ex_insert_into_field(union acpi_operand_object *obj_desc,
/* Compute the number of datums (access width data items) */ /* Compute the number of datums (access width data items) */
datum_count = ACPI_ROUND_UP_TO(obj_desc->common_field.bit_length, datum_count = ACPI_ROUND_UP_TO(obj_desc->common_field.bit_length,
obj_desc->common_field.access_bit_width); access_bit_width);
field_datum_count = ACPI_ROUND_UP_TO(obj_desc->common_field.bit_length + field_datum_count = ACPI_ROUND_UP_TO(obj_desc->common_field.bit_length +
obj_desc->common_field. obj_desc->common_field.
start_field_bit_offset, start_field_bit_offset,
obj_desc->common_field.
access_bit_width); access_bit_width);
/* Get initial Datum from the input buffer */ /* Get initial Datum from the input buffer */
...@@ -905,12 +930,11 @@ acpi_ex_insert_into_field(union acpi_operand_object *obj_desc, ...@@ -905,12 +930,11 @@ acpi_ex_insert_into_field(union acpi_operand_object *obj_desc,
* This avoids the differences in behavior between different compilers * This avoids the differences in behavior between different compilers
* concerning shift values larger than the target data width. * concerning shift values larger than the target data width.
*/ */
if ((obj_desc->common_field.access_bit_width - if ((access_bit_width -
obj_desc->common_field.start_field_bit_offset) < obj_desc->common_field.start_field_bit_offset) <
ACPI_INTEGER_BIT_SIZE) { ACPI_INTEGER_BIT_SIZE) {
merged_datum = merged_datum =
raw_datum >> (obj_desc->common_field. raw_datum >> (access_bit_width -
access_bit_width -
obj_desc->common_field. obj_desc->common_field.
start_field_bit_offset); start_field_bit_offset);
} else { } else {
...@@ -929,6 +953,7 @@ acpi_ex_insert_into_field(union acpi_operand_object *obj_desc, ...@@ -929,6 +953,7 @@ acpi_ex_insert_into_field(union acpi_operand_object *obj_desc,
ACPI_MEMCPY(&raw_datum, ((char *)buffer) + buffer_offset, ACPI_MEMCPY(&raw_datum, ((char *)buffer) + buffer_offset,
ACPI_MIN(obj_desc->common_field.access_byte_width, ACPI_MIN(obj_desc->common_field.access_byte_width,
buffer_length - buffer_offset)); buffer_length - buffer_offset));
merged_datum |= merged_datum |=
raw_datum << obj_desc->common_field.start_field_bit_offset; raw_datum << obj_desc->common_field.start_field_bit_offset;
} }
...@@ -937,7 +962,7 @@ acpi_ex_insert_into_field(union acpi_operand_object *obj_desc, ...@@ -937,7 +962,7 @@ acpi_ex_insert_into_field(union acpi_operand_object *obj_desc,
buffer_tail_bits = (obj_desc->common_field.bit_length + buffer_tail_bits = (obj_desc->common_field.bit_length +
obj_desc->common_field.start_field_bit_offset) % obj_desc->common_field.start_field_bit_offset) %
obj_desc->common_field.access_bit_width; access_bit_width;
if (buffer_tail_bits) { if (buffer_tail_bits) {
mask &= ACPI_MASK_BITS_ABOVE(buffer_tail_bits); mask &= ACPI_MASK_BITS_ABOVE(buffer_tail_bits);
} }
......
...@@ -355,12 +355,10 @@ acpi_ex_prep_common_field_object(union acpi_operand_object *obj_desc, ...@@ -355,12 +355,10 @@ acpi_ex_prep_common_field_object(union acpi_operand_object *obj_desc,
return_ACPI_STATUS(AE_AML_OPERAND_VALUE); 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) obj_desc->common_field.access_byte_width = (u8)
ACPI_DIV_8(access_bit_width); /* 1, 2, 4, 8 */ ACPI_DIV_8(access_bit_width);
obj_desc->common_field.access_bit_width = (u8) access_bit_width;
/* /*
* base_byte_offset is the address of the start of the field within the * base_byte_offset is the address of the start of the field within the
...@@ -405,8 +403,9 @@ acpi_status acpi_ex_prep_field_value(struct acpi_create_field_info *info) ...@@ -405,8 +403,9 @@ acpi_status acpi_ex_prep_field_value(struct acpi_create_field_info *info)
{ {
union acpi_operand_object *obj_desc; union acpi_operand_object *obj_desc;
union acpi_operand_object *second_desc = NULL; union acpi_operand_object *second_desc = NULL;
u32 type;
acpi_status status; acpi_status status;
u32 access_byte_width;
u32 type;
ACPI_FUNCTION_TRACE(ex_prep_field_value); ACPI_FUNCTION_TRACE(ex_prep_field_value);
...@@ -421,8 +420,8 @@ acpi_status acpi_ex_prep_field_value(struct acpi_create_field_info *info) ...@@ -421,8 +420,8 @@ acpi_status acpi_ex_prep_field_value(struct acpi_create_field_info *info)
type = acpi_ns_get_type(info->region_node); type = acpi_ns_get_type(info->region_node);
if (type != ACPI_TYPE_REGION) { if (type != ACPI_TYPE_REGION) {
ACPI_ERROR((AE_INFO, ACPI_ERROR((AE_INFO,
"Needed Region, found type 0x%X (%s)", "Needed Region, found type 0x%X (%s)", type,
type, acpi_ut_get_type_name(type))); acpi_ut_get_type_name(type)));
return_ACPI_STATUS(AE_AML_OPERAND_TYPE); return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
} }
...@@ -438,7 +437,8 @@ acpi_status acpi_ex_prep_field_value(struct acpi_create_field_info *info) ...@@ -438,7 +437,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 */ /* Initialize areas of the object that are common to all fields */
obj_desc->common_field.node = info->field_node; 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->attribute,
info->field_bit_position, info->field_bit_position,
info->field_bit_length); info->field_bit_length);
...@@ -455,26 +455,25 @@ acpi_status acpi_ex_prep_field_value(struct acpi_create_field_info *info) ...@@ -455,26 +455,25 @@ acpi_status acpi_ex_prep_field_value(struct acpi_create_field_info *info)
obj_desc->field.region_obj = obj_desc->field.region_obj =
acpi_ns_get_attached_object(info->region_node); acpi_ns_get_attached_object(info->region_node);
/* An additional reference for the container */ /* Allow full data read from EC address space */
acpi_ut_add_reference(obj_desc->field.region_obj); 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 */
/* allow full data read from EC address space */ if (access_byte_width < 256) {
if (obj_desc->field.region_obj->region.space_id ==
ACPI_ADR_SPACE_EC) {
if (obj_desc->common_field.bit_length > 8) {
unsigned width =
ACPI_ROUND_BITS_UP_TO_BYTES(
obj_desc->common_field.bit_length);
// access_bit_width is u8, don't overflow it
if (width > 8)
width = 8;
obj_desc->common_field.access_byte_width = obj_desc->common_field.access_byte_width =
width; (u8)access_byte_width;
obj_desc->common_field.access_bit_width =
8 * width;
} }
} }
/* An additional reference for the container */
acpi_ut_add_reference(obj_desc->field.region_obj);
ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
"RegionField: BitOff %X, Off %X, Gran %X, Region %p\n", "RegionField: BitOff %X, Off %X, Gran %X, Region %p\n",
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment