blob: 49efc28028e425797d2091be2729ce3787655feb [file] [log] [blame]
/*
* Copyright (c) 2023, Intel Corporation.
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr/ztest.h>
#include <zephyr/ztress.h>
#include <zephyr/sip_svc/sip_svc.h>
#include <zephyr/drivers/sip_svc/sip_svc_agilex_mailbox.h>
#include <zephyr/drivers/sip_svc/sip_svc_agilex_smc.h>
#include <zephyr/sys/__assert.h>
ZTEST_SUITE(sip_svc_tests, NULL, NULL, NULL, NULL, NULL);
#define SVC_METHOD "smc"
#define ECHO_CMD (0x01U)
#define TEST_VAL (0xDEADBEEFU)
#define SIP_SVC_CLIENT_INSTANCES CONFIG_ZTRESS_MAX_THREADS
struct private_data {
uint64_t time_start;
uint64_t time_end;
struct k_sem semaphore;
};
struct total_time {
uint64_t sync_time;
uint64_t async_time;
};
static void get_sync_callback(uint32_t c_token, struct sip_svc_response *response)
{
if (response == NULL) {
return;
}
struct private_data *priv = (struct private_data *)response->priv_data;
priv->time_end = k_cycle_get_64();
printk("sip_svc version in TFA is %2ld.%02ld\n", response->a2, response->a3);
k_sem_give(&(priv->semaphore));
}
/**
* @brief send SYNC request
*
* @param token sip_svc token
*/
static void sip_svc_send_sync_request(uint32_t token)
{
int err, trans_id;
void *ctrl;
uint64_t t = 0;
struct total_time *tot_time;
struct private_data priv;
struct sip_svc_request req = {0};
ctrl = sip_svc_get_controller(SVC_METHOD);
__ASSERT(ctrl != NULL, "couldn't get the controller");
tot_time = (struct total_time *)sip_svc_get_priv_data(ctrl, token);
__ASSERT(tot_time != NULL, "tot_time should not be NULL");
err = sip_svc_open(ctrl, token, K_FOREVER);
__ASSERT(err == 0, "couldn't open channel");
k_sem_init(&(priv.semaphore), 0, 1);
req.header = SIP_SVC_PROTO_HEADER(SIP_SVC_PROTO_CMD_SYNC, 0);
req.a0 = SMC_FUNC_ID_GET_SVC_VERSION;
req.priv_data = (void *)&priv;
priv.time_start = k_cycle_get_64();
trans_id = sip_svc_send(ctrl, token, &req, get_sync_callback);
__ASSERT(trans_id >= 0, "error in sending request");
err = k_sem_take(&(priv.semaphore), K_FOREVER);
__ASSERT(err == 0, "Error in taking semaphore");
t = k_cyc_to_us_ceil64(priv.time_end - priv.time_start);
tot_time->sync_time += t;
printk("In %s got SYNC response for id 0x%02x and time taken is %lldus\n",
k_thread_name_get(k_current_get()), trans_id, t);
err = sip_svc_close(ctrl, token, NULL);
__ASSERT(err == 0, "error in closing channel");
}
static void get_async_callback(uint32_t c_token, struct sip_svc_response *response)
{
if (response == NULL) {
return;
}
struct private_data *priv = (struct private_data *)response->priv_data;
priv->time_end = k_cycle_get_64();
uint32_t *resp_data = (uint32_t *)response->resp_data_addr;
uint32_t resp_len = response->resp_data_size / sizeof(uint32_t);
if (resp_data && resp_len) {
__ASSERT((resp_data[1] == TEST_VAL), "SDM response is not matching");
}
k_sem_give(&(priv->semaphore));
k_free(resp_data);
}
/**
* @brief send ASYNC request
*
* @param token sip_svc token
*/
static void sip_svc_send_async_request(uint32_t token)
{
int err, trans_id;
/* size of mailbox command buffer, here we require 2 words */
uint32_t cmd_size = (2 * sizeof(uint32_t));
/* size of mailbox response buffer, here we require 2 words */
uint32_t resp_size = (2 * sizeof(uint32_t));
uint64_t t = 0;
uint32_t *cmd_addr, *resp_addr;
void *ctrl;
struct total_time *tot_time;
struct private_data priv;
struct sip_svc_request req = {0};
ctrl = sip_svc_get_controller(SVC_METHOD);
__ASSERT(ctrl != NULL, "couldn't get the controller");
err = sip_svc_open(ctrl, token, K_FOREVER);
__ASSERT(err == 0, "couldn't open channel");
tot_time = (struct total_time *)sip_svc_get_priv_data(ctrl, token);
__ASSERT(tot_time != NULL, "tot_time should not be NULL");
resp_addr = (uint32_t *)k_malloc(resp_size);
__ASSERT(resp_addr != NULL, "couldn' get memory");
k_sem_init(&(priv.semaphore), 0, 1);
cmd_addr = (uint32_t *)k_malloc(cmd_size);
__ASSERT(cmd_addr != NULL, "couldn't get memory");
cmd_addr[0] = (1 << 12) | ECHO_CMD;
cmd_addr[1] = 0xDEADBEEF;
req.header = SIP_SVC_PROTO_HEADER(SIP_SVC_PROTO_CMD_ASYNC, 0);
req.a0 = SMC_FUNC_ID_MAILBOX_SEND_COMMAND;
req.a2 = (uint64_t)cmd_addr;
req.a3 = (uint64_t)cmd_size;
req.resp_data_addr = (uint64_t)resp_addr;
req.resp_data_size = (uint64_t)resp_size;
req.priv_data = (void *)&priv;
priv.time_start = k_cycle_get_64();
trans_id = sip_svc_send(ctrl, token, &req, get_async_callback);
__ASSERT(trans_id >= 0, "error in sending request");
err = k_sem_take(&(priv.semaphore), K_FOREVER);
__ASSERT(err == 0, "Error in taking semaphore");
t = k_cyc_to_us_ceil64(priv.time_end - priv.time_start);
tot_time->async_time += t;
printk("In %s got ASYNC response for id 0x%02x and time taken is %lldus\n",
k_thread_name_get(k_current_get()), trans_id, t);
err = sip_svc_close(ctrl, token, NULL);
__ASSERT(err == 0, "error in closing channel");
}
static bool sip_svc_register_and_send(void *user_data, uint32_t cnt, bool last, int prio)
{
int err, token;
void *ctrl;
printk("\nIn %s and count is %d\n", k_thread_name_get(k_current_get()), cnt);
ctrl = sip_svc_get_controller(SVC_METHOD);
if (ctrl == NULL) {
return false;
}
token = sip_svc_register(ctrl, user_data);
if (token == SIP_SVC_ID_INVALID) {
return false;
}
for (uint32_t i = 0; i < CONFIG_PACKETS_PER_ITERATION; i++) {
sip_svc_send_sync_request(token);
sip_svc_send_async_request(token);
}
err = sip_svc_unregister(ctrl, token);
if (err < 0) {
return false;
}
return true;
}
ZTEST(sip_svc_tests, test_sip_stress)
{
struct total_time t[SIP_SVC_CLIENT_INSTANCES] = {0};
struct total_time average = {0};
ZTRESS_EXECUTE(ZTRESS_THREAD(sip_svc_register_and_send, &t[0], CONFIG_ITERATIONS, 0,
Z_TIMEOUT_TICKS(10)),
ZTRESS_THREAD(sip_svc_register_and_send, &t[1], CONFIG_ITERATIONS, 0,
Z_TIMEOUT_TICKS(10)),
ZTRESS_THREAD(sip_svc_register_and_send, &t[2], CONFIG_ITERATIONS, 0,
Z_TIMEOUT_TICKS(10)),
ZTRESS_THREAD(sip_svc_register_and_send, &t[3], CONFIG_ITERATIONS, 0,
Z_TIMEOUT_TICKS(10)),
ZTRESS_THREAD(sip_svc_register_and_send, &t[4], CONFIG_ITERATIONS, 0,
Z_TIMEOUT_TICKS(10)),
ZTRESS_THREAD(sip_svc_register_and_send, &t[5], CONFIG_ITERATIONS, 0,
Z_TIMEOUT_TICKS(10)),
ZTRESS_THREAD(sip_svc_register_and_send, &t[6], CONFIG_ITERATIONS, 0,
Z_TIMEOUT_TICKS(10)),
ZTRESS_THREAD(sip_svc_register_and_send, &t[7], CONFIG_ITERATIONS, 0,
Z_TIMEOUT_TICKS(10)),
ZTRESS_THREAD(sip_svc_register_and_send, &t[8], CONFIG_ITERATIONS, 0,
Z_TIMEOUT_TICKS(10)),
ZTRESS_THREAD(sip_svc_register_and_send, &t[9], CONFIG_ITERATIONS, 0,
Z_TIMEOUT_TICKS(10)),
ZTRESS_THREAD(sip_svc_register_and_send, &t[10], CONFIG_ITERATIONS, 0,
Z_TIMEOUT_TICKS(10)),
ZTRESS_THREAD(sip_svc_register_and_send, &t[11], CONFIG_ITERATIONS, 0,
Z_TIMEOUT_TICKS(10)),
ZTRESS_THREAD(sip_svc_register_and_send, &t[12], CONFIG_ITERATIONS, 0,
Z_TIMEOUT_TICKS(10)),
ZTRESS_THREAD(sip_svc_register_and_send, &t[13], CONFIG_ITERATIONS, 0,
Z_TIMEOUT_TICKS(10)),
ZTRESS_THREAD(sip_svc_register_and_send, &t[14], CONFIG_ITERATIONS, 0,
Z_TIMEOUT_TICKS(10)),
ZTRESS_THREAD(sip_svc_register_and_send, &t[15], CONFIG_ITERATIONS, 0,
Z_TIMEOUT_TICKS(10)));
for (uint32_t i = 0; i < SIP_SVC_CLIENT_INSTANCES; i++) {
average.sync_time += t[i].sync_time;
average.async_time += t[i].async_time;
}
average.sync_time = average.sync_time / (CONFIG_ITERATIONS * CONFIG_PACKETS_PER_ITERATION *
SIP_SVC_CLIENT_INSTANCES);
average.async_time =
average.async_time /
(CONFIG_ITERATIONS * CONFIG_PACKETS_PER_ITERATION * SIP_SVC_CLIENT_INSTANCES);
printk("\n***************************************\n");
printk("Average SYNC transaction time is %lldus\n", average.sync_time);
printk("Average ASYNC transaction time is %lldus\n", average.async_time);
printk("\n***************************************\n");
}