• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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, &noti_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