1 /*
2 * Copyright (C) 2021 HiSilicon (Shanghai) Technologies CO., LIMITED.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 */
18
19 #include "tde_osilist.h"
20 #ifdef HI_BUILD_IN_BOOT
21 #include "exports.h"
22 #endif
23 #ifdef HI_BUILD_IN_MINI_BOOT
24 #include "delay.h"
25 #endif
26 #include "tde_handle.h"
27 #include "tde_buffer.h"
28 #include "tde_hal.h"
29 #include "wmalloc.h"
30 #include "tde_handle.h"
31
32 /* JOB LIST head node definition */
33 typedef struct {
34 struct osal_list_head list;
35 hi_s32 handle_last; /* job handle wait for last submit */
36 hi_s32 handle_finished; /* job handle last completed */
37 hi_u32 job_num; /* job number in queue */
38 #ifndef HI_BUILD_IN_BOOT
39 osal_spinlock_t lock;
40 #endif
41 tde_swjob *job_committed; /* last submitted job node pointer, which is the first job */
42 tde_swjob *job_to_commit; /* job node pointer wait for submit,which is the first job */
43 hi_u32 job_finished;
44 tde_swjob *job_last; /* last job in the list */
45 } tde_swjoblist;
46
47 #ifndef HI_BUILD_IN_BOOT
48 typedef hi_void (*TDE_WQ_CB)(hi_u32);
49
50 typedef struct {
51 hi_u32 count;
52 TDE_WQ_CB wqcb;
53 struct osal_work_struct work;
54 } tdefreewq;
55
56 static osal_wait_t g_tde_block_job_wq; /* wait queue used to block */
57 #endif
58 static tde_swjoblist *g_tde_osi_job_list;
59
60 #ifdef TDE_HWC_COOPERATE
61 static hi_bool g_working_flag = HI_FALSE;
62 osal_spinlock_t g_working_flag_lock;
63 #endif
64
65 static hi_void tde_osi_list_do_free_phy_buff(hi_u32 buff_num);
66 static hi_void tde_osi_list_safe_destroy_job(tde_swjob *job);
67 static hi_void tde_osi_list_release_handle(hi_handle_mgr *job_header);
68 static hi_void tde_osi_list_add_job(tde_swjob *job);
69 static hi_void tde_osi_list_destroy_job(tde_swjob *job);
70
tde_osi_list_safe_destroy_job(tde_swjob * job)71 static hi_void tde_osi_list_safe_destroy_job(tde_swjob *job)
72 {
73 if (job == HI_NULL) {
74 return;
75 }
76 #ifndef HI_BUILD_IN_BOOT
77 /* if user query this job, release job in query function */
78 if (job->wait_for_done_count != 0) {
79 tde_info("query handle %d complete!\n", job->handle);
80 job->noti_type = TDE_JOB_NOTIFY_BUTT;
81 osal_wakeup(&job->query);
82 return;
83 }
84 #endif
85
86 tde_osi_list_destroy_job(job);
87
88 return;
89 }
90
tde_osi_list_release_handle(hi_handle_mgr * job_header)91 static hi_void tde_osi_list_release_handle(hi_handle_mgr *job_header)
92 {
93 if (job_header == HI_NULL) {
94 tde_error("pstJobHeader is null %s(line=%d)\n", __FUNCTION__, __LINE__);
95 return;
96 }
97 if (job_header != HI_NULL) {
98 if (tde_release_handle(job_header->handle)) {
99 tde_free(job_header);
100 }
101 }
102 return;
103 }
104
tde_osi_list_do_free_phy_buff(hi_u32 buff_num)105 static hi_void tde_osi_list_do_free_phy_buff(hi_u32 buff_num)
106 {
107 hi_u32 i;
108 for (i = 0; i < buff_num; i++) {
109 tde_free_physic_buff();
110 }
111 return;
112 }
113
tde_osi_list_init(hi_void)114 hi_s32 tde_osi_list_init(hi_void)
115 {
116 #ifndef HI_BUILD_IN_BOOT
117 if (osal_wait_init(&g_tde_block_job_wq) != 0) {
118 return HI_FAILURE;
119 }
120 #endif
121 if (!tde_initial_handle()) {
122 #ifndef HI_BUILD_IN_BOOT
123 osal_wait_destroy(&g_tde_block_job_wq);
124 #endif
125 return HI_FAILURE;
126 }
127
128 g_tde_osi_job_list = (tde_swjoblist *)tde_malloc(sizeof(tde_swjoblist));
129 if (g_tde_osi_job_list == HI_NULL) {
130 #ifndef HI_BUILD_IN_BOOT
131 osal_wait_destroy(&g_tde_block_job_wq);
132 #endif
133 tde_destroy_handle();
134 return HI_FAILURE;
135 }
136
137 OSAL_INIT_LIST_HEAD(&g_tde_osi_job_list->list);
138 #ifndef HI_BUILD_IN_BOOT
139 osal_spin_lock_init(&g_tde_osi_job_list->lock);
140 osal_spin_lock_init(&g_tde_buff_lock);
141
142 #ifdef TDE_HWC_COOPERATE
143 osal_spin_lock_init(&g_working_flag_lock);
144 #endif
145 #endif
146
147 return HI_SUCCESS;
148 }
149
tde_osi_list_free_node(tde_swnode * node)150 static hi_void tde_osi_list_free_node(tde_swnode *node)
151 {
152 if (node == HI_NULL) {
153 tde_error("pNode is null %s(line=%d)\n", __FUNCTION__, __LINE__);
154 return;
155 }
156 osal_list_del_init(&node->list);
157 if (node->node_buf.buf != HI_NULL) {
158 tde_free(node->node_buf.buf);
159 }
160
161 tde_osi_list_put_phy_buff(node->phy_buff_num);
162
163 tde_free(node);
164 }
165
166 /*
167 * Function: tde_osi_list_free_serial_cmd
168 * Description: release from FstCmd to LastCmd
169 * Input: fst_cmd: first node
170 * last_cmd:last node
171 */
tde_osi_list_free_serial_cmd(tde_swnode * fst_cmd,tde_swnode * last_cmd)172 hi_void tde_osi_list_free_serial_cmd(tde_swnode *fst_cmd, tde_swnode *last_cmd)
173 {
174 tde_swnode *next_cmd = HI_NULL;
175 tde_swnode *cur_cmd = HI_NULL;
176
177 if ((fst_cmd == HI_NULL) || (last_cmd == HI_NULL)) {
178 return;
179 }
180
181 cur_cmd = next_cmd = fst_cmd;
182 while (next_cmd != last_cmd) {
183 next_cmd = osal_list_entry(cur_cmd->list.next, tde_swnode, list);
184 if (next_cmd == HI_NULL) {
185 return;
186 }
187 tde_osi_list_free_node(cur_cmd);
188 cur_cmd = next_cmd;
189 }
190
191 tde_osi_list_free_node(last_cmd);
192 return;
193 }
194
195 #ifndef HI_BUILD_IN_BOOT
tde_osi_list_term(hi_void)196 hi_void tde_osi_list_term(hi_void)
197 {
198 tde_swjob *job = HI_NULL;
199
200 #ifndef HI_BUILD_IN_BOOT
201 osal_wait_destroy(&g_tde_block_job_wq);
202 #endif
203 osal_spin_lock_destroy(&g_tde_buff_lock);
204 #ifdef TDE_HWC_COOPERATE
205 osal_spin_lock_destroy(&g_working_flag_lock);
206 #endif
207 if (g_tde_osi_job_list == HI_NULL) {
208 return;
209 }
210
211 while (!osal_list_empty(&g_tde_osi_job_list->list)) {
212 job = osal_list_entry(g_tde_osi_job_list->list.next, tde_swjob, list);
213 osal_list_del_init(&job->list);
214 tde_osi_list_destroy_job(job);
215 }
216 osal_spin_lock_destroy(&g_tde_osi_job_list->lock);
217
218 tde_free(g_tde_osi_job_list);
219 g_tde_osi_job_list = HI_NULL;
220
221 tde_destroy_handle();
222 return;
223 }
224
tde_osi_list_flush_node(tde_swnode * node)225 hi_void tde_osi_list_flush_node(tde_swnode *node)
226 {
227 tde_node_buf *node_buf_info = HI_NULL;
228 hi_u32 cur_node_phy; /* The current node corresponding physical addresses */
229
230 if (node == HI_NULL) {
231 tde_error("pNode is null %s(line=%d)\n", __FUNCTION__, __LINE__);
232 return;
233 }
234
235 node_buf_info = &node->node_buf;
236
237 if (node_buf_info->buf != HI_NULL) {
238 cur_node_phy = wgetphy(node_buf_info->buf);
239 tde_flush_cached_mmb((hi_u8 *)node_buf_info->buf, cur_node_phy,
240 node_buf_info->node_sz + TDE_NODE_HEAD_BYTE + TDE_NODE_TAIL_BYTE);
241 }
242 return;
243 }
244
tde_osi_list_flush_job(tde_swjob * job)245 hi_void tde_osi_list_flush_job(tde_swjob *job)
246 {
247 tde_swnode *next_cmd = HI_NULL;
248 tde_swnode *cur_cmd = HI_NULL;
249 tde_swnode *fst_cmd = HI_NULL;
250 tde_swnode *last_cmd = HI_NULL;
251
252 if (job == HI_NULL) {
253 tde_error("pstJob is null %s(line=%d)\n", __FUNCTION__, __LINE__);
254 return;
255 }
256
257 fst_cmd = job->first_cmd;
258 last_cmd = job->tail_node;
259
260 if ((fst_cmd == HI_NULL) || (last_cmd == HI_NULL)) {
261 return;
262 }
263
264 cur_cmd = next_cmd = fst_cmd;
265 while (next_cmd != last_cmd) {
266 next_cmd = osal_list_entry(cur_cmd->list.next, tde_swnode, list);
267 tde_osi_list_flush_node(cur_cmd);
268 cur_cmd = next_cmd;
269 }
270
271 tde_osi_list_flush_node(last_cmd);
272 return;
273 }
274 #endif
275
tde_osi_list_add_job(tde_swjob * job)276 static hi_void tde_osi_list_add_job(tde_swjob *job)
277 {
278 osal_list_add_tail(&job->list, &g_tde_osi_job_list->list);
279 g_tde_osi_job_list->job_num++;
280 g_tde_osi_job_list->handle_last = job->handle;
281 g_tde_osi_job_list->job_last = job;
282 }
283
tde_osi_list_begin_job(hi_s32 * handle,hi_void * private_data)284 hi_s32 tde_osi_list_begin_job(hi_s32 *handle, hi_void *private_data)
285 {
286 hi_handle_mgr *handle_mgr = HI_NULL;
287 tde_swjob *job = HI_NULL;
288 hi_s32 ret;
289
290 if (handle == HI_NULL) {
291 return HI_ERR_TDE_NULL_PTR;
292 }
293 handle_mgr = (hi_handle_mgr *)tde_malloc(sizeof(hi_handle_mgr) + sizeof(tde_swjob));
294 if (handle_mgr == HI_NULL) {
295 tde_error("TDE BegJob Malloc Fail!\n");
296 return HI_ERR_TDE_NO_MEM;
297 }
298 job = (tde_swjob *)((hi_u8 *)handle_mgr + sizeof(hi_handle_mgr));
299 handle_mgr->res = (hi_void *)job;
300 tde_get_handle(handle_mgr, handle);
301 #ifndef HI_BUILD_IN_BOOT
302 ret = osal_wait_init(&job->query);
303 if (ret != 0) {
304 tde_error("osal_wait_init Fail!\n");
305 tde_osi_list_release_handle(handle_mgr);
306 return HI_ERR_TDE_NO_MEM;
307 }
308 #endif
309 OSAL_INIT_LIST_HEAD(&job->list);
310 job->handle = *handle;
311 if (private_data != HI_NULL) {
312 job->private_data = private_data;
313 }
314 return HI_SUCCESS;
315 }
316
tde_osi_list_destroy_job(tde_swjob * job)317 static hi_void tde_osi_list_destroy_job(tde_swjob *job)
318 {
319 hi_handle_mgr *handle_mgr = HI_NULL;
320
321 #ifdef CONFIG_GFX_MMU_SUPPORT
322 tde_hw_node *hw_node = HI_NULL;
323 #endif
324
325 if (!tde_query_handle(job->handle, &handle_mgr)) {
326 tde_info("handle %d does not exist!\n", job->handle);
327 return;
328 }
329
330 #ifdef CONFIG_GFX_MMU_SUPPORT
331 hw_node = (tde_hw_node *)(job->first_cmd->node_buf.buf + TDE_NODE_HEAD_BYTE);
332 tde_hal_free_tmp_buf(hw_node);
333 #endif
334
335 tde_osi_list_free_serial_cmd(job->first_cmd, job->tail_node);
336
337 #ifndef HI_BUILD_IN_BOOT
338 osal_wait_destroy(&job->query);
339 #endif
340
341 tde_osi_list_release_handle(handle_mgr);
342
343 return;
344 }
345
346 #ifndef HI_BUILD_IN_BOOT
tde_osi_list_cancel_job(hi_s32 handle)347 hi_s32 tde_osi_list_cancel_job(hi_s32 handle)
348 {
349 hi_handle_mgr *handle_mgr = HI_NULL;
350 tde_swjob *job = HI_NULL;
351 #ifndef HI_BUILD_IN_BOOT
352 unsigned long lockflags;
353 #endif
354
355 tde_spin_lock(&g_tde_osi_job_list->lock, lockflags);
356 if (!tde_query_handle(handle, &handle_mgr)) {
357 tde_spin_unlock(&g_tde_osi_job_list->lock, lockflags);
358 return HI_SUCCESS;
359 }
360 job = (tde_swjob *)handle_mgr->res;
361
362 if (job->submitted) {
363 tde_spin_unlock(&g_tde_osi_job_list->lock, lockflags);
364 tde_error("Handle %d has been submitted!\n", handle);
365 return HI_FAILURE;
366 }
367
368 tde_osi_list_free_serial_cmd(job->first_cmd, job->tail_node);
369
370 #ifndef HI_BUILD_IN_BOOT
371 osal_wait_destroy(&job->query);
372 #endif
373
374 tde_osi_list_release_handle(handle_mgr);
375 tde_spin_unlock(&g_tde_osi_job_list->lock, lockflags);
376 return HI_SUCCESS;
377 }
378 #else
tde_osi_list_wait_tde_idle(hi_void)379 static hi_void tde_osi_list_wait_tde_idle(hi_void)
380 {
381 while (1) {
382 udelay(10 * 1000); /* delay 10*1000 ms */
383 if (tde_hal_ctl_is_idle_safely()) {
384 return;
385 }
386 }
387 }
388 #endif
389
tdeosi_wait_call_back(const hi_void * param)390 hi_s32 tdeosi_wait_call_back(const hi_void *param)
391 {
392 tde_swjob *job = HI_NULL;
393
394 if (param == HI_NULL) {
395 return HI_FAILURE;
396 }
397 job = (tde_swjob *)param;
398 return (job->noti_type == TDE_JOB_NOTIFY_BUTT);
399 }
400
tde_job_to_commit(tde_swjob * job,tde_func_cb func_compl_cb,hi_void * func_para,tde_notify_mode noti_type)401 static hi_void tde_job_to_commit(tde_swjob *job, tde_func_cb func_compl_cb, hi_void *func_para,
402 tde_notify_mode noti_type)
403 {
404 hi_u8 *next_node_buf = HI_NULL;
405
406 job->submitted = HI_TRUE;
407 job->noti_type = noti_type;
408 job->func_compl_cb = func_compl_cb;
409 job->func_para = func_para;
410 /* If the job to commit is not null,join the current job to the tail node of the last job. */
411 if (g_tde_osi_job_list->job_to_commit != HI_NULL) {
412 tde_swnode *tail_node_in_job_list = g_tde_osi_job_list->job_last->tail_node;
413 next_node_buf = (hi_u8 *)tail_node_in_job_list->node_buf.buf + TDE_NODE_HEAD_BYTE;
414 tde_hal_next_node_addr((hi_void *)next_node_buf, job->first_cmd->node_buf.phy_addr);
415 if (job->aq_use_buff) {
416 g_tde_osi_job_list->job_to_commit->aq_use_buff = HI_TRUE;
417 }
418 #ifdef TDE_CACH_STRATEGY
419 /* Flush all hw will be the job of the corresponding node into memory, ensure correct hardware can access */
420 tde_osi_list_flush_job(g_tde_osi_job_list->job_last);
421 #endif
422 } else {
423 g_tde_osi_job_list->job_to_commit = job;
424 }
425
426 #ifdef TDE_CACH_STRATEGY
427 /* Flush all hw will be the job of the corresponding node into memory, ensure correct hardware can access */
428 tde_osi_list_flush_job(job);
429 #endif
430 tde_osi_list_add_job(job);
431 return;
432 }
433
434 #if (TDE_CAPABILITY & SYNC)
tde_list_set_job(tde_swjob ** job,hi_s32 handle,hi_bool is_sync)435 static hi_s32 tde_list_set_job(tde_swjob **job, hi_s32 handle, hi_bool is_sync)
436 #else
437 static hi_s32 tde_list_set_job(tde_swjob **job, hi_s32 handle)
438 #endif
439 {
440 hi_bool valid = HI_FALSE;
441 hi_handle_mgr *handle_mgr = HI_NULL;
442 tde_swnode *tail_node = HI_NULL;
443 hi_u8 *buf = HI_NULL;
444
445 valid = tde_query_handle(handle, &handle_mgr);
446 if (!valid) {
447 tde_error("invalid handle %d!\n", handle);
448 return HI_ERR_TDE_INVALID_HANDLE;
449 }
450
451 *job = (tde_swjob *)handle_mgr->res;
452 if ((*job)->submitted) {
453 tde_error("job %d already submitted!\n", handle);
454 return HI_ERR_TDE_INVALID_HANDLE;
455 }
456 if ((*job)->first_cmd == HI_NULL) {
457 tde_info("no cmd !\n");
458
459 #ifndef HI_BUILD_IN_BOOT
460 osal_wait_destroy(&(*job)->query);
461 #endif
462 tde_osi_list_release_handle(handle_mgr);
463 return HI_FAILURE;
464 }
465 tail_node = (*job)->tail_node;
466
467 buf = (hi_u8 *)tail_node->node_buf.buf + TDE_NODE_HEAD_BYTE;
468 tde_hal_node_enable_complete_int((hi_void *)buf);
469
470 #if (TDE_CAPABILITY & SYNC)
471 if (is_sync) {
472 tde_hal_node_enable_sync((hi_void *)buf);
473 }
474 #endif
475 return HI_SUCCESS;
476 }
477
tde_list_submit_first_cmd(hi_void)478 static hi_void tde_list_submit_first_cmd(hi_void)
479 {
480 hi_s32 ret;
481 #ifdef TDE_HWC_COOPERATE
482 unsigned long lock;
483 #endif
484
485 #ifdef TDE_HWC_COOPERATE
486 tde_osi_list_lock_working_flag(&lock);
487 if (!g_working_flag) {
488 #endif
489 ret = tde_hal_node_execute(g_tde_osi_job_list->job_to_commit->first_cmd->node_buf.phy_addr,
490 g_tde_osi_job_list->job_to_commit->first_cmd->node_buf.update,
491 g_tde_osi_job_list->job_to_commit->aq_use_buff);
492 if (ret == HI_SUCCESS) {
493 g_tde_osi_job_list->job_committed = g_tde_osi_job_list->job_to_commit;
494 g_tde_osi_job_list->job_to_commit = HI_NULL;
495 g_tde_osi_job_list->job_finished = 0x0;
496 #ifdef TDE_HWC_COOPERATE
497 g_working_flag = 1;
498 #endif
499 }
500 #ifdef TDE_HWC_COOPERATE
501 }
502 #endif
503
504 #ifdef TDE_HWC_COOPERATE
505 tde_osi_list_unlock_working_flag(&lock);
506 #endif
507 return;
508 }
509
tde_osi_list_event(tde_swjob * job,tde_notify_mode noti_type,hi_bool asynflag,hi_u32 time_out)510 static hi_s32 tde_osi_list_event(tde_swjob *job, tde_notify_mode noti_type, hi_bool asynflag, hi_u32 time_out)
511 {
512 unsigned long lockflags;
513 hi_s32 ret;
514 tde_spin_lock(&g_tde_osi_job_list->lock, lockflags);
515 if (noti_type == TDE_JOB_WAKE_NOTIFY) {
516 job->wait_for_done_count++;
517 tde_spin_unlock(&g_tde_osi_job_list->lock, lockflags);
518 ret = osal_wait_event_timeout_uninterruptible(&g_tde_block_job_wq, tdeosi_wait_call_back, (hi_void *)job,
519 time_out);
520 tde_spin_lock(&g_tde_osi_job_list->lock, lockflags);
521 job->wait_for_done_count--;
522 if (job->noti_type == TDE_JOB_NOTIFY_BUTT) {
523 tde_info("handle:%d complete!\n", job->handle);
524 if (job->wait_for_done_count == 0) {
525 tde_osi_list_destroy_job(job);
526 }
527 tde_spin_unlock(&g_tde_osi_job_list->lock, lockflags);
528 return -1;
529 } else {
530 job->noti_type = TDE_JOB_COMPL_NOTIFY;
531 tde_spin_unlock(&g_tde_osi_job_list->lock, lockflags);
532 if (ret == (-ERESTARTSYS)) {
533 tde_error("handle:%d interrupt!\n", job->handle);
534 return HI_ERR_TDE_INTERRUPT;
535 }
536 if (asynflag == 1) {
537 /* If from a non-blocking way to block the way, no overtime information */
538 return -1;
539 }
540 tde_error("handle:%d timeout!\n", job->handle);
541 return HI_ERR_TDE_JOB_TIMEOUT;
542 }
543 }
544 tde_spin_unlock(&g_tde_osi_job_list->lock, lockflags);
545 return HI_SUCCESS;
546 }
547
tde_set_job_wake_notify(tde_swjob * job,tde_notify_mode * noti_type,hi_u32 * time_out,hi_bool * asynflag)548 static hi_void tde_set_job_wake_notify(tde_swjob *job, tde_notify_mode *noti_type, hi_u32 *time_out,
549 hi_bool *asynflag)
550 {
551 #ifndef HI_BUILD_IN_BOOT
552 if (*noti_type != TDE_JOB_WAKE_NOTIFY) {
553 if ((!osal_in_interrupt()) && (wgetfreenum() < 5)) { /* 5 num */
554 job->noti_type = TDE_JOB_WAKE_NOTIFY;
555 *noti_type = TDE_JOB_WAKE_NOTIFY;
556 *time_out = 1000; /* timeout 1000ms */
557 *asynflag = 1; /* By sign non-blocking way to block the way */
558 }
559 }
560 #endif
561 return;
562 }
563
564 #ifdef HI_BUILD_IN_BOOT
tde_osi_idle(tde_swjob * job)565 static hi_void tde_osi_idle(tde_swjob *job)
566 {
567 /* Waiting for the TDE task to complete */
568 tde_osi_list_wait_tde_idle();
569 /* Deleted from the list the job node, prevent again traverse to the node */
570 osal_list_del_init(&job->list);
571 /* release job */
572 tde_osi_list_safe_destroy_job(job);
573
574 tde_info("handle:%d complete!\n", job->handle);
575 }
576 #endif
577
578 #if (TDE_CAPABILITY & SYNC)
tde_osi_list_submit_job(drv_tde_end_job_cmd * end_job,tde_func_cb func_compl_cb,hi_void * func_para,tde_notify_mode noti_type,hi_bool is_sync)579 hi_s32 tde_osi_list_submit_job(drv_tde_end_job_cmd *end_job, tde_func_cb func_compl_cb, hi_void *func_para,
580 tde_notify_mode noti_type, hi_bool is_sync)
581 #else
582 hi_s32 tde_osi_list_submit_job(drv_tde_end_job_cmd *end_job, tde_func_cb func_compl_cb, hi_void *func_para,
583 tde_notify_mode noti_type)
584 #endif
585 {
586 tde_swjob *job = HI_NULL;
587 hi_s32 ret;
588 hi_s32 handle = end_job->handle;
589 hi_u32 time_out = end_job->time_out;
590 #ifndef HI_BUILD_IN_BOOT
591 unsigned long lockflags;
592 hi_bool asynflag = HI_FALSE;
593 #endif
594
595 tde_spin_lock(&g_tde_osi_job_list->lock, lockflags);
596 #if (TDE_CAPABILITY & SYNC)
597 ret = tde_list_set_job(&job, handle, is_sync);
598 if (ret != HI_SUCCESS) {
599 #else
600 ret = tde_list_set_job(&job, handle);
601 if (ret != HI_SUCCESS) {
602 #endif
603 tde_spin_unlock(&g_tde_osi_job_list->lock, lockflags);
604 if (ret == -1) {
605 return HI_SUCCESS;
606 }
607 return ret;
608 }
609 tde_job_to_commit(job, func_compl_cb, func_para, noti_type);
610 tde_set_job_wake_notify(job, ¬i_type, &time_out, &asynflag);
611 tde_list_submit_first_cmd();
612
613 #ifndef HI_BUILD_IN_BOOT
614 tde_spin_unlock(&g_tde_osi_job_list->lock, lockflags);
615 ret = tde_osi_list_event(job, noti_type, asynflag, time_out);
616 if (ret != HI_SUCCESS) {
617 if (ret == -1) {
618 return HI_SUCCESS;
619 }
620 return ret;
621 }
622 #else
623 tde_osi_idle(job);
624 #endif
625 return HI_SUCCESS;
626 }
627
628 #ifndef HI_BUILD_IN_BOOT
629 /*
630 * Prototype : tde_osi_list_wait_all_done
631 * Description : wait for all TDE operate is completed,that is to say wait for the last job to be completed.
632 * Return Value : HI_SUCCESS,TDE operate completed
633 */
634 hi_s32 tde_osi_list_wait_all_done(hi_void)
635 {
636 hi_s32 wait_handle;
637 unsigned long lockflags;
638
639 tde_spin_lock(&g_tde_osi_job_list->lock, lockflags);
640 wait_handle = g_tde_osi_job_list->handle_last;
641 tde_spin_unlock(&g_tde_osi_job_list->lock, lockflags);
642 if (wait_handle == -1) {
643 return HI_SUCCESS;
644 }
645 return tde_osi_list_wait_for_done(wait_handle, 0);
646 }
647
648 static hi_s32 tde_osi_list_timeout(tde_swjob *job, hi_u32 time_out)
649 {
650 hi_s32 ret;
651 unsigned long lockflags;
652
653 ret = osal_wait_event_timeout_uninterruptible(&(job->query), tdeosi_wait_call_back, (hi_void *)job, time_out);
654 tde_spin_lock(&g_tde_osi_job_list->lock, lockflags);
655 job->wait_for_done_count--;
656
657 if (job->noti_type != TDE_JOB_NOTIFY_BUTT) {
658 tde_spin_unlock(&g_tde_osi_job_list->lock, lockflags);
659 if (ret == (-ERESTARTSYS)) {
660 tde_error("query handle (%d) interrupt!\n", job->handle);
661 return HI_ERR_TDE_INTERRUPT;
662 } else {
663 tde_error("query handle (%d) time out!\n", job->handle);
664 }
665 return HI_ERR_TDE_QUERY_TIMEOUT;
666 }
667
668 /* complete */
669 if (job->wait_for_done_count == 0) {
670 tde_osi_list_destroy_job(job);
671 }
672 tde_spin_unlock(&g_tde_osi_job_list->lock, lockflags);
673 return HI_SUCCESS;
674 }
675
676 /*
677 * Function: tde_osi_list_wait_for_done
678 * Description: block to wait for job done
679 * Input: handle: job handle
680 * time_out: timeout value
681 * Return: =0,successfully completed <0,error
682 */
683 hi_s32 tde_osi_list_wait_for_done(hi_s32 handle, hi_u32 time_out)
684 {
685 tde_swjob *job = HI_NULL;
686 hi_handle_mgr *handle_mgr = HI_NULL;
687 hi_s32 ret;
688 hi_bool valid = HI_FALSE;
689 unsigned long lockflags;
690
691 tde_spin_lock(&g_tde_osi_job_list->lock, lockflags);
692 valid = tde_query_handle(handle, &handle_mgr);
693 if (!valid) {
694 tde_spin_unlock(&g_tde_osi_job_list->lock, lockflags);
695 return HI_SUCCESS;
696 }
697
698 job = (tde_swjob *)handle_mgr->res;
699 if (!job->submitted) {
700 tde_spin_unlock(&g_tde_osi_job_list->lock, lockflags);
701 tde_error("job %d has no submitted!\n", handle);
702 return HI_ERR_TDE_INVALID_HANDLE;
703 }
704 job->wait_for_done_count++;
705 tde_spin_unlock(&g_tde_osi_job_list->lock, lockflags);
706 if (time_out) {
707 ret = tde_osi_list_timeout(job, time_out);
708 if (ret != HI_SUCCESS) {
709 return ret;
710 }
711 return HI_SUCCESS;
712 }
713 ret = osal_wait_event_interruptible(&(job->query), tdeosi_wait_call_back, (hi_void *)job);
714 tde_spin_lock(&g_tde_osi_job_list->lock, lockflags);
715 job->wait_for_done_count--;
716 if (ret == (-ERESTARTSYS)) {
717 if ((job->noti_type == TDE_JOB_NOTIFY_BUTT) && (job->wait_for_done_count == 0)) {
718 tde_osi_list_destroy_job(job);
719 }
720 tde_spin_unlock(&g_tde_osi_job_list->lock, lockflags);
721 tde_error("query handle (%d) interrupt!\n", job->handle);
722 return HI_ERR_TDE_INTERRUPT;
723 }
724
725 if (job->wait_for_done_count == 0) {
726 tde_osi_list_destroy_job(job);
727 }
728 tde_spin_unlock(&g_tde_osi_job_list->lock, lockflags);
729 return HI_SUCCESS;
730 }
731
732 /*
733 * Prototype : tde_osi_list_comp_proc
734 * Description : list complete interrupt servic, mainly complete switch on hardware lists
735 * Modification : Created function
736 */
737 hi_void tde_osi_list_comp_proc()
738 {
739 hi_s32 ret;
740
741 if (g_tde_osi_job_list->job_to_commit != HI_NULL) {
742 ret = tde_hal_node_execute(g_tde_osi_job_list->job_to_commit->first_cmd->node_buf.phy_addr,
743 g_tde_osi_job_list->job_to_commit->first_cmd->node_buf.update,
744 g_tde_osi_job_list->job_to_commit->aq_use_buff);
745 if (ret == HI_SUCCESS) {
746 g_tde_osi_job_list->job_committed = g_tde_osi_job_list->job_to_commit;
747 g_tde_osi_job_list->job_to_commit = HI_NULL;
748 g_tde_osi_job_list->job_finished = 0x0;
749
750 #ifdef TDE_HWC_COOPERATE
751 g_working_flag = 1;
752 #endif
753 }
754 }
755
756 return;
757 }
758
759 #ifdef TDE_HWC_COOPERATE
760 hi_void tde_osi_list_comp(hi_void)
761 {
762 unsigned long lockflags;
763 unsigned long lock;
764
765 tde_spin_lock(&g_tde_osi_job_list->lock, lock);
766 tde_osi_list_lock_working_flag(&lockflags);
767 if (!g_working_flag) {
768 if (tde_hal_ctl_is_idle_safely()) {
769 tde_osi_list_comp_proc();
770 }
771 }
772
773 tde_osi_list_unlock_working_flag(&lockflags);
774 tde_spin_unlock(&g_tde_osi_job_list->lock, lock);
775 return;
776 }
777 #endif
778
779 static hi_s32 tde_list_comp_get_finished_handle(hi_s32 *finished_handle, hi_handle_mgr *handle_mgr)
780 {
781 tde_swjob *job = HI_NULL;
782 tde_swjob *del_job = HI_NULL;
783
784 job = (tde_swjob *)handle_mgr->res;
785 if (job->list.prev == &g_tde_osi_job_list->list) {
786 tde_info("No pre Job left, finishedhandle:%d\n", *finished_handle);
787 return HI_FAILURE;
788 }
789
790 del_job = osal_list_entry(job->list.prev, tde_swjob, list);
791 *finished_handle = del_job->handle;
792 g_tde_osi_job_list->job_finished = 0x0;
793 return HI_SUCCESS;
794 }
795
796 static hi_void tde_list_comp_wakeup(tde_swjob *del_job, hi_size_t *lockflags)
797 {
798 tde_info("handle:%d!\n", del_job->handle);
799 del_job->noti_type = TDE_JOB_NOTIFY_BUTT;
800 if (del_job->func_compl_cb != HI_NULL) {
801 tde_info("handle:%d has callback func!\n", del_job->handle);
802 osal_spin_unlock_irqrestore(&g_tde_osi_job_list->lock, lockflags);
803 del_job->func_compl_cb(del_job->func_para, &(del_job->handle));
804 osal_spin_lock_irqsave(&g_tde_osi_job_list->lock, lockflags);
805 }
806
807 if (del_job->wait_for_done_count != 0) {
808 tde_info("query handle %d complete!\n", del_job->handle);
809 osal_wakeup(&del_job->query);
810 }
811
812 osal_wakeup(&g_tde_block_job_wq);
813 }
814
815 static hi_void tde_list_comp_proc_job(hi_void)
816 {
817 if (tde_hal_ctl_is_idle_safely()) {
818 tde_hal_ctl_int_status();
819 tde_osi_list_comp_proc();
820 }
821 }
822
823 static hi_s32 tde_list_comp_delete_job(hi_bool work, hi_s32 finished_handle, hi_size_t *lockflags)
824 {
825 tde_swjob *del_job = HI_NULL;
826 hi_s32 delhandle;
827 #ifdef TDE_HWC_COOPERATE
828 unsigned long lock;
829 #endif
830
831 while (!osal_list_empty(&g_tde_osi_job_list->list)) {
832 del_job = osal_list_entry(g_tde_osi_job_list->list.next, tde_swjob, list);
833 delhandle = del_job->handle;
834 g_tde_osi_job_list->job_num--;
835 if (delhandle == g_tde_osi_job_list->handle_last) {
836 g_tde_osi_job_list->handle_last = -1;
837 }
838 osal_list_del_init(&del_job->list);
839 if (del_job->noti_type == TDE_JOB_WAKE_NOTIFY) {
840 tde_list_comp_wakeup(del_job, lockflags);
841 } else if (del_job->noti_type == TDE_JOB_COMPL_NOTIFY) {
842 tde_info("handle:%d!\n", del_job->handle);
843 if (del_job->func_compl_cb != HI_NULL) {
844 tde_info("handle:%d has callback func!\n", del_job->handle);
845 osal_spin_unlock_irqrestore(&g_tde_osi_job_list->lock, lockflags);
846 del_job->func_compl_cb(del_job->func_para, &(del_job->handle));
847 osal_spin_lock_irqsave(&g_tde_osi_job_list->lock, lockflags);
848 }
849 tde_osi_list_safe_destroy_job(del_job);
850 } else {
851 tde_error("Error Status!!\n");
852 }
853 if (delhandle == finished_handle) {
854 if (!work) {
855 #ifdef TDE_HWC_COOPERATE
856 tde_osi_list_lock_working_flag(&lock);
857 g_working_flag = 0;
858 tde_osi_list_unlock_working_flag(&lock);
859 #else
860 tde_list_comp_proc_job();
861 #endif
862 }
863 osal_spin_unlock_irqrestore(&g_tde_osi_job_list->lock, lockflags);
864 return HI_SUCCESS;
865 }
866 }
867 return HI_FAILURE;
868 }
869
870 /*
871 * Function: tde_osi_list_node_comp
872 * Description: node complete interrupt service, maily complete deleting node and resume suspending,free node
873 * Return: create job handle
874 * Modification : Created function
875 */
876 hi_void tde_osi_list_node_comp()
877 {
878 hi_handle_mgr *handle_mgr = HI_NULL;
879 hi_s32 finished_handle;
880 hi_u64 running_sw_node_addr;
881 hi_bool work = HI_TRUE;
882 hi_u32 *finish_handle = HI_NULL;
883 unsigned long lockflags;
884
885 tde_spin_lock(&g_tde_osi_job_list->lock, lockflags);
886 if (tde_hal_ctl_is_idle_safely()) {
887 work = HI_FALSE;
888 }
889 running_sw_node_addr = tde_hal_cur_node();
890 if ((running_sw_node_addr == 0) || (running_sw_node_addr == g_tde_osi_job_list->job_finished)) {
891 tde_spin_unlock(&g_tde_osi_job_list->lock, lockflags);
892 return;
893 }
894
895 finish_handle = (hi_u32 *)wgetvrt(running_sw_node_addr - TDE_NODE_HEAD_BYTE + 8); /* 8 alg data */
896 if (finish_handle == HI_NULL) {
897 tde_spin_unlock(&g_tde_osi_job_list->lock, lockflags);
898 return;
899 }
900
901 finished_handle = *finish_handle;
902 if (!tde_query_handle(finished_handle, &handle_mgr)) {
903 tde_spin_unlock(&g_tde_osi_job_list->lock, lockflags);
904 return;
905 }
906 if (!work) {
907 g_tde_osi_job_list->job_finished = running_sw_node_addr;
908 } else if (tde_list_comp_get_finished_handle(&finished_handle, handle_mgr) < 0) {
909 tde_spin_unlock(&g_tde_osi_job_list->lock, lockflags);
910 return;
911 }
912
913 if (!tde_query_handle(finished_handle, &handle_mgr)) {
914 tde_info("handle %d already delete!\n", finished_handle);
915 tde_spin_unlock(&g_tde_osi_job_list->lock, lockflags);
916 return;
917 }
918
919 g_tde_osi_job_list->handle_finished = finished_handle;
920 if (tde_list_comp_delete_job(work, finished_handle, &lockflags) == HI_SUCCESS) {
921 return;
922 }
923 if (tde_hal_ctl_is_idle_safely()) {
924 tde_info("tde_hal_ctl_is_idle_safely HI_FALSE!\r\n");
925 }
926 tde_spin_unlock(&g_tde_osi_job_list->lock, lockflags);
927 }
928 #endif
929
930 /*
931 * Function: tde_osi_list_get_phy_buff
932 * Description: get one physical buffer, to deflicker and zoom
933 * Return: created job handle
934 */
935 hi_u32 tde_osi_list_get_phy_buff(hi_u32 cb_cr_offset)
936 {
937 #ifndef HI_BUILD_IN_BOOT
938 if (osal_in_interrupt()) {
939 return 0;
940 }
941 #endif
942 return tde_alloc_physic_buff(cb_cr_offset);
943 }
944
945 #ifndef HI_BUILD_IN_BOOT
946 void tde_osi_list_freevmem(struct osal_work_struct *work)
947 {
948 tdefreewq *w_queue_info = osal_container_of(work, tdefreewq, work);
949 if (w_queue_info != HI_NULL) {
950 w_queue_info->wqcb(w_queue_info->count);
951 tde_free(w_queue_info);
952 }
953 return;
954 }
955
956 void tde_osi_list_hsr(hi_void *func, hi_u32 data)
957 {
958 tdefreewq *wq = HI_NULL;
959
960 wq = tde_malloc(sizeof(tdefreewq));
961 if (wq == HI_NULL) {
962 tde_error("Malloc TDEFREEWQ_S failed!\n");
963 return;
964 }
965 wq->count = data;
966 wq->wqcb = (TDE_WQ_CB)func;
967 OSAL_INIT_WORK(&wq->work, tde_osi_list_freevmem);
968 osal_schedule_work(&wq->work);
969 return;
970 }
971 #endif
972
973 hi_void tde_osi_list_put_phy_buff(hi_u32 buff_num)
974 {
975 if (buff_num == 0) {
976 return;
977 }
978 #ifndef HI_BUILD_IN_BOOT
979 tde_osi_list_hsr((hi_void *)tde_osi_list_do_free_phy_buff, buff_num);
980 #else
981 tde_osi_list_do_free_phy_buff(buff_num);
982 #endif
983 return;
984 }
985
986 #ifdef TDE_HWC_COOPERATE
987 hi_s32 tde_osi_list_lock_working_flag(unsigned long *lock)
988 {
989 if (lock == HI_NULL) {
990 return HI_FAILURE;
991 }
992 tde_spin_lock(&g_working_flag_lock, *lock);
993
994 return HI_SUCCESS;
995 }
996
997 hi_s32 tde_osi_list_unlock_working_flag(unsigned long *lock)
998 {
999 if (lock == HI_NULL) {
1000 return HI_FAILURE;
1001 }
1002 tde_spin_unlock(&g_working_flag_lock, *lock);
1003
1004 return HI_SUCCESS;
1005 }
1006
1007 hi_s32 tde_osi_list_get_working_flag(hi_bool *flag)
1008 {
1009 if (flag == HI_NULL) {
1010 return HI_FAILURE;
1011 }
1012 *flag = g_working_flag;
1013
1014 return HI_SUCCESS;
1015 }
1016 #endif
1017
1018 hi_void tde_free_pending_job(hi_void *private_data)
1019 {
1020 hi_handle_mgr *handle = HI_NULL;
1021 hi_handle_mgr *save = HI_NULL;
1022 tde_swjob *job = HI_NULL;
1023 unsigned long lockflags;
1024 hi_handle_mgr *tde_handle_list = tde_get_handle_list();
1025
1026 if (tde_handle_list == HI_NULL) {
1027 return;
1028 }
1029 tde_spin_lock(&g_tde_osi_job_list->lock, lockflags);
1030 handle = osal_list_entry(tde_handle_list->header.next, hi_handle_mgr, header);
1031 if (handle == HI_NULL) {
1032 tde_info("No pending job!!\n");
1033 tde_spin_unlock(&g_tde_osi_job_list->lock, lockflags);
1034 return;
1035 }
1036 while (handle != tde_handle_list) {
1037 save = handle;
1038 job = (tde_swjob *)save->res;
1039 /* debug */
1040 if (job == HI_NULL) {
1041 tde_error("ERR:pstJob Null Pointer!!!\n");
1042 tde_spin_unlock(&g_tde_osi_job_list->lock, lockflags);
1043 return;
1044 }
1045
1046 /* END */
1047 handle = osal_list_entry(handle->header.next, hi_handle_mgr, header);
1048 /* free when it is not submitted */
1049 #ifndef __RTOS__
1050 if ((!job->submitted) && (private_data == job->private_data)) {
1051 #else
1052 if (!job->submitted) {
1053 hi_unused(private_data);
1054 #endif
1055 /* free handle resource */
1056 tde_osi_list_free_serial_cmd(job->first_cmd, job->tail_node);
1057 #ifndef HI_BUILD_IN_BOOT
1058 osal_wait_destroy(&job->query);
1059 #endif
1060 osal_list_del_init(&save->header);
1061 tde_free(save);
1062 }
1063
1064 if (handle == HI_NULL) {
1065 tde_error("ERR: pstHandle Null Pointer!!\n");
1066 tde_spin_unlock(&g_tde_osi_job_list->lock, lockflags);
1067 return;
1068 }
1069 }
1070 tde_spin_unlock(&g_tde_osi_job_list->lock, lockflags);
1071 return;
1072 }
1073