]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/acpi/executer/exfldio.c
Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/linville/wireles...
[linux-2.6-omap-h63xx.git] / drivers / acpi / executer / exfldio.c
index 65a48b6170ee3c9803771cad7a58c2caecc04b77..e336b5dc7a50431720fa4aa437b85c5f1fd0ff94 100644 (file)
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2007, R. Byron Moore
+ * Copyright (C) 2000 - 2008, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -263,7 +263,8 @@ acpi_ex_access_region(union acpi_operand_object *obj_desc,
                              rgn_desc->region.space_id,
                              obj_desc->common_field.access_byte_width,
                              obj_desc->common_field.base_byte_offset,
-                             field_datum_byte_offset, (void *)address));
+                             field_datum_byte_offset, ACPI_CAST_PTR(void,
+                                                                    address)));
 
        /* Invoke the appropriate address_space/op_region handler */
 
@@ -805,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;
        }
 
        /*
@@ -866,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;
@@ -924,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);
 }