]> Pileus Git - ~andy/linux/blobdiff - drivers/acpi/acpica/rscalc.c
Merge tag 'sound-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound
[~andy/linux] / drivers / acpi / acpica / rscalc.c
index 3a8a89ec2ca4195d14a90b620918f6f4aa9cd881..3c6df4b7eb2ddc200575ea8849b905519efe6f87 100644 (file)
@@ -5,7 +5,7 @@
  ******************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -313,6 +313,38 @@ acpi_rs_get_aml_length(struct acpi_resource * resource, acpi_size * size_needed)
                                                          resource_source));
                        break;
 
+               case ACPI_RESOURCE_TYPE_GPIO:
+
+                       total_size =
+                           (acpi_rs_length) (total_size +
+                                             (resource->data.gpio.
+                                              pin_table_length * 2) +
+                                             resource->data.gpio.
+                                             resource_source.string_length +
+                                             resource->data.gpio.
+                                             vendor_length);
+
+                       break;
+
+               case ACPI_RESOURCE_TYPE_SERIAL_BUS:
+
+                       total_size =
+                           acpi_gbl_aml_resource_serial_bus_sizes[resource->
+                                                                  data.
+                                                                  common_serial_bus.
+                                                                  type];
+
+                       total_size = (acpi_rs_length) (total_size +
+                                                      resource->data.
+                                                      i2c_serial_bus.
+                                                      resource_source.
+                                                      string_length +
+                                                      resource->data.
+                                                      i2c_serial_bus.
+                                                      vendor_length);
+
+                       break;
+
                default:
                        break;
                }
@@ -362,10 +394,11 @@ acpi_rs_get_list_length(u8 * aml_buffer,
        u32 extra_struct_bytes;
        u8 resource_index;
        u8 minimum_aml_resource_length;
+       union aml_resource *aml_resource;
 
        ACPI_FUNCTION_TRACE(rs_get_list_length);
 
-       *size_needed = 0;
+       *size_needed = ACPI_RS_SIZE_MIN;        /* Minimum size is one end_tag */
        end_aml = aml_buffer + aml_buffer_length;
 
        /* Walk the list of AML resource descriptors */
@@ -376,9 +409,15 @@ acpi_rs_get_list_length(u8 * aml_buffer,
 
                status = acpi_ut_validate_resource(aml_buffer, &resource_index);
                if (ACPI_FAILURE(status)) {
+                       /*
+                        * Exit on failure. Cannot continue because the descriptor length
+                        * may be bogus also.
+                        */
                        return_ACPI_STATUS(status);
                }
 
+               aml_resource = (void *)aml_buffer;
+
                /* Get the resource length and base (minimum) AML size */
 
                resource_length = acpi_ut_get_resource_length(aml_buffer);
@@ -422,10 +461,8 @@ acpi_rs_get_list_length(u8 * aml_buffer,
 
                case ACPI_RESOURCE_NAME_END_TAG:
                        /*
-                        * End Tag:
-                        * This is the normal exit, add size of end_tag
+                        * End Tag: This is the normal exit
                         */
-                       *size_needed += ACPI_RS_SIZE_MIN;
                        return_ACPI_STATUS(AE_OK);
 
                case ACPI_RESOURCE_NAME_ADDRESS32:
@@ -457,6 +494,33 @@ acpi_rs_get_list_length(u8 * aml_buffer,
                                                         minimum_aml_resource_length);
                        break;
 
+               case ACPI_RESOURCE_NAME_GPIO:
+
+                       /* Vendor data is optional */
+
+                       if (aml_resource->gpio.vendor_length) {
+                               extra_struct_bytes +=
+                                   aml_resource->gpio.vendor_offset -
+                                   aml_resource->gpio.pin_table_offset +
+                                   aml_resource->gpio.vendor_length;
+                       } else {
+                               extra_struct_bytes +=
+                                   aml_resource->large_header.resource_length +
+                                   sizeof(struct aml_resource_large_header) -
+                                   aml_resource->gpio.pin_table_offset;
+                       }
+                       break;
+
+               case ACPI_RESOURCE_NAME_SERIAL_BUS:
+
+                       minimum_aml_resource_length =
+                           acpi_gbl_resource_aml_serial_bus_sizes
+                           [aml_resource->common_serial_bus.type];
+                       extra_struct_bytes +=
+                           aml_resource->common_serial_bus.resource_length -
+                           minimum_aml_resource_length;
+                       break;
+
                default:
                        break;
                }
@@ -467,9 +531,18 @@ acpi_rs_get_list_length(u8 * aml_buffer,
                 * Important: Round the size up for the appropriate alignment. This
                 * is a requirement on IA64.
                 */
-               buffer_size = acpi_gbl_resource_struct_sizes[resource_index] +
-                   extra_struct_bytes;
-               buffer_size = (u32) ACPI_ROUND_UP_TO_NATIVE_WORD(buffer_size);
+               if (acpi_ut_get_resource_type(aml_buffer) ==
+                   ACPI_RESOURCE_NAME_SERIAL_BUS) {
+                       buffer_size =
+                           acpi_gbl_resource_struct_serial_bus_sizes
+                           [aml_resource->common_serial_bus.type] +
+                           extra_struct_bytes;
+               } else {
+                       buffer_size =
+                           acpi_gbl_resource_struct_sizes[resource_index] +
+                           extra_struct_bytes;
+               }
+               buffer_size = (u32)ACPI_ROUND_UP_TO_NATIVE_WORD(buffer_size);
 
                *size_needed += buffer_size;