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