1 /* SPDX-License-Identifier: Apache-2.0 OR MIT */
2 /*
3 * Copyright (c) 2021 Rockchip Electronics Co., Ltd.
4 */
5
6 #define MODULE_TAG "mpp_server"
7
8 #include <sys/ioctl.h>
9 #include <fcntl.h>
10 #include <errno.h>
11 #include <string.h>
12
13 #include "mpp_env.h"
14 #include "mpp_list.h"
15 #include "mpp_time.h"
16 #include "osal_2str.h"
17 #include "mpp_common.h"
18 #include "mpp_thread.h"
19 #include "mpp_mem_pool.h"
20 #include "mpp_singleton.h"
21
22 #include "mpp_server.h"
23 #include "mpp_device_debug.h"
24 #include "mpp_service_impl.h"
25
26 #define MAX_BATCH_TASK 8
27 #define MAX_SESSION_TASK 4
28 #define MAX_REQ_SEND_CNT MAX_REQ_NUM
29 #define MAX_REQ_WAIT_CNT 2
30
31 #define MPP_SERVER_DBG_FLOW (0x00000001)
32
33 #define mpp_serv_dbg(flag, fmt, ...) _mpp_dbg(mpp_server_debug, flag, fmt, ## __VA_ARGS__)
34 #define mpp_serv_dbg_f(flag, fmt, ...) _mpp_dbg_f(mpp_server_debug, flag, fmt, ## __VA_ARGS__)
35
36 #define mpp_serv_dbg_flow(fmt, ...) mpp_serv_dbg(MPP_SERVER_DBG_FLOW, fmt, ## __VA_ARGS__)
37
38 #define FIFO_WRITE(size, count, wr, rd) \
39 do { \
40 wr++; \
41 if (wr >= size) wr = 0; \
42 count++; \
43 mpp_assert(count <= size); \
44 } while (0)
45
46 #define FIFO_READ(size, count, wr, rd) \
47 do { \
48 rd++; \
49 if (rd >= size) rd = 0; \
50 count--; \
51 mpp_assert(count >= 0); \
52 } while (0)
53
54 #define get_srv_server() \
55 ({ \
56 MppDevServer *__tmp; \
57 if (!srv_server) { \
58 mpp_server_init(); \
59 } \
60 __tmp = srv_server; \
61 if (!__tmp || !__tmp->inited) { \
62 mpp_err("mpp server srv not init for %s at %s\n", \
63 __tmp ? __tmp->server_error : "invalid server", __FUNCTION__); \
64 __tmp = NULL; \
65 } \
66 __tmp; \
67 })
68
69 typedef struct MppDevTask_t MppDevTask;
70 typedef struct MppDevBatTask_t MppDevBatTask;
71 typedef struct MppDevSession_t MppDevSession;
72 typedef struct MppDevBatServ_t MppDevBatServ;
73
74 struct MppDevTask_t {
75 /* link to server */
76 struct list_head link_server;
77 /* link to session tasks */
78 struct list_head link_session;
79 /* link to batch tasks */
80 struct list_head link_batch;
81
82 MppDevSession *session;
83 MppDevBatTask *batch;
84
85 rk_s32 slot_idx;
86
87 /* lock by server */
88 rk_s32 task_id;
89 /* lock by batch */
90 rk_s32 batch_slot_id;
91
92 MppReqV1 *req;
93 rk_s32 req_cnt;
94 };
95
96 struct MppDevBatTask_t {
97 MppMutexCond cond;
98
99 /* link to server */
100 struct list_head link_server;
101 /* link to session tasks */
102 struct list_head link_tasks;
103
104 rk_u32 batch_id;
105
106 MppDevBatCmd *bat_cmd;
107 MppReqV1 *send_reqs;
108 MppReqV1 *wait_reqs;
109
110 /* lock and clean by server */
111 rk_s32 send_req_cnt;
112 rk_s32 wait_req_cnt;
113
114 /* lock by server */
115 rk_s32 fill_cnt;
116 rk_s32 fill_full;
117 rk_s32 fill_timeout;
118 rk_s32 poll_cnt;
119 };
120
121 struct MppDevSession_t {
122 MppMutexCond cond_lock;
123
124 /* hash table to server */
125 struct list_head list_server;
126 /* link to session waiting tasks */
127 struct list_head list_wait;
128 /* link to session free tasks */
129 struct list_head list_done;
130
131 MppDevMppService *ctx;
132 MppDevBatServ *server;
133
134 rk_s32 client;
135
136 rk_s32 task_wait;
137 rk_s32 task_done;
138
139 MppDevTask tasks[MAX_SESSION_TASK];
140 };
141
142 struct MppDevBatServ_t {
143 MppMutex lock;
144
145 rk_s32 server_fd;
146 rk_u32 batch_id;
147 rk_u32 task_id;
148
149 /* timer for serializing process */
150 MppTimer timer;
151
152 /* session register */
153 struct list_head session_list;
154 rk_s32 session_count;
155
156 /* batch task queue */
157 struct list_head list_batch;
158 struct list_head list_batch_free;
159 MppMemPool batch_pool;
160 rk_s32 batch_max_count;
161 rk_s32 batch_task_size;
162 rk_s32 batch_run;
163 rk_s32 batch_free;
164 rk_s32 max_task_in_batch;
165
166 /* link to all pending tasks */
167 struct list_head pending_task;
168 rk_s32 pending_count;
169 };
170
171 typedef struct MppDevServer_t {
172 const char *server_error;
173 const char *server_name;
174 rk_s32 inited;
175 rk_u32 enable;
176 MppMutex lock;
177 MppDevBatServ *bat_server[VPU_CLIENT_BUTT];
178
179 MppMemPool session_pool;
180 MppMemPool batch_pool;
181
182 rk_s32 max_task_in_batch;
183
184 const MppServiceCmdCap *cmd_cap;
185 } MppDevServer;
186
187 static MppDevServer *srv_server = NULL;
188 static rk_u32 mpp_server_debug = 0;
189
batch_reset(MppDevBatTask * batch)190 static void batch_reset(MppDevBatTask *batch)
191 {
192 mpp_assert(list_empty(&batch->link_tasks));
193
194 batch->fill_cnt = 0;
195 batch->fill_full = 0;
196 batch->fill_timeout = 0;
197 batch->poll_cnt = 0;
198 batch->send_req_cnt = 0;
199 batch->wait_req_cnt = 0;
200 }
201
batch_add(MppDevBatServ * server)202 MppDevBatTask *batch_add(MppDevBatServ *server)
203 {
204 MppDevBatTask *batch = (MppDevBatTask *)mpp_mem_pool_get_f(server->batch_pool);
205
206 mpp_assert(batch);
207 if (!batch)
208 return batch;
209
210 INIT_LIST_HEAD(&batch->link_server);
211 INIT_LIST_HEAD(&batch->link_tasks);
212
213 batch->send_reqs = (MppReqV1 *)(batch + 1);
214 batch->wait_reqs = batch->send_reqs +
215 (server->max_task_in_batch * MAX_REQ_SEND_CNT);
216 batch->bat_cmd = (MppDevBatCmd *)(batch->wait_reqs +
217 (server->max_task_in_batch * MAX_REQ_WAIT_CNT));
218
219 batch_reset(batch);
220 list_add_tail(&batch->link_server, &server->list_batch_free);
221 server->batch_free++;
222
223 mpp_serv_dbg_flow("batch add free count %d:%d\n", server->batch_run, server->batch_free);
224 return batch;
225 }
226
batch_del(MppDevBatServ * server,MppDevBatTask * batch)227 void batch_del(MppDevBatServ *server, MppDevBatTask *batch)
228 {
229 mpp_assert(batch);
230 mpp_assert(batch->fill_cnt == 0);
231 mpp_assert(list_empty(&batch->link_tasks));
232
233 list_del_init(&batch->link_server);
234
235 mpp_mem_pool_put_f(server->batch_pool, batch);
236 server->batch_free--;
237 mpp_serv_dbg_flow("batch del free count %d:%d\n", server->batch_run, server->batch_free);
238 }
239
batch_send(MppDevBatServ * server,MppDevBatTask * batch)240 void batch_send(MppDevBatServ *server, MppDevBatTask *batch)
241 {
242 rk_s32 ret = 0;
243
244 mpp_assert(batch->send_req_cnt);
245
246 ret = mpp_service_ioctl_request(server->server_fd, batch->send_reqs);
247 if (ret) {
248 mpp_err_f("ioctl batch cmd failed ret %d errno %d %s\n",
249 ret, errno, strerror(errno));
250 ret = errno;
251 mpp_serv_dbg_flow("batch %d -> send failed\n", batch->batch_id);
252 }
253
254 list_del_init(&batch->link_server);
255 list_add_tail(&batch->link_server, &server->list_batch);
256 server->batch_free--;
257 server->batch_run++;
258 mpp_serv_dbg_flow("batch %d -> send %d for %s\n", batch->batch_id,
259 batch->fill_cnt, batch->fill_timeout ? "timeout" : "ready");
260 }
261
process_task(void * p)262 void process_task(void *p)
263 {
264 MppDevBatServ *server = (MppDevBatServ *)p;
265 MppMutex *lock = &server->lock;
266 rk_s32 ret = rk_ok;
267 MppDevTask *task;
268 MppDevBatTask *batch;
269 MppDevSession *session = NULL;
270 MppDevBatCmd *bat_cmd;
271 MppReqV1 *req = NULL;
272 rk_s32 pending = 0;
273
274 mpp_serv_dbg_flow("process task start\n");
275
276 /* 1. try poll and get finished task */
277 do {
278 batch = list_first_entry_or_null(&server->list_batch, MppDevBatTask, link_server);
279 if (!batch)
280 break;
281
282 mpp_assert(batch->wait_req_cnt);
283 ret = mpp_service_ioctl_request(server->server_fd, batch->wait_reqs);
284 if (!ret) {
285 MppDevTask *n;
286
287 list_for_each_entry_safe(task, n, &batch->link_tasks, MppDevTask, link_batch) {
288 rk_s32 batch_slot_id = task->batch_slot_id;
289 MppDevBatCmd *cmd = batch->bat_cmd + batch_slot_id;
290
291 mpp_assert(batch_slot_id < server->max_task_in_batch);
292 session = task->session;
293
294 ret = cmd->ret;
295 if (ret == EAGAIN)
296 continue;
297
298 if (ret == -EIO) {
299 mpp_err_f("batch %d:%d task %d poll error found\n",
300 batch->batch_id, task->batch_slot_id, task->task_id);
301 cmd->flag |= 1;
302 continue;
303 }
304 if (ret == 0) {
305 list_del_init(&task->link_batch);
306 task->batch = NULL;
307
308 mpp_serv_dbg_flow("batch %d:%d session %d ready and remove\n",
309 batch->batch_id, task->batch_slot_id, session->client);
310 mpp_mutex_cond_lock(&session->cond_lock);
311 session->task_done++;
312 mpp_mutex_cond_signal(&session->cond_lock);
313 mpp_mutex_cond_unlock(&session->cond_lock);
314 if (session->ctx && session->ctx->dev_cb)
315 mpp_callback(session->ctx->dev_cb, NULL);
316
317 batch->poll_cnt++;
318 cmd->flag |= 1;
319 }
320 }
321
322 mpp_serv_dbg_flow("batch %d fill %d poll %d\n", batch->batch_id,
323 batch->fill_cnt, batch->poll_cnt);
324
325 if (batch->poll_cnt == batch->fill_cnt) {
326 mpp_serv_dbg_flow("batch %d poll done\n", batch->batch_id);
327 list_del_init(&batch->link_server);
328 list_add_tail(&batch->link_server, &server->list_batch_free);
329 server->batch_run--;
330 server->batch_free++;
331
332 batch_reset(batch);
333 batch = NULL;
334 continue;
335 }
336 } else {
337 mpp_log_f("batch %d poll ret %d errno %d %s", batch->batch_id,
338 ret, errno, strerror(errno));
339 mpp_log_f("stop timer\n");
340 mpp_timer_set_enable(server->timer, 0);
341 }
342 break;
343 } while (1);
344
345 /* 2. get prending task to fill */
346 mpp_mutex_lock(lock);
347 pending = server->pending_count;
348 if (!pending && !server->batch_run && !server->session_count) {
349 mpp_timer_set_enable(server->timer, 0);
350 mpp_serv_dbg_flow("stop timer\n");
351 }
352 mpp_mutex_unlock(lock);
353
354 mpp_serv_dbg_flow("pending %d running %d free %d max %d process start\n",
355 pending, server->batch_run, server->batch_free, server->batch_max_count);
356
357 try_proc_pending_task:
358 /* 3. try get batch task*/
359 if (!server->batch_free) {
360 /* if not enough and max count does not reached create new batch */
361 if (server->batch_free + server->batch_run >= server->batch_max_count) {
362 mpp_serv_dbg_flow("finish for not batch slot\n");
363 return ;
364 }
365
366 batch_add(server);
367 }
368 mpp_assert(server->batch_free);
369
370 /* 4. if no pending task to send check timeout batch and send it */
371 if (!pending) {
372 if (!server->batch_free) {
373 /* no pending and no free batch just done */
374 return;
375 }
376
377 batch = list_first_entry_or_null(&server->list_batch_free, MppDevBatTask, link_server);
378 mpp_assert(batch);
379 if (!batch) {
380 mpp_log_f("batch run %d free %d\n", server->batch_run, server->batch_free);
381 return;
382 }
383
384 /* send one timeout task */
385 if (batch->fill_cnt)
386 batch_send(server, batch);
387
388 mpp_serv_dbg_flow("finish for no pending task\n");
389 return;
390 }
391
392 mpp_serv_dbg_flow("pending task %d left to process\n", pending);
393
394 /* 5. add task to add batch and try send batch */
395 if (!server->batch_free) {
396 /* no pending and no free batch just done */
397 return;
398 }
399
400 batch = list_first_entry_or_null(&server->list_batch_free, MppDevBatTask, link_server);
401 mpp_assert(batch);
402 mpp_assert(pending);
403
404 task = NULL;
405 mpp_mutex_lock(lock);
406 task = list_first_entry_or_null(&server->pending_task, MppDevTask, link_server);
407 list_del_init(&task->link_server);
408 server->pending_count--;
409 mpp_mutex_unlock(lock);
410 pending--;
411
412 /* first task and setup new batch id */
413 if (!batch->fill_cnt)
414 batch->batch_id = server->batch_id++;
415
416 task->batch = batch;
417 task->batch_slot_id = batch->fill_cnt++;
418 mpp_assert(task->batch_slot_id < server->max_task_in_batch);
419 list_add_tail(&task->link_batch, &batch->link_tasks);
420 if (batch->fill_cnt >= server->max_task_in_batch)
421 batch->fill_full = 1;
422
423 session = task->session;
424 mpp_assert(session);
425 mpp_assert(session->ctx);
426
427 bat_cmd = batch->bat_cmd + task->batch_slot_id;
428 bat_cmd->flag = 0;
429 bat_cmd->client = session->client;
430 bat_cmd->ret = 0;
431
432 /* fill task to batch */
433 /* add session info before each session task and then copy session request */
434 req = &batch->send_reqs[batch->send_req_cnt++];
435 req->cmd = MPP_CMD_SET_SESSION_FD;
436 req->flag = MPP_FLAGS_MULTI_MSG;
437 req->offset = 0;
438 req->size = sizeof(*bat_cmd);
439 req->data_ptr = REQ_DATA_PTR(bat_cmd);
440
441 {
442 rk_s32 i;
443
444 for (i = 0; i < task->req_cnt; i++)
445 batch->send_reqs[batch->send_req_cnt++] = task->req[i];
446 }
447
448 mpp_assert(batch->send_req_cnt <= server->max_task_in_batch * MAX_REQ_NUM);
449
450 /* setup poll request */
451 req = &batch->wait_reqs[batch->wait_req_cnt++];
452 req->cmd = MPP_CMD_SET_SESSION_FD;
453 req->flag = MPP_FLAGS_MULTI_MSG;
454 req->offset = 0;
455 req->size = sizeof(*bat_cmd);
456 req->data_ptr = REQ_DATA_PTR(bat_cmd);
457
458 req = &batch->wait_reqs[batch->wait_req_cnt++];
459 req->cmd = MPP_CMD_POLL_HW_FINISH;
460 req->flag = MPP_FLAGS_POLL_NON_BLOCK | MPP_FLAGS_MULTI_MSG | MPP_FLAGS_LAST_MSG;
461 req->offset = 0;
462 req->size = 0;
463 req->data_ptr = 0;
464
465 mpp_serv_dbg_flow("batch %d:%d add task %d:%d:%d\n",
466 batch->batch_id, task->batch_slot_id, session->client,
467 task->slot_idx, task->task_id);
468
469 if (batch->fill_full) {
470 list_del_init(&batch->link_server);
471 list_add_tail(&batch->link_server, &server->list_batch);
472 mpp_serv_dbg_flow("batch %d -> fill_nb %d fill ready\n",
473 batch->batch_id, batch->fill_cnt);
474 batch_send(server, batch);
475 batch = NULL;
476 }
477 goto try_proc_pending_task;
478 }
479
mpp_server_thread(void * ctx)480 static void *mpp_server_thread(void *ctx)
481 {
482 process_task((MppDevBatServ *)ctx);
483 return NULL;
484 }
485
send_task(MppDevMppService * ctx)486 rk_s32 send_task(MppDevMppService *ctx)
487 {
488 MppDevTask *task = NULL;
489 MppDevSession *session = (MppDevSession *)ctx->serv_ctx;
490
491 if (!session || !session->server) {
492 mpp_err_f("invalid ctx %p session %p send task\n", ctx, session);
493 return rk_nok;
494 }
495
496 MppDevBatServ *server = session->server;
497
498 /* get free task from session and add to run list */
499 mpp_mutex_cond_lock(&session->cond_lock);
500 /* get a free task and setup */
501 task = list_first_entry_or_null(&session->list_done, MppDevTask, link_session);
502 mpp_assert(task);
503
504 task->req = ctx->reqs;
505 task->req_cnt = ctx->req_cnt;
506
507 list_del_init(&task->link_session);
508 list_add_tail(&task->link_session, &session->list_wait);
509
510 session->task_wait++;
511 mpp_mutex_cond_unlock(&session->cond_lock);
512
513 mpp_mutex_lock(&server->lock);
514 task->task_id = server->task_id++;
515 list_del_init(&task->link_server);
516 list_add_tail(&task->link_server, &server->pending_task);
517 server->pending_count++;
518 mpp_serv_dbg_flow("session %d:%d add pending %d\n",
519 session->client, task->slot_idx, server->pending_count);
520
521 mpp_timer_set_enable(server->timer, 1);
522 mpp_mutex_unlock(&server->lock);
523
524 return rk_ok;
525 }
526
wait_task(MppDevMppService * ctx,rk_s64 timeout)527 rk_s32 wait_task(MppDevMppService *ctx, rk_s64 timeout)
528 {
529 rk_s32 ret = rk_ok;
530 MppDevTask *task = NULL;
531 MppDevSession *session = (MppDevSession *)ctx->serv_ctx;
532 (void) timeout;
533
534 if (!session) {
535 mpp_err_f("invalid ctx %p send task\n", ctx);
536 return rk_nok;
537 }
538
539 task = list_first_entry_or_null(&session->list_wait, MppDevTask, link_session);
540 mpp_assert(task);
541
542 mpp_mutex_cond_lock(&session->cond_lock);
543 if (session->task_wait != session->task_done) {
544 mpp_serv_dbg_flow("session %d wait %d start %d:%d\n", session->client,
545 task->task_id, session->task_wait, session->task_done);
546 mpp_mutex_cond_wait(&session->cond_lock);
547 }
548 mpp_serv_dbg_flow("session %d wait %d done %d:%d\n", session->client,
549 task->task_id, session->task_wait, session->task_done);
550 mpp_mutex_cond_unlock(&session->cond_lock);
551
552 list_del_init(&task->link_session);
553 list_add_tail(&task->link_session, &session->list_done);
554
555 return ret;
556 }
557
bat_server_get(MppDevServer * srv,MppClientType client_type)558 static MppDevBatServ *bat_server_get(MppDevServer *srv, MppClientType client_type)
559 {
560 MppDevBatServ *server = NULL;
561 char timer_name[32];
562
563 mpp_mutex_lock(&srv->lock);
564
565 server = srv->bat_server[client_type];
566 if (server) {
567 mpp_mutex_unlock(&srv->lock);
568 return server;
569 }
570
571 server = mpp_calloc(MppDevBatServ, 1);
572 if (!server) {
573 mpp_err("mpp server failed to get bat server\n");
574 mpp_mutex_unlock(&srv->lock);
575 return NULL;
576 }
577
578 server->server_fd = open(srv->server_name, O_RDWR | O_CLOEXEC);
579 if (server->server_fd < 0) {
580 mpp_err("mpp server get bat server failed to open device\n");
581 goto failed;
582 }
583
584 snprintf(timer_name, sizeof(timer_name) - 1, "%s_bat",
585 strof_client_type(client_type));
586
587 server->timer = mpp_timer_get(timer_name);
588 if (!server->timer) {
589 mpp_err("mpp server get bat server failed to create timer\n");
590 goto failed;
591 }
592
593 mpp_mutex_init(&server->lock);
594
595 mpp_timer_set_callback(server->timer, mpp_server_thread, server);
596 /* 10ms */
597 mpp_timer_set_timing(server->timer, 10, 10);
598
599 INIT_LIST_HEAD(&server->session_list);
600 INIT_LIST_HEAD(&server->list_batch);
601 INIT_LIST_HEAD(&server->list_batch_free);
602 INIT_LIST_HEAD(&server->pending_task);
603
604 server->batch_pool = srv->batch_pool;
605 server->max_task_in_batch = srv->max_task_in_batch;
606
607 srv->bat_server[client_type] = server;
608 mpp_mutex_unlock(&srv->lock);
609
610 return server;
611
612 failed:
613 if (server) {
614 if (server->timer) {
615 mpp_timer_put(server->timer);
616 server->timer = NULL;
617 }
618
619 if (server->server_fd >= 0) {
620 close(server->server_fd);
621 server->server_fd = -1;
622 }
623 mpp_mutex_destroy(&server->lock);
624 }
625 MPP_FREE(server);
626 mpp_mutex_unlock(&srv->lock);
627
628 return NULL;
629 }
630
bat_server_put(MppDevServer * srv,MppClientType client_type)631 static rk_s32 bat_server_put(MppDevServer *srv, MppClientType client_type)
632 {
633 MppDevBatServ *server = NULL;
634 MppDevBatTask *batch, *n;
635
636 mpp_mutex_lock(&srv->lock);
637
638 if (!srv->bat_server[client_type]) {
639 mpp_mutex_unlock(&srv->lock);
640 return rk_ok;
641 }
642
643 server = srv->bat_server[client_type];
644 srv->bat_server[client_type] = NULL;
645
646 mpp_assert(server->batch_run == 0);
647 mpp_assert(list_empty(&server->list_batch));
648 mpp_assert(server->pending_count == 0);
649
650 /* stop thread first */
651 if (server->timer) {
652 mpp_timer_put(server->timer);
653 server->timer = NULL;
654 }
655
656 if (server->batch_free) {
657 list_for_each_entry_safe(batch, n, &server->list_batch_free, MppDevBatTask, link_server) {
658 batch_del(server, batch);
659 }
660 } else {
661 mpp_assert(list_empty(&server->list_batch_free));
662 }
663
664 if (server->server_fd >= 0) {
665 close(server->server_fd);
666 server->server_fd = -1;
667 }
668 mpp_mutex_destroy(&server->lock);
669 MPP_FREE(server);
670 mpp_mutex_unlock(&srv->lock);
671
672 return rk_ok;
673 }
674
server_attach(MppDevServer * srv,MppDevMppService * ctx)675 static rk_s32 server_attach(MppDevServer *srv, MppDevMppService *ctx)
676 {
677 MppClientType client_type = (MppClientType)ctx->client_type;
678 MppDevBatServ *server;
679 MppDevSession *session;
680 rk_u32 i;
681
682 if (client_type < 0 || client_type >= VPU_CLIENT_BUTT) {
683 mpp_err("mpp server attach failed with invalid client type %d\n", client_type);
684 return rk_nok;
685 }
686
687 /* if client type server is not created create it first */
688 server = bat_server_get(srv, client_type);
689 if (!server) {
690 mpp_err("mpp server get bat server with client type %d failed\n", client_type);
691 return rk_nok;
692 }
693
694 mpp_mutex_lock(&srv->lock);
695 if (ctx->serv_ctx) {
696 mpp_mutex_unlock(&srv->lock);
697 return rk_ok;
698 }
699
700 session = (MppDevSession *)mpp_mem_pool_get_f(srv->session_pool);
701
702 INIT_LIST_HEAD(&session->list_server);
703 INIT_LIST_HEAD(&session->list_wait);
704 INIT_LIST_HEAD(&session->list_done);
705
706 session->ctx = ctx;
707 session->server = server;
708 session->client = ctx->client;
709 mpp_mutex_cond_init(&session->cond_lock);
710 session->task_wait = 0;
711 session->task_done = 0;
712
713 for (i = 0; i < MPP_ARRAY_ELEMS(session->tasks); i++) {
714 MppDevTask *task = &session->tasks[i];
715
716 INIT_LIST_HEAD(&task->link_server);
717 INIT_LIST_HEAD(&task->link_session);
718 INIT_LIST_HEAD(&task->link_batch);
719 task->session = session;
720 task->batch = NULL;
721 task->task_id = -1;
722 task->slot_idx = i;
723
724 list_add_tail(&task->link_session, &session->list_done);
725 }
726
727 list_add_tail(&session->list_server, &server->session_list);
728 ctx->serv_ctx = session;
729
730 if (srv->enable) {
731 ctx->batch_io = 1;
732 ctx->server = server->server_fd;
733 } else {
734 ctx->batch_io = 0;
735 ctx->server = ctx->client;
736 }
737
738 server->batch_max_count++;
739 server->session_count++;
740 mpp_mutex_unlock(&srv->lock);
741
742 return rk_ok;
743 }
744
server_detach(MppDevServer * srv,MppDevMppService * ctx)745 static rk_s32 server_detach(MppDevServer *srv, MppDevMppService *ctx)
746 {
747 MppClientType client_type = (MppClientType)ctx->client_type;
748 MppDevBatServ *server = bat_server_get(srv, client_type);
749 MppDevSession *session = (MppDevSession *)ctx->serv_ctx;
750
751 mpp_assert(server);
752
753 mpp_mutex_lock(&srv->lock);
754 if (!ctx->serv_ctx) {
755 mpp_mutex_unlock(&srv->lock);
756 return rk_ok;
757 }
758
759 ctx->server = ctx->client;
760 ctx->serv_ctx = NULL;
761 ctx->batch_io = 0;
762
763 mpp_assert(server);
764 mpp_assert(session);
765 mpp_assert(session->client == ctx->client);
766 mpp_assert(session->task_wait == session->task_done);
767 mpp_assert(list_empty(&session->list_wait));
768
769 list_del_init(&session->list_server);
770
771 mpp_mutex_cond_destroy(&session->cond_lock);
772
773 mpp_mem_pool_put_f(srv->session_pool, session);
774 server->batch_max_count++;
775 server->session_count++;
776
777 mpp_mutex_unlock(&srv->lock);
778
779 return rk_ok;
780 }
781
server_clear(MppDevServer * srv)782 static void server_clear(MppDevServer *srv)
783 {
784 if (srv) {
785 if (srv->session_pool) {
786 mpp_mem_pool_deinit_f(srv->session_pool);
787 srv->session_pool = NULL;
788 }
789
790 if (srv->batch_pool) {
791 mpp_mem_pool_deinit_f(srv->batch_pool);
792 srv->batch_pool = NULL;
793 }
794
795 srv->inited = 0;
796 srv->enable = 0;
797
798 mpp_free(srv);
799 }
800 }
801
mpp_server_init()802 static void mpp_server_init()
803 {
804 MppDevServer *srv = srv_server;
805 rk_s32 batch_task_size = 0;
806
807 if (srv)
808 return;
809
810 srv = mpp_calloc(MppDevServer, 1);
811 if (!srv) {
812 mpp_err_f("failed to allocate mpp_server service\n");
813 return;
814 }
815
816 srv_server = srv;
817
818 srv->server_error = NULL;
819 srv->server_name = NULL;
820 srv->inited = 0;
821 srv->enable = 1;
822 srv->session_pool = NULL;
823 srv->batch_pool = NULL;
824 srv->max_task_in_batch = 0;
825 srv->cmd_cap = NULL;
826
827 mpp_env_get_u32("mpp_server_debug", &mpp_server_debug, 0);
828 mpp_env_get_u32("mpp_server_enable", &srv->enable, 1);
829 mpp_env_get_u32("mpp_server_batch_task", (rk_u32 *)&srv->max_task_in_batch,
830 MAX_BATCH_TASK);
831
832 mpp_assert(srv->max_task_in_batch >= 1 && srv->max_task_in_batch <= 32);
833 batch_task_size = sizeof(MppDevBatTask) + srv->max_task_in_batch *
834 (sizeof(MppReqV1) * (MAX_REQ_SEND_CNT + MAX_REQ_WAIT_CNT) +
835 sizeof(MppDevBatCmd));
836
837 srv->cmd_cap = mpp_get_mpp_service_cmd_cap();
838 if (rk_ok != mpp_service_check_cmd_valid(MPP_CMD_SET_SESSION_FD, srv->cmd_cap)) {
839 srv->server_error = "mpp_service cmd not support";
840 return;
841 }
842
843 mpp_mutex_init(&srv->lock);
844 memset(srv->bat_server, 0, sizeof(srv->bat_server));
845
846 do {
847 srv->server_name = mpp_get_mpp_service_name();
848 if (!srv->server_name) {
849 srv->server_error = "get service device failed";
850 break;
851 }
852
853 srv->session_pool = mpp_mem_pool_init_f("server_session", sizeof(MppDevSession));
854 if (!srv->session_pool) {
855 srv->server_error = "create session pool failed";
856 break;
857 }
858
859 srv->batch_pool = mpp_mem_pool_init_f("server_batch", batch_task_size);
860 if (!srv->batch_pool) {
861 srv->server_error = "create batch tack pool failed";
862 break;
863 }
864
865 srv->inited = 1;
866 } while (0);
867
868 if (!srv->inited) {
869 server_clear(srv);
870 srv_server = NULL;
871 }
872 }
873
mpp_server_deinit()874 static void mpp_server_deinit()
875 {
876 MppDevServer *srv = srv_server;
877
878 srv_server = NULL;
879
880 if (srv) {
881 rk_s32 i;
882
883 for (i = 0; i < VPU_CLIENT_BUTT; i++)
884 bat_server_put(srv, (MppClientType)i);
885
886 mpp_mutex_destroy(&srv->lock);
887 server_clear(srv);
888 }
889 }
890
mpp_server_attach(MppDev ctx)891 rk_s32 mpp_server_attach(MppDev ctx)
892 {
893 MppDevServer *srv = get_srv_server();
894 rk_s32 ret = rk_nok;
895
896 if (srv && ctx) {
897 MppDevMppService *dev = (MppDevMppService *)ctx;
898
899 ret = server_attach(srv, dev);
900 }
901
902 return ret;
903 }
904
mpp_server_detach(MppDev ctx)905 rk_s32 mpp_server_detach(MppDev ctx)
906 {
907 MppDevServer *srv = get_srv_server();
908 rk_s32 ret = rk_nok;
909
910 if (srv && ctx) {
911 MppDevMppService *dev = (MppDevMppService *)ctx;
912
913 ret = server_detach(srv, dev);
914 }
915
916 return ret;
917 }
918
mpp_server_send_task(MppDev ctx)919 rk_s32 mpp_server_send_task(MppDev ctx)
920 {
921 MppDevServer *srv = get_srv_server();
922 rk_s32 ret = rk_nok;
923
924 if (srv && ctx)
925 ret = send_task((MppDevMppService *)ctx);
926
927 return ret;
928 }
929
mpp_server_wait_task(MppDev ctx,rk_s64 timeout)930 rk_s32 mpp_server_wait_task(MppDev ctx, rk_s64 timeout)
931 {
932 MppDevServer *srv = get_srv_server();
933 rk_s32 ret = rk_nok;
934
935 if (srv && ctx)
936 ret = wait_task((MppDevMppService *)ctx, timeout);
937
938 return ret;
939 }
940
941 MPP_SINGLETON(MPP_SGLN_SERVER, mpp_server, mpp_server_init, mpp_server_deinit)
942