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