diff options
Diffstat (limited to 'drivers/acpi/acpica/nsrepair.c')
-rw-r--r-- | drivers/acpi/acpica/nsrepair.c | 91 |
1 files changed, 65 insertions, 26 deletions
diff --git a/drivers/acpi/acpica/nsrepair.c b/drivers/acpi/acpica/nsrepair.c index db2b2a99c3a8..dfa31c5ba6c3 100644 --- a/drivers/acpi/acpica/nsrepair.c +++ b/drivers/acpi/acpica/nsrepair.c @@ -77,6 +77,11 @@ acpi_ns_repair_object(struct acpi_predefined_data *data, union acpi_operand_object *new_object; acpi_size length; + /* + * At this point, we know that the type of the returned object was not + * one of the expected types for this predefined name. Attempt to + * repair the object. Only a limited number of repairs are possible. + */ switch (return_object->common.type) { case ACPI_TYPE_BUFFER: @@ -111,43 +116,77 @@ acpi_ns_repair_object(struct acpi_predefined_data *data, */ ACPI_MEMCPY(new_object->string.pointer, return_object->buffer.pointer, length); + break; - /* - * If the original object is a package element, we need to: - * 1. Set the reference count of the new object to match the - * reference count of the old object. - * 2. Decrement the reference count of the original object. - */ - if (package_index != ACPI_NOT_PACKAGE_ELEMENT) { - new_object->common.reference_count = - return_object->common.reference_count; + case ACPI_TYPE_INTEGER: + + /* Does the method/object legally return a string? */ - if (return_object->common.reference_count > 1) { - return_object->common.reference_count--; + if (expected_btypes & ACPI_RTYPE_STRING) { + /* + * The only supported Integer-to-String conversion is to convert + * an integer of value 0 to a NULL string. The last element of + * _BIF and _BIX packages occasionally need this fix. + */ + if (return_object->integer.value != 0) { + return (AE_AML_OPERAND_TYPE); } - ACPI_WARN_PREDEFINED((AE_INFO, data->pathname, - data->node_flags, - "Converted Buffer to expected String at index %u", - package_index)); + /* Allocate a new NULL string object */ + + new_object = acpi_ut_create_string_object(0); + if (!new_object) { + return (AE_NO_MEMORY); + } } else { - ACPI_WARN_PREDEFINED((AE_INFO, data->pathname, - data->node_flags, - "Converted Buffer to expected String")); + return (AE_AML_OPERAND_TYPE); } + break; - /* Delete old object, install the new return object */ + default: - acpi_ut_remove_reference(return_object); - *return_object_ptr = new_object; - data->flags |= ACPI_OBJECT_REPAIRED; - return (AE_OK); + /* We cannot repair this object */ - default: - break; + return (AE_AML_OPERAND_TYPE); + } + + /* Object was successfully repaired */ + + /* + * If the original object is a package element, we need to: + * 1. Set the reference count of the new object to match the + * reference count of the old object. + * 2. Decrement the reference count of the original object. + */ + if (package_index != ACPI_NOT_PACKAGE_ELEMENT) { + new_object->common.reference_count = + return_object->common.reference_count; + + if (return_object->common.reference_count > 1) { + return_object->common.reference_count--; + } + + ACPI_WARN_PREDEFINED((AE_INFO, data->pathname, data->node_flags, + "Converted %s to expected %s at index %u", + acpi_ut_get_object_type_name + (return_object), + acpi_ut_get_object_type_name(new_object), + package_index)); + } else { + ACPI_WARN_PREDEFINED((AE_INFO, data->pathname, data->node_flags, + "Converted %s to expected %s", + acpi_ut_get_object_type_name + (return_object), + acpi_ut_get_object_type_name + (new_object))); } - return (AE_AML_OPERAND_TYPE); + /* Delete old object, install the new return object */ + + acpi_ut_remove_reference(return_object); + *return_object_ptr = new_object; + data->flags |= ACPI_OBJECT_REPAIRED; + return (AE_OK); } /******************************************************************************* |