1 /*
2 * Copyright (c) 2023, Intel Corporation.
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <zephyr/ztest.h>
8 #include <zephyr/ztress.h>
9 #include <zephyr/sip_svc/sip_svc.h>
10 #include <zephyr/drivers/sip_svc/sip_svc_agilex_mailbox.h>
11 #include <zephyr/drivers/sip_svc/sip_svc_agilex_smc.h>
12 #include <zephyr/sys/__assert.h>
13
14 ZTEST_SUITE(sip_svc_tests, NULL, NULL, NULL, NULL, NULL);
15
16 #define SVC_METHOD "smc"
17 #define ECHO_CMD (0x01U)
18 #define TEST_VAL (0xDEADBEEFU)
19
20 #define SIP_SVC_CLIENT_INSTANCES CONFIG_ZTRESS_MAX_THREADS
21
22 struct private_data {
23 uint64_t time_start;
24 uint64_t time_end;
25 struct k_sem semaphore;
26 };
27
28 struct total_time {
29 uint64_t sync_time;
30 uint64_t async_time;
31 };
32
get_sync_callback(uint32_t c_token,struct sip_svc_response * response)33 static void get_sync_callback(uint32_t c_token, struct sip_svc_response *response)
34 {
35 if (response == NULL) {
36 return;
37 }
38
39 struct private_data *priv = (struct private_data *)response->priv_data;
40
41 priv->time_end = k_cycle_get_64();
42 printk("sip_svc version in TFA is %2ld.%02ld\n", response->a2, response->a3);
43
44 k_sem_give(&(priv->semaphore));
45 }
46
47 /**
48 * @brief send SYNC request
49 *
50 * @param token sip_svc token
51 */
sip_svc_send_sync_request(uint32_t token)52 static void sip_svc_send_sync_request(uint32_t token)
53 {
54 int err, trans_id;
55 void *ctrl;
56 uint64_t t = 0;
57 struct total_time *tot_time;
58 struct private_data priv;
59 struct sip_svc_request req = {0};
60
61 ctrl = sip_svc_get_controller(SVC_METHOD);
62 __ASSERT(ctrl != NULL, "couldn't get the controller");
63
64 tot_time = (struct total_time *)sip_svc_get_priv_data(ctrl, token);
65 __ASSERT(tot_time != NULL, "tot_time should not be NULL");
66
67 err = sip_svc_open(ctrl, token, K_FOREVER);
68 __ASSERT(err == 0, "couldn't open channel");
69
70 k_sem_init(&(priv.semaphore), 0, 1);
71
72 req.header = SIP_SVC_PROTO_HEADER(SIP_SVC_PROTO_CMD_SYNC, 0);
73 req.a0 = SMC_FUNC_ID_GET_SVC_VERSION;
74 req.priv_data = (void *)&priv;
75
76 priv.time_start = k_cycle_get_64();
77 trans_id = sip_svc_send(ctrl, token, &req, get_sync_callback);
78 __ASSERT(trans_id >= 0, "error in sending request");
79
80 err = k_sem_take(&(priv.semaphore), K_FOREVER);
81 __ASSERT(err == 0, "Error in taking semaphore");
82
83 t = k_cyc_to_us_ceil64(priv.time_end - priv.time_start);
84 tot_time->sync_time += t;
85
86 printk("In %s got SYNC response for id 0x%02x and time taken is %lldus\n",
87 k_thread_name_get(k_current_get()), trans_id, t);
88
89 err = sip_svc_close(ctrl, token, NULL);
90 __ASSERT(err == 0, "error in closing channel");
91 }
92
get_async_callback(uint32_t c_token,struct sip_svc_response * response)93 static void get_async_callback(uint32_t c_token, struct sip_svc_response *response)
94 {
95 if (response == NULL) {
96 return;
97 }
98
99 struct private_data *priv = (struct private_data *)response->priv_data;
100
101 priv->time_end = k_cycle_get_64();
102 uint32_t *resp_data = (uint32_t *)response->resp_data_addr;
103 uint32_t resp_len = response->resp_data_size / sizeof(uint32_t);
104
105 if (resp_data && resp_len) {
106 __ASSERT((resp_data[1] == TEST_VAL), "SDM response is not matching");
107 }
108
109 k_sem_give(&(priv->semaphore));
110 k_free(resp_data);
111 }
112
113 /**
114 * @brief send ASYNC request
115 *
116 * @param token sip_svc token
117 */
sip_svc_send_async_request(uint32_t token)118 static void sip_svc_send_async_request(uint32_t token)
119 {
120 int err, trans_id;
121 /* size of mailbox command buffer, here we require 2 words */
122 uint32_t cmd_size = (2 * sizeof(uint32_t));
123 /* size of mailbox response buffer, here we require 2 words */
124 uint32_t resp_size = (2 * sizeof(uint32_t));
125 uint64_t t = 0;
126 uint32_t *cmd_addr, *resp_addr;
127 void *ctrl;
128 struct total_time *tot_time;
129 struct private_data priv;
130 struct sip_svc_request req = {0};
131
132 ctrl = sip_svc_get_controller(SVC_METHOD);
133 __ASSERT(ctrl != NULL, "couldn't get the controller");
134
135 err = sip_svc_open(ctrl, token, K_FOREVER);
136 __ASSERT(err == 0, "couldn't open channel");
137
138 tot_time = (struct total_time *)sip_svc_get_priv_data(ctrl, token);
139 __ASSERT(tot_time != NULL, "tot_time should not be NULL");
140
141 resp_addr = (uint32_t *)k_malloc(resp_size);
142 __ASSERT(resp_addr != NULL, "couldn' get memory");
143
144 k_sem_init(&(priv.semaphore), 0, 1);
145
146 cmd_addr = (uint32_t *)k_malloc(cmd_size);
147 __ASSERT(cmd_addr != NULL, "couldn't get memory");
148
149 cmd_addr[0] = (1 << 12) | ECHO_CMD;
150 cmd_addr[1] = 0xDEADBEEF;
151
152 req.header = SIP_SVC_PROTO_HEADER(SIP_SVC_PROTO_CMD_ASYNC, 0);
153 req.a0 = SMC_FUNC_ID_MAILBOX_SEND_COMMAND;
154 req.a2 = (uint64_t)cmd_addr;
155 req.a3 = (uint64_t)cmd_size;
156 req.resp_data_addr = (uint64_t)resp_addr;
157 req.resp_data_size = (uint64_t)resp_size;
158 req.priv_data = (void *)&priv;
159
160 priv.time_start = k_cycle_get_64();
161 trans_id = sip_svc_send(ctrl, token, &req, get_async_callback);
162 __ASSERT(trans_id >= 0, "error in sending request");
163
164 err = k_sem_take(&(priv.semaphore), K_FOREVER);
165 __ASSERT(err == 0, "Error in taking semaphore");
166
167 t = k_cyc_to_us_ceil64(priv.time_end - priv.time_start);
168 tot_time->async_time += t;
169
170 printk("In %s got ASYNC response for id 0x%02x and time taken is %lldus\n",
171 k_thread_name_get(k_current_get()), trans_id, t);
172
173 err = sip_svc_close(ctrl, token, NULL);
174 __ASSERT(err == 0, "error in closing channel");
175 }
176
sip_svc_register_and_send(void * user_data,uint32_t cnt,bool last,int prio)177 static bool sip_svc_register_and_send(void *user_data, uint32_t cnt, bool last, int prio)
178 {
179 int err, token;
180 void *ctrl;
181
182 printk("\nIn %s and count is %d\n", k_thread_name_get(k_current_get()), cnt);
183
184 ctrl = sip_svc_get_controller(SVC_METHOD);
185 if (ctrl == NULL) {
186 return false;
187 }
188
189 token = sip_svc_register(ctrl, user_data);
190 if (token == SIP_SVC_ID_INVALID) {
191 return false;
192 }
193
194 for (uint32_t i = 0; i < CONFIG_PACKETS_PER_ITERATION; i++) {
195 sip_svc_send_sync_request(token);
196 sip_svc_send_async_request(token);
197 }
198
199 err = sip_svc_unregister(ctrl, token);
200 if (err < 0) {
201 return false;
202 }
203
204 return true;
205 }
206
ZTEST(sip_svc_tests,test_sip_stress)207 ZTEST(sip_svc_tests, test_sip_stress)
208 {
209 struct total_time t[SIP_SVC_CLIENT_INSTANCES] = {0};
210 struct total_time average = {0};
211
212 ZTRESS_EXECUTE(ZTRESS_THREAD(sip_svc_register_and_send, &t[0], CONFIG_ITERATIONS, 0,
213 Z_TIMEOUT_TICKS(10)),
214 ZTRESS_THREAD(sip_svc_register_and_send, &t[1], CONFIG_ITERATIONS, 0,
215 Z_TIMEOUT_TICKS(10)),
216 ZTRESS_THREAD(sip_svc_register_and_send, &t[2], CONFIG_ITERATIONS, 0,
217 Z_TIMEOUT_TICKS(10)),
218 ZTRESS_THREAD(sip_svc_register_and_send, &t[3], CONFIG_ITERATIONS, 0,
219 Z_TIMEOUT_TICKS(10)),
220 ZTRESS_THREAD(sip_svc_register_and_send, &t[4], CONFIG_ITERATIONS, 0,
221 Z_TIMEOUT_TICKS(10)),
222 ZTRESS_THREAD(sip_svc_register_and_send, &t[5], CONFIG_ITERATIONS, 0,
223 Z_TIMEOUT_TICKS(10)),
224 ZTRESS_THREAD(sip_svc_register_and_send, &t[6], CONFIG_ITERATIONS, 0,
225 Z_TIMEOUT_TICKS(10)),
226 ZTRESS_THREAD(sip_svc_register_and_send, &t[7], CONFIG_ITERATIONS, 0,
227 Z_TIMEOUT_TICKS(10)),
228 ZTRESS_THREAD(sip_svc_register_and_send, &t[8], CONFIG_ITERATIONS, 0,
229 Z_TIMEOUT_TICKS(10)),
230 ZTRESS_THREAD(sip_svc_register_and_send, &t[9], CONFIG_ITERATIONS, 0,
231 Z_TIMEOUT_TICKS(10)),
232 ZTRESS_THREAD(sip_svc_register_and_send, &t[10], CONFIG_ITERATIONS, 0,
233 Z_TIMEOUT_TICKS(10)),
234 ZTRESS_THREAD(sip_svc_register_and_send, &t[11], CONFIG_ITERATIONS, 0,
235 Z_TIMEOUT_TICKS(10)),
236 ZTRESS_THREAD(sip_svc_register_and_send, &t[12], CONFIG_ITERATIONS, 0,
237 Z_TIMEOUT_TICKS(10)),
238 ZTRESS_THREAD(sip_svc_register_and_send, &t[13], CONFIG_ITERATIONS, 0,
239 Z_TIMEOUT_TICKS(10)),
240 ZTRESS_THREAD(sip_svc_register_and_send, &t[14], CONFIG_ITERATIONS, 0,
241 Z_TIMEOUT_TICKS(10)),
242 ZTRESS_THREAD(sip_svc_register_and_send, &t[15], CONFIG_ITERATIONS, 0,
243 Z_TIMEOUT_TICKS(10)));
244
245 for (uint32_t i = 0; i < SIP_SVC_CLIENT_INSTANCES; i++) {
246 average.sync_time += t[i].sync_time;
247 average.async_time += t[i].async_time;
248 }
249
250 average.sync_time = average.sync_time / (CONFIG_ITERATIONS * CONFIG_PACKETS_PER_ITERATION *
251 SIP_SVC_CLIENT_INSTANCES);
252 average.async_time =
253 average.async_time /
254 (CONFIG_ITERATIONS * CONFIG_PACKETS_PER_ITERATION * SIP_SVC_CLIENT_INSTANCES);
255
256 printk("\n***************************************\n");
257 printk("Average SYNC transaction time is %lldus\n", average.sync_time);
258 printk("Average ASYNC transaction time is %lldus\n", average.async_time);
259 printk("\n***************************************\n");
260 }
261