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