[PATCH] acpi: method: implement _CST sanity checks
Colin King
colin.king at canonical.com
Tue Jan 8 16:29:02 UTC 2013
From: Colin Ian King <colin.king at canonical.com>
Implement C-State _CST checks
Signed-off-by: Colin Ian King <colin.king at canonical.com>
---
src/acpi/method/method.c | 180 ++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 178 insertions(+), 2 deletions(-)
diff --git a/src/acpi/method/method.c b/src/acpi/method/method.c
index 2d6c0d8..f8330a7 100644
--- a/src/acpi/method/method.c
+++ b/src/acpi/method/method.c
@@ -70,7 +70,7 @@
* _CRS 6.2.2 Y
* _CRT 11.4.4 Y
* _CSD 8.4.2.2 Y
- * _CST 8.4.2.1 N
+ * _CST 8.4.2.1 Y
* _CWS 9.18.6 N
* _DCK 6.5.2 Y
* _DCS B.6.6 Y
@@ -2311,6 +2311,182 @@ static int method_test_CSD(fwts_framework *fw)
"_CSD", NULL, 0, method_test_CSD_return, NULL);
}
+static void method_test_CST_return(
+ fwts_framework *fw,
+ char *name,
+ ACPI_BUFFER *buf,
+ ACPI_OBJECT *obj,
+ void *private)
+{
+ uint32_t i, j;
+ bool failed = false;
+ bool *cst_elements_ok;
+ bool an_element_ok = false;
+
+ typedef struct {
+ const uint32_t type;
+ const char *name;
+ } cstate_info;
+
+ static const cstate_info cstate_types[] = {
+ { ACPI_TYPE_BUFFER, "buffer" },
+ { ACPI_TYPE_INTEGER, "integer" },
+ { ACPI_TYPE_INTEGER, "integer" },
+ { ACPI_TYPE_INTEGER, "integer" },
+ };
+
+ FWTS_UNUSED(private);
+
+ if (obj == NULL)
+ return;
+
+ if (method_check_type(fw, name, buf, ACPI_TYPE_PACKAGE) != FWTS_OK)
+ return;
+
+ /* _CST has at least two elements */
+ if (obj->Package.Count < 3) {
+ fwts_failed(fw, LOG_LEVEL_MEDIUM, "Method_CSTElementCount",
+ "_CST should return package of at least 2 elements, "
+ "got %" PRIu32 " elements instead.",
+ obj->Package.Count);
+ fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
+ return;
+ }
+
+ /* Element 1 must be an integer */
+ if (obj->Package.Elements[0].Type != ACPI_TYPE_INTEGER) {
+ fwts_failed(fw, LOG_LEVEL_MEDIUM, "Method_CSTElement0NotInteger",
+ "_CST should return package with element zero being an integer "
+ "count of the number of C state sub-packages.");
+ fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
+ return;
+ }
+
+ if (obj->Package.Elements[0].Integer.Value != obj->Package.Count - 1) {
+ fwts_failed(fw, LOG_LEVEL_MEDIUM, "Method_CSTElement0CountMismatch",
+ "_CST should return package with element zero containing "
+ "the number of C state sub-elements. However, _CST has "
+ "%" PRIu32 " returned C state sub-elements yet _CST "
+ "reports it has %" PRIu64 " C states.",
+ obj->Package.Count - 1,
+ obj->Package.Elements[0].Integer.Value);
+ fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
+ return;
+ }
+
+ cst_elements_ok = calloc(obj->Package.Count, sizeof(bool));
+ if (cst_elements_ok == NULL) {
+ fwts_log_error(fw, "Cannot allocate an array. Test aborted.");
+ return;
+ }
+
+ /* Could be one or more packages */
+ for (i = 1; i < obj->Package.Count; i++) {
+ cst_elements_ok[i] = true;
+
+ ACPI_OBJECT *pkg;
+ if (obj->Package.Elements[i].Type != ACPI_TYPE_PACKAGE) {
+ fwts_failed(fw, LOG_LEVEL_MEDIUM,
+ "Method_CSTElementType",
+ "_CST package element %" PRIu32 " was not a package.",
+ i);
+ fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
+ cst_elements_ok[i] = false;
+ failed = true;
+ continue; /* Skip processing sub-package */
+ }
+
+ pkg = &obj->Package.Elements[i];
+
+ if (pkg->Package.Count != 4) {
+ fwts_failed(fw, LOG_LEVEL_MEDIUM,
+ "Method_CSTElementPackageCountInvalid",
+ "_CST package element %" PRIu32 " should have "
+ "4 elements, instead it had %" PRIu32 ".",
+ i, pkg->Package.Count);
+ cst_elements_ok[i] = false;
+ failed = true;
+ continue;
+ }
+
+ for (j = 0; j < 4; j++) {
+ if (pkg->Package.Elements[j].Type != cstate_types[j].type) {
+ fwts_failed(fw, LOG_LEVEL_MEDIUM,
+ "Method_CSTCStatePackageElementInvalidType",
+ "_CST C-State package %" PRIu32 " element %" PRIu32
+ " was not a %s.",
+ i, j, cstate_types[j].name);
+ cst_elements_ok[i] = false;
+ failed = true;
+ }
+ }
+
+ /* Some very simple sanity checks on Register Resource Buffer */
+ if (pkg->Package.Elements[0].Type == ACPI_TYPE_BUFFER) {
+ if (pkg->Package.Elements[0].Buffer.Pointer == NULL) {
+ fwts_failed(fw, LOG_LEVEL_MEDIUM,
+ "Method_CSTCStateRegisterResourceBufferNull",
+ "_CST C-State package %" PRIu32 " has a NULL "
+ "Register Resource Buffer", i);
+ failed = true;
+ } else {
+ uint8_t *data = (uint8_t *)pkg->Package.Elements[0].Buffer.Pointer;
+ size_t length = (size_t)pkg->Package.Elements[0].Buffer.Length;
+
+ if (data[0] != 0x82) {
+ fwts_failed(fw, LOG_LEVEL_MEDIUM,
+ "Method_CSTCStateResourceBufferWrongType",
+ "_CST C-State package %" PRIu32 " has a Resource "
+ "type 0x%2.2" PRIx8 ", however, was expecting a Register "
+ "Resource type 0x82.", i, data[0]);
+ failed = true;
+ }
+ else {
+ bool passed = true;
+ method_test_CRS_large_size(fw, name, data, length, 12, 12, &passed);
+ if (!passed)
+ failed = true;
+ }
+ }
+ }
+
+ if (cst_elements_ok[i])
+ an_element_ok = true;
+ }
+
+ /* Now dump out per CPU C-state information */
+ if (an_element_ok) {
+ fwts_log_info_verbatum(fw, "%s values:", name);
+ fwts_log_info_verbatum(fw, "# C-State Latency Power");
+ fwts_log_info_verbatum(fw, " (us) (mW)");
+ for (i = 1; i < obj->Package.Count; i++){
+ if (cst_elements_ok[i]) {
+ ACPI_OBJECT *pkg = &obj->Package.Elements[i];
+ fwts_log_info_verbatum(fw,
+ "%2" PRIu32 " C%" PRIu64 " %6" PRIu64 " %6" PRIu64,
+ i,
+ pkg->Package.Elements[1].Integer.Value,
+ pkg->Package.Elements[2].Integer.Value,
+ pkg->Package.Elements[3].Integer.Value);
+ } else {
+ fwts_log_info_verbatum(fw,
+ "%2" PRIu32 " -- ----- -----", i);
+ }
+ }
+ }
+
+ free(cst_elements_ok);
+
+ if (!failed)
+ fwts_passed(fw, "%s correctly returned sane looking values.", name);
+}
+
+static int method_test_CST(fwts_framework *fw)
+{
+ return method_evaluate_method(fw, METHOD_OPTIONAL,
+ "_CST", NULL, 0, method_test_CST_return, NULL);
+}
+
static void method_test_PCT_return(
fwts_framework *fw,
char *name,
@@ -4656,7 +4832,7 @@ static fwts_framework_minor_test method_tests[] = {
{ method_test_PSS, "Check _PSS (Performance Supported States)." },
{ method_test_CPC, "Check _CPC (Continuous Performance Control)." },
{ method_test_CSD, "Check _CSD (C State Dependencies)." },
- /* { method_test_CST, "Check _CST (C States)." }, */
+ { method_test_CST, "Check _CST (C States)." },
{ method_test_PCT, "Check _PCT (Performance Control)." },
/* { method_test_PDC, "Check _PDC (Processor Driver Capabilities)." }, */
{ method_test_PDL, "Check _PDL (P-State Depth Limit)." },
--
1.8.0
More information about the fwts-devel
mailing list