xref: /rockchip-linux_mpp/osal/driver/mpp_server.c (revision 437bfbeb9567cca9cd9080e3f6954aa9d6a94f18)
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