1 /*
2  * Copyright (c) 2022-2023, Intel Corporation.
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * ARM SiP services implementation.
7  *
8  *
9  * ********
10  * Overview
11  * ********
12  *
13  * Typical flow
14  *   (1) register a client, service returns a token
15  *   (2) client opens a channel, (optionally only allow one channel at one time)
16  *   (3) client send request with callback, service returns transaction id
17  *   (5) service callback once the transaction complete
18  *   (6) client close channel after receive callback
19  *   (7) ... repeats (2) to (7) to send more request
20  *   (8) unregister the client
21  *
22  * Abort opened channel
23  *   (1) for some reasons, client want to terminate the operation
24  *       on the opened channel. client may close the channel
25  *       without waiting for all transaction being completed
26  *   (2) service will proceed to close the channel and set the client
27  *       at ABORT state. The client will be not allowed to reopen
28  *       the channel until service complete all its associated transactions
29  *       and bring the client back to IDLE state.
30  *
31  * callback implementation requirement
32  *   (1) the callback is provided by client, it will be called and executed
33  *       in sip_svc thread once transaction is completed.
34  *   (2) callback is requested to do the following:
35  *       - if the client is running with a thread, callback should ensure
36  *         the thread is still alive before handle the response
37  *       - response data pointer is not retained after the callback function.
38  *         thus, the callback should copy the response data when needed.
39  *       - callback responsible to free the asynchronous response data memory
40  *         space
41  *
42  *
43  * ***************************************
44  * sip_svc service and client overview
45  * ***************************************
46  * ------------------------------------------------------
47  *                 Client1     Client2     Client3 ...
48  * Support            |           *           |
49  * multiple           |           * open      |
50  * clients            |           * channel   |
51  *                    |           *           |
52  * ------------------------------------------------------
53  * sip_svc
54  * service
55  * Thread
56  *                ----------
57  *                | Create | when receive first request
58  *                ----------
59  *                     |
60  *                     | Run
61  *                     |
62  *                -------------------
63  *            --> | Request handler | Process the request, perform smc/hvc
64  *            |   -------------------
65  *            |        |
66  *    Resume  |        |
67  *    when    |        |
68  *    receive |   --------------------------
69  *    new     |   | Async response handler | Poll response of async request
70  *    request |   -------------------------- perform smc/hvc
71  *            |        |
72  *            |        | Suspend when all transactions
73  *            |        | completed without new request
74  *            |        |
75  *            |   ------------------
76  *            --- | Suspend Thread |
77  *                ------------------
78  * ------------------------------------------------------
79  *
80  * ***************************************
81  * sip_svc service ID management
82  * ***************************************
83  * ------------------------------------------------------
84  * client         Client                    Client
85  *                   |                         |
86  *                   | Register                | Send
87  *                   |                         | Request
88  *                   V                         V
89  * ------------------------------------------------------
90  * sip_svc            ^                        ^
91  * service            | Client Token           | Transaction ID
92  *                    |                        |
93  *          ---------------------   -----------------------
94  *          |  Alloc an client  |   | Alloc a Transaction |
95  *          |  placeholder and  |   | ID for the request  |
96  *          | generate a unique |   -----------------------
97  *          |   token for it    |              |
98  *          ---------------------              |
99  *                                             |
100  *                                             | Transaction ID
101  *                                             V
102  * ------------------------------------------------------
103  * EL2/EL3                                      ^
104  * firmware                                     |
105  *                                   Return same Transaction ID
106  * ------------------------------------------------------
107  *
108  */
109 
110 #include <zephyr/sip_svc/sip_svc.h>
111 #include <zephyr/sip_svc/sip_svc_controller.h>
112 #include <zephyr/drivers/sip_svc/sip_svc_driver.h>
113 #include <zephyr/sys/iterable_sections.h>
114 #include "sip_svc_id_mgr.h"
115 #include <string.h>
116 
117 #include <zephyr/logging/log.h>
118 LOG_MODULE_REGISTER(sip_svc_subsys, CONFIG_ARM_SIP_SVC_SUBSYS_LOG_LEVEL);
119 
sip_svc_generate_c_token(void)120 static uint32_t sip_svc_generate_c_token(void)
121 {
122 	uint32_t c_token = k_cycle_get_32();
123 	return c_token;
124 }
125 
is_sip_svc_controller(void * ct)126 static inline bool is_sip_svc_controller(void *ct)
127 {
128 	if (ct == NULL) {
129 		return false;
130 	}
131 
132 	STRUCT_SECTION_FOREACH(sip_svc_controller, ctrl) {
133 		if ((void *)ctrl == ct) {
134 			return true;
135 		}
136 	}
137 	return false;
138 }
139 
sip_svc_get_c_idx(struct sip_svc_controller * ctrl,uint32_t c_token)140 static uint32_t sip_svc_get_c_idx(struct sip_svc_controller *ctrl, uint32_t c_token)
141 {
142 	uint32_t i;
143 
144 	if (!ctrl) {
145 		return SIP_SVC_ID_INVALID;
146 	}
147 
148 	for (i = 0; i < ctrl->num_clients; i++) {
149 		if (ctrl->clients[i].token == c_token) {
150 			return i;
151 		}
152 	}
153 
154 	return SIP_SVC_ID_INVALID;
155 }
156 
sip_svc_register(void * ct,void * priv_data)157 uint32_t sip_svc_register(void *ct, void *priv_data)
158 {
159 	int err;
160 	uint32_t c_idx = SIP_SVC_ID_INVALID;
161 
162 	if (ct == NULL || !is_sip_svc_controller(ct)) {
163 		return SIP_SVC_ID_INVALID;
164 	}
165 
166 	struct sip_svc_controller *ctrl = (struct sip_svc_controller *)ct;
167 
168 	err = k_mutex_lock(&ctrl->data_mutex, K_FOREVER);
169 	if (err != 0) {
170 		LOG_ERR("Error in acquiring mutex %d", err);
171 		return SIP_SVC_ID_INVALID;
172 	}
173 
174 	c_idx = sip_svc_id_mgr_alloc(ctrl->client_id_pool);
175 	if (c_idx != SIP_SVC_ID_INVALID) {
176 		ctrl->clients[c_idx].id = c_idx;
177 		ctrl->clients[c_idx].token = sip_svc_generate_c_token();
178 		ctrl->clients[c_idx].state = SIP_SVC_CLIENT_ST_IDLE;
179 		ctrl->clients[c_idx].priv_data = priv_data;
180 		k_mutex_unlock(&ctrl->data_mutex);
181 		LOG_INF("Register the client channel 0x%x", ctrl->clients[c_idx].token);
182 		return ctrl->clients[c_idx].token;
183 	}
184 
185 	k_mutex_unlock(&ctrl->data_mutex);
186 	return SIP_SVC_ID_INVALID;
187 }
188 
sip_svc_unregister(void * ct,uint32_t c_token)189 int sip_svc_unregister(void *ct, uint32_t c_token)
190 {
191 	int err;
192 	uint32_t c_idx;
193 
194 	if (ct == NULL || !is_sip_svc_controller(ct)) {
195 		return -EINVAL;
196 	}
197 
198 	struct sip_svc_controller *ctrl = (struct sip_svc_controller *)ct;
199 
200 	err = k_mutex_lock(&ctrl->data_mutex, K_FOREVER);
201 	if (err != 0) {
202 		LOG_ERR("Error in acquiring mutex %d", err);
203 		return -ENOLCK;
204 	}
205 
206 	c_idx = sip_svc_get_c_idx(ctrl, c_token);
207 	if (c_idx == SIP_SVC_ID_INVALID) {
208 		k_mutex_unlock(&ctrl->data_mutex);
209 		return -EINVAL;
210 	}
211 
212 	if (ctrl->clients[c_idx].id == SIP_SVC_ID_INVALID) {
213 		k_mutex_unlock(&ctrl->data_mutex);
214 		return -ENODATA;
215 	}
216 
217 	if (ctrl->clients[c_idx].active_trans_cnt != 0) {
218 		k_mutex_unlock(&ctrl->data_mutex);
219 		return -EBUSY;
220 	}
221 
222 	if (ctrl->clients[c_idx].state != SIP_SVC_CLIENT_ST_IDLE) {
223 		k_mutex_unlock(&ctrl->data_mutex);
224 		return -ECANCELED;
225 	}
226 
227 	LOG_INF("Unregister the client channel 0x%x", ctrl->clients[c_idx].token);
228 	ctrl->clients[c_idx].id = SIP_SVC_ID_INVALID;
229 	ctrl->clients[c_idx].state = SIP_SVC_CLIENT_ST_INVALID;
230 	ctrl->clients[c_idx].token = SIP_SVC_ID_INVALID;
231 	ctrl->clients[c_idx].priv_data = NULL;
232 	sip_svc_id_mgr_free(ctrl->client_id_pool, c_idx);
233 
234 	k_mutex_unlock(&ctrl->data_mutex);
235 	return 0;
236 }
237 
get_timer_status(bool * first_iteration,struct k_timer * timer,k_timeout_t duration)238 static bool get_timer_status(bool *first_iteration, struct k_timer *timer, k_timeout_t duration)
239 {
240 	if (first_iteration == NULL || timer == NULL) {
241 		return false;
242 	}
243 
244 	if (!(*first_iteration)) {
245 		/* start the timer using the timeout variable provided and return true*/
246 		k_timer_start(timer, duration, K_NO_WAIT);
247 		*first_iteration = true;
248 		return true;
249 	} else if (K_TIMEOUT_EQ(duration, K_NO_WAIT)) {
250 		/* here we will be at second iteration if duration is K_NO_WAIT, return false */
251 		return false;
252 	} else if (K_TIMEOUT_EQ(duration, K_FOREVER)) {
253 		/* k_timer won't start for K_FOREVER, so return true*/
254 		return true;
255 	} else if (k_timer_remaining_get(timer) > 0) {
256 		/* return true if timer has not expired */
257 		return true;
258 	}
259 
260 	return false;
261 }
262 
sip_svc_open(void * ct,uint32_t c_token,k_timeout_t k_timeout)263 int sip_svc_open(void *ct, uint32_t c_token, k_timeout_t k_timeout)
264 {
265 
266 	uint32_t c_idx;
267 	int ret;
268 	struct k_timer timer;
269 
270 	if (ct == NULL || !is_sip_svc_controller(ct)) {
271 		return -EINVAL;
272 	}
273 
274 	struct sip_svc_controller *ctrl = (struct sip_svc_controller *)ct;
275 
276 	/* Initialize the timer */
277 	k_timer_init(&timer, NULL, NULL);
278 
279 	/**
280 	 * Run through the loop until the client is in IDLE state.
281 	 * Then move the client state to open. If the client has any pending transactions,
282 	 * the client state will be ABORT state.This will only change when the pending
283 	 * transactions are complete.
284 	 */
285 	for (bool first_iteration = false; get_timer_status(&first_iteration, &timer, k_timeout);
286 	     k_usleep(CONFIG_ARM_SIP_SVC_SUBSYS_ASYNC_POLLING_DELAY)) {
287 
288 		ret = k_mutex_lock(&ctrl->data_mutex, K_NO_WAIT);
289 		if (ret != 0) {
290 			LOG_WRN("0x%x didn't get data lock", c_token);
291 			continue;
292 		}
293 
294 		c_idx = sip_svc_get_c_idx(ctrl, c_token);
295 		if (c_idx == SIP_SVC_ID_INVALID) {
296 			LOG_ERR("Invalid client token");
297 			k_mutex_unlock(&ctrl->data_mutex);
298 			k_timer_stop(&timer);
299 			return -EINVAL;
300 		}
301 
302 		/* Check if the state of client is already open state*/
303 		if (ctrl->clients[c_idx].state == SIP_SVC_CLIENT_ST_OPEN) {
304 			LOG_DBG("client with token 0x%x is already open", c_token);
305 			k_mutex_unlock(&ctrl->data_mutex);
306 			k_timer_stop(&timer);
307 			return -EALREADY;
308 		}
309 
310 		/* Check if the state of client is in idle state*/
311 		if (ctrl->clients[c_idx].state != SIP_SVC_CLIENT_ST_IDLE) {
312 			LOG_DBG("client with token 0x%x is not idle", c_token);
313 			k_mutex_unlock(&ctrl->data_mutex);
314 			continue;
315 		}
316 
317 #if CONFIG_ARM_SIP_SVC_SUBSYS_SINGLY_OPEN
318 		/**
319 		 * Acquire open lock, when only one client can transact at
320 		 * a time.
321 		 */
322 		if (!atomic_cas(&ctrl->open_lock, SIP_SVC_OPEN_UNLOCKED, SIP_SVC_OPEN_LOCKED)) {
323 			LOG_DBG("0x%x didn't get open lock, wait for it to be released", c_token);
324 			k_mutex_unlock(&ctrl->data_mutex);
325 			continue;
326 		}
327 #endif
328 
329 		/* Make the client state to be open and stop timer*/
330 		ctrl->clients[c_idx].state = SIP_SVC_CLIENT_ST_OPEN;
331 		LOG_INF("0x%x successfully opened a connection with sip_svc", c_token);
332 		k_mutex_unlock(&ctrl->data_mutex);
333 		k_timer_stop(&timer);
334 		return 0;
335 	}
336 
337 	k_timer_stop(&timer);
338 	LOG_ERR("Timedout at %s for 0x%x", __func__, c_token);
339 	return -ETIMEDOUT;
340 }
341 
sip_svc_close(void * ct,uint32_t c_token,struct sip_svc_request * pre_close_req)342 int sip_svc_close(void *ct, uint32_t c_token, struct sip_svc_request *pre_close_req)
343 {
344 	uint32_t c_idx;
345 	int err;
346 
347 	if (ct == NULL || !is_sip_svc_controller(ct)) {
348 		return -EINVAL;
349 	}
350 
351 	struct sip_svc_controller *ctrl = (struct sip_svc_controller *)ct;
352 
353 	/*If pre-close request is provided, send it to lower layers*/
354 	if (pre_close_req != NULL) {
355 		err = sip_svc_send(ct, c_token, pre_close_req, NULL);
356 		if (err < 0) {
357 			LOG_ERR("Error sending pre_close_req : %d", err);
358 			return -ENOTSUP;
359 		}
360 	}
361 
362 	err = k_mutex_lock(&ctrl->data_mutex, K_FOREVER);
363 	if (err != 0) {
364 		LOG_ERR("Error in acquiring lock %d", err);
365 		return err;
366 	}
367 
368 	c_idx = sip_svc_get_c_idx(ctrl, c_token);
369 	if (c_idx == SIP_SVC_ID_INVALID) {
370 		k_mutex_unlock(&ctrl->data_mutex);
371 		return -EINVAL;
372 	}
373 
374 	if (ctrl->clients[c_idx].state != SIP_SVC_CLIENT_ST_OPEN) {
375 		LOG_ERR("Client is in wrong state  %d", ctrl->clients[c_idx].state);
376 		k_mutex_unlock(&ctrl->data_mutex);
377 		return -EPROTO;
378 	}
379 
380 	if (ctrl->clients[c_idx].active_trans_cnt != 0) {
381 		ctrl->clients[c_idx].state = SIP_SVC_CLIENT_ST_ABORT;
382 	} else {
383 		ctrl->clients[c_idx].state = SIP_SVC_CLIENT_ST_IDLE;
384 	}
385 
386 #if CONFIG_ARM_SIP_SVC_SUBSYS_SINGLY_OPEN
387 	(void)atomic_set(&ctrl->open_lock, SIP_SVC_OPEN_UNLOCKED);
388 #endif
389 	k_mutex_unlock(&ctrl->data_mutex);
390 
391 	LOG_INF("Close the client channel 0x%x", ctrl->clients[c_idx].token);
392 	return 0;
393 }
394 
sip_svc_callback(struct sip_svc_controller * ctrl,uint32_t trans_id,struct sip_svc_response * response)395 static void sip_svc_callback(struct sip_svc_controller *ctrl, uint32_t trans_id,
396 			     struct sip_svc_response *response)
397 {
398 	struct sip_svc_id_map_item *trans_id_item;
399 	uint64_t data_addr;
400 	uint64_t c_idx;
401 	int err;
402 
403 	if (!ctrl) {
404 		return;
405 	}
406 
407 	LOG_INF("Got response for trans id 0x%x", trans_id);
408 
409 	err = k_mutex_lock(&ctrl->data_mutex, K_FOREVER);
410 	if (err != 0) {
411 		LOG_ERR("Failed to get lock,%d", err);
412 		return;
413 	}
414 
415 	/* Get trans id callback context from map */
416 	trans_id_item = sip_svc_id_map_query_item(ctrl->trans_id_map, trans_id);
417 
418 	if (!trans_id_item) {
419 		LOG_ERR("Failed to get the entry from database");
420 		k_mutex_unlock(&ctrl->data_mutex);
421 		return;
422 	}
423 
424 	c_idx = (uint64_t)trans_id_item->arg6;
425 	__ASSERT(c_idx < ctrl->num_clients, "c_idx shouldn't be greater than ctrl->num_clients");
426 
427 	__ASSERT(ctrl->clients[c_idx].active_trans_cnt != 0,
428 		 "At this stage active_trans_cnt shouldn't be 0");
429 	--ctrl->clients[c_idx].active_trans_cnt;
430 
431 	if (ctrl->clients[c_idx].state == SIP_SVC_CLIENT_ST_OPEN && trans_id_item->arg1) {
432 
433 		((sip_svc_cb_fn)(trans_id_item->arg1))(ctrl->clients[c_idx].token, response);
434 	} else {
435 		LOG_INF("Resp data is released as the client channel is closed");
436 		/* Free response memory space if callback is skipped.*/
437 		data_addr =
438 			(((uint64_t)trans_id_item->arg2) << 32) | ((uint64_t)trans_id_item->arg3);
439 
440 		if (data_addr) {
441 			k_free((char *)data_addr);
442 		}
443 	}
444 
445 	/* Free trans id */
446 	sip_svc_id_map_remove_item(ctrl->trans_id_map, trans_id);
447 	sip_svc_id_mgr_free(ctrl->clients[c_idx].trans_idx_pool,
448 			    sip_svc_plat_get_trans_idx(ctrl->dev, trans_id));
449 
450 	if (ctrl->clients[c_idx].active_trans_cnt != 0) {
451 		k_mutex_unlock(&ctrl->data_mutex);
452 		return;
453 	}
454 
455 	if (ctrl->clients[c_idx].state == SIP_SVC_CLIENT_ST_ABORT) {
456 		ctrl->clients[c_idx].state = SIP_SVC_CLIENT_ST_IDLE;
457 	}
458 
459 	k_mutex_unlock(&ctrl->data_mutex);
460 }
461 
sip_svc_request_handler(struct sip_svc_controller * ctrl)462 static int sip_svc_request_handler(struct sip_svc_controller *ctrl)
463 {
464 	struct arm_smccc_res res;
465 	struct sip_svc_request request;
466 	struct sip_svc_response response;
467 	uint32_t trans_id;
468 	uint32_t cmd_code;
469 	uint32_t error_code;
470 
471 	if (!ctrl) {
472 		LOG_ERR("Error ctrl is NULL");
473 		return -EINVAL;
474 	}
475 
476 	/**
477 	 * If transaction's are more than ctrl->max_transactions,
478 	 * return -EBUSY.
479 	 */
480 	if (ctrl->active_job_cnt >= ctrl->max_transactions) {
481 		return -EBUSY;
482 	}
483 
484 	if (k_msgq_num_used_get(&ctrl->req_msgq) == 0) {
485 		return 0;
486 	}
487 
488 	if (k_msgq_get(&ctrl->req_msgq, &request, K_NO_WAIT) != 0) {
489 		return -EAGAIN;
490 	}
491 
492 	/* Get command code from request header */
493 	cmd_code = SIP_SVC_PROTO_HEADER_GET_CODE(request.header);
494 
495 	/* Get trans_id from request header */
496 	trans_id = SIP_SVC_PROTO_HEADER_GET_TRANS_ID(request.header);
497 
498 	/* Process the request, trigger smc/hvc call */
499 	if (cmd_code == SIP_SVC_PROTO_CMD_ASYNC) {
500 		sip_svc_plat_update_trans_id(ctrl->dev, &request, trans_id);
501 	}
502 
503 	/* Increase active job count. Job means communication with
504 	 * secure monitor firmware
505 	 */
506 	++ctrl->active_job_cnt;
507 
508 	/* Trigger smc call */
509 	LOG_INF("%s : triggering %s call", __func__, ctrl->method);
510 	LOG_DBG("\theader         %08x", request.header);
511 	LOG_DBG("\tresp_data_addr %08llx", request.resp_data_addr);
512 	LOG_DBG("\tresp_data_size %d", request.resp_data_size);
513 	LOG_DBG("\tpriv_data      %p", request.priv_data);
514 
515 	sip_supervisory_call(ctrl->dev, request.a0, request.a1, request.a2, request.a3, request.a4,
516 			     request.a5, request.a6, request.a7, &res);
517 
518 	/* Release async command data dynamic memory */
519 	if (cmd_code == SIP_SVC_PROTO_CMD_ASYNC) {
520 		sip_svc_plat_free_async_memory(ctrl->dev, &request);
521 	}
522 
523 	/* Callback if fail or sync command */
524 	error_code = sip_svc_plat_get_error_code(ctrl->dev, &res);
525 	if (error_code != 0 || cmd_code == SIP_SVC_PROTO_CMD_SYNC) {
526 		response.header = SIP_SVC_PROTO_HEADER(error_code, trans_id);
527 		response.a0 = res.a0;
528 		response.a1 = res.a1;
529 		response.a2 = res.a2;
530 		response.a3 = res.a3;
531 		response.resp_data_addr = request.resp_data_addr;
532 		response.resp_data_size = request.resp_data_size;
533 		response.priv_data = request.priv_data;
534 
535 		sip_svc_callback(ctrl, trans_id, &response);
536 
537 		__ASSERT(ctrl->active_job_cnt != 0, "ctrl->active_job_cnt cannot be zero here");
538 		--ctrl->active_job_cnt;
539 	} else {
540 		++ctrl->active_async_job_cnt;
541 	}
542 
543 	return -EINPROGRESS;
544 }
545 
sip_svc_async_response_handler(struct sip_svc_controller * ctrl)546 static int sip_svc_async_response_handler(struct sip_svc_controller *ctrl)
547 {
548 	struct sip_svc_id_map_item *trans_id_item;
549 	struct sip_svc_response response;
550 	uint32_t trans_id;
551 	uint64_t data_addr;
552 	size_t data_size;
553 	int ret;
554 
555 	unsigned long a0 = 0;
556 	unsigned long a1 = 0;
557 	unsigned long a2 = 0;
558 	unsigned long a3 = 0;
559 	unsigned long a4 = 0;
560 	unsigned long a5 = 0;
561 	unsigned long a6 = 0;
562 	unsigned long a7 = 0;
563 	struct arm_smccc_res res;
564 
565 	if (!ctrl) {
566 		LOG_ERR("controller is NULL");
567 		return -EINVAL;
568 	}
569 
570 	/* Return if no busy job id */
571 	if (ctrl->active_async_job_cnt == 0) {
572 		LOG_INF("Async resp job queue is empty");
573 		return 0;
574 	}
575 
576 	if (sip_svc_plat_async_res_req(ctrl->dev, &a0, &a1, &a2, &a3, &a4, &a5, &a6, &a7,
577 				       ctrl->async_resp_data, ctrl->resp_size)) {
578 		LOG_ERR("Error during creation of ASYNC polling request");
579 		return -ENOTSUP;
580 	}
581 
582 	/* Trigger SMC call */
583 	LOG_INF("%s : triggering %s call", __func__, ctrl->method);
584 	LOG_DBG("%s (polling async response)", ctrl->method);
585 
586 	sip_supervisory_call(ctrl->dev, a0, a1, a2, a3, a4, a5, a6, a7, &res);
587 
588 	/* Callback if get response */
589 	ret = sip_svc_plat_async_res_res(ctrl->dev, &res, ctrl->async_resp_data, &data_size,
590 					 &trans_id);
591 
592 	if (ret != 0) {
593 		return -EINPROGRESS;
594 	}
595 
596 	/* get caller information based on trans id */
597 	trans_id_item = sip_svc_id_map_query_item(ctrl->trans_id_map, trans_id);
598 
599 	if (!trans_id_item) {
600 		LOG_ERR("Failed to get entry from database");
601 		return -ENOENT;
602 	}
603 
604 	/* Get caller provided memory space to put response */
605 	data_addr = (((uint64_t)trans_id_item->arg3) | ((uint64_t)trans_id_item->arg2) << 32);
606 
607 	/* Check caller provided memory space to avoid overflow */
608 	if (data_size > ((size_t)trans_id_item->arg4)) {
609 		data_size = ((size_t)trans_id_item->arg4);
610 	}
611 
612 	response.header =
613 		SIP_SVC_PROTO_HEADER(sip_svc_plat_get_error_code(ctrl->dev, &res), trans_id);
614 	response.a0 = res.a0;
615 	response.a1 = res.a1;
616 	response.a2 = res.a2;
617 	response.a3 = res.a3;
618 	response.resp_data_addr = data_addr;
619 	response.resp_data_size = data_size;
620 	response.priv_data = trans_id_item->arg5;
621 
622 	/* Copy async cmd response into caller given memory space */
623 	if (data_addr) {
624 		memcpy((char *)data_addr, ctrl->async_resp_data, data_size);
625 	}
626 
627 	sip_svc_callback(ctrl, trans_id, &response);
628 
629 	__ASSERT(ctrl->active_job_cnt, "ctrl->active_job_cnt cannot be zero here");
630 	--ctrl->active_job_cnt;
631 
632 	__ASSERT(ctrl->active_async_job_cnt != 0, "ctrl->active_async_job_cnt cannot be zero here");
633 	--ctrl->active_async_job_cnt;
634 
635 	/* Check again is there any async busy job id */
636 	if (ctrl->active_async_job_cnt == 0) {
637 		LOG_INF("Async resp job queue is serviced");
638 		return 0;
639 	}
640 
641 	return -EINPROGRESS;
642 }
643 
sip_svc_thread(void * ctrl_ptr,void * arg2,void * arg3)644 static void sip_svc_thread(void *ctrl_ptr, void *arg2, void *arg3)
645 {
646 	ARG_UNUSED(arg2);
647 	ARG_UNUSED(arg3);
648 
649 	struct sip_svc_controller *ctrl = (struct sip_svc_controller *)ctrl_ptr;
650 	int ret_msgq;
651 	int ret_resp;
652 
653 	while (1) {
654 		ret_msgq = -EINPROGRESS;
655 		ret_resp = -EINPROGRESS;
656 		while (ret_msgq != 0 || ret_resp != 0) {
657 			ret_resp = sip_svc_async_response_handler(ctrl);
658 			ret_msgq = sip_svc_request_handler(ctrl);
659 
660 			/* sleep only when waiting for ASYNC responses*/
661 			if (ret_msgq == 0 && ret_resp != 0) {
662 				k_usleep(CONFIG_ARM_SIP_SVC_SUBSYS_ASYNC_POLLING_DELAY);
663 			}
664 		}
665 		LOG_INF("Suspend thread, all transactions are completed");
666 		k_thread_suspend(ctrl->tid);
667 	}
668 }
669 
sip_svc_send(void * ct,uint32_t c_token,struct sip_svc_request * request,sip_svc_cb_fn cb)670 int sip_svc_send(void *ct, uint32_t c_token, struct sip_svc_request *request, sip_svc_cb_fn cb)
671 {
672 	uint32_t trans_id = SIP_SVC_ID_INVALID;
673 	uint32_t trans_idx = SIP_SVC_ID_INVALID;
674 	uint32_t c_idx;
675 	int ret;
676 
677 	if (ct == NULL || !is_sip_svc_controller(ct) || request == NULL) {
678 		return -EINVAL;
679 	}
680 
681 	struct sip_svc_controller *ctrl = (struct sip_svc_controller *)ct;
682 
683 	if (!sip_svc_plat_func_id_valid(ctrl->dev,
684 					(uint32_t)SIP_SVC_PROTO_HEADER_GET_CODE(request->header),
685 					(uint32_t)request->a0)) {
686 		return -EOPNOTSUPP;
687 	}
688 
689 	ret = k_mutex_lock(&ctrl->data_mutex, K_FOREVER);
690 	if (ret != 0) {
691 		LOG_ERR("Failed to get lock %d", ret);
692 		return -ENOLCK;
693 	}
694 
695 	c_idx = sip_svc_get_c_idx(ctrl, c_token);
696 	if (c_idx == SIP_SVC_ID_INVALID) {
697 		k_mutex_unlock(&ctrl->data_mutex);
698 		return -EINVAL;
699 	}
700 
701 	if (ctrl->clients[c_idx].state != SIP_SVC_CLIENT_ST_OPEN) {
702 		k_mutex_unlock(&ctrl->data_mutex);
703 		return -ESRCH;
704 	}
705 
706 	/* Allocate a trans id for the request */
707 	trans_idx = sip_svc_id_mgr_alloc(ctrl->clients[c_idx].trans_idx_pool);
708 	if (trans_idx == SIP_SVC_ID_INVALID) {
709 		LOG_ERR("Fail to allocate transaction id");
710 		k_mutex_unlock(&ctrl->data_mutex);
711 		return -ENOMEM;
712 	}
713 
714 	trans_id = sip_svc_plat_format_trans_id(ctrl->dev, c_idx, trans_idx);
715 	/* Additional check for an unsupported condition*/
716 	if (((int)trans_id) < 0) {
717 		LOG_ERR("Unsupported condition, trans_id < 0");
718 		sip_svc_id_mgr_free(ctrl->clients[c_idx].trans_idx_pool, trans_idx);
719 		k_mutex_unlock(&ctrl->data_mutex);
720 		return -ENOTSUP;
721 	}
722 
723 	/* Assign the trans id of this request */
724 	SIP_SVC_PROTO_HEADER_SET_TRANS_ID(request->header, trans_id);
725 
726 	/* Map trans id to client, callback, response data addr */
727 	if (sip_svc_id_map_insert_item(ctrl->trans_id_map, trans_id, (void *)cb,
728 				       (void *)((request->resp_data_addr >> 32) & 0xFFFFFFFF),
729 				       (void *)(request->resp_data_addr & 0xFFFFFFFF),
730 				       (void *)(uint64_t)request->resp_data_size,
731 				       request->priv_data, (void *)(uint64_t)c_idx) != 0) {
732 
733 		LOG_ERR("Fail to insert transaction id to map");
734 		sip_svc_id_mgr_free(ctrl->clients[c_idx].trans_idx_pool, trans_idx);
735 		k_mutex_unlock(&ctrl->data_mutex);
736 		return -ENOMSG;
737 	}
738 
739 	/* Insert request to MSGQ */
740 	LOG_INF("send command to msgq");
741 	if (k_msgq_put(&ctrl->req_msgq, (void *)request, K_NO_WAIT) != 0) {
742 		LOG_ERR("Request msgq full");
743 		sip_svc_id_map_remove_item(ctrl->trans_id_map, trans_id);
744 		sip_svc_id_mgr_free(ctrl->clients[c_idx].trans_idx_pool, trans_idx);
745 		k_mutex_unlock(&ctrl->data_mutex);
746 		return -ENOBUFS;
747 	}
748 	++ctrl->clients[c_idx].active_trans_cnt;
749 
750 	if (!ctrl->tid) {
751 		LOG_ERR("Thread not spawned during init");
752 		sip_svc_id_map_remove_item(ctrl->trans_id_map, trans_id);
753 		sip_svc_id_mgr_free(ctrl->clients[c_idx].trans_idx_pool, trans_idx);
754 		k_mutex_unlock(&ctrl->data_mutex);
755 		return -EHOSTDOWN;
756 	}
757 
758 	LOG_INF("Wakeup sip_svc thread");
759 	k_thread_resume(ctrl->tid);
760 	k_mutex_unlock(&ctrl->data_mutex);
761 
762 	return (int)trans_id;
763 }
764 
sip_svc_get_priv_data(void * ct,uint32_t c_token)765 void *sip_svc_get_priv_data(void *ct, uint32_t c_token)
766 {
767 	uint32_t c_idx;
768 	int err;
769 
770 	if (ct == NULL || !is_sip_svc_controller(ct)) {
771 		return NULL;
772 	}
773 
774 	struct sip_svc_controller *ctrl = (struct sip_svc_controller *)ct;
775 
776 	err = k_mutex_lock(&ctrl->data_mutex, K_FOREVER);
777 	if (err != 0) {
778 		LOG_ERR("Failed to get lock %d", err);
779 		return NULL;
780 	}
781 
782 	c_idx = sip_svc_get_c_idx(ctrl, c_token);
783 	if (c_idx == SIP_SVC_ID_INVALID) {
784 		LOG_ERR("Client id is invalid");
785 		k_mutex_unlock(&ctrl->data_mutex);
786 		return NULL;
787 	}
788 
789 	k_mutex_unlock(&ctrl->data_mutex);
790 	return ctrl->clients[c_idx].priv_data;
791 }
792 
sip_svc_get_controller(char * method)793 void *sip_svc_get_controller(char *method)
794 {
795 	if (method == NULL) {
796 		LOG_ERR("controller is NULL");
797 		return NULL;
798 	}
799 
800 	/**
801 	 * For more info on below code check @ref SIP_SVC_CONTROLLER_DEFINE()
802 	 */
803 	STRUCT_SECTION_FOREACH(sip_svc_controller, ctrl) {
804 		if (!strncmp(ctrl->method, method, SIP_SVC_SUBSYS_CONDUIT_NAME_LENGTH)) {
805 			return (void *)ctrl;
806 		}
807 	}
808 
809 	LOG_ERR("controller couldn't be found");
810 	return NULL;
811 }
812 
sip_svc_subsys_init(void)813 static int sip_svc_subsys_init(void)
814 {
815 	int ret = 0;
816 	uint32_t ctrl_count = 0;
817 	char *msgq_buf = NULL;
818 	struct device *dev = NULL;
819 	struct sip_svc_client *client = NULL;
820 
821 	LOG_INF("Start of %s", __func__);
822 
823 	STRUCT_SECTION_COUNT(sip_svc_controller, &ctrl_count);
824 	__ASSERT(ctrl_count <= 2, "There should be at most 2 controllers");
825 
826 	/**
827 	 * Get controller array ,Controller which is instantiated by driver using
828 	 * SIP_SVC_CONTROLLER_DEFINE(),see @ref SIP_SVC_CONTROLLER_DEFINE() for more
829 	 * info.
830 	 */
831 	STRUCT_SECTION_FOREACH(sip_svc_controller, ctrl) {
832 		if (!device_is_ready(ctrl->dev)) {
833 			LOG_ERR("device not ready");
834 			return -ENODEV;
835 		}
836 		dev = (struct device *)(ctrl->dev);
837 
838 		LOG_INF("Got registered conduit %.*s", (int)sizeof(ctrl->method), ctrl->method);
839 
840 		ctrl->async_resp_data = k_malloc(ctrl->resp_size);
841 		if (ctrl->async_resp_data == NULL) {
842 			return -ENOMEM;
843 		}
844 
845 		ctrl->client_id_pool = sip_svc_id_mgr_create(ctrl->num_clients);
846 		if (!ctrl->client_id_pool) {
847 			k_free(ctrl->async_resp_data);
848 			return -ENOMEM;
849 		}
850 
851 		ctrl->trans_id_map = sip_svc_id_map_create(ctrl->max_transactions);
852 		if (!ctrl->trans_id_map) {
853 			sip_svc_id_mgr_delete(ctrl->client_id_pool);
854 			k_free(ctrl->async_resp_data);
855 			return -ENOMEM;
856 		}
857 
858 		/* Alloc request msgq ring buffer */
859 		msgq_buf = k_malloc(sizeof(struct sip_svc_request) *
860 				    CONFIG_ARM_SIP_SVC_SUBSYS_MSGQ_DEPTH);
861 		if (!msgq_buf) {
862 			sip_svc_id_mgr_delete(ctrl->client_id_pool);
863 			sip_svc_id_map_delete(ctrl->trans_id_map);
864 			k_free(ctrl->async_resp_data);
865 			return -ENOMEM;
866 		}
867 
868 		ctrl->clients = k_malloc(ctrl->num_clients * sizeof(struct sip_svc_client));
869 		if (ctrl->clients == NULL) {
870 			sip_svc_id_mgr_delete(ctrl->client_id_pool);
871 			sip_svc_id_map_delete(ctrl->trans_id_map);
872 			k_free(msgq_buf);
873 			k_free(ctrl->async_resp_data);
874 			return -ENOMEM;
875 		}
876 
877 		memset(ctrl->clients, 0, ctrl->num_clients * sizeof(struct sip_svc_client));
878 
879 		/* Initialize request msgq */
880 		k_msgq_init(&ctrl->req_msgq, msgq_buf, sizeof(struct sip_svc_request),
881 			    CONFIG_ARM_SIP_SVC_SUBSYS_MSGQ_DEPTH);
882 
883 		/* Initialize client contents */
884 		for (uint32_t i = 0; i < ctrl->num_clients; i++) {
885 			client = &ctrl->clients[i];
886 			client->id = SIP_SVC_ID_INVALID;
887 			client->token = SIP_SVC_ID_INVALID;
888 			client->state = SIP_SVC_CLIENT_ST_INVALID;
889 			client->active_trans_cnt = 0;
890 
891 			client->trans_idx_pool = sip_svc_id_mgr_create(
892 				CONFIG_ARM_SIP_SVC_SUBSYS_MAX_TRANSACTION_ID_COUNT);
893 			if (!client->trans_idx_pool) {
894 				ret = -ENOMEM;
895 				break;
896 			}
897 		}
898 
899 		if (ret != 0) {
900 			sip_svc_id_mgr_delete(ctrl->client_id_pool);
901 			sip_svc_id_map_delete(ctrl->trans_id_map);
902 			k_free(msgq_buf);
903 			k_free(ctrl->clients);
904 			k_free(ctrl->async_resp_data);
905 
906 			for (uint32_t i = 0; i < ctrl->num_clients; i++) {
907 				client = &ctrl->clients[i];
908 				if (client->trans_idx_pool) {
909 					sip_svc_id_mgr_delete(client->trans_idx_pool);
910 				}
911 			}
912 			return ret;
913 		}
914 
915 		/* Create and run the thread */
916 		ctrl->tid = k_thread_create(
917 			&ctrl->thread, ctrl->stack, CONFIG_ARM_SIP_SVC_SUBSYS_THREAD_STACK_SIZE,
918 			sip_svc_thread, ctrl, NULL, NULL, CONFIG_ARM_SIP_SVC_SUBSYS_THREAD_PRIORITY,
919 			K_ESSENTIAL, K_NO_WAIT);
920 		k_thread_name_set(ctrl->tid, "sip_svc");
921 
922 		ctrl->active_job_cnt = 0;
923 		ctrl->active_async_job_cnt = 0;
924 
925 		/* Initialize atomic variable */
926 #if CONFIG_ARM_SIP_SVC_SUBSYS_SINGLY_OPEN
927 		(void)atomic_set(&ctrl->open_lock, SIP_SVC_OPEN_UNLOCKED);
928 #endif
929 		/* Initialize mutex */
930 		k_mutex_init(&ctrl->data_mutex);
931 
932 		ctrl->init = true;
933 	}
934 
935 	LOG_INF("Completed %s", __func__);
936 	return 0;
937 }
938 
939 SYS_INIT(sip_svc_subsys_init, POST_KERNEL, CONFIG_ARM_SIP_SVC_SUBSYS_INIT_PRIORITY);
940