ACPICA: Add several repairs for _CST predefined name
Sort list based on the C-state, remove invalid/zero entries. ACPICA BZ 890. Lv Zheng. Fixes these possible problems with the _CST object: 1. Sort the list ascending by C state type. 2. Ensure type cannot be zero. 3. A sub-package count of zero means _CST is meaningless. 4. Count must match the number of C state sub-packages. References: https://bugs.acpica.org/show_bug.cgi?id=890 Signed-off-by: Lv Zheng <lv.zheng@intel.com> Signed-off-by: Bob Moore <robert.moore@intel.com> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
This commit is contained in:
parent
aa6329c44b
commit
5a9792f3be
|
@ -159,9 +159,10 @@ acpi_ns_check_return_value(struct acpi_namespace_node *node,
|
||||||
status = acpi_ns_check_package(info, return_object_ptr);
|
status = acpi_ns_check_package(info, return_object_ptr);
|
||||||
if (ACPI_FAILURE(status)) {
|
if (ACPI_FAILURE(status)) {
|
||||||
|
|
||||||
/* We might be able to fix an operand type error (_PRT) */
|
/* We might be able to fix some errors */
|
||||||
|
|
||||||
if (status != AE_AML_OPERAND_TYPE) {
|
if ((status != AE_AML_OPERAND_TYPE) &&
|
||||||
|
(status != AE_AML_OPERAND_VALUE)) {
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -78,6 +78,10 @@ static acpi_status
|
||||||
acpi_ns_repair_CID(struct acpi_evaluate_info *info,
|
acpi_ns_repair_CID(struct acpi_evaluate_info *info,
|
||||||
union acpi_operand_object **return_object_ptr);
|
union acpi_operand_object **return_object_ptr);
|
||||||
|
|
||||||
|
static acpi_status
|
||||||
|
acpi_ns_repair_CST(struct acpi_evaluate_info *info,
|
||||||
|
union acpi_operand_object **return_object_ptr);
|
||||||
|
|
||||||
static acpi_status
|
static acpi_status
|
||||||
acpi_ns_repair_FDE(struct acpi_evaluate_info *info,
|
acpi_ns_repair_FDE(struct acpi_evaluate_info *info,
|
||||||
union acpi_operand_object **return_object_ptr);
|
union acpi_operand_object **return_object_ptr);
|
||||||
|
@ -101,19 +105,23 @@ acpi_ns_repair_TSS(struct acpi_evaluate_info *info,
|
||||||
static acpi_status
|
static acpi_status
|
||||||
acpi_ns_check_sorted_list(struct acpi_evaluate_info *info,
|
acpi_ns_check_sorted_list(struct acpi_evaluate_info *info,
|
||||||
union acpi_operand_object *return_object,
|
union acpi_operand_object *return_object,
|
||||||
|
u32 start_index,
|
||||||
u32 expected_count,
|
u32 expected_count,
|
||||||
u32 sort_index,
|
u32 sort_index,
|
||||||
u8 sort_direction, char *sort_key_name);
|
u8 sort_direction, char *sort_key_name);
|
||||||
|
|
||||||
static void
|
|
||||||
acpi_ns_sort_list(union acpi_operand_object **elements,
|
|
||||||
u32 count, u32 index, u8 sort_direction);
|
|
||||||
|
|
||||||
/* Values for sort_direction above */
|
/* Values for sort_direction above */
|
||||||
|
|
||||||
#define ACPI_SORT_ASCENDING 0
|
#define ACPI_SORT_ASCENDING 0
|
||||||
#define ACPI_SORT_DESCENDING 1
|
#define ACPI_SORT_DESCENDING 1
|
||||||
|
|
||||||
|
static void
|
||||||
|
acpi_ns_remove_element(union acpi_operand_object *obj_desc, u32 index);
|
||||||
|
|
||||||
|
static void
|
||||||
|
acpi_ns_sort_list(union acpi_operand_object **elements,
|
||||||
|
u32 count, u32 index, u8 sort_direction);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This table contains the names of the predefined methods for which we can
|
* This table contains the names of the predefined methods for which we can
|
||||||
* perform more complex repairs.
|
* perform more complex repairs.
|
||||||
|
@ -122,6 +130,7 @@ acpi_ns_sort_list(union acpi_operand_object **elements,
|
||||||
*
|
*
|
||||||
* _ALR: Sort the list ascending by ambient_illuminance
|
* _ALR: Sort the list ascending by ambient_illuminance
|
||||||
* _CID: Strings: uppercase all, remove any leading asterisk
|
* _CID: Strings: uppercase all, remove any leading asterisk
|
||||||
|
* _CST: Sort the list ascending by C state type
|
||||||
* _FDE: Convert Buffer of BYTEs to a Buffer of DWORDs
|
* _FDE: Convert Buffer of BYTEs to a Buffer of DWORDs
|
||||||
* _GTM: Convert Buffer of BYTEs to a Buffer of DWORDs
|
* _GTM: Convert Buffer of BYTEs to a Buffer of DWORDs
|
||||||
* _HID: Strings: uppercase all, remove any leading asterisk
|
* _HID: Strings: uppercase all, remove any leading asterisk
|
||||||
|
@ -139,6 +148,7 @@ acpi_ns_sort_list(union acpi_operand_object **elements,
|
||||||
static const struct acpi_repair_info acpi_ns_repairable_names[] = {
|
static const struct acpi_repair_info acpi_ns_repairable_names[] = {
|
||||||
{"_ALR", acpi_ns_repair_ALR},
|
{"_ALR", acpi_ns_repair_ALR},
|
||||||
{"_CID", acpi_ns_repair_CID},
|
{"_CID", acpi_ns_repair_CID},
|
||||||
|
{"_CST", acpi_ns_repair_CST},
|
||||||
{"_FDE", acpi_ns_repair_FDE},
|
{"_FDE", acpi_ns_repair_FDE},
|
||||||
{"_GTM", acpi_ns_repair_FDE}, /* _GTM has same repair as _FDE */
|
{"_GTM", acpi_ns_repair_FDE}, /* _GTM has same repair as _FDE */
|
||||||
{"_HID", acpi_ns_repair_HID},
|
{"_HID", acpi_ns_repair_HID},
|
||||||
|
@ -243,7 +253,7 @@ acpi_ns_repair_ALR(struct acpi_evaluate_info *info,
|
||||||
union acpi_operand_object *return_object = *return_object_ptr;
|
union acpi_operand_object *return_object = *return_object_ptr;
|
||||||
acpi_status status;
|
acpi_status status;
|
||||||
|
|
||||||
status = acpi_ns_check_sorted_list(info, return_object, 2, 1,
|
status = acpi_ns_check_sorted_list(info, return_object, 0, 2, 1,
|
||||||
ACPI_SORT_ASCENDING,
|
ACPI_SORT_ASCENDING,
|
||||||
"AmbientIlluminance");
|
"AmbientIlluminance");
|
||||||
|
|
||||||
|
@ -409,6 +419,92 @@ acpi_ns_repair_CID(struct acpi_evaluate_info *info,
|
||||||
return (AE_OK);
|
return (AE_OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
*
|
||||||
|
* FUNCTION: acpi_ns_repair_CST
|
||||||
|
*
|
||||||
|
* PARAMETERS: info - Method execution information block
|
||||||
|
* return_object_ptr - Pointer to the object returned from the
|
||||||
|
* evaluation of a method or object
|
||||||
|
*
|
||||||
|
* RETURN: Status. AE_OK if object is OK or was repaired successfully
|
||||||
|
*
|
||||||
|
* DESCRIPTION: Repair for the _CST object:
|
||||||
|
* 1. Sort the list ascending by C state type
|
||||||
|
* 2. Ensure type cannot be zero
|
||||||
|
* 3. A sub-package count of zero means _CST is meaningless
|
||||||
|
* 4. Count must match the number of C state sub-packages
|
||||||
|
*
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
static acpi_status
|
||||||
|
acpi_ns_repair_CST(struct acpi_evaluate_info *info,
|
||||||
|
union acpi_operand_object **return_object_ptr)
|
||||||
|
{
|
||||||
|
union acpi_operand_object *return_object = *return_object_ptr;
|
||||||
|
union acpi_operand_object **outer_elements;
|
||||||
|
u32 outer_element_count;
|
||||||
|
union acpi_operand_object *obj_desc;
|
||||||
|
acpi_status status;
|
||||||
|
u8 removing;
|
||||||
|
u32 i;
|
||||||
|
|
||||||
|
ACPI_FUNCTION_NAME(ns_repair_CST);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Entries (subpackages) in the _CST Package must be sorted by the
|
||||||
|
* C-state type, in ascending order.
|
||||||
|
*/
|
||||||
|
status = acpi_ns_check_sorted_list(info, return_object, 1, 4, 1,
|
||||||
|
ACPI_SORT_ASCENDING, "C-State Type");
|
||||||
|
if (ACPI_FAILURE(status)) {
|
||||||
|
return (status);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We now know the list is correctly sorted by C-state type. Check if
|
||||||
|
* the C-state type values are proportional.
|
||||||
|
*/
|
||||||
|
outer_element_count = return_object->package.count - 1;
|
||||||
|
i = 0;
|
||||||
|
while (i < outer_element_count) {
|
||||||
|
outer_elements = &return_object->package.elements[i + 1];
|
||||||
|
removing = FALSE;
|
||||||
|
|
||||||
|
if ((*outer_elements)->package.count == 0) {
|
||||||
|
ACPI_WARN_PREDEFINED((AE_INFO, info->full_pathname,
|
||||||
|
info->node_flags,
|
||||||
|
"SubPackage[%u] - removing entry due to zero count",
|
||||||
|
i));
|
||||||
|
removing = TRUE;
|
||||||
|
goto remove_element;
|
||||||
|
}
|
||||||
|
|
||||||
|
obj_desc = (*outer_elements)->package.elements[1]; /* Index1 = Type */
|
||||||
|
if ((u32)obj_desc->integer.value == 0) {
|
||||||
|
ACPI_WARN_PREDEFINED((AE_INFO, info->full_pathname,
|
||||||
|
info->node_flags,
|
||||||
|
"SubPackage[%u] - removing entry due to invalid Type(0)",
|
||||||
|
i));
|
||||||
|
removing = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
remove_element:
|
||||||
|
if (removing) {
|
||||||
|
acpi_ns_remove_element(return_object, i + 1);
|
||||||
|
outer_element_count--;
|
||||||
|
} else {
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Update top-level package count, Type "Integer" checked elsewhere */
|
||||||
|
|
||||||
|
obj_desc = return_object->package.elements[0];
|
||||||
|
obj_desc->integer.value = outer_element_count;
|
||||||
|
return (AE_OK);
|
||||||
|
}
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
*
|
*
|
||||||
* FUNCTION: acpi_ns_repair_HID
|
* FUNCTION: acpi_ns_repair_HID
|
||||||
|
@ -588,7 +684,7 @@ acpi_ns_repair_PSS(struct acpi_evaluate_info *info,
|
||||||
* incorrectly sorted, sort it. We sort by cpu_frequency, since this
|
* incorrectly sorted, sort it. We sort by cpu_frequency, since this
|
||||||
* should be proportional to the power.
|
* should be proportional to the power.
|
||||||
*/
|
*/
|
||||||
status = acpi_ns_check_sorted_list(info, return_object, 6, 0,
|
status = acpi_ns_check_sorted_list(info, return_object, 0, 6, 0,
|
||||||
ACPI_SORT_DESCENDING,
|
ACPI_SORT_DESCENDING,
|
||||||
"CpuFrequency");
|
"CpuFrequency");
|
||||||
if (ACPI_FAILURE(status)) {
|
if (ACPI_FAILURE(status)) {
|
||||||
|
@ -658,7 +754,7 @@ acpi_ns_repair_TSS(struct acpi_evaluate_info *info,
|
||||||
return (AE_OK);
|
return (AE_OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
status = acpi_ns_check_sorted_list(info, return_object, 5, 1,
|
status = acpi_ns_check_sorted_list(info, return_object, 0, 5, 1,
|
||||||
ACPI_SORT_DESCENDING,
|
ACPI_SORT_DESCENDING,
|
||||||
"PowerDissipation");
|
"PowerDissipation");
|
||||||
|
|
||||||
|
@ -671,6 +767,7 @@ acpi_ns_repair_TSS(struct acpi_evaluate_info *info,
|
||||||
*
|
*
|
||||||
* PARAMETERS: info - Method execution information block
|
* PARAMETERS: info - Method execution information block
|
||||||
* return_object - Pointer to the top-level returned object
|
* return_object - Pointer to the top-level returned object
|
||||||
|
* start_index - Index of the first sub-package
|
||||||
* expected_count - Minimum length of each sub-package
|
* expected_count - Minimum length of each sub-package
|
||||||
* sort_index - Sub-package entry to sort on
|
* sort_index - Sub-package entry to sort on
|
||||||
* sort_direction - Ascending or descending
|
* sort_direction - Ascending or descending
|
||||||
|
@ -687,6 +784,7 @@ acpi_ns_repair_TSS(struct acpi_evaluate_info *info,
|
||||||
static acpi_status
|
static acpi_status
|
||||||
acpi_ns_check_sorted_list(struct acpi_evaluate_info *info,
|
acpi_ns_check_sorted_list(struct acpi_evaluate_info *info,
|
||||||
union acpi_operand_object *return_object,
|
union acpi_operand_object *return_object,
|
||||||
|
u32 start_index,
|
||||||
u32 expected_count,
|
u32 expected_count,
|
||||||
u32 sort_index,
|
u32 sort_index,
|
||||||
u8 sort_direction, char *sort_key_name)
|
u8 sort_direction, char *sort_key_name)
|
||||||
|
@ -711,12 +809,14 @@ acpi_ns_check_sorted_list(struct acpi_evaluate_info *info,
|
||||||
* Any NULL elements should have been removed by earlier call
|
* Any NULL elements should have been removed by earlier call
|
||||||
* to acpi_ns_remove_null_elements.
|
* to acpi_ns_remove_null_elements.
|
||||||
*/
|
*/
|
||||||
outer_elements = return_object->package.elements;
|
|
||||||
outer_element_count = return_object->package.count;
|
outer_element_count = return_object->package.count;
|
||||||
if (!outer_element_count) {
|
if (!outer_element_count || start_index >= outer_element_count) {
|
||||||
return (AE_AML_PACKAGE_LIMIT);
|
return (AE_AML_PACKAGE_LIMIT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
outer_elements = &return_object->package.elements[start_index];
|
||||||
|
outer_element_count -= start_index;
|
||||||
|
|
||||||
previous_value = 0;
|
previous_value = 0;
|
||||||
if (sort_direction == ACPI_SORT_DESCENDING) {
|
if (sort_direction == ACPI_SORT_DESCENDING) {
|
||||||
previous_value = ACPI_UINT32_MAX;
|
previous_value = ACPI_UINT32_MAX;
|
||||||
|
@ -753,7 +853,8 @@ acpi_ns_check_sorted_list(struct acpi_evaluate_info *info,
|
||||||
(obj_desc->integer.value < previous_value)) ||
|
(obj_desc->integer.value < previous_value)) ||
|
||||||
((sort_direction == ACPI_SORT_DESCENDING) &&
|
((sort_direction == ACPI_SORT_DESCENDING) &&
|
||||||
(obj_desc->integer.value > previous_value))) {
|
(obj_desc->integer.value > previous_value))) {
|
||||||
acpi_ns_sort_list(return_object->package.elements,
|
acpi_ns_sort_list(&return_object->package.
|
||||||
|
elements[start_index],
|
||||||
outer_element_count, sort_index,
|
outer_element_count, sort_index,
|
||||||
sort_direction);
|
sort_direction);
|
||||||
|
|
||||||
|
@ -820,3 +921,52 @@ acpi_ns_sort_list(union acpi_operand_object **elements,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
*
|
||||||
|
* FUNCTION: acpi_ns_remove_element
|
||||||
|
*
|
||||||
|
* PARAMETERS: obj_desc - Package object element list
|
||||||
|
* index - Index of element to remove
|
||||||
|
*
|
||||||
|
* RETURN: None
|
||||||
|
*
|
||||||
|
* DESCRIPTION: Remove the requested element of a package and delete it.
|
||||||
|
*
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
static void
|
||||||
|
acpi_ns_remove_element(union acpi_operand_object *obj_desc, u32 index)
|
||||||
|
{
|
||||||
|
union acpi_operand_object **source;
|
||||||
|
union acpi_operand_object **dest;
|
||||||
|
u32 count;
|
||||||
|
u32 new_count;
|
||||||
|
u32 i;
|
||||||
|
|
||||||
|
ACPI_FUNCTION_NAME(ns_remove_element);
|
||||||
|
|
||||||
|
count = obj_desc->package.count;
|
||||||
|
new_count = count - 1;
|
||||||
|
|
||||||
|
source = obj_desc->package.elements;
|
||||||
|
dest = source;
|
||||||
|
|
||||||
|
/* Examine all elements of the package object, remove matched index */
|
||||||
|
|
||||||
|
for (i = 0; i < count; i++) {
|
||||||
|
if (i == index) {
|
||||||
|
acpi_ut_remove_reference(*source); /* Remove one ref for being in pkg */
|
||||||
|
acpi_ut_remove_reference(*source);
|
||||||
|
} else {
|
||||||
|
*dest = *source;
|
||||||
|
dest++;
|
||||||
|
}
|
||||||
|
source++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* NULL terminate list and update the package count */
|
||||||
|
|
||||||
|
*dest = NULL;
|
||||||
|
obj_desc->package.count = new_count;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue