diff --git a/test/objects.mk b/test/objects.mk index 0d0b29d..f8edf61 100644 --- a/test/objects.mk +++ b/test/objects.mk @@ -18,3 +18,33 @@ test-elfs-y += test_srvgrp_hsm test_srvgrp_hsm-objs-y += test/test_log.o test_srvgrp_hsm-objs-y += test/test_common.o + +test-elfs-y += test_srvgrp_sysmsi + +test_srvgrp_sysmsi-objs-y += test/test_log.o +test_srvgrp_sysmsi-objs-y += test/test_common.o + +test-elfs-y += test_srvgrp_syssusp + +test_srvgrp_syssusp-objs-y += test/test_log.o +test_srvgrp_syssusp-objs-y += test/test_common.o + +test-elfs-y += test_srvgrp_cppc + +test_srvgrp_cppc-objs-y += test/test_log.o +test_srvgrp_cppc-objs-y += test/test_common.o + +test-elfs-y += test_srvgrp_voltage + +test_srvgrp_voltage-objs-y += test/test_log.o +test_srvgrp_voltage-objs-y += test/test_common.o + +test-elfs-y += test_srvgrp_clock + +test_srvgrp_clock-objs-y += test/test_log.o +test_srvgrp_clock-objs-y += test/test_common.o + +test-elfs-y += test_srvgrp_device_power + +test_srvgrp_device_power-objs-y += test/test_log.o +test_srvgrp_device_power-objs-y += test/test_common.o diff --git a/test/test_common.c b/test/test_common.c index f39edf1..6549a09 100644 --- a/test/test_common.c +++ b/test/test_common.c @@ -78,8 +78,61 @@ static void test_wait(struct rpmi_test_scenario *scene, struct rpmi_test *test, } } +static int test_check_no_ack(struct rpmi_test_scenario *scene, + struct rpmi_test *test, + struct rpmi_message *resp_msg) +{ + int rc; + + rpmi_env_memset(resp_msg, 0, sizeof(*resp_msg)); + rc = rpmi_transport_dequeue(scene->xport, RPMI_QUEUE_P2A_ACK, resp_msg); + if (rc == RPMI_ERR_IO) + return 0; + + if (rc == RPMI_SUCCESS) + printf("%s: unexpected acknowledgment for posted request\n", test->name); + else + printf("%s: failed to check acknowledgment queue (error %d)\n", + test->name, rc); + + return 1; +} + +static int test_verify_header(struct rpmi_test *test, struct rpmi_message *msg, + rpmi_uint16_t token) +{ + int failed = 0; + + if (msg->header.flags != RPMI_MSG_ACKNOWLEDGEMENT) { + printf("%s: response flags mismatch: expected: %d, got: %d\n", + test->name, RPMI_MSG_ACKNOWLEDGEMENT, msg->header.flags); + failed = 1; + } + + if (msg->header.servicegroup_id != test->attrs.servicegroup_id) { + printf("%s: response servicegroup mismatch: expected: %d, got: %d\n", + test->name, test->attrs.servicegroup_id, msg->header.servicegroup_id); + failed = 1; + } + + if (msg->header.service_id != test->attrs.service_id) { + printf("%s: response service mismatch: expected: %d, got: %d\n", + test->name, test->attrs.service_id, msg->header.service_id); + failed = 1; + } + + if (msg->header.token != token) { + printf("%s: response token mismatch: expected: %d, got: %d\n", + test->name, token, msg->header.token); + failed = 1; + } + + return failed; +} + static void test_verify(struct rpmi_test *test, struct rpmi_message *msg, - void *exp_data, rpmi_uint16_t exp_data_len) + void *exp_data, rpmi_uint16_t exp_data_len, + int *nfail) { int failed = 0; @@ -107,33 +160,36 @@ static void test_verify(struct rpmi_test *test, struct rpmi_message *msg, } printf("TEST: %-50s \t : %s!\n", test->name, failed ? "Failed" : "Succeeded"); + if (failed) + (*nfail)++; } -static void execute_scenario(struct rpmi_test_scenario *scene) +static int execute_scenario(struct rpmi_test_scenario *scene) { struct rpmi_message *req_msg, *resp_msg; rpmi_uint16_t exp_data_len; struct rpmi_test *test; void *exp_data; - int i, rc; + rpmi_uint16_t token; + int i, rc, failed, nfail = 0; req_msg = rpmi_env_zalloc(scene->slot_size); if (!req_msg) { printf("Failed to allocate request message\n"); - return; + return 1; } exp_data = rpmi_env_zalloc(RPMI_MSG_DATA_SIZE(scene->slot_size)); if (!exp_data) { printf("Failed to allocate expected message\n"); rpmi_env_free(req_msg); - return; + return 1; } resp_msg = rpmi_env_zalloc(scene->slot_size); if (!resp_msg) { printf("Failed to allocate response message\n"); rpmi_env_free(exp_data); rpmi_env_free(req_msg); - return; + return 1; } printf("\nExecuting %s test scenario :\n", scene->name); @@ -148,13 +204,16 @@ static void execute_scenario(struct rpmi_test_scenario *scene) rc = 0; if (rc) { printf("Failed to initialize test %s (error %d)\n", test->name, rc); + nfail++; continue; } /* Initialize request message header */ req_msg->header.servicegroup_id = test->attrs.servicegroup_id; req_msg->header.service_id = test->attrs.service_id; + req_msg->header.flags = test->attrs.flags; req_msg->header.datalen = 0; + token = scene->token_sequence; req_msg->header.token = scene->token_sequence; scene->token_sequence++; @@ -178,6 +237,7 @@ static void execute_scenario(struct rpmi_test_scenario *scene) rc = test_run(scene, test, req_msg); if (rc) { printf("Failed to run test %s (error %d)\n", test->name, rc); + nfail++; goto skip; } @@ -186,14 +246,25 @@ static void execute_scenario(struct rpmi_test_scenario *scene) else scenario_process(scene); + failed = 0; + if ((test->attrs.flags & RPMI_MSG_FLAGS_TYPE) == RPMI_MSG_POSTED_REQUEST) + failed = test_check_no_ack(scene, test, resp_msg); + /* Wait for test to finish */ if (test->wait) test->wait(scene, test, resp_msg); - else + else if (!failed) test_wait(scene, test, resp_msg); + if (!failed && (test->attrs.flags & RPMI_MSG_FLAGS_TYPE) == RPMI_MSG_NORMAL_REQUEST) + failed = test_verify_header(test, resp_msg, token); + /* Verify and report */ - test_verify(test, resp_msg, exp_data, exp_data_len); + test_verify(test, resp_msg, exp_data, exp_data_len, &failed); + if (test->verify) + failed += test->verify(scene, test, resp_msg); + if (failed) + nfail++; skip: /* Cleanup if needed */ @@ -204,6 +275,8 @@ static void execute_scenario(struct rpmi_test_scenario *scene) rpmi_env_free(resp_msg); rpmi_env_free(exp_data); rpmi_env_free(req_msg); + + return nfail; } rpmi_uint16_t test_init_request_data_from_attrs(struct rpmi_test_scenario *scene, @@ -313,13 +386,14 @@ int test_scenario_execute(struct rpmi_test_scenario *scene) return rc; } - execute_scenario(scene); + rc = execute_scenario(scene); + if (rc) + printf("%d test(s) failed in scenario %s\n", rc, scene->name); - rc = scene->cleanup(scene); - if (rc) { + if (scene->cleanup(scene)) { printf("Failed to cleanup test scenario %s\n", scene->name); - return rc; + return RPMI_ERR_FAILED; } - return 0; + return rc ? RPMI_ERR_FAILED : 0; } diff --git a/test/test_common.h b/test/test_common.h index 29cd5a1..5d8ab20 100644 --- a/test/test_common.h +++ b/test/test_common.h @@ -11,6 +11,10 @@ #include #include +#ifndef ARRAY_SIZE +#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) +#endif + /* * Qemu shared memory offsets. * its better to decode these data from DTS file, hardcoding for now. @@ -51,6 +55,8 @@ struct rpmi_test { struct rpmi_message *msg); void (*wait)(struct rpmi_test_scenario *scene, struct rpmi_test *test, struct rpmi_message *msg); + int (*verify)(struct rpmi_test_scenario *scene, struct rpmi_test *test, + struct rpmi_message *msg); void (*cleanup)(struct rpmi_test_scenario *scene, struct rpmi_test *test); }; diff --git a/test/test_srvgrp_base.c b/test/test_srvgrp_base.c index f669526..ca5a9f3 100644 --- a/test/test_srvgrp_base.c +++ b/test/test_srvgrp_base.c @@ -50,6 +50,27 @@ static rpmi_uint32_t probe_expdata_default[] = { RPMI_BASE_VERSION(1, 0), }; +static rpmi_uint32_t probe_sysreset_reqdata_default[] = { + RPMI_SRVGRP_SYSTEM_RESET, +}; + +static rpmi_uint32_t probe_unsupported_expdata_default[] = { + RPMI_SUCCESS, + 0, +}; + +static rpmi_uint32_t probe_experimental_reqdata_default[] = { + RPMI_SRVGRP_EXPERIMENTAL_START, +}; + +static rpmi_uint32_t probe_vendor_reqdata_default[] = { + RPMI_SRVGRP_VENDOR_START, +}; + +static rpmi_uint32_t invalid_service_expdata_default[] = { + RPMI_ERR_NOTSUPP, +}; + static rpmi_uint32_t attribs_expdata_default[] = { RPMI_SUCCESS, RPMI_BASE_FLAGS_F0_PRIVILEGE, @@ -70,7 +91,7 @@ static struct rpmi_test_scenario scenario_base_default = { .init = test_scenario_default_init, .cleanup = test_scenario_default_cleanup, - .num_tests = 7, + .num_tests = 11, .tests = { { .name = "RPMI_BASE_SRV_ENABLE_NOTIFICATION", @@ -141,6 +162,59 @@ static struct rpmi_test_scenario scenario_base_default = { .init_request_data = test_init_request_data_from_attrs, .init_expected_data = test_init_expected_data_from_attrs, }, + { + .name = "RPMI_BASE_SRV_PROBE_SERVICE_GROUP unsupported", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_BASE, + .service_id = RPMI_BASE_SRV_PROBE_SERVICE_GROUP, + .flags = RPMI_MSG_NORMAL_REQUEST, + .request_data = probe_sysreset_reqdata_default, + .request_data_len = sizeof(probe_sysreset_reqdata_default), + .expected_data = probe_unsupported_expdata_default, + .expected_data_len = sizeof(probe_unsupported_expdata_default), + }, + .init_request_data = test_init_request_data_from_attrs, + .init_expected_data = test_init_expected_data_from_attrs, + }, + { + .name = "RPMI_BASE_SRV_PROBE_SERVICE_GROUP experimental", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_BASE, + .service_id = RPMI_BASE_SRV_PROBE_SERVICE_GROUP, + .flags = RPMI_MSG_NORMAL_REQUEST, + .request_data = probe_experimental_reqdata_default, + .request_data_len = sizeof(probe_experimental_reqdata_default), + .expected_data = probe_unsupported_expdata_default, + .expected_data_len = sizeof(probe_unsupported_expdata_default), + }, + .init_request_data = test_init_request_data_from_attrs, + .init_expected_data = test_init_expected_data_from_attrs, + }, + { + .name = "RPMI_BASE_SRV_PROBE_SERVICE_GROUP vendor", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_BASE, + .service_id = RPMI_BASE_SRV_PROBE_SERVICE_GROUP, + .flags = RPMI_MSG_NORMAL_REQUEST, + .request_data = probe_vendor_reqdata_default, + .request_data_len = sizeof(probe_vendor_reqdata_default), + .expected_data = probe_unsupported_expdata_default, + .expected_data_len = sizeof(probe_unsupported_expdata_default), + }, + .init_request_data = test_init_request_data_from_attrs, + .init_expected_data = test_init_expected_data_from_attrs, + }, + { + .name = "RPMI_BASE invalid service", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_BASE, + .service_id = RPMI_BASE_SRV_ID_MAX, + .flags = RPMI_MSG_NORMAL_REQUEST, + .expected_data = invalid_service_expdata_default, + .expected_data_len = sizeof(invalid_service_expdata_default), + }, + .init_expected_data = test_init_expected_data_from_attrs, + }, { .name = "RPMI_BASE_SRV_GET_ATTRIBUTES", .attrs = { diff --git a/test/test_srvgrp_clock.c b/test/test_srvgrp_clock.c new file mode 100644 index 0000000..855e6dd --- /dev/null +++ b/test/test_srvgrp_clock.c @@ -0,0 +1,573 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2024 Ventana Micro Systems Inc. + */ + +#include +#include +#include "test_common.h" +#include "test_log.h" + +#define TEST_CLK_COUNT 2 +#define TEST_CLK_CPU 0 +#define TEST_CLK_BUS 1 +#define TEST_CLK_INVALID TEST_CLK_COUNT +#define TEST_EVENT_ID 0x0 +#define TEST_REQUEST_STATE_ENABLE 0x1 +#define TEST_CLK_CPU_LATENCY 5 +#define TEST_CLK_BUS_LATENCY 7 +#define TEST_CLK_CPU_INITIAL_RATE 100000000ULL +#define TEST_CLK_CPU_TARGET_RATE 200000000ULL +#define TEST_CLK_CPU_UNSUPP_RATE 123456789ULL +#define TEST_CLK_BUS_MIN_RATE 500000000ULL +#define TEST_CLK_BUS_MAX_RATE 1000000000ULL +#define TEST_CLK_BUS_STEP_RATE 100000000ULL + +#define RATE_LO(_rate) ((rpmi_uint32_t)((rpmi_uint64_t)(_rate))) +#define RATE_HI(_rate) ((rpmi_uint32_t)(((rpmi_uint64_t)(_rate)) >> 32)) + +struct test_clk_attrs_expdata { + rpmi_uint32_t status; + rpmi_uint32_t flags; + rpmi_uint32_t rate_count; + rpmi_uint32_t transition_latency; + char name[16]; +}; + +static const rpmi_uint64_t test_cpu_rates[] = { + TEST_CLK_CPU_INITIAL_RATE, + TEST_CLK_CPU_TARGET_RATE, + 400000000ULL, +}; + +static const rpmi_uint64_t test_bus_rates[] = { + TEST_CLK_BUS_MIN_RATE, + TEST_CLK_BUS_MAX_RATE, + TEST_CLK_BUS_STEP_RATE, +}; + +static struct rpmi_clock_data test_clock_data[TEST_CLK_COUNT] = { + [TEST_CLK_CPU] = { + .parent_id = -1U, + .transition_latency_ms = TEST_CLK_CPU_LATENCY, + .rate_count = ARRAY_SIZE(test_cpu_rates), + .clock_type = RPMI_CLK_TYPE_DISCRETE, + .name = "clk_cpu", + .clock_rate_array = test_cpu_rates, + }, + [TEST_CLK_BUS] = { + .parent_id = -1U, + .transition_latency_ms = TEST_CLK_BUS_LATENCY, + .rate_count = ARRAY_SIZE(test_bus_rates), + .clock_type = RPMI_CLK_TYPE_LINEAR, + .name = "clk_bus", + .clock_rate_array = test_bus_rates, + }, +}; + +static enum rpmi_clock_state test_clock_state[TEST_CLK_COUNT] = { + RPMI_CLK_STATE_DISABLED, + RPMI_CLK_STATE_ENABLED, +}; + +static rpmi_uint64_t test_clock_rate[TEST_CLK_COUNT] = { + TEST_CLK_CPU_INITIAL_RATE, + TEST_CLK_BUS_MIN_RATE, +}; + +static rpmi_uint32_t enable_notif_reqdata[] = { + TEST_EVENT_ID, + TEST_REQUEST_STATE_ENABLE, +}; + +static rpmi_uint32_t notsupp_expdata[] = { + RPMI_ERR_NOTSUPP, +}; + +static rpmi_uint32_t get_num_clocks_expdata[] = { + RPMI_SUCCESS, + TEST_CLK_COUNT, +}; + +static rpmi_uint32_t clk_cpu_reqdata[] = { + TEST_CLK_CPU, +}; + +static rpmi_uint32_t clk_invalid_reqdata[] = { + TEST_CLK_INVALID, +}; + +static struct test_clk_attrs_expdata get_attrs_cpu_expdata = { + .status = RPMI_SUCCESS, + .flags = 0, + .rate_count = ARRAY_SIZE(test_cpu_rates), + .transition_latency = TEST_CLK_CPU_LATENCY, + .name = "clk_cpu", +}; + +static rpmi_uint32_t invalid_param_expdata[] = { + RPMI_ERR_INVALID_PARAM, +}; + +static rpmi_uint32_t get_cpu_rates_reqdata[] = { + TEST_CLK_CPU, + 1, +}; + +static rpmi_uint32_t get_cpu_rates_expdata[] = { + RPMI_SUCCESS, + 0, + 0, + 2, + RATE_LO(TEST_CLK_CPU_TARGET_RATE), + RATE_HI(TEST_CLK_CPU_TARGET_RATE), + RATE_LO(400000000ULL), + RATE_HI(400000000ULL), +}; + +static rpmi_uint32_t get_bus_rates_reqdata[] = { + TEST_CLK_BUS, + 0, +}; + +static rpmi_uint32_t get_bus_rates_expdata[] = { + RPMI_SUCCESS, + 0, + 0, + 3, + RATE_LO(TEST_CLK_BUS_MIN_RATE), + RATE_HI(TEST_CLK_BUS_MIN_RATE), + RATE_LO(TEST_CLK_BUS_MAX_RATE), + RATE_HI(TEST_CLK_BUS_MAX_RATE), + RATE_LO(TEST_CLK_BUS_STEP_RATE), + RATE_HI(TEST_CLK_BUS_STEP_RATE), +}; + +static rpmi_uint32_t get_cpu_rates_bad_index_reqdata[] = { + TEST_CLK_CPU, + 4, +}; + +static rpmi_uint32_t set_config_enable_reqdata[] = { + TEST_CLK_CPU, + 1, +}; + +static rpmi_uint32_t success_expdata[] = { + RPMI_SUCCESS, +}; + +static rpmi_uint32_t get_config_enabled_expdata[] = { + RPMI_SUCCESS, + 1, +}; + +static rpmi_uint32_t set_rate_cpu_reqdata[] = { + TEST_CLK_CPU, + RPMI_CLK_RATE_MATCH_ROUND_UP, + RATE_LO(TEST_CLK_CPU_TARGET_RATE), + RATE_HI(TEST_CLK_CPU_TARGET_RATE), +}; + +static rpmi_uint32_t get_rate_cpu_expdata[] = { + RPMI_SUCCESS, + RATE_LO(TEST_CLK_CPU_TARGET_RATE), + RATE_HI(TEST_CLK_CPU_TARGET_RATE), +}; + +static rpmi_uint32_t set_rate_bad_match_reqdata[] = { + TEST_CLK_CPU, + RPMI_CLK_RATE_MATCH_MAX, + RATE_LO(TEST_CLK_CPU_TARGET_RATE), + RATE_HI(TEST_CLK_CPU_TARGET_RATE), +}; + +static rpmi_uint32_t set_rate_zero_reqdata[] = { + TEST_CLK_CPU, + RPMI_CLK_RATE_MATCH_PLATFORM, + 0, + 0, +}; + +static rpmi_uint32_t set_rate_unsupported_reqdata[] = { + TEST_CLK_CPU, + RPMI_CLK_RATE_MATCH_PLATFORM, + RATE_LO(TEST_CLK_CPU_UNSUPP_RATE), + RATE_HI(TEST_CLK_CPU_UNSUPP_RATE), +}; + +static rpmi_bool_t test_clock_rate_supported(rpmi_uint32_t clock_id, + rpmi_uint64_t rate) +{ + const rpmi_uint64_t *rates; + rpmi_uint32_t count, i; + + if (clock_id >= TEST_CLK_COUNT) + return false; + + if (clock_id == TEST_CLK_CPU) { + rates = test_cpu_rates; + count = ARRAY_SIZE(test_cpu_rates); + } else { + rates = test_bus_rates; + count = ARRAY_SIZE(test_bus_rates); + } + + for (i = 0; i < count; i++) { + if (rates[i] == rate) + return true; + } + + return false; +} + +static enum rpmi_error test_clock_set_state(void *priv, + rpmi_uint32_t clock_id, + enum rpmi_clock_state state) +{ + if (clock_id >= TEST_CLK_COUNT || state >= RPMI_CLK_STATE_MAX) + return RPMI_ERR_INVALID_PARAM; + + test_clock_state[clock_id] = state; + return RPMI_SUCCESS; +} + +static enum rpmi_error test_clock_get_state_and_rate(void *priv, + rpmi_uint32_t clock_id, + enum rpmi_clock_state *state, + rpmi_uint64_t *rate) +{ + if (clock_id >= TEST_CLK_COUNT) + return RPMI_ERR_INVALID_PARAM; + + if (state) + *state = test_clock_state[clock_id]; + if (rate) + *rate = test_clock_rate[clock_id]; + + return RPMI_SUCCESS; +} + +static rpmi_bool_t test_clock_rate_change_match(void *priv, + rpmi_uint32_t clock_id, + rpmi_uint64_t rate) +{ + if (clock_id >= TEST_CLK_COUNT) + return false; + + return test_clock_rate[clock_id] != rate; +} + +static enum rpmi_error test_clock_set_rate(void *priv, + rpmi_uint32_t clock_id, + enum rpmi_clock_rate_match match, + rpmi_uint64_t rate, + rpmi_uint64_t *new_rate) +{ + if (clock_id >= TEST_CLK_COUNT || !new_rate) + return RPMI_ERR_INVALID_PARAM; + + if (!test_clock_rate_supported(clock_id, rate)) + return RPMI_ERR_INVALID_PARAM; + + test_clock_rate[clock_id] = rate; + *new_rate = rate; + return RPMI_SUCCESS; +} + +static enum rpmi_error test_clock_set_rate_recalc(void *priv, + rpmi_uint32_t clock_id, + rpmi_uint64_t parent_rate, + rpmi_uint64_t *new_rate) +{ + if (clock_id >= TEST_CLK_COUNT || !new_rate) + return RPMI_ERR_INVALID_PARAM; + + test_clock_rate[clock_id] = parent_rate; + *new_rate = parent_rate; + return RPMI_SUCCESS; +} + +static struct rpmi_clock_platform_ops test_clock_ops = { + .set_state = test_clock_set_state, + .get_state_and_rate = test_clock_get_state_and_rate, + .rate_change_match = test_clock_rate_change_match, + .set_rate = test_clock_set_rate, + .set_rate_recalc = test_clock_set_rate_recalc, +}; + +static int test_clock_state_init(struct rpmi_test_scenario *scene, + struct rpmi_test *test) +{ + test_clock_state[TEST_CLK_CPU] = RPMI_CLK_STATE_DISABLED; + test_clock_state[TEST_CLK_BUS] = RPMI_CLK_STATE_ENABLED; + test_clock_rate[TEST_CLK_CPU] = TEST_CLK_CPU_INITIAL_RATE; + test_clock_rate[TEST_CLK_BUS] = TEST_CLK_BUS_MIN_RATE; + return 0; +} + +static int test_clock_scenario_init(struct rpmi_test_scenario *scene) +{ + struct rpmi_service_group *grp; + int ret; + + ret = test_scenario_default_init(scene); + if (ret) + return RPMI_ERR_FAILED; + + test_clock_state[TEST_CLK_CPU] = RPMI_CLK_STATE_DISABLED; + test_clock_state[TEST_CLK_BUS] = RPMI_CLK_STATE_ENABLED; + test_clock_rate[TEST_CLK_CPU] = TEST_CLK_CPU_INITIAL_RATE; + test_clock_rate[TEST_CLK_BUS] = TEST_CLK_BUS_MIN_RATE; + + grp = rpmi_service_group_clock_create(TEST_CLK_COUNT, + test_clock_data, + &test_clock_ops, NULL); + if (!grp) { + printf("failed to create rpmi clock service group"); + return RPMI_ERR_FAILED; + } + + rpmi_context_add_group(scene->cntx, grp); + return 0; +} + +static struct rpmi_test_scenario scenario_clock_default = { + .name = "Clock Service Group", + .shm_size = RPMI_SHM_SZ, + .slot_size = RPMI_SLOT_SIZE, + .max_num_groups = RPMI_SRVGRP_ID_MAX_COUNT, + .priv = NULL, + + .init = test_clock_scenario_init, + .cleanup = test_scenario_default_cleanup, + + .num_tests = 16, + .tests = { + { + .name = "ENABLE NOTIFICATION TEST (notifications not supported)", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_CLOCK, + .service_id = RPMI_CLK_SRV_ENABLE_NOTIFICATION, + .flags = RPMI_MSG_NORMAL_REQUEST, + .request_data = enable_notif_reqdata, + .request_data_len = sizeof(enable_notif_reqdata), + .expected_data = notsupp_expdata, + .expected_data_len = sizeof(notsupp_expdata), + }, + .init_request_data = test_init_request_data_from_attrs, + .init_expected_data = test_init_expected_data_from_attrs, + }, + { + .name = "GET NUM CLOCKS", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_CLOCK, + .service_id = RPMI_CLK_SRV_GET_NUM_CLOCKS, + .flags = RPMI_MSG_NORMAL_REQUEST, + .expected_data = get_num_clocks_expdata, + .expected_data_len = sizeof(get_num_clocks_expdata), + }, + .init_expected_data = test_init_expected_data_from_attrs, + }, + { + .name = "GET ATTRIBUTES", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_CLOCK, + .service_id = RPMI_CLK_SRV_GET_ATTRIBUTES, + .flags = RPMI_MSG_NORMAL_REQUEST, + .request_data = clk_cpu_reqdata, + .request_data_len = sizeof(clk_cpu_reqdata), + .expected_data = &get_attrs_cpu_expdata, + .expected_data_len = sizeof(get_attrs_cpu_expdata), + }, + .init_request_data = test_init_request_data_from_attrs, + .init_expected_data = test_init_expected_data_from_attrs, + }, + { + .name = "GET ATTRIBUTES (invalid clock)", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_CLOCK, + .service_id = RPMI_CLK_SRV_GET_ATTRIBUTES, + .flags = RPMI_MSG_NORMAL_REQUEST, + .request_data = clk_invalid_reqdata, + .request_data_len = sizeof(clk_invalid_reqdata), + .expected_data = invalid_param_expdata, + .expected_data_len = sizeof(invalid_param_expdata), + }, + .init_request_data = test_init_request_data_from_attrs, + .init_expected_data = test_init_expected_data_from_attrs, + }, + { + .name = "GET SUPPORTED RATES (discrete)", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_CLOCK, + .service_id = RPMI_CLK_SRV_GET_SUPPORTED_RATES, + .flags = RPMI_MSG_NORMAL_REQUEST, + .request_data = get_cpu_rates_reqdata, + .request_data_len = sizeof(get_cpu_rates_reqdata), + .expected_data = get_cpu_rates_expdata, + .expected_data_len = sizeof(get_cpu_rates_expdata), + }, + .init_request_data = test_init_request_data_from_attrs, + .init_expected_data = test_init_expected_data_from_attrs, + }, + { + .name = "GET SUPPORTED RATES (linear)", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_CLOCK, + .service_id = RPMI_CLK_SRV_GET_SUPPORTED_RATES, + .flags = RPMI_MSG_NORMAL_REQUEST, + .request_data = get_bus_rates_reqdata, + .request_data_len = sizeof(get_bus_rates_reqdata), + .expected_data = get_bus_rates_expdata, + .expected_data_len = sizeof(get_bus_rates_expdata), + }, + .init_request_data = test_init_request_data_from_attrs, + .init_expected_data = test_init_expected_data_from_attrs, + }, + { + .name = "GET SUPPORTED RATES (bad index)", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_CLOCK, + .service_id = RPMI_CLK_SRV_GET_SUPPORTED_RATES, + .flags = RPMI_MSG_NORMAL_REQUEST, + .request_data = get_cpu_rates_bad_index_reqdata, + .request_data_len = sizeof(get_cpu_rates_bad_index_reqdata), + .expected_data = invalid_param_expdata, + .expected_data_len = sizeof(invalid_param_expdata), + }, + .init_request_data = test_init_request_data_from_attrs, + .init_expected_data = test_init_expected_data_from_attrs, + }, + { + .name = "SET CONFIG (enable)", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_CLOCK, + .service_id = RPMI_CLK_SRV_SET_CONFIG, + .flags = RPMI_MSG_NORMAL_REQUEST, + .request_data = set_config_enable_reqdata, + .request_data_len = sizeof(set_config_enable_reqdata), + .expected_data = success_expdata, + .expected_data_len = sizeof(success_expdata), + }, + .init = test_clock_state_init, + .init_request_data = test_init_request_data_from_attrs, + .init_expected_data = test_init_expected_data_from_attrs, + }, + { + .name = "GET CONFIG (enabled)", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_CLOCK, + .service_id = RPMI_CLK_SRV_GET_CONFIG, + .flags = RPMI_MSG_NORMAL_REQUEST, + .request_data = clk_cpu_reqdata, + .request_data_len = sizeof(clk_cpu_reqdata), + .expected_data = get_config_enabled_expdata, + .expected_data_len = sizeof(get_config_enabled_expdata), + }, + .init_request_data = test_init_request_data_from_attrs, + .init_expected_data = test_init_expected_data_from_attrs, + }, + { + .name = "GET CONFIG (short request)", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_CLOCK, + .service_id = RPMI_CLK_SRV_GET_CONFIG, + .flags = RPMI_MSG_NORMAL_REQUEST, + .expected_data = notsupp_expdata, + .expected_data_len = sizeof(notsupp_expdata), + }, + .init_expected_data = test_init_expected_data_from_attrs, + }, + { + .name = "SET RATE", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_CLOCK, + .service_id = RPMI_CLK_SRV_SET_RATE, + .flags = RPMI_MSG_NORMAL_REQUEST, + .request_data = set_rate_cpu_reqdata, + .request_data_len = sizeof(set_rate_cpu_reqdata), + .expected_data = success_expdata, + .expected_data_len = sizeof(success_expdata), + }, + .init_request_data = test_init_request_data_from_attrs, + .init_expected_data = test_init_expected_data_from_attrs, + }, + { + .name = "GET RATE", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_CLOCK, + .service_id = RPMI_CLK_SRV_GET_RATE, + .flags = RPMI_MSG_NORMAL_REQUEST, + .request_data = clk_cpu_reqdata, + .request_data_len = sizeof(clk_cpu_reqdata), + .expected_data = get_rate_cpu_expdata, + .expected_data_len = sizeof(get_rate_cpu_expdata), + }, + .init_request_data = test_init_request_data_from_attrs, + .init_expected_data = test_init_expected_data_from_attrs, + }, + { + .name = "SET RATE (bad match)", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_CLOCK, + .service_id = RPMI_CLK_SRV_SET_RATE, + .flags = RPMI_MSG_NORMAL_REQUEST, + .request_data = set_rate_bad_match_reqdata, + .request_data_len = sizeof(set_rate_bad_match_reqdata), + .expected_data = invalid_param_expdata, + .expected_data_len = sizeof(invalid_param_expdata), + }, + .init_request_data = test_init_request_data_from_attrs, + .init_expected_data = test_init_expected_data_from_attrs, + }, + { + .name = "SET RATE (zero rate)", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_CLOCK, + .service_id = RPMI_CLK_SRV_SET_RATE, + .flags = RPMI_MSG_NORMAL_REQUEST, + .request_data = set_rate_zero_reqdata, + .request_data_len = sizeof(set_rate_zero_reqdata), + .expected_data = invalid_param_expdata, + .expected_data_len = sizeof(invalid_param_expdata), + }, + .init_request_data = test_init_request_data_from_attrs, + .init_expected_data = test_init_expected_data_from_attrs, + }, + { + .name = "SET RATE (unsupported rate)", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_CLOCK, + .service_id = RPMI_CLK_SRV_SET_RATE, + .flags = RPMI_MSG_NORMAL_REQUEST, + .request_data = set_rate_unsupported_reqdata, + .request_data_len = sizeof(set_rate_unsupported_reqdata), + .expected_data = invalid_param_expdata, + .expected_data_len = sizeof(invalid_param_expdata), + }, + .init_request_data = test_init_request_data_from_attrs, + .init_expected_data = test_init_expected_data_from_attrs, + }, + { + .name = "GET RATE (invalid clock)", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_CLOCK, + .service_id = RPMI_CLK_SRV_GET_RATE, + .flags = RPMI_MSG_NORMAL_REQUEST, + .request_data = clk_invalid_reqdata, + .request_data_len = sizeof(clk_invalid_reqdata), + .expected_data = invalid_param_expdata, + .expected_data_len = sizeof(invalid_param_expdata), + }, + .init_request_data = test_init_request_data_from_attrs, + .init_expected_data = test_init_expected_data_from_attrs, + }, + }, +}; + +int main(int argc, char *argv[]) +{ + printf("Test Clock Service Group\n"); + return test_scenario_execute(&scenario_clock_default); +} diff --git a/test/test_srvgrp_cppc.c b/test/test_srvgrp_cppc.c new file mode 100644 index 0000000..42511a9 --- /dev/null +++ b/test/test_srvgrp_cppc.c @@ -0,0 +1,428 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2024 Ventana Micro Systems Inc. + */ + +#include +#include +#include "librpmi_internal.h" +#include "test_common.h" +#include "test_log.h" + +#define TEST_HART_ID 0 +#define TEST_HART_ID_INVALID 1 +#define TEST_EVENT_ID 0x0 +#define TEST_REQUEST_STATE_ENABLE 0x1 +#define TEST_CPPC_HIGHEST_PERF 0x64 +#define TEST_CPPC_NOMINAL_PERF 0x50 +#define TEST_CPPC_COUNTER_LO 0x55667788 +#define TEST_CPPC_COUNTER_HI 0x11223344 +#define TEST_CPPC_FASTCHAN_SIZE 64 +#define TEST_CPPC_FASTCHAN_REQ_OFFSET 0 +#define TEST_CPPC_FASTCHAN_FB_OFFSET RPMI_CPPC_FASTCHAN_SIZE + +static rpmi_uint8_t test_fastchan_mem[TEST_CPPC_FASTCHAN_SIZE] + __aligned(RPMI_CPPC_FASTCHAN_SIZE); + +static rpmi_uint32_t test_hartid_array[] = { + TEST_HART_ID, +}; + +static struct rpmi_cppc_regs test_cppc_regs = { + .highest_perf = TEST_CPPC_HIGHEST_PERF, + .nominal_perf = TEST_CPPC_NOMINAL_PERF, + .lowest_nonlinear_perf = 0x30, + .lowest_perf = 0x10, + .reference_perf = TEST_CPPC_NOMINAL_PERF, + .lowest_freq = 1000000000U, + .nominal_freq = 2000000000U, + .transition_latency = 10, +}; + +static rpmi_uint32_t enable_notif_reqdata[] = { + TEST_EVENT_ID, + TEST_REQUEST_STATE_ENABLE, +}; + +static rpmi_uint32_t enable_notif_expdata[] = { + RPMI_ERR_NOTSUPP, +}; + +static rpmi_uint32_t probe_highest_reqdata[] = { + TEST_HART_ID, + RPMI_CPPC_HIGHEST_PERF, +}; + +static rpmi_uint32_t probe_32bit_expdata[] = { + RPMI_SUCCESS, + 32, +}; + +static rpmi_uint32_t probe_not_supp_reqdata[] = { + TEST_HART_ID, + RPMI_CPPC_MIN_PERF, +}; + +static rpmi_uint32_t probe_not_supp_expdata[] = { + RPMI_ERR_NOTSUPP, + 0, +}; + +static rpmi_uint32_t probe_invalid_reg_reqdata[] = { + TEST_HART_ID, + RPMI_CPPC_NON_ACPI_REG_MAX_IDX, +}; + +static rpmi_uint32_t invalid_param_expdata[] = { + RPMI_ERR_INVALID_PARAM, +}; + +static rpmi_uint32_t read_highest_reqdata[] = { + TEST_HART_ID, + RPMI_CPPC_HIGHEST_PERF, +}; + +static rpmi_uint32_t read_highest_expdata[] = { + RPMI_SUCCESS, + TEST_CPPC_HIGHEST_PERF, + 0, +}; + +static rpmi_uint32_t read_counter_reqdata[] = { + TEST_HART_ID, + RPMI_CPPC_REFERENCE_PERF_COUNTER, +}; + +static rpmi_uint32_t read_counter_expdata[] = { + RPMI_SUCCESS, + TEST_CPPC_COUNTER_LO, + TEST_CPPC_COUNTER_HI, +}; + +static rpmi_uint32_t read_invalid_hart_reqdata[] = { + TEST_HART_ID_INVALID, + RPMI_CPPC_HIGHEST_PERF, +}; + +static rpmi_uint32_t write_readonly_reqdata[] = { + TEST_HART_ID, + RPMI_CPPC_HIGHEST_PERF, + 1, + 0, +}; + +static rpmi_uint32_t denied_expdata[] = { + RPMI_ERR_DENIED, +}; + +static rpmi_uint32_t get_fastchan_offset_reqdata[] = { + TEST_HART_ID, +}; + +static rpmi_uint32_t get_fastchan_offset_expdata[] = { + RPMI_SUCCESS, + TEST_CPPC_FASTCHAN_REQ_OFFSET, + 0, + TEST_CPPC_FASTCHAN_FB_OFFSET, + 0, +}; + +static rpmi_uint32_t get_hart_list_reqdata[] = { + 0, +}; + +static rpmi_uint32_t get_hart_list_expdata[] = { + RPMI_SUCCESS, + 0, + 1, + TEST_HART_ID, +}; + +static enum rpmi_hart_hw_state test_hart_get_hw_state(void *priv, + rpmi_uint32_t hart_index) +{ + return RPMI_HART_HW_STATE_STARTED; +} + +static struct rpmi_hsm_platform_ops test_hsm_ops = { + .hart_get_hw_state = test_hart_get_hw_state, +}; + +static enum rpmi_error test_cppc_get_reg(void *priv, rpmi_uint32_t reg_id, + rpmi_uint32_t hart_index, + rpmi_uint64_t *val) +{ + if (reg_id == RPMI_CPPC_REFERENCE_PERF_COUNTER) { + *val = ((rpmi_uint64_t)TEST_CPPC_COUNTER_HI << 32) | + TEST_CPPC_COUNTER_LO; + return RPMI_SUCCESS; + } + + *val = 0; + return RPMI_ERR_NOTSUPP; +} + +static enum rpmi_error test_cppc_set_reg(void *priv, rpmi_uint32_t reg_id, + rpmi_uint32_t hart_index, + rpmi_uint64_t val) +{ + return RPMI_SUCCESS; +} + +static enum rpmi_error test_cppc_update_perf(void *priv, + rpmi_uint32_t hart_index, + rpmi_uint32_t desired_perf) +{ + return RPMI_SUCCESS; +} + +static enum rpmi_error test_cppc_get_current_freq(void *priv, + rpmi_uint32_t hart_index, + rpmi_uint64_t *current_freq_hz) +{ + *current_freq_hz = 2000000000ULL; + return RPMI_SUCCESS; +} + +static struct rpmi_cppc_platform_ops test_cppc_ops = { + .cppc_get_reg = test_cppc_get_reg, + .cppc_set_reg = test_cppc_set_reg, + .cppc_update_perf = test_cppc_update_perf, + .cppc_get_current_freq = test_cppc_get_current_freq, +}; + +static rpmi_uint16_t init_fastchan_region_expected(struct rpmi_test_scenario *scene, + struct rpmi_test *test, + void *data, + rpmi_uint16_t max_data_len) +{ + rpmi_uint32_t *exp = data; + rpmi_uint64_t base = (rpmi_uint64_t)(rpmi_uintptr_t)test_fastchan_mem; + + exp[0] = RPMI_SUCCESS; + exp[1] = 0; + exp[2] = (rpmi_uint32_t)base; + exp[3] = (rpmi_uint32_t)(base >> 32); + exp[4] = TEST_CPPC_FASTCHAN_SIZE; + exp[5] = 0; + exp[6] = 0; + exp[7] = 0; + exp[8] = 0; + exp[9] = 0; + exp[10] = 0; + exp[11] = 0; + + return 12 * sizeof(*exp); +} + +static int test_cppc_scenario_init(struct rpmi_test_scenario *scene) +{ + struct rpmi_service_group *grp; + struct rpmi_shmem *fastchan_shmem; + struct rpmi_hsm *hsm; + int ret; + + ret = test_scenario_default_init(scene); + if (ret) + return RPMI_ERR_FAILED; + + hsm = rpmi_hsm_create(ARRAY_SIZE(test_hartid_array), + test_hartid_array, 0, NULL, &test_hsm_ops, NULL); + if (!hsm) { + printf("failed to create rpmi hsm"); + return RPMI_ERR_FAILED; + } + + fastchan_shmem = rpmi_shmem_create("test_cppc_fastchan", + (rpmi_uint64_t)(rpmi_uintptr_t)test_fastchan_mem, + sizeof(test_fastchan_mem), + &rpmi_shmem_simple_ops, NULL); + if (!fastchan_shmem) { + printf("failed to create cppc fastchannel shmem"); + return RPMI_ERR_FAILED; + } + + grp = rpmi_service_group_cppc_create(hsm, &test_cppc_regs, + RPMI_CPPC_PASSIVE_MODE, + fastchan_shmem, + TEST_CPPC_FASTCHAN_REQ_OFFSET, + TEST_CPPC_FASTCHAN_FB_OFFSET, + &test_cppc_ops, NULL); + if (!grp) { + printf("failed to create rpmi cppc service group"); + return RPMI_ERR_FAILED; + } + + rpmi_context_add_group(scene->cntx, grp); + return 0; +} + +static struct rpmi_test_scenario scenario_cppc_default = { + .name = "CPPC Service Group", + .shm_size = RPMI_SHM_SZ, + .slot_size = RPMI_SLOT_SIZE, + .max_num_groups = RPMI_SRVGRP_ID_MAX_COUNT, + .priv = NULL, + + .init = test_cppc_scenario_init, + .cleanup = test_scenario_default_cleanup, + + .num_tests = 11, + .tests = { + { + .name = "ENABLE NOTIFICATION TEST (notifications not supported)", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_CPPC, + .service_id = RPMI_CPPC_SRV_ENABLE_NOTIFICATION, + .flags = RPMI_MSG_NORMAL_REQUEST, + .request_data = enable_notif_reqdata, + .request_data_len = sizeof(enable_notif_reqdata), + .expected_data = enable_notif_expdata, + .expected_data_len = sizeof(enable_notif_expdata), + }, + .init_request_data = test_init_request_data_from_attrs, + .init_expected_data = test_init_expected_data_from_attrs, + }, + { + .name = "PROBE REG (implemented 32-bit reg)", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_CPPC, + .service_id = RPMI_CPPC_SRV_PROBE_REG, + .flags = RPMI_MSG_NORMAL_REQUEST, + .request_data = probe_highest_reqdata, + .request_data_len = sizeof(probe_highest_reqdata), + .expected_data = probe_32bit_expdata, + .expected_data_len = sizeof(probe_32bit_expdata), + }, + .init_request_data = test_init_request_data_from_attrs, + .init_expected_data = test_init_expected_data_from_attrs, + }, + { + .name = "PROBE REG (not supported reg)", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_CPPC, + .service_id = RPMI_CPPC_SRV_PROBE_REG, + .flags = RPMI_MSG_NORMAL_REQUEST, + .request_data = probe_not_supp_reqdata, + .request_data_len = sizeof(probe_not_supp_reqdata), + .expected_data = probe_not_supp_expdata, + .expected_data_len = sizeof(probe_not_supp_expdata), + }, + .init_request_data = test_init_request_data_from_attrs, + .init_expected_data = test_init_expected_data_from_attrs, + }, + { + .name = "PROBE REG (invalid reg)", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_CPPC, + .service_id = RPMI_CPPC_SRV_PROBE_REG, + .flags = RPMI_MSG_NORMAL_REQUEST, + .request_data = probe_invalid_reg_reqdata, + .request_data_len = sizeof(probe_invalid_reg_reqdata), + .expected_data = invalid_param_expdata, + .expected_data_len = sizeof(invalid_param_expdata), + }, + .init_request_data = test_init_request_data_from_attrs, + .init_expected_data = test_init_expected_data_from_attrs, + }, + { + .name = "READ REG (static 32-bit reg)", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_CPPC, + .service_id = RPMI_CPPC_SRV_READ_REG, + .flags = RPMI_MSG_NORMAL_REQUEST, + .request_data = read_highest_reqdata, + .request_data_len = sizeof(read_highest_reqdata), + .expected_data = read_highest_expdata, + .expected_data_len = sizeof(read_highest_expdata), + }, + .init_request_data = test_init_request_data_from_attrs, + .init_expected_data = test_init_expected_data_from_attrs, + }, + { + .name = "READ REG (platform 64-bit counter)", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_CPPC, + .service_id = RPMI_CPPC_SRV_READ_REG, + .flags = RPMI_MSG_NORMAL_REQUEST, + .request_data = read_counter_reqdata, + .request_data_len = sizeof(read_counter_reqdata), + .expected_data = read_counter_expdata, + .expected_data_len = sizeof(read_counter_expdata), + }, + .init_request_data = test_init_request_data_from_attrs, + .init_expected_data = test_init_expected_data_from_attrs, + }, + { + .name = "READ REG (invalid hart)", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_CPPC, + .service_id = RPMI_CPPC_SRV_READ_REG, + .flags = RPMI_MSG_NORMAL_REQUEST, + .request_data = read_invalid_hart_reqdata, + .request_data_len = sizeof(read_invalid_hart_reqdata), + .expected_data = invalid_param_expdata, + .expected_data_len = sizeof(invalid_param_expdata), + }, + .init_request_data = test_init_request_data_from_attrs, + .init_expected_data = test_init_expected_data_from_attrs, + }, + { + .name = "WRITE REG (read-only reg denied)", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_CPPC, + .service_id = RPMI_CPPC_SRV_WRITE_REG, + .flags = RPMI_MSG_NORMAL_REQUEST, + .request_data = write_readonly_reqdata, + .request_data_len = sizeof(write_readonly_reqdata), + .expected_data = denied_expdata, + .expected_data_len = sizeof(denied_expdata), + }, + .init_request_data = test_init_request_data_from_attrs, + .init_expected_data = test_init_expected_data_from_attrs, + }, + { + .name = "GET FAST CHANNEL REGION", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_CPPC, + .service_id = RPMI_CPPC_SRV_GET_FAST_CHANNEL_REGION, + .flags = RPMI_MSG_NORMAL_REQUEST, + }, + .init_expected_data = init_fastchan_region_expected, + }, + { + .name = "GET FAST CHANNEL OFFSET", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_CPPC, + .service_id = RPMI_CPPC_SRV_GET_FAST_CHANNEL_OFFSET, + .flags = RPMI_MSG_NORMAL_REQUEST, + .request_data = get_fastchan_offset_reqdata, + .request_data_len = sizeof(get_fastchan_offset_reqdata), + .expected_data = get_fastchan_offset_expdata, + .expected_data_len = sizeof(get_fastchan_offset_expdata), + }, + .init_request_data = test_init_request_data_from_attrs, + .init_expected_data = test_init_expected_data_from_attrs, + }, + { + .name = "GET HART LIST", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_CPPC, + .service_id = RPMI_CPPC_SRV_GET_HART_LIST, + .flags = RPMI_MSG_NORMAL_REQUEST, + .request_data = get_hart_list_reqdata, + .request_data_len = sizeof(get_hart_list_reqdata), + .expected_data = get_hart_list_expdata, + .expected_data_len = sizeof(get_hart_list_expdata), + }, + .init_request_data = test_init_request_data_from_attrs, + .init_expected_data = test_init_expected_data_from_attrs, + }, + }, +}; + +int main(int argc, char *argv[]) +{ + printf("Test CPPC Service Group\n"); + return test_scenario_execute(&scenario_cppc_default); +} diff --git a/test/test_srvgrp_device_power.c b/test/test_srvgrp_device_power.c new file mode 100644 index 0000000..5e3f627 --- /dev/null +++ b/test/test_srvgrp_device_power.c @@ -0,0 +1,297 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2024 Ventana Micro Systems Inc. + */ + +#include +#include +#include "test_common.h" +#include "test_log.h" + +#define TEST_DPWR_COUNT 2 +#define TEST_DPWR_GPU 0 +#define TEST_DPWR_NPU 1 +#define TEST_DPWR_INVALID TEST_DPWR_COUNT +#define TEST_DPWR_GPU_LATENCY 15 +#define TEST_DPWR_BAD_STATE 1 +#define TEST_EVENT_ID 0x0 +#define TEST_REQUEST_STATE_ENABLE 0x1 + +struct test_dpwr_attrs_expdata { + rpmi_uint32_t status; + rpmi_uint32_t flags; + rpmi_uint32_t trans_latency; + char name[16]; +}; + +static struct rpmi_dpwr_data test_dpwr_data[TEST_DPWR_COUNT] = { + [TEST_DPWR_GPU] = { + .trans_latency = TEST_DPWR_GPU_LATENCY, + .name = "gpu_pd", + }, + [TEST_DPWR_NPU] = { + .trans_latency = 25, + .name = "npu_pd", + }, +}; + +static rpmi_uint32_t test_dpwr_state[TEST_DPWR_COUNT] = { + RPMI_DPWR_STATE_ON, + RPMI_DPWR_STATE_OFF, +}; + +static rpmi_uint32_t enable_notif_reqdata[] = { + TEST_EVENT_ID, + TEST_REQUEST_STATE_ENABLE, +}; + +static rpmi_uint32_t notsupp_expdata[] = { + RPMI_ERR_NOTSUPP, +}; + +static rpmi_uint32_t get_num_domains_expdata[] = { + RPMI_SUCCESS, + TEST_DPWR_COUNT, +}; + +static rpmi_uint32_t dpwr_gpu_reqdata[] = { + TEST_DPWR_GPU, +}; + +static rpmi_uint32_t dpwr_invalid_reqdata[] = { + TEST_DPWR_INVALID, +}; + +static struct test_dpwr_attrs_expdata get_attrs_gpu_expdata = { + .status = RPMI_SUCCESS, + .flags = 0, + .trans_latency = TEST_DPWR_GPU_LATENCY, + .name = "gpu_pd", +}; + +static rpmi_uint32_t invalid_param_expdata[] = { + RPMI_ERR_INVALID_PARAM, +}; + +static rpmi_uint32_t set_state_off_reqdata[] = { + TEST_DPWR_GPU, + RPMI_DPWR_STATE_OFF, +}; + +static rpmi_uint32_t success_expdata[] = { + RPMI_SUCCESS, +}; + +static rpmi_uint32_t get_state_off_expdata[] = { + RPMI_SUCCESS, + RPMI_DPWR_STATE_OFF, +}; + +static rpmi_uint32_t set_state_bad_reqdata[] = { + TEST_DPWR_GPU, + TEST_DPWR_BAD_STATE, +}; + +static enum rpmi_error test_dpwr_get_state(void *priv, + rpmi_uint32_t dpwr_id, + rpmi_uint32_t *state) +{ + if (dpwr_id >= TEST_DPWR_COUNT || !state) + return RPMI_ERR_INVALID_PARAM; + + *state = test_dpwr_state[dpwr_id]; + return RPMI_SUCCESS; +} + +static enum rpmi_error test_dpwr_set_state(void *priv, + rpmi_uint32_t dpwr_id, + rpmi_uint32_t state) +{ + if (dpwr_id >= TEST_DPWR_COUNT) + return RPMI_ERR_INVALID_PARAM; + + if (state != RPMI_DPWR_STATE_ON && state != RPMI_DPWR_STATE_OFF) + return RPMI_ERR_INVALID_PARAM; + + test_dpwr_state[dpwr_id] = state; + return RPMI_SUCCESS; +} + +static struct rpmi_dpwr_platform_ops test_dpwr_ops = { + .get_state = test_dpwr_get_state, + .set_state = test_dpwr_set_state, +}; + +static int test_dpwr_state_init(struct rpmi_test_scenario *scene, + struct rpmi_test *test) +{ + test_dpwr_state[TEST_DPWR_GPU] = RPMI_DPWR_STATE_ON; + test_dpwr_state[TEST_DPWR_NPU] = RPMI_DPWR_STATE_OFF; + return 0; +} + +static int test_dpwr_scenario_init(struct rpmi_test_scenario *scene) +{ + struct rpmi_service_group *grp; + int ret; + + ret = test_scenario_default_init(scene); + if (ret) + return RPMI_ERR_FAILED; + + test_dpwr_state[TEST_DPWR_GPU] = RPMI_DPWR_STATE_ON; + test_dpwr_state[TEST_DPWR_NPU] = RPMI_DPWR_STATE_OFF; + + grp = rpmi_service_group_dpwr_create(TEST_DPWR_COUNT, + test_dpwr_data, + &test_dpwr_ops, NULL); + if (!grp) { + printf("failed to create rpmi dpwr service group"); + return RPMI_ERR_FAILED; + } + + rpmi_context_add_group(scene->cntx, grp); + return 0; +} + +static struct rpmi_test_scenario scenario_dpwr_default = { + .name = "Device Power Service Group", + .shm_size = RPMI_SHM_SZ, + .slot_size = RPMI_SLOT_SIZE, + .max_num_groups = RPMI_SRVGRP_ID_MAX_COUNT, + .priv = NULL, + + .init = test_dpwr_scenario_init, + .cleanup = test_scenario_default_cleanup, + + .num_tests = 9, + .tests = { + { + .name = "ENABLE NOTIFICATION TEST (notifications not supported)", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_DEVICE_POWER, + .service_id = RPMI_DPWR_SRV_ENABLE_NOTIFICATION, + .flags = RPMI_MSG_NORMAL_REQUEST, + .request_data = enable_notif_reqdata, + .request_data_len = sizeof(enable_notif_reqdata), + .expected_data = notsupp_expdata, + .expected_data_len = sizeof(notsupp_expdata), + }, + .init_request_data = test_init_request_data_from_attrs, + .init_expected_data = test_init_expected_data_from_attrs, + }, + { + .name = "GET NUM DOMAINS", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_DEVICE_POWER, + .service_id = RPMI_DPWR_SRV_GET_NUM_DOMAINS, + .flags = RPMI_MSG_NORMAL_REQUEST, + .expected_data = get_num_domains_expdata, + .expected_data_len = sizeof(get_num_domains_expdata), + }, + .init_expected_data = test_init_expected_data_from_attrs, + }, + { + .name = "GET ATTRIBUTES", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_DEVICE_POWER, + .service_id = RPMI_DPWR_SRV_GET_ATTRIBUTES, + .flags = RPMI_MSG_NORMAL_REQUEST, + .request_data = dpwr_gpu_reqdata, + .request_data_len = sizeof(dpwr_gpu_reqdata), + .expected_data = &get_attrs_gpu_expdata, + .expected_data_len = sizeof(get_attrs_gpu_expdata), + }, + .init_request_data = test_init_request_data_from_attrs, + .init_expected_data = test_init_expected_data_from_attrs, + }, + { + .name = "GET ATTRIBUTES (invalid domain)", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_DEVICE_POWER, + .service_id = RPMI_DPWR_SRV_GET_ATTRIBUTES, + .flags = RPMI_MSG_NORMAL_REQUEST, + .request_data = dpwr_invalid_reqdata, + .request_data_len = sizeof(dpwr_invalid_reqdata), + .expected_data = invalid_param_expdata, + .expected_data_len = sizeof(invalid_param_expdata), + }, + .init_request_data = test_init_request_data_from_attrs, + .init_expected_data = test_init_expected_data_from_attrs, + }, + { + .name = "SET STATE (off)", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_DEVICE_POWER, + .service_id = RPMI_DPWR_SRV_SET_DPWR_STATE, + .flags = RPMI_MSG_NORMAL_REQUEST, + .request_data = set_state_off_reqdata, + .request_data_len = sizeof(set_state_off_reqdata), + .expected_data = success_expdata, + .expected_data_len = sizeof(success_expdata), + }, + .init = test_dpwr_state_init, + .init_request_data = test_init_request_data_from_attrs, + .init_expected_data = test_init_expected_data_from_attrs, + }, + { + .name = "GET STATE (off)", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_DEVICE_POWER, + .service_id = RPMI_DPWR_SRV_GET_DPWR_STATE, + .flags = RPMI_MSG_NORMAL_REQUEST, + .request_data = dpwr_gpu_reqdata, + .request_data_len = sizeof(dpwr_gpu_reqdata), + .expected_data = get_state_off_expdata, + .expected_data_len = sizeof(get_state_off_expdata), + }, + .init_request_data = test_init_request_data_from_attrs, + .init_expected_data = test_init_expected_data_from_attrs, + }, + { + .name = "SET STATE (unsupported state)", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_DEVICE_POWER, + .service_id = RPMI_DPWR_SRV_SET_DPWR_STATE, + .flags = RPMI_MSG_NORMAL_REQUEST, + .request_data = set_state_bad_reqdata, + .request_data_len = sizeof(set_state_bad_reqdata), + .expected_data = invalid_param_expdata, + .expected_data_len = sizeof(invalid_param_expdata), + }, + .init_request_data = test_init_request_data_from_attrs, + .init_expected_data = test_init_expected_data_from_attrs, + }, + { + .name = "GET STATE (invalid domain)", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_DEVICE_POWER, + .service_id = RPMI_DPWR_SRV_GET_DPWR_STATE, + .flags = RPMI_MSG_NORMAL_REQUEST, + .request_data = dpwr_invalid_reqdata, + .request_data_len = sizeof(dpwr_invalid_reqdata), + .expected_data = invalid_param_expdata, + .expected_data_len = sizeof(invalid_param_expdata), + }, + .init_request_data = test_init_request_data_from_attrs, + .init_expected_data = test_init_expected_data_from_attrs, + }, + { + .name = "GET STATE (short request)", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_DEVICE_POWER, + .service_id = RPMI_DPWR_SRV_GET_DPWR_STATE, + .flags = RPMI_MSG_NORMAL_REQUEST, + .expected_data = notsupp_expdata, + .expected_data_len = sizeof(notsupp_expdata), + }, + .init_expected_data = test_init_expected_data_from_attrs, + }, + }, +}; + +int main(int argc, char *argv[]) +{ + printf("Test Device Power Service Group\n"); + return test_scenario_execute(&scenario_dpwr_default); +} diff --git a/test/test_srvgrp_hsm.c b/test/test_srvgrp_hsm.c index 94712f3..629fcc4 100644 --- a/test/test_srvgrp_hsm.c +++ b/test/test_srvgrp_hsm.c @@ -96,6 +96,33 @@ static rpmi_uint32_t get_hart_state_invalid_hartid_expdata[] = { TEST_HART_STATE_IGNORED_VALUE }; +/* Get Suspend Types - Request Data */ +static rpmi_uint32_t get_suspend_types_reqdata[] = { + 0, +}; + +/* Get Suspend Types - Response Data */ +static rpmi_uint32_t get_suspend_types_expdata[] = { + RPMI_SUCCESS, + 0, + 0, +}; + +/* Get Suspend Info invalid type - Request Data */ +static rpmi_uint32_t get_suspend_info_invalid_reqdata[] = { + 0, +}; + +/* Get Suspend Info invalid type - Response Data */ +static rpmi_uint32_t get_suspend_info_invalid_expdata[] = { + RPMI_ERR_INVALID_PARAM, + 0, + 0, + 0, + 0, + 0, +}; + /* Hart Start (valid hartid) - Request Data */ static rpmi_uint32_t hart_start_valid_hartid_reqdata[] = { TEST_HART_ID_VALID, @@ -150,6 +177,19 @@ static rpmi_uint32_t hart_suspend_notsupp_expdata[] = { RPMI_ERR_NOTSUPP, }; +/* Hart Suspend invalid type - Request Data */ +static rpmi_uint32_t hart_suspend_invalid_type_reqdata[] = { + TEST_HART_ID_VALID, + 0, + 0, + 0, +}; + +/* Hart Suspend invalid type - Response Data */ +static rpmi_uint32_t hart_suspend_invalid_type_expdata[] = { + RPMI_ERR_INVALID_PARAM, +}; + /** * Platform Callbacks for Hart State Management */ @@ -253,7 +293,7 @@ static struct rpmi_test_scenario scenario_hsm_default = { .init = test_hsm_scenario_init, .cleanup = test_scenario_default_cleanup, - .num_tests = 10, + .num_tests = 13, .tests = { { .name = "ENABLE NOTIFICATION TEST (notifications not supported)", @@ -325,6 +365,34 @@ static struct rpmi_test_scenario scenario_hsm_default = { .init_request_data = test_init_request_data_from_attrs, .init_expected_data = test_init_expected_data_from_attrs, }, + { + .name = "GET SUSPEND TYPES (none configured)", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_HSM, + .service_id = RPMI_HSM_SRV_GET_SUSPEND_TYPES, + .flags = RPMI_MSG_NORMAL_REQUEST, + .request_data = get_suspend_types_reqdata, + .request_data_len = sizeof(get_suspend_types_reqdata), + .expected_data = get_suspend_types_expdata, + .expected_data_len = sizeof(get_suspend_types_expdata), + }, + .init_request_data = test_init_request_data_from_attrs, + .init_expected_data = test_init_expected_data_from_attrs, + }, + { + .name = "GET SUSPEND INFO (invalid type)", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_HSM, + .service_id = RPMI_HSM_SRV_GET_SUSPEND_INFO, + .flags = RPMI_MSG_NORMAL_REQUEST, + .request_data = get_suspend_info_invalid_reqdata, + .request_data_len = sizeof(get_suspend_info_invalid_reqdata), + .expected_data = get_suspend_info_invalid_expdata, + .expected_data_len = sizeof(get_suspend_info_invalid_expdata), + }, + .init_request_data = test_init_request_data_from_attrs, + .init_expected_data = test_init_expected_data_from_attrs, + }, { .name = "HART START (valid hart id, hart already started)", .attrs = { @@ -381,6 +449,20 @@ static struct rpmi_test_scenario scenario_hsm_default = { .init_request_data = test_init_request_data_from_attrs, .init_expected_data = test_init_expected_data_from_attrs, }, + { + .name = "HART Suspend (invalid type)", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_HSM, + .service_id = RPMI_HSM_SRV_HART_SUSPEND, + .flags = RPMI_MSG_NORMAL_REQUEST, + .request_data = hart_suspend_invalid_type_reqdata, + .request_data_len = sizeof(hart_suspend_invalid_type_reqdata), + .expected_data = hart_suspend_invalid_type_expdata, + .expected_data_len = sizeof(hart_suspend_invalid_type_expdata), + }, + .init_request_data = test_init_request_data_from_attrs, + .init_expected_data = test_init_expected_data_from_attrs, + }, { .name = "HART Suspend (not supported)", .attrs = { diff --git a/test/test_srvgrp_sysmsi.c b/test/test_srvgrp_sysmsi.c new file mode 100644 index 0000000..32b4b6d --- /dev/null +++ b/test/test_srvgrp_sysmsi.c @@ -0,0 +1,294 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2024 Ventana Micro Systems Inc. + */ + +#include +#include +#include "test_common.h" +#include "test_log.h" + +#define TEST_SYSMSI_COUNT 2 +#define TEST_SYSMSI_VALID_INDEX 0 +#define TEST_SYSMSI_INVALID_INDEX TEST_SYSMSI_COUNT +#define TEST_SYSMSI_ADDR_LOW 0x12345000 +#define TEST_SYSMSI_ADDR_HIGH 0x0 +#define TEST_SYSMSI_DATA 0x55aa55aa +#define TEST_SYSMSI_BAD_ADDR_LOW 0xdead0000 +#define TEST_EVENT_ID 0x0 +#define TEST_REQUEST_STATE_ENABLE 0x1 + +static rpmi_uint32_t enable_notif_reqdata[] = { + TEST_EVENT_ID, + TEST_REQUEST_STATE_ENABLE, +}; + +static rpmi_uint32_t enable_notif_expdata[] = { + RPMI_ERR_NOTSUPP, +}; + +static rpmi_uint32_t get_attrs_expdata[] = { + RPMI_SUCCESS, + TEST_SYSMSI_COUNT, + 0, + 0, +}; + +static rpmi_uint32_t get_msi_attrs_reqdata[] = { + TEST_SYSMSI_VALID_INDEX, +}; + +static rpmi_uint32_t get_msi_attrs_expdata[] = { + RPMI_SUCCESS, + RPMI_SYSMSI_MSI_ATTRIBUTES_FLAG0_PREF_PRIV, + 0, + 0, + 0, + 0, + 0, +}; + +static rpmi_uint32_t invalid_msi_reqdata[] = { + TEST_SYSMSI_INVALID_INDEX, +}; + +static rpmi_uint32_t invalid_param_expdata[] = { + RPMI_ERR_INVALID_PARAM, +}; + +static rpmi_uint32_t set_msi_state_reqdata[] = { + TEST_SYSMSI_VALID_INDEX, + RPMI_SYSMSI_MSI_STATE_ENABLE, +}; + +static rpmi_uint32_t success_expdata[] = { + RPMI_SUCCESS, +}; + +static rpmi_uint32_t get_msi_state_reqdata[] = { + TEST_SYSMSI_VALID_INDEX, +}; + +static rpmi_uint32_t get_msi_state_expdata[] = { + RPMI_SUCCESS, + RPMI_SYSMSI_MSI_STATE_ENABLE, +}; + +static rpmi_uint32_t set_msi_target_reqdata[] = { + TEST_SYSMSI_VALID_INDEX, + TEST_SYSMSI_ADDR_LOW, + TEST_SYSMSI_ADDR_HIGH, + TEST_SYSMSI_DATA, +}; + +static rpmi_uint32_t get_msi_target_expdata[] = { + RPMI_SUCCESS, + TEST_SYSMSI_ADDR_LOW, + TEST_SYSMSI_ADDR_HIGH, + TEST_SYSMSI_DATA, +}; + +static rpmi_uint32_t set_msi_bad_target_reqdata[] = { + TEST_SYSMSI_VALID_INDEX, + TEST_SYSMSI_BAD_ADDR_LOW, + 0, + TEST_SYSMSI_DATA, +}; + +static rpmi_uint32_t invalid_addr_expdata[] = { + RPMI_ERR_INVALID_ADDR, +}; + +static rpmi_bool_t test_validate_msi_addr(void *priv, rpmi_uint64_t msi_addr) +{ + return msi_addr == TEST_SYSMSI_ADDR_LOW; +} + +static rpmi_bool_t test_mmode_preferred(void *priv, rpmi_uint32_t msi_index) +{ + return msi_index == TEST_SYSMSI_VALID_INDEX; +} + +static struct rpmi_sysmsi_platform_ops test_sysmsi_ops = { + .validate_msi_addr = test_validate_msi_addr, + .mmode_preferred = test_mmode_preferred, +}; + +static int test_sysmsi_scenario_init(struct rpmi_test_scenario *scene) +{ + struct rpmi_service_group *grp; + int ret; + + ret = test_scenario_default_init(scene); + if (ret) + return RPMI_ERR_FAILED; + + grp = rpmi_service_group_sysmsi_create(TEST_SYSMSI_COUNT, + TEST_SYSMSI_VALID_INDEX, + &test_sysmsi_ops, NULL); + if (!grp) { + printf("failed to create rpmi sysmsi service group"); + return RPMI_ERR_FAILED; + } + + rpmi_context_add_group(scene->cntx, grp); + return 0; +} + +static struct rpmi_test_scenario scenario_sysmsi_default = { + .name = "System MSI Service Group", + .shm_size = RPMI_SHM_SZ, + .slot_size = RPMI_SLOT_SIZE, + .max_num_groups = RPMI_SRVGRP_ID_MAX_COUNT, + .priv = NULL, + + .init = test_sysmsi_scenario_init, + .cleanup = test_scenario_default_cleanup, + + .num_tests = 10, + .tests = { + { + .name = "ENABLE NOTIFICATION TEST (notifications not supported)", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_SYSTEM_MSI, + .service_id = RPMI_SYSMSI_SRV_ENABLE_NOTIFICATION, + .flags = RPMI_MSG_NORMAL_REQUEST, + .request_data = enable_notif_reqdata, + .request_data_len = sizeof(enable_notif_reqdata), + .expected_data = enable_notif_expdata, + .expected_data_len = sizeof(enable_notif_expdata), + }, + .init_request_data = test_init_request_data_from_attrs, + .init_expected_data = test_init_expected_data_from_attrs, + }, + { + .name = "GET ATTRIBUTES", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_SYSTEM_MSI, + .service_id = RPMI_SYSMSI_SRV_GET_ATTRIBUTES, + .flags = RPMI_MSG_NORMAL_REQUEST, + .expected_data = get_attrs_expdata, + .expected_data_len = sizeof(get_attrs_expdata), + }, + .init_expected_data = test_init_expected_data_from_attrs, + }, + { + .name = "GET MSI ATTRIBUTES", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_SYSTEM_MSI, + .service_id = RPMI_SYSMSI_SRV_GET_MSI_ATTRIBUTES, + .flags = RPMI_MSG_NORMAL_REQUEST, + .request_data = get_msi_attrs_reqdata, + .request_data_len = sizeof(get_msi_attrs_reqdata), + .expected_data = get_msi_attrs_expdata, + .expected_data_len = sizeof(get_msi_attrs_expdata), + }, + .init_request_data = test_init_request_data_from_attrs, + .init_expected_data = test_init_expected_data_from_attrs, + }, + { + .name = "GET MSI ATTRIBUTES (invalid index)", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_SYSTEM_MSI, + .service_id = RPMI_SYSMSI_SRV_GET_MSI_ATTRIBUTES, + .flags = RPMI_MSG_NORMAL_REQUEST, + .request_data = invalid_msi_reqdata, + .request_data_len = sizeof(invalid_msi_reqdata), + .expected_data = invalid_param_expdata, + .expected_data_len = sizeof(invalid_param_expdata), + }, + .init_request_data = test_init_request_data_from_attrs, + .init_expected_data = test_init_expected_data_from_attrs, + }, + { + .name = "SET MSI STATE (enable)", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_SYSTEM_MSI, + .service_id = RPMI_SYSMSI_SRV_SET_MSI_STATE, + .flags = RPMI_MSG_NORMAL_REQUEST, + .request_data = set_msi_state_reqdata, + .request_data_len = sizeof(set_msi_state_reqdata), + .expected_data = success_expdata, + .expected_data_len = sizeof(success_expdata), + }, + .init_request_data = test_init_request_data_from_attrs, + .init_expected_data = test_init_expected_data_from_attrs, + }, + { + .name = "GET MSI STATE (enabled)", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_SYSTEM_MSI, + .service_id = RPMI_SYSMSI_SRV_GET_MSI_STATE, + .flags = RPMI_MSG_NORMAL_REQUEST, + .request_data = get_msi_state_reqdata, + .request_data_len = sizeof(get_msi_state_reqdata), + .expected_data = get_msi_state_expdata, + .expected_data_len = sizeof(get_msi_state_expdata), + }, + .init_request_data = test_init_request_data_from_attrs, + .init_expected_data = test_init_expected_data_from_attrs, + }, + { + .name = "GET MSI STATE (invalid index)", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_SYSTEM_MSI, + .service_id = RPMI_SYSMSI_SRV_GET_MSI_STATE, + .flags = RPMI_MSG_NORMAL_REQUEST, + .request_data = invalid_msi_reqdata, + .request_data_len = sizeof(invalid_msi_reqdata), + .expected_data = invalid_param_expdata, + .expected_data_len = sizeof(invalid_param_expdata), + }, + .init_request_data = test_init_request_data_from_attrs, + .init_expected_data = test_init_expected_data_from_attrs, + }, + { + .name = "SET MSI TARGET", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_SYSTEM_MSI, + .service_id = RPMI_SYSMSI_SRV_SET_MSI_TARGET, + .flags = RPMI_MSG_NORMAL_REQUEST, + .request_data = set_msi_target_reqdata, + .request_data_len = sizeof(set_msi_target_reqdata), + .expected_data = success_expdata, + .expected_data_len = sizeof(success_expdata), + }, + .init_request_data = test_init_request_data_from_attrs, + .init_expected_data = test_init_expected_data_from_attrs, + }, + { + .name = "GET MSI TARGET", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_SYSTEM_MSI, + .service_id = RPMI_SYSMSI_SRV_GET_MSI_TARGET, + .flags = RPMI_MSG_NORMAL_REQUEST, + .request_data = get_msi_state_reqdata, + .request_data_len = sizeof(get_msi_state_reqdata), + .expected_data = get_msi_target_expdata, + .expected_data_len = sizeof(get_msi_target_expdata), + }, + .init_request_data = test_init_request_data_from_attrs, + .init_expected_data = test_init_expected_data_from_attrs, + }, + { + .name = "SET MSI TARGET (invalid address)", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_SYSTEM_MSI, + .service_id = RPMI_SYSMSI_SRV_SET_MSI_TARGET, + .flags = RPMI_MSG_NORMAL_REQUEST, + .request_data = set_msi_bad_target_reqdata, + .request_data_len = sizeof(set_msi_bad_target_reqdata), + .expected_data = invalid_addr_expdata, + .expected_data_len = sizeof(invalid_addr_expdata), + }, + .init_request_data = test_init_request_data_from_attrs, + .init_expected_data = test_init_expected_data_from_attrs, + }, + }, +}; + +int main(int argc, char *argv[]) +{ + printf("Test System MSI Service Group\n"); + return test_scenario_execute(&scenario_sysmsi_default); +} diff --git a/test/test_srvgrp_sysreset.c b/test/test_srvgrp_sysreset.c index b870397..9b6cd5d 100644 --- a/test/test_srvgrp_sysreset.c +++ b/test/test_srvgrp_sysreset.c @@ -66,8 +66,24 @@ static rpmi_uint32_t reset_reqdata_supp[] = { RPMI_SYSRST_TYPE_COLD_REBOOT, }; +static rpmi_uint32_t reset_reqdata_shutdown[] = { + RPMI_SYSRST_TYPE_SHUTDOWN, +}; + +static rpmi_uint32_t reset_reqdata_unsupported[] = { + RPMI_SYSRST_TYPE_WARM_REBOOT, +}; + +static rpmi_uint32_t reset_type_cold = RPMI_SYSRST_TYPE_COLD_REBOOT; +static rpmi_uint32_t reset_type_shutdown = RPMI_SYSRST_TYPE_SHUTDOWN; + +static rpmi_uint32_t test_reset_call_count; +static rpmi_uint32_t test_reset_last_type = RPMI_SYSRST_TYPE_MAX; + static void rpmi_do_system_reset(void *priv, rpmi_uint32_t reset_type) { + test_reset_call_count++; + test_reset_last_type = reset_type; if (reset_type == RPMI_SYSRST_TYPE_WARM_REBOOT) { printf("platform callback: warm reset\n"); } else if (reset_type == RPMI_SYSRST_TYPE_COLD_REBOOT) { @@ -85,6 +101,48 @@ struct rpmi_sysreset_platform_ops rpmi_reset_ops = { .do_system_reset = rpmi_do_system_reset }; +static int test_reset_callback_init(struct rpmi_test_scenario *scene, + struct rpmi_test *test) +{ + test_reset_call_count = 0; + test_reset_last_type = RPMI_SYSRST_TYPE_MAX; + return 0; +} + +static int test_reset_callback_verify(struct rpmi_test_scenario *scene, + struct rpmi_test *test, + struct rpmi_message *msg) +{ + rpmi_uint32_t expected_type = *(rpmi_uint32_t *)test->priv; + + if (test_reset_call_count != 1) { + printf("%s: expected one reset callback, got %d\n", + test->name, test_reset_call_count); + return 1; + } + + if (test_reset_last_type != expected_type) { + printf("%s: expected reset type %d, got %d\n", + test->name, expected_type, test_reset_last_type); + return 1; + } + + return 0; +} + +static int test_no_reset_callback_verify(struct rpmi_test_scenario *scene, + struct rpmi_test *test, + struct rpmi_message *msg) +{ + if (test_reset_call_count) { + printf("%s: unexpected reset callback count %d, last type %d\n", + test->name, test_reset_call_count, test_reset_last_type); + return 1; + } + + return 0; +} + static int test_sysreset_scenario_init(struct rpmi_test_scenario *scene) { int ret; @@ -112,7 +170,7 @@ static struct rpmi_test_scenario scenario_sysreset_default = { .init = test_sysreset_scenario_init, .cleanup = test_scenario_default_cleanup, - .num_tests = 5, + .num_tests = 7, .tests = { { .name = "ENABLE NOTIFICATION TEST (notifications not supported)", @@ -180,6 +238,36 @@ static struct rpmi_test_scenario scenario_sysreset_default = { .request_data_len = sizeof(reset_reqdata_supp), }, .init_request_data = test_init_request_data_from_attrs, + .init = test_reset_callback_init, + .verify = test_reset_callback_verify, + .priv = &reset_type_cold, + }, + { + .name = "SYSTEM RESET (shutdown reset type)", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_SYSTEM_RESET, + .service_id = RPMI_SYSRST_SRV_SYSTEM_RESET, + .flags = RPMI_MSG_POSTED_REQUEST, + .request_data = reset_reqdata_shutdown, + .request_data_len = sizeof(reset_reqdata_shutdown), + }, + .init_request_data = test_init_request_data_from_attrs, + .init = test_reset_callback_init, + .verify = test_reset_callback_verify, + .priv = &reset_type_shutdown, + }, + { + .name = "SYSTEM RESET (unsupported reset type)", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_SYSTEM_RESET, + .service_id = RPMI_SYSRST_SRV_SYSTEM_RESET, + .flags = RPMI_MSG_POSTED_REQUEST, + .request_data = reset_reqdata_unsupported, + .request_data_len = sizeof(reset_reqdata_unsupported), + }, + .init_request_data = test_init_request_data_from_attrs, + .init = test_reset_callback_init, + .verify = test_no_reset_callback_verify, }, }, }; diff --git a/test/test_srvgrp_syssusp.c b/test/test_srvgrp_syssusp.c new file mode 100644 index 0000000..0ee3553 --- /dev/null +++ b/test/test_srvgrp_syssusp.c @@ -0,0 +1,299 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2024 Ventana Micro Systems Inc. + */ + +#include +#include +#include "test_common.h" +#include "test_log.h" + +#define TEST_HART_ID 0 +#define TEST_EVENT_ID 0x0 +#define TEST_REQUEST_STATE_ENABLE 0x1 +#define TEST_RESUME_ADDR_LOW 0x80000000 +#define TEST_RESUME_ADDR_HIGH 0x0 + +static rpmi_uint32_t test_hartid_array[] = { + TEST_HART_ID, +}; + +static struct rpmi_system_suspend_type test_syssusp_types[] = { + { + .type = RPMI_SYSSUSP_TYPE_SUSPEND_TO_RAM, + .attr = RPMI_SYSSUSP_ATTRS_FLAGS_RESUMEADDR, + }, +}; + +static rpmi_uint32_t enable_notif_reqdata[] = { + TEST_EVENT_ID, + TEST_REQUEST_STATE_ENABLE, +}; + +static rpmi_uint32_t enable_notif_expdata[] = { + RPMI_ERR_NOTSUPP, +}; + +static rpmi_uint32_t get_attrs_supp_reqdata[] = { + RPMI_SYSSUSP_TYPE_SUSPEND_TO_RAM, +}; + +static rpmi_uint32_t get_attrs_supp_expdata[] = { + RPMI_SUCCESS, + RPMI_SYSSUSP_ATTRS_FLAGS_SUSPENDTYPE | RPMI_SYSSUSP_ATTRS_FLAGS_RESUMEADDR, +}; + +static rpmi_uint32_t get_attrs_notsupp_reqdata[] = { + RPMI_SYSSUSP_TYPE_MAX, +}; + +static rpmi_uint32_t get_attrs_notsupp_expdata[] = { + RPMI_SUCCESS, + 0, +}; + +static rpmi_uint32_t suspend_reqdata[] = { + TEST_HART_ID, + RPMI_SYSSUSP_TYPE_SUSPEND_TO_RAM, + TEST_RESUME_ADDR_LOW, + TEST_RESUME_ADDR_HIGH, +}; + +static rpmi_uint32_t suspend_invalid_type_reqdata[] = { + TEST_HART_ID, + RPMI_SYSSUSP_TYPE_MAX, + TEST_RESUME_ADDR_LOW, + TEST_RESUME_ADDR_HIGH, +}; + +static rpmi_uint32_t success_expdata[] = { + RPMI_SUCCESS, +}; + +static rpmi_uint32_t invalid_param_expdata[] = { + RPMI_ERR_INVALID_PARAM, +}; + +static rpmi_uint32_t prepare_count; +static rpmi_uint32_t finalize_count; +static rpmi_uint32_t resume_count; +static rpmi_uint32_t last_hart_index; +static rpmi_uint32_t last_suspend_type; +static rpmi_uint64_t last_resume_addr; + +static enum rpmi_hart_hw_state test_hart_get_hw_state(void *priv, + rpmi_uint32_t hart_index) +{ + return RPMI_HART_HW_STATE_STARTED; +} + +static struct rpmi_hsm_platform_ops test_hsm_ops = { + .hart_get_hw_state = test_hart_get_hw_state, +}; + +static enum rpmi_error +test_system_suspend_prepare(void *priv, rpmi_uint32_t hart_index, + const struct rpmi_system_suspend_type *syssusp_type, + rpmi_uint64_t resume_addr) +{ + prepare_count++; + last_hart_index = hart_index; + last_suspend_type = syssusp_type->type; + last_resume_addr = resume_addr; + return RPMI_SUCCESS; +} + +static rpmi_bool_t test_system_suspend_ready(void *priv, rpmi_uint32_t hart_index) +{ + return true; +} + +static void test_system_suspend_finalize(void *priv, rpmi_uint32_t hart_index, + const struct rpmi_system_suspend_type *syssusp_type, + rpmi_uint64_t resume_addr) +{ + finalize_count++; + last_hart_index = hart_index; + last_suspend_type = syssusp_type->type; + last_resume_addr = resume_addr; +} + +static rpmi_bool_t test_system_suspend_can_resume(void *priv, rpmi_uint32_t hart_index) +{ + return true; +} + +static enum rpmi_error +test_system_suspend_resume(void *priv, rpmi_uint32_t hart_index, + const struct rpmi_system_suspend_type *syssusp_type, + rpmi_uint64_t resume_addr) +{ + resume_count++; + return RPMI_SUCCESS; +} + +static struct rpmi_syssusp_platform_ops test_syssusp_ops = { + .system_suspend_prepare = test_system_suspend_prepare, + .system_suspend_ready = test_system_suspend_ready, + .system_suspend_finalize = test_system_suspend_finalize, + .system_suspend_can_resume = test_system_suspend_can_resume, + .system_suspend_resume = test_system_suspend_resume, +}; + +static int test_suspend_callback_init(struct rpmi_test_scenario *scene, + struct rpmi_test *test) +{ + prepare_count = 0; + finalize_count = 0; + resume_count = 0; + last_hart_index = -1U; + last_suspend_type = RPMI_SYSSUSP_TYPE_MAX; + last_resume_addr = 0; + return 0; +} + +static int test_suspend_callback_verify(struct rpmi_test_scenario *scene, + struct rpmi_test *test, + struct rpmi_message *msg) +{ + rpmi_uint64_t expected_resume_addr = TEST_RESUME_ADDR_LOW; + + if (prepare_count != 1 || finalize_count != 1) { + printf("%s: expected prepare/finalize once, got %d/%d\n", + test->name, prepare_count, finalize_count); + return 1; + } + + if (last_hart_index != 0 || last_suspend_type != RPMI_SYSSUSP_TYPE_SUSPEND_TO_RAM || + last_resume_addr != expected_resume_addr) { + printf("%s: unexpected callback args hart=%d type=%d resume=0x%lx\n", + test->name, last_hart_index, last_suspend_type, + (unsigned long)last_resume_addr); + return 1; + } + + return 0; +} + +static int test_syssusp_scenario_init(struct rpmi_test_scenario *scene) +{ + struct rpmi_service_group *grp; + struct rpmi_hsm *hsm; + int ret; + + ret = test_scenario_default_init(scene); + if (ret) + return RPMI_ERR_FAILED; + + hsm = rpmi_hsm_create(ARRAY_SIZE(test_hartid_array), + test_hartid_array, 0, NULL, &test_hsm_ops, NULL); + if (!hsm) { + printf("failed to create rpmi hsm"); + return RPMI_ERR_FAILED; + } + + grp = rpmi_service_group_syssusp_create(hsm, + ARRAY_SIZE(test_syssusp_types), + test_syssusp_types, + &test_syssusp_ops, NULL); + if (!grp) { + printf("failed to create rpmi syssusp service group"); + return RPMI_ERR_FAILED; + } + + rpmi_context_add_group(scene->cntx, grp); + return 0; +} + +static struct rpmi_test_scenario scenario_syssusp_default = { + .name = "System Suspend Service Group", + .shm_size = RPMI_SHM_SZ, + .slot_size = RPMI_SLOT_SIZE, + .max_num_groups = RPMI_SRVGRP_ID_MAX_COUNT, + .priv = NULL, + + .init = test_syssusp_scenario_init, + .cleanup = test_scenario_default_cleanup, + + .num_tests = 5, + .tests = { + { + .name = "ENABLE NOTIFICATION TEST (notifications not supported)", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_SYSTEM_SUSPEND, + .service_id = RPMI_SYSSUSP_SRV_ENABLE_NOTIFICATION, + .flags = RPMI_MSG_NORMAL_REQUEST, + .request_data = enable_notif_reqdata, + .request_data_len = sizeof(enable_notif_reqdata), + .expected_data = enable_notif_expdata, + .expected_data_len = sizeof(enable_notif_expdata), + }, + .init_request_data = test_init_request_data_from_attrs, + .init_expected_data = test_init_expected_data_from_attrs, + }, + { + .name = "GET ATTRIBUTES TEST (for supported suspend type)", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_SYSTEM_SUSPEND, + .service_id = RPMI_SYSSUSP_SRV_GET_ATTRIBUTES, + .flags = RPMI_MSG_NORMAL_REQUEST, + .request_data = get_attrs_supp_reqdata, + .request_data_len = sizeof(get_attrs_supp_reqdata), + .expected_data = get_attrs_supp_expdata, + .expected_data_len = sizeof(get_attrs_supp_expdata), + }, + .init_request_data = test_init_request_data_from_attrs, + .init_expected_data = test_init_expected_data_from_attrs, + }, + { + .name = "GET ATTRIBUTES TEST (for unsupported suspend type)", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_SYSTEM_SUSPEND, + .service_id = RPMI_SYSSUSP_SRV_GET_ATTRIBUTES, + .flags = RPMI_MSG_NORMAL_REQUEST, + .request_data = get_attrs_notsupp_reqdata, + .request_data_len = sizeof(get_attrs_notsupp_reqdata), + .expected_data = get_attrs_notsupp_expdata, + .expected_data_len = sizeof(get_attrs_notsupp_expdata), + }, + .init_request_data = test_init_request_data_from_attrs, + .init_expected_data = test_init_expected_data_from_attrs, + }, + { + .name = "SYSTEM SUSPEND (valid suspend type)", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_SYSTEM_SUSPEND, + .service_id = RPMI_SYSSUSP_SRV_SYSTEM_SUSPEND, + .flags = RPMI_MSG_NORMAL_REQUEST, + .request_data = suspend_reqdata, + .request_data_len = sizeof(suspend_reqdata), + .expected_data = success_expdata, + .expected_data_len = sizeof(success_expdata), + }, + .init_request_data = test_init_request_data_from_attrs, + .init_expected_data = test_init_expected_data_from_attrs, + .init = test_suspend_callback_init, + .verify = test_suspend_callback_verify, + }, + { + .name = "SYSTEM SUSPEND (invalid suspend type)", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_SYSTEM_SUSPEND, + .service_id = RPMI_SYSSUSP_SRV_SYSTEM_SUSPEND, + .flags = RPMI_MSG_NORMAL_REQUEST, + .request_data = suspend_invalid_type_reqdata, + .request_data_len = sizeof(suspend_invalid_type_reqdata), + .expected_data = invalid_param_expdata, + .expected_data_len = sizeof(invalid_param_expdata), + }, + .init_request_data = test_init_request_data_from_attrs, + .init_expected_data = test_init_expected_data_from_attrs, + }, + }, +}; + +int main(int argc, char *argv[]) +{ + printf("Test System Suspend Service Group\n"); + return test_scenario_execute(&scenario_syssusp_default); +} diff --git a/test/test_srvgrp_voltage.c b/test/test_srvgrp_voltage.c new file mode 100644 index 0000000..a2f6d1c --- /dev/null +++ b/test/test_srvgrp_voltage.c @@ -0,0 +1,562 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2024 Ventana Micro Systems Inc. + */ + +#include +#include +#include "test_common.h" +#include "test_log.h" + +#define TEST_VOLT_COUNT 2 +#define TEST_VOLT_CPU 0 +#define TEST_VOLT_MEM 1 +#define TEST_VOLT_INVALID TEST_VOLT_COUNT +#define TEST_EVENT_ID 0x0 +#define TEST_REQUEST_STATE_ENABLE 0x1 +#define TEST_VOLT_CPU_LATENCY 10 +#define TEST_VOLT_MEM_LATENCY 20 +#define TEST_VOLT_CPU_INITIAL 800000 +#define TEST_VOLT_CPU_TARGET 1000000 +#define TEST_VOLT_CPU_UNSUPP 1100000 +#define TEST_VOLT_BAD_CONFIG RPMI_VOLT_CONFIG_MAX + +struct test_volt_attrs_expdata { + rpmi_uint32_t status; + rpmi_uint32_t capability; + rpmi_uint32_t num_levels; + rpmi_uint32_t trans_latency; + char name[16]; +}; + +static rpmi_int32_t test_cpu_levels[] = { + 800000, + 900000, + 1000000, +}; + +static rpmi_int32_t test_mem_levels[] = { + 1800000, + 1900000, +}; + +static struct rpmi_voltage_discrete_range test_cpu_range = { + .uvolt = (rpmi_uint32_t *)test_cpu_levels, +}; + +static struct rpmi_voltage_linear_range test_mem_range = { + .uvolt_min = 1800000, + .uvolt_max = 1900000, + .uvolt_step = 100000, +}; + +static struct rpmi_voltage_data test_voltage_data[TEST_VOLT_COUNT] = { + [TEST_VOLT_CPU] = { + .name = "vdd_cpu", + .voltage_type = RPMI_VOLT_TYPE_DISCRETE, + .control = RPMI_VOLT_CAPABILITY_ENABLED_DISABLED, + .config = RPMI_VOLT_CONFIG_DISABLED, + .num_levels = ARRAY_SIZE(test_cpu_levels), + .trans_latency = TEST_VOLT_CPU_LATENCY, + .discrete_range = &test_cpu_range, + .discrete_levels = test_cpu_levels, + .level_uv = TEST_VOLT_CPU_INITIAL, + }, + [TEST_VOLT_MEM] = { + .name = "vdd_mem", + .voltage_type = RPMI_VOLT_TYPE_LINEAR, + .control = RPMI_VOLT_CAPABILITY_ALWAYS_ON, + .config = RPMI_VOLT_CONFIG_NOT_SUPPORTED, + .num_levels = ARRAY_SIZE(test_mem_levels), + .trans_latency = TEST_VOLT_MEM_LATENCY, + .linear_range = &test_mem_range, + .linear_levels = test_mem_levels, + .level_uv = 1800000, + }, +}; + +static rpmi_uint32_t test_current_config[TEST_VOLT_COUNT] = { + RPMI_VOLT_CONFIG_DISABLED, + RPMI_VOLT_CONFIG_NOT_SUPPORTED, +}; + +static rpmi_int32_t test_current_level[TEST_VOLT_COUNT] = { + TEST_VOLT_CPU_INITIAL, + 1800000, +}; + +static rpmi_uint32_t enable_notif_reqdata[] = { + TEST_EVENT_ID, + TEST_REQUEST_STATE_ENABLE, +}; + +static rpmi_uint32_t notsupp_expdata[] = { + RPMI_ERR_NOTSUPP, +}; + +static rpmi_uint32_t get_num_domains_expdata[] = { + RPMI_SUCCESS, + TEST_VOLT_COUNT, +}; + +static rpmi_uint32_t volt_cpu_reqdata[] = { + TEST_VOLT_CPU, +}; + +static rpmi_uint32_t volt_invalid_reqdata[] = { + TEST_VOLT_INVALID, +}; + +static struct test_volt_attrs_expdata get_attrs_cpu_expdata = { + .status = RPMI_SUCCESS, + .capability = RPMI_VOLT_TYPE_DISCRETE | RPMI_VOLT_CAPABILITY_ENABLED_DISABLED, + .num_levels = ARRAY_SIZE(test_cpu_levels), + .trans_latency = TEST_VOLT_CPU_LATENCY, + .name = "vdd_cpu", +}; + +static rpmi_uint32_t invalid_param_expdata[] = { + RPMI_ERR_INVALID_PARAM, +}; + +static rpmi_uint32_t get_cpu_levels_reqdata[] = { + TEST_VOLT_CPU, + 1, +}; + +static rpmi_uint32_t get_cpu_levels_expdata[] = { + RPMI_SUCCESS, + 0, + 0, + 2, + 900000, + 1000000, +}; + +static rpmi_uint32_t get_mem_levels_reqdata[] = { + TEST_VOLT_MEM, + 0, +}; + +static rpmi_uint32_t get_mem_levels_expdata[] = { + RPMI_SUCCESS, + 0, + 0, + 2, + 1800000, + 1900000, +}; + +static rpmi_uint32_t get_invalid_levels_reqdata[] = { + TEST_VOLT_INVALID, + 0, +}; + +static rpmi_uint32_t set_config_enable_reqdata[] = { + TEST_VOLT_CPU, + RPMI_VOLT_CONFIG_ENABLED, +}; + +static rpmi_uint32_t success_expdata[] = { + RPMI_SUCCESS, +}; + +static rpmi_uint32_t get_config_enabled_expdata[] = { + RPMI_SUCCESS, + RPMI_VOLT_CONFIG_ENABLED, +}; + +static rpmi_uint32_t set_config_bad_reqdata[] = { + TEST_VOLT_CPU, + TEST_VOLT_BAD_CONFIG, +}; + +static rpmi_uint32_t set_level_cpu_reqdata[] = { + TEST_VOLT_CPU, + TEST_VOLT_CPU_TARGET, +}; + +static rpmi_uint32_t get_level_cpu_expdata[] = { + RPMI_SUCCESS, + TEST_VOLT_CPU_TARGET, +}; + +static rpmi_uint32_t set_level_unsupported_reqdata[] = { + TEST_VOLT_CPU, + TEST_VOLT_CPU_UNSUPP, +}; + +static enum rpmi_error test_voltage_set_config(void *priv, + rpmi_uint32_t volt_id, + rpmi_uint32_t config) +{ + if (volt_id >= TEST_VOLT_COUNT) + return RPMI_ERR_INVALID_PARAM; + + if (config >= RPMI_VOLT_CONFIG_MAX) + return RPMI_ERR_INVALID_PARAM; + + test_current_config[volt_id] = config; + return RPMI_SUCCESS; +} + +static enum rpmi_error test_voltage_get_config(void *priv, + rpmi_uint32_t volt_id, + rpmi_uint32_t *config) +{ + if (volt_id >= TEST_VOLT_COUNT || !config) + return RPMI_ERR_INVALID_PARAM; + + *config = test_current_config[volt_id]; + return RPMI_SUCCESS; +} + +static rpmi_bool_t test_voltage_level_supported(rpmi_uint32_t volt_id, + rpmi_int32_t level) +{ + rpmi_int32_t *levels; + rpmi_uint32_t i, count; + + if (volt_id >= TEST_VOLT_COUNT) + return false; + + if (volt_id == TEST_VOLT_CPU) { + levels = test_cpu_levels; + count = ARRAY_SIZE(test_cpu_levels); + } else { + levels = test_mem_levels; + count = ARRAY_SIZE(test_mem_levels); + } + + for (i = 0; i < count; i++) { + if (levels[i] == level) + return true; + } + + return false; +} + +static enum rpmi_error test_voltage_set_level(void *priv, + rpmi_uint32_t volt_id, + rpmi_int32_t *volt_level) +{ + if (volt_id >= TEST_VOLT_COUNT || !volt_level) + return RPMI_ERR_INVALID_PARAM; + + if (!test_voltage_level_supported(volt_id, *volt_level)) + return RPMI_ERR_INVALID_PARAM; + + test_current_level[volt_id] = *volt_level; + return RPMI_SUCCESS; +} + +static enum rpmi_error test_voltage_get_level(void *priv, + rpmi_uint32_t volt_id, + rpmi_int32_t *volt_level) +{ + if (volt_id >= TEST_VOLT_COUNT || !volt_level) + return RPMI_ERR_INVALID_PARAM; + + *volt_level = test_current_level[volt_id]; + return RPMI_SUCCESS; +} + +static enum rpmi_error test_voltage_get_supp_levels(void *priv, + rpmi_uint32_t volt_id, + rpmi_uint32_t max, + rpmi_uint32_t volt_index, + rpmi_uint32_t *returned_levels, + rpmi_int32_t *level_array) +{ + rpmi_int32_t *src; + rpmi_uint32_t count, returned, i; + + if (volt_id >= TEST_VOLT_COUNT || !returned_levels || !level_array) + return RPMI_ERR_INVALID_PARAM; + + if (volt_id == TEST_VOLT_CPU) { + src = test_cpu_levels; + count = ARRAY_SIZE(test_cpu_levels); + } else { + src = test_mem_levels; + count = ARRAY_SIZE(test_mem_levels); + } + + if (volt_index >= count) + return RPMI_ERR_INVALID_PARAM; + + returned = count - volt_index; + if (returned > max) + returned = max; + + for (i = 0; i < returned; i++) + level_array[i] = src[volt_index + i]; + + *returned_levels = returned; + return RPMI_SUCCESS; +} + +static struct rpmi_voltage_platform_ops test_voltage_ops = { + .set_config = test_voltage_set_config, + .get_config = test_voltage_get_config, + .set_level = test_voltage_set_level, + .get_level = test_voltage_get_level, + .get_supp_levels = test_voltage_get_supp_levels, +}; + +static int test_voltage_state_init(struct rpmi_test_scenario *scene, + struct rpmi_test *test) +{ + test_current_config[TEST_VOLT_CPU] = RPMI_VOLT_CONFIG_DISABLED; + test_current_config[TEST_VOLT_MEM] = RPMI_VOLT_CONFIG_NOT_SUPPORTED; + test_current_level[TEST_VOLT_CPU] = TEST_VOLT_CPU_INITIAL; + test_current_level[TEST_VOLT_MEM] = test_mem_levels[0]; + return 0; +} + +static int test_voltage_scenario_init(struct rpmi_test_scenario *scene) +{ + struct rpmi_service_group *grp; + int ret; + + ret = test_scenario_default_init(scene); + if (ret) + return RPMI_ERR_FAILED; + + grp = rpmi_service_group_voltage_create(TEST_VOLT_COUNT, + test_voltage_data, + &test_voltage_ops, NULL); + if (!grp) { + printf("failed to create rpmi voltage service group"); + return RPMI_ERR_FAILED; + } + + rpmi_context_add_group(scene->cntx, grp); + return 0; +} + +static struct rpmi_test_scenario scenario_voltage_default = { + .name = "Voltage Service Group", + .shm_size = RPMI_SHM_SZ, + .slot_size = RPMI_SLOT_SIZE, + .max_num_groups = RPMI_SRVGRP_ID_MAX_COUNT, + .priv = NULL, + + .init = test_voltage_scenario_init, + .cleanup = test_scenario_default_cleanup, + + .num_tests = 15, + .tests = { + { + .name = "ENABLE NOTIFICATION TEST (notifications not supported)", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_VOLTAGE, + .service_id = RPMI_VOLT_SRV_ENABLE_NOTIFICATION, + .flags = RPMI_MSG_NORMAL_REQUEST, + .request_data = enable_notif_reqdata, + .request_data_len = sizeof(enable_notif_reqdata), + .expected_data = notsupp_expdata, + .expected_data_len = sizeof(notsupp_expdata), + }, + .init_request_data = test_init_request_data_from_attrs, + .init_expected_data = test_init_expected_data_from_attrs, + }, + { + .name = "GET NUM DOMAINS", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_VOLTAGE, + .service_id = RPMI_VOLT_SRV_GET_NUM_DOMAINS, + .flags = RPMI_MSG_NORMAL_REQUEST, + .expected_data = get_num_domains_expdata, + .expected_data_len = sizeof(get_num_domains_expdata), + }, + .init_expected_data = test_init_expected_data_from_attrs, + }, + { + .name = "GET ATTRIBUTES", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_VOLTAGE, + .service_id = RPMI_VOLT_SRV_GET_ATTRIBUTES, + .flags = RPMI_MSG_NORMAL_REQUEST, + .request_data = volt_cpu_reqdata, + .request_data_len = sizeof(volt_cpu_reqdata), + .expected_data = &get_attrs_cpu_expdata, + .expected_data_len = sizeof(get_attrs_cpu_expdata), + }, + .init_request_data = test_init_request_data_from_attrs, + .init_expected_data = test_init_expected_data_from_attrs, + }, + { + .name = "GET ATTRIBUTES (invalid domain)", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_VOLTAGE, + .service_id = RPMI_VOLT_SRV_GET_ATTRIBUTES, + .flags = RPMI_MSG_NORMAL_REQUEST, + .request_data = volt_invalid_reqdata, + .request_data_len = sizeof(volt_invalid_reqdata), + .expected_data = invalid_param_expdata, + .expected_data_len = sizeof(invalid_param_expdata), + }, + .init_request_data = test_init_request_data_from_attrs, + .init_expected_data = test_init_expected_data_from_attrs, + }, + { + .name = "GET SUPPORTED LEVELS (discrete)", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_VOLTAGE, + .service_id = RPMI_VOLT_SRV_GET_SUPPORTED_LEVELS, + .flags = RPMI_MSG_NORMAL_REQUEST, + .request_data = get_cpu_levels_reqdata, + .request_data_len = sizeof(get_cpu_levels_reqdata), + .expected_data = get_cpu_levels_expdata, + .expected_data_len = sizeof(get_cpu_levels_expdata), + }, + .init_request_data = test_init_request_data_from_attrs, + .init_expected_data = test_init_expected_data_from_attrs, + }, + { + .name = "GET SUPPORTED LEVELS (linear)", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_VOLTAGE, + .service_id = RPMI_VOLT_SRV_GET_SUPPORTED_LEVELS, + .flags = RPMI_MSG_NORMAL_REQUEST, + .request_data = get_mem_levels_reqdata, + .request_data_len = sizeof(get_mem_levels_reqdata), + .expected_data = get_mem_levels_expdata, + .expected_data_len = sizeof(get_mem_levels_expdata), + }, + .init_request_data = test_init_request_data_from_attrs, + .init_expected_data = test_init_expected_data_from_attrs, + }, + { + .name = "GET SUPPORTED LEVELS (invalid domain)", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_VOLTAGE, + .service_id = RPMI_VOLT_SRV_GET_SUPPORTED_LEVELS, + .flags = RPMI_MSG_NORMAL_REQUEST, + .request_data = get_invalid_levels_reqdata, + .request_data_len = sizeof(get_invalid_levels_reqdata), + .expected_data = invalid_param_expdata, + .expected_data_len = sizeof(invalid_param_expdata), + }, + .init_request_data = test_init_request_data_from_attrs, + .init_expected_data = test_init_expected_data_from_attrs, + }, + { + .name = "SET CONFIG (enable)", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_VOLTAGE, + .service_id = RPMI_VOLT_SRV_SET_CONFIG, + .flags = RPMI_MSG_NORMAL_REQUEST, + .request_data = set_config_enable_reqdata, + .request_data_len = sizeof(set_config_enable_reqdata), + .expected_data = success_expdata, + .expected_data_len = sizeof(success_expdata), + }, + .init = test_voltage_state_init, + .init_request_data = test_init_request_data_from_attrs, + .init_expected_data = test_init_expected_data_from_attrs, + }, + { + .name = "GET CONFIG (enabled)", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_VOLTAGE, + .service_id = RPMI_VOLT_SRV_GET_CONFIG, + .flags = RPMI_MSG_NORMAL_REQUEST, + .request_data = volt_cpu_reqdata, + .request_data_len = sizeof(volt_cpu_reqdata), + .expected_data = get_config_enabled_expdata, + .expected_data_len = sizeof(get_config_enabled_expdata), + }, + .init_request_data = test_init_request_data_from_attrs, + .init_expected_data = test_init_expected_data_from_attrs, + }, + { + .name = "GET CONFIG (short request)", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_VOLTAGE, + .service_id = RPMI_VOLT_SRV_GET_CONFIG, + .flags = RPMI_MSG_NORMAL_REQUEST, + .expected_data = notsupp_expdata, + .expected_data_len = sizeof(notsupp_expdata), + }, + .init_expected_data = test_init_expected_data_from_attrs, + }, + { + .name = "SET CONFIG (invalid config)", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_VOLTAGE, + .service_id = RPMI_VOLT_SRV_SET_CONFIG, + .flags = RPMI_MSG_NORMAL_REQUEST, + .request_data = set_config_bad_reqdata, + .request_data_len = sizeof(set_config_bad_reqdata), + .expected_data = invalid_param_expdata, + .expected_data_len = sizeof(invalid_param_expdata), + }, + .init_request_data = test_init_request_data_from_attrs, + .init_expected_data = test_init_expected_data_from_attrs, + }, + { + .name = "SET VOLT LEVEL", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_VOLTAGE, + .service_id = RPMI_VOLT_SRV_SET_VOLT_LEVEL, + .flags = RPMI_MSG_NORMAL_REQUEST, + .request_data = set_level_cpu_reqdata, + .request_data_len = sizeof(set_level_cpu_reqdata), + .expected_data = success_expdata, + .expected_data_len = sizeof(success_expdata), + }, + .init_request_data = test_init_request_data_from_attrs, + .init_expected_data = test_init_expected_data_from_attrs, + }, + { + .name = "GET VOLT LEVEL", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_VOLTAGE, + .service_id = RPMI_VOLT_SRV_GET_VOLT_LEVEL, + .flags = RPMI_MSG_NORMAL_REQUEST, + .request_data = volt_cpu_reqdata, + .request_data_len = sizeof(volt_cpu_reqdata), + .expected_data = get_level_cpu_expdata, + .expected_data_len = sizeof(get_level_cpu_expdata), + }, + .init_request_data = test_init_request_data_from_attrs, + .init_expected_data = test_init_expected_data_from_attrs, + }, + { + .name = "SET VOLT LEVEL (unsupported level)", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_VOLTAGE, + .service_id = RPMI_VOLT_SRV_SET_VOLT_LEVEL, + .flags = RPMI_MSG_NORMAL_REQUEST, + .request_data = set_level_unsupported_reqdata, + .request_data_len = sizeof(set_level_unsupported_reqdata), + .expected_data = invalid_param_expdata, + .expected_data_len = sizeof(invalid_param_expdata), + }, + .init_request_data = test_init_request_data_from_attrs, + .init_expected_data = test_init_expected_data_from_attrs, + }, + { + .name = "GET VOLT LEVEL (invalid domain)", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_VOLTAGE, + .service_id = RPMI_VOLT_SRV_GET_VOLT_LEVEL, + .flags = RPMI_MSG_NORMAL_REQUEST, + .request_data = volt_invalid_reqdata, + .request_data_len = sizeof(volt_invalid_reqdata), + .expected_data = invalid_param_expdata, + .expected_data_len = sizeof(invalid_param_expdata), + }, + .init_request_data = test_init_request_data_from_attrs, + .init_expected_data = test_init_expected_data_from_attrs, + }, + }, +}; + +int main(int argc, char *argv[]) +{ + printf("Test Voltage Service Group\n"); + return test_scenario_execute(&scenario_voltage_default); +}