aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi
diff options
context:
space:
mode:
authorLv Zheng <lv.zheng@intel.com>2013-06-07 21:01:07 -0400
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2013-06-19 19:39:09 -0400
commit5a9792f3be74bfad2985b3f4c7afc9e6f6a3f798 (patch)
treea022831452c1378dde4a952e081c787418ca672b /drivers/acpi
parentaa6329c44bccedbd8b17094c1c1aee1d9a9de461 (diff)
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>
Diffstat (limited to 'drivers/acpi')
-rw-r--r--drivers/acpi/acpica/nspredef.c5
-rw-r--r--drivers/acpi/acpica/nsrepair2.c170
2 files changed, 163 insertions, 12 deletions
diff --git a/drivers/acpi/acpica/nspredef.c b/drivers/acpi/acpica/nspredef.c
index 8d59ac2399e0..24b71a01bf93 100644
--- a/drivers/acpi/acpica/nspredef.c
+++ b/drivers/acpi/acpica/nspredef.c
@@ -159,9 +159,10 @@ acpi_ns_check_return_value(struct acpi_namespace_node *node,
159 status = acpi_ns_check_package(info, return_object_ptr); 159 status = acpi_ns_check_package(info, return_object_ptr);
160 if (ACPI_FAILURE(status)) { 160 if (ACPI_FAILURE(status)) {
161 161
162 /* We might be able to fix an operand type error (_PRT) */ 162 /* We might be able to fix some errors */
163 163
164 if (status != AE_AML_OPERAND_TYPE) { 164 if ((status != AE_AML_OPERAND_TYPE) &&
165 (status != AE_AML_OPERAND_VALUE)) {
165 goto exit; 166 goto exit;
166 } 167 }
167 } 168 }
diff --git a/drivers/acpi/acpica/nsrepair2.c b/drivers/acpi/acpica/nsrepair2.c
index aca9bdf74e1f..029816edd392 100644
--- a/drivers/acpi/acpica/nsrepair2.c
+++ b/drivers/acpi/acpica/nsrepair2.c
@@ -79,6 +79,10 @@ acpi_ns_repair_CID(struct acpi_evaluate_info *info,
79 union acpi_operand_object **return_object_ptr); 79 union acpi_operand_object **return_object_ptr);
80 80
81static acpi_status 81static acpi_status
82acpi_ns_repair_CST(struct acpi_evaluate_info *info,
83 union acpi_operand_object **return_object_ptr);
84
85static acpi_status
82acpi_ns_repair_FDE(struct acpi_evaluate_info *info, 86acpi_ns_repair_FDE(struct acpi_evaluate_info *info,
83 union acpi_operand_object **return_object_ptr); 87 union acpi_operand_object **return_object_ptr);
84 88
@@ -101,19 +105,23 @@ acpi_ns_repair_TSS(struct acpi_evaluate_info *info,
101static acpi_status 105static acpi_status
102acpi_ns_check_sorted_list(struct acpi_evaluate_info *info, 106acpi_ns_check_sorted_list(struct acpi_evaluate_info *info,
103 union acpi_operand_object *return_object, 107 union acpi_operand_object *return_object,
108 u32 start_index,
104 u32 expected_count, 109 u32 expected_count,
105 u32 sort_index, 110 u32 sort_index,
106 u8 sort_direction, char *sort_key_name); 111 u8 sort_direction, char *sort_key_name);
107 112
108static void
109acpi_ns_sort_list(union acpi_operand_object **elements,
110 u32 count, u32 index, u8 sort_direction);
111
112/* Values for sort_direction above */ 113/* Values for sort_direction above */
113 114
114#define ACPI_SORT_ASCENDING 0 115#define ACPI_SORT_ASCENDING 0
115#define ACPI_SORT_DESCENDING 1 116#define ACPI_SORT_DESCENDING 1
116 117
118static void
119acpi_ns_remove_element(union acpi_operand_object *obj_desc, u32 index);
120
121static void
122acpi_ns_sort_list(union acpi_operand_object **elements,
123 u32 count, u32 index, u8 sort_direction);
124
117/* 125/*
118 * This table contains the names of the predefined methods for which we can 126 * This table contains the names of the predefined methods for which we can
119 * perform more complex repairs. 127 * perform more complex repairs.
@@ -122,6 +130,7 @@ acpi_ns_sort_list(union acpi_operand_object **elements,
122 * 130 *
123 * _ALR: Sort the list ascending by ambient_illuminance 131 * _ALR: Sort the list ascending by ambient_illuminance
124 * _CID: Strings: uppercase all, remove any leading asterisk 132 * _CID: Strings: uppercase all, remove any leading asterisk
133 * _CST: Sort the list ascending by C state type
125 * _FDE: Convert Buffer of BYTEs to a Buffer of DWORDs 134 * _FDE: Convert Buffer of BYTEs to a Buffer of DWORDs
126 * _GTM: Convert Buffer of BYTEs to a Buffer of DWORDs 135 * _GTM: Convert Buffer of BYTEs to a Buffer of DWORDs
127 * _HID: Strings: uppercase all, remove any leading asterisk 136 * _HID: Strings: uppercase all, remove any leading asterisk
@@ -139,6 +148,7 @@ acpi_ns_sort_list(union acpi_operand_object **elements,
139static const struct acpi_repair_info acpi_ns_repairable_names[] = { 148static const struct acpi_repair_info acpi_ns_repairable_names[] = {
140 {"_ALR", acpi_ns_repair_ALR}, 149 {"_ALR", acpi_ns_repair_ALR},
141 {"_CID", acpi_ns_repair_CID}, 150 {"_CID", acpi_ns_repair_CID},
151 {"_CST", acpi_ns_repair_CST},
142 {"_FDE", acpi_ns_repair_FDE}, 152 {"_FDE", acpi_ns_repair_FDE},
143 {"_GTM", acpi_ns_repair_FDE}, /* _GTM has same repair as _FDE */ 153 {"_GTM", acpi_ns_repair_FDE}, /* _GTM has same repair as _FDE */
144 {"_HID", acpi_ns_repair_HID}, 154 {"_HID", acpi_ns_repair_HID},
@@ -243,7 +253,7 @@ acpi_ns_repair_ALR(struct acpi_evaluate_info *info,
243 union acpi_operand_object *return_object = *return_object_ptr; 253 union acpi_operand_object *return_object = *return_object_ptr;
244 acpi_status status; 254 acpi_status status;
245 255
246 status = acpi_ns_check_sorted_list(info, return_object, 2, 1, 256 status = acpi_ns_check_sorted_list(info, return_object, 0, 2, 1,
247 ACPI_SORT_ASCENDING, 257 ACPI_SORT_ASCENDING,
248 "AmbientIlluminance"); 258 "AmbientIlluminance");
249 259
@@ -411,6 +421,92 @@ acpi_ns_repair_CID(struct acpi_evaluate_info *info,
411 421
412/****************************************************************************** 422/******************************************************************************
413 * 423 *
424 * FUNCTION: acpi_ns_repair_CST
425 *
426 * PARAMETERS: info - Method execution information block
427 * return_object_ptr - Pointer to the object returned from the
428 * evaluation of a method or object
429 *
430 * RETURN: Status. AE_OK if object is OK or was repaired successfully
431 *
432 * DESCRIPTION: Repair for the _CST object:
433 * 1. Sort the list ascending by C state type
434 * 2. Ensure type cannot be zero
435 * 3. A sub-package count of zero means _CST is meaningless
436 * 4. Count must match the number of C state sub-packages
437 *
438 *****************************************************************************/
439
440static acpi_status
441acpi_ns_repair_CST(struct acpi_evaluate_info *info,
442 union acpi_operand_object **return_object_ptr)
443{
444 union acpi_operand_object *return_object = *return_object_ptr;
445 union acpi_operand_object **outer_elements;
446 u32 outer_element_count;
447 union acpi_operand_object *obj_desc;
448 acpi_status status;
449 u8 removing;
450 u32 i;
451
452 ACPI_FUNCTION_NAME(ns_repair_CST);
453
454 /*
455 * Entries (subpackages) in the _CST Package must be sorted by the
456 * C-state type, in ascending order.
457 */
458 status = acpi_ns_check_sorted_list(info, return_object, 1, 4, 1,
459 ACPI_SORT_ASCENDING, "C-State Type");
460 if (ACPI_FAILURE(status)) {
461 return (status);
462 }
463
464 /*
465 * We now know the list is correctly sorted by C-state type. Check if
466 * the C-state type values are proportional.
467 */
468 outer_element_count = return_object->package.count - 1;
469 i = 0;
470 while (i < outer_element_count) {
471 outer_elements = &return_object->package.elements[i + 1];
472 removing = FALSE;
473
474 if ((*outer_elements)->package.count == 0) {
475 ACPI_WARN_PREDEFINED((AE_INFO, info->full_pathname,
476 info->node_flags,
477 "SubPackage[%u] - removing entry due to zero count",
478 i));
479 removing = TRUE;
480 goto remove_element;
481 }
482
483 obj_desc = (*outer_elements)->package.elements[1]; /* Index1 = Type */
484 if ((u32)obj_desc->integer.value == 0) {
485 ACPI_WARN_PREDEFINED((AE_INFO, info->full_pathname,
486 info->node_flags,
487 "SubPackage[%u] - removing entry due to invalid Type(0)",
488 i));
489 removing = TRUE;
490 }
491
492 remove_element:
493 if (removing) {
494 acpi_ns_remove_element(return_object, i + 1);
495 outer_element_count--;
496 } else {
497 i++;
498 }
499 }
500
501 /* Update top-level package count, Type "Integer" checked elsewhere */
502
503 obj_desc = return_object->package.elements[0];
504 obj_desc->integer.value = outer_element_count;
505 return (AE_OK);
506}
507
508/******************************************************************************
509 *
414 * FUNCTION: acpi_ns_repair_HID 510 * FUNCTION: acpi_ns_repair_HID
415 * 511 *
416 * PARAMETERS: info - Method execution information block 512 * PARAMETERS: info - Method execution information block
@@ -588,7 +684,7 @@ acpi_ns_repair_PSS(struct acpi_evaluate_info *info,
588 * incorrectly sorted, sort it. We sort by cpu_frequency, since this 684 * incorrectly sorted, sort it. We sort by cpu_frequency, since this
589 * should be proportional to the power. 685 * should be proportional to the power.
590 */ 686 */
591 status = acpi_ns_check_sorted_list(info, return_object, 6, 0, 687 status = acpi_ns_check_sorted_list(info, return_object, 0, 6, 0,
592 ACPI_SORT_DESCENDING, 688 ACPI_SORT_DESCENDING,
593 "CpuFrequency"); 689 "CpuFrequency");
594 if (ACPI_FAILURE(status)) { 690 if (ACPI_FAILURE(status)) {
@@ -658,7 +754,7 @@ acpi_ns_repair_TSS(struct acpi_evaluate_info *info,
658 return (AE_OK); 754 return (AE_OK);
659 } 755 }
660 756
661 status = acpi_ns_check_sorted_list(info, return_object, 5, 1, 757 status = acpi_ns_check_sorted_list(info, return_object, 0, 5, 1,
662 ACPI_SORT_DESCENDING, 758 ACPI_SORT_DESCENDING,
663 "PowerDissipation"); 759 "PowerDissipation");
664 760
@@ -671,6 +767,7 @@ acpi_ns_repair_TSS(struct acpi_evaluate_info *info,
671 * 767 *
672 * PARAMETERS: info - Method execution information block 768 * PARAMETERS: info - Method execution information block
673 * return_object - Pointer to the top-level returned object 769 * return_object - Pointer to the top-level returned object
770 * start_index - Index of the first sub-package
674 * expected_count - Minimum length of each sub-package 771 * expected_count - Minimum length of each sub-package
675 * sort_index - Sub-package entry to sort on 772 * sort_index - Sub-package entry to sort on
676 * sort_direction - Ascending or descending 773 * sort_direction - Ascending or descending
@@ -687,6 +784,7 @@ acpi_ns_repair_TSS(struct acpi_evaluate_info *info,
687static acpi_status 784static acpi_status
688acpi_ns_check_sorted_list(struct acpi_evaluate_info *info, 785acpi_ns_check_sorted_list(struct acpi_evaluate_info *info,
689 union acpi_operand_object *return_object, 786 union acpi_operand_object *return_object,
787 u32 start_index,
690 u32 expected_count, 788 u32 expected_count,
691 u32 sort_index, 789 u32 sort_index,
692 u8 sort_direction, char *sort_key_name) 790 u8 sort_direction, char *sort_key_name)
@@ -711,12 +809,14 @@ acpi_ns_check_sorted_list(struct acpi_evaluate_info *info,
711 * Any NULL elements should have been removed by earlier call 809 * Any NULL elements should have been removed by earlier call
712 * to acpi_ns_remove_null_elements. 810 * to acpi_ns_remove_null_elements.
713 */ 811 */
714 outer_elements = return_object->package.elements;
715 outer_element_count = return_object->package.count; 812 outer_element_count = return_object->package.count;
716 if (!outer_element_count) { 813 if (!outer_element_count || start_index >= outer_element_count) {
717 return (AE_AML_PACKAGE_LIMIT); 814 return (AE_AML_PACKAGE_LIMIT);
718 } 815 }
719 816
817 outer_elements = &return_object->package.elements[start_index];
818 outer_element_count -= start_index;
819
720 previous_value = 0; 820 previous_value = 0;
721 if (sort_direction == ACPI_SORT_DESCENDING) { 821 if (sort_direction == ACPI_SORT_DESCENDING) {
722 previous_value = ACPI_UINT32_MAX; 822 previous_value = ACPI_UINT32_MAX;
@@ -753,7 +853,8 @@ acpi_ns_check_sorted_list(struct acpi_evaluate_info *info,
753 (obj_desc->integer.value < previous_value)) || 853 (obj_desc->integer.value < previous_value)) ||
754 ((sort_direction == ACPI_SORT_DESCENDING) && 854 ((sort_direction == ACPI_SORT_DESCENDING) &&
755 (obj_desc->integer.value > previous_value))) { 855 (obj_desc->integer.value > previous_value))) {
756 acpi_ns_sort_list(return_object->package.elements, 856 acpi_ns_sort_list(&return_object->package.
857 elements[start_index],
757 outer_element_count, sort_index, 858 outer_element_count, sort_index,
758 sort_direction); 859 sort_direction);
759 860
@@ -820,3 +921,52 @@ acpi_ns_sort_list(union acpi_operand_object **elements,
820 } 921 }
821 } 922 }
822} 923}
924
925/******************************************************************************
926 *
927 * FUNCTION: acpi_ns_remove_element
928 *
929 * PARAMETERS: obj_desc - Package object element list
930 * index - Index of element to remove
931 *
932 * RETURN: None
933 *
934 * DESCRIPTION: Remove the requested element of a package and delete it.
935 *
936 *****************************************************************************/
937
938static void
939acpi_ns_remove_element(union acpi_operand_object *obj_desc, u32 index)
940{
941 union acpi_operand_object **source;
942 union acpi_operand_object **dest;
943 u32 count;
944 u32 new_count;
945 u32 i;
946
947 ACPI_FUNCTION_NAME(ns_remove_element);
948
949 count = obj_desc->package.count;
950 new_count = count - 1;
951
952 source = obj_desc->package.elements;
953 dest = source;
954
955 /* Examine all elements of the package object, remove matched index */
956
957 for (i = 0; i < count; i++) {
958 if (i == index) {
959 acpi_ut_remove_reference(*source); /* Remove one ref for being in pkg */
960 acpi_ut_remove_reference(*source);
961 } else {
962 *dest = *source;
963 dest++;
964 }
965 source++;
966 }
967
968 /* NULL terminate list and update the package count */
969
970 *dest = NULL;
971 obj_desc->package.count = new_count;
972}