summaryrefslogtreecommitdiff
path: root/drivers/acpi/executer/exfldio.c
diff options
context:
space:
mode:
authorBob Moore <robert.moore@intel.com>2008-04-10 19:06:41 +0400
committerLen Brown <len.brown@intel.com>2008-04-22 14:29:28 -0400
commit9aa6169f471771324b476a90d9392daa06d63a2d (patch)
tree56b435edcccebf6c2803799b91350c50598d8fe9 /drivers/acpi/executer/exfldio.c
parent549f46044e1e207a2cbfdfb3f9a0d3fd5fd4105e (diff)
ACPICA: Fixed a problem with Index Fields where the Index register was incorrectly limited to a maximum of 32 bits
Now any size may be used. Signed-off-by: Bob Moore <robert.moore@intel.com> Signed-off-by: Alexey Starikovskiy <astarikovskiy@suse.de> Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers/acpi/executer/exfldio.c')
-rw-r--r--drivers/acpi/executer/exfldio.c41
1 files changed, 34 insertions, 7 deletions
diff --git a/drivers/acpi/executer/exfldio.c b/drivers/acpi/executer/exfldio.c
index 1ece1c3fc375..ae402949c357 100644
--- a/drivers/acpi/executer/exfldio.c
+++ b/drivers/acpi/executer/exfldio.c
@@ -806,18 +806,39 @@ acpi_ex_insert_into_field(union acpi_operand_object *obj_desc,
u32 datum_count;
u32 field_datum_count;
u32 i;
+ u32 required_length;
+ void *new_buffer;
ACPI_FUNCTION_TRACE(ex_insert_into_field);
/* Validate input buffer */
- if (buffer_length <
- ACPI_ROUND_BITS_UP_TO_BYTES(obj_desc->common_field.bit_length)) {
- ACPI_ERROR((AE_INFO,
- "Field size %X (bits) is too large for buffer (%X)",
- obj_desc->common_field.bit_length, buffer_length));
+ new_buffer = NULL;
+ required_length =
+ ACPI_ROUND_BITS_UP_TO_BYTES(obj_desc->common_field.bit_length);
+ /*
+ * We must have a buffer that is at least as long as the field
+ * we are writing to. This is because individual fields are
+ * indivisible and partial writes are not supported -- as per
+ * the ACPI specification.
+ */
+ if (buffer_length < required_length) {
- return_ACPI_STATUS(AE_BUFFER_OVERFLOW);
+ /* We need to create a new buffer */
+
+ new_buffer = ACPI_ALLOCATE_ZEROED(required_length);
+ if (!new_buffer) {
+ return_ACPI_STATUS(AE_NO_MEMORY);
+ }
+
+ /*
+ * Copy the original data to the new buffer, starting
+ * at Byte zero. All unused (upper) bytes of the
+ * buffer will be 0.
+ */
+ ACPI_MEMCPY((char *)new_buffer, (char *)buffer, buffer_length);
+ buffer = new_buffer;
+ buffer_length = required_length;
}
/*
@@ -867,7 +888,7 @@ acpi_ex_insert_into_field(union acpi_operand_object *obj_desc,
merged_datum,
field_offset);
if (ACPI_FAILURE(status)) {
- return_ACPI_STATUS(status);
+ goto exit;
}
field_offset += obj_desc->common_field.access_byte_width;
@@ -925,5 +946,11 @@ acpi_ex_insert_into_field(union acpi_operand_object *obj_desc,
mask, merged_datum,
field_offset);
+ exit:
+ /* Free temporary buffer if we used one */
+
+ if (new_buffer) {
+ ACPI_FREE(new_buffer);
+ }
return_ACPI_STATUS(status);
}