[PATCH] acpi: method: implement _CST sanity checks

Keng-Yu Lin kengyu at canonical.com
Wed Jan 23 11:32:58 UTC 2013


On Wed, Jan 9, 2013 at 12:29 AM, Colin King <colin.king at canonical.com> wrote:
> 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
>
Acked-by: Keng-Yu Lin <kengyu at canonical.com>



More information about the fwts-devel mailing list