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