• 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 /* 1 头文件包含 */
19 #if (_PRE_OS_VERSION_LITEOS == _PRE_OS_VERSION)
20 #include "hi_task.h"
21 #endif
22 #include "frw_event.h"
23 #include "frw_task.h"
24 #include "frw_main.h"
25 
26 #ifdef __cplusplus
27 #if __cplusplus
28 extern "C" {
29 #endif
30 #endif
31 #if (_PRE_OS_VERSION_LINUX == _PRE_OS_VERSION)
32 #define FRW_THREAD_NAME_MAX_SIZE 20
33 #endif
34 #if (_PRE_FRW_FEATURE_PROCESS_ENTITY_TYPE == _PRE_FRW_FEATURE_PROCESS_ENTITY_THREAD)
35 #define FRW_TASK_PRIO 4 /* 驱动task的优先级,建议比上层高 */
36 hi_char g_frw_thread_name[] = { "hisi_frw" };
37 #endif
38 /* *****************************************************************************
39     事件处理全局变量
40 ****************************************************************************** */
41 frw_task_stru g_ast_event_task;
42 /* ****************************************************************************
43     线程退出标志全局变量
44 ****************************************************************************** */
45 hi_u8 g_frw_exit = HI_FALSE;
46 hi_u8 g_frw_stop = HI_FALSE;
47 /* ****************************************************************************
48   3 函数实现
49 **************************************************************************** */
50 #if (_PRE_FRW_FEATURE_PROCESS_ENTITY_TYPE == _PRE_FRW_FEATURE_PROCESS_ENTITY_THREAD)
51 /* ****************************************************************************S
52  功能描述  : frw 内核线程主程序
53 **************************************************************************** */
54 #if (_PRE_OS_VERSION_LITEOS == _PRE_OS_VERSION)
frw_task_thread(hi_void * bind_cpu)55 hi_void *frw_task_thread(hi_void *bind_cpu)
56 {
57 #if (_PRE_MULTI_CORE_MODE != _PRE_MULTI_CORE_MODE_OFFLOAD_HMAC)
58     hi_u32 event;
59 #else
60     hi_s32 ret;
61 #endif
62     hi_unref_param(bind_cpu);
63     /* 死循环直至事件调度完 */
64     for (;;) {
65 #if (_PRE_MULTI_CORE_MODE != _PRE_MULTI_CORE_MODE_OFFLOAD_HMAC)
66         while (!frw_task_thread_condition_check()) {
67             hi_event_wait(get_app_event_id(), HI_EVENT_FRW_TASK, &event, HI_SYS_WAIT_FOREVER,
68                 HI_EVENT_WAITMODE_AND | HI_EVENT_WAITMODE_CLR);
69         }
70 #else
71         /* state为TASK_INTERRUPTIBLE,condition不成立则线程阻塞,直到被唤醒进入waitqueue */
72         ret = hi_wait_event_interruptible(g_ast_event_task.frw_wq, frw_task_thread_condition_check() == HI_TRUE);
73         if (oal_unlikely(ret == -ERESTARTSYS)) {
74             hi_diag_log_msg_i0(0, "wifi task was interrupted by a signal\n");
75             break;
76         }
77 #endif
78         frw_event_process_all_event();
79     }
80     return HI_NULL; /* 任务管理函数,for (;;) 死循环后需要return,lin_t e527告警屏蔽 */
81 }
82 #endif
83 #endif /* #if (_PRE_FRW_FEATURE_PROCESS_ENTITY_TYPE == _PRE_FRW_FEATURE_PROCESS_ENTITY_THREAD) */
84 /* ****************************************************************************
85  功能描述  : kthread初始化接口
86 **************************************************************************** */
87 #if (_PRE_OS_VERSION_LITEOS == _PRE_OS_VERSION)
frw_task_init(void)88 hi_u32 frw_task_init(void)
89 {
90     /* 对固定长度的数组进行初始化,或对固定长度的结构体进行内存初始化 */
91     memset_s(&g_ast_event_task, sizeof(g_ast_event_task), 0, sizeof(g_ast_event_task));
92 
93     hi_wait_queue_init_head(&g_ast_event_task.frw_wq);
94 
95 #if (_PRE_FRW_FEATURE_PROCESS_ENTITY_TYPE == _PRE_FRW_FEATURE_PROCESS_ENTITY_THREAD)
96     hi_u32 ret, taskid;
97     hi_task_attr attr = { 0 };
98 
99     attr.stack_size = FRW_TASK_SIZE;
100     attr.task_prio = FRW_TASK_PRIO;
101     attr.task_name = g_frw_thread_name;
102     attr.task_policy = 1; /* SCHED_FIFO */
103     attr.task_cpuid = 0;
104     ret = hi_task_create(&taskid, &attr, frw_task_thread, 0);
105     if (ret != HI_SUCCESS) {
106         return HI_FAIL;
107     }
108     g_ast_event_task.taskid = taskid;
109 #elif (_PRE_FRW_FEATURE_PROCESS_ENTITY_TYPE == _PRE_FRW_FEATURE_PROCESS_ENTITY_TASKLET)
110     oal_task_kill(&g_ast_event_task.event_tasklet);
111 #endif
112     return HI_SUCCESS;
113 }
114 #endif
115 
116 #if (_PRE_OS_VERSION_LITEOS == _PRE_OS_VERSION)
117 /* ****************************************************************************
118  功能描述  : 线程退出函数
119  修改历史      :
120   1.日    期   : 2015年4月9日
121 **************************************************************************** */
frw_task_exit(hi_void)122 hi_void frw_task_exit(hi_void)
123 {
124 #if (_PRE_FRW_FEATURE_PROCESS_ENTITY_TYPE == _PRE_FRW_FEATURE_PROCESS_ENTITY_THREAD)
125     if (g_ast_event_task.taskid) {
126         hi_task_delete(g_ast_event_task.taskid);
127         g_ast_event_task.taskid = 0;
128     }
129 #elif (_PRE_FRW_FEATURE_PROCESS_ENTITY_TYPE == _PRE_FRW_FEATURE_PROCESS_ENTITY_TASKLET)
130     oal_task_kill(&g_ast_event_task.event_tasklet);
131 #endif
132 }
133 #endif /* #if (_PRE_OS_VERSION_LITEOS == _PRE_OS_VERSION) */
134 
135 /* ****************************************************************************
136  功能描述  : 供外部模块注册tasklet处理函数中执行的函数
137  输入参数  : p_func: 需要被执行的函数
138 
139  修改历史      :
140   1.日    期   : 2015年4月9日
141     作    者   : HiSilicon
142     修改内容   : 新生成函数
143 **************************************************************************** */
frw_task_event_handler_register(hi_void (* func)(hi_void))144 hi_void frw_task_event_handler_register(hi_void (*func)(hi_void))
145 {
146     if (oal_unlikely(func == HI_NULL)) {
147         hi_diag_log_msg_i0(0, "{frw_task_event_handler_register:: p_func is null ptr}");
148         return;
149     }
150 
151 #if (_PRE_FRW_FEATURE_PROCESS_ENTITY_TYPE == _PRE_FRW_FEATURE_PROCESS_ENTITY_TASKLET)
152     g_ast_event_task.event_handler_func = func;
153 #endif
154 }
155 
156 #if (_PRE_OS_VERSION_LITEOS == _PRE_OS_VERSION)
157 /* ****************************************************************************
158  功能描述  : 唤醒event时间处理线程,与wake_event_interruptible对应
159  修改历史      :
160   1.日    期   : 2015年4月9日
161     作    者   : HiSilicon
162     修改内容   : 新生成函数
163 **************************************************************************** */
frw_task_sched(hi_void)164 hi_void frw_task_sched(hi_void)
165 {
166 #if (_PRE_FRW_FEATURE_PROCESS_ENTITY_TYPE == _PRE_FRW_FEATURE_PROCESS_ENTITY_THREAD)
167 #if (_PRE_MULTI_CORE_MODE != _PRE_MULTI_CORE_MODE_OFFLOAD_HMAC)
168     (hi_void)hi_event_send(get_app_event_id(), HI_EVENT_FRW_TASK);
169 #else
170     hi_wait_queue_wake_up_interrupt(&g_ast_event_task.frw_wq);
171 #endif
172 #elif (_PRE_FRW_FEATURE_PROCESS_ENTITY_TYPE == _PRE_FRW_FEATURE_PROCESS_ENTITY_TASKLET)
173     if (oal_task_is_scheduled(&g_ast_event_task.event_tasklet)) {
174         return;
175     }
176     oal_task_sched(&g_ast_event_task.event_tasklet);
177 #endif
178 }
179 #endif
180 
181 #if (_PRE_FRW_FEATURE_PROCESS_ENTITY_TYPE == _PRE_FRW_FEATURE_PROCESS_ENTITY_TASKLET)
182 /* ****************************************************************************
183  功能描述  : 将tasklet调度执行,被IPI中断调度执行
184 **************************************************************************** */
frw_remote_task_receive(hi_void * info)185 hi_void frw_remote_task_receive(hi_void *info)
186 {
187     oal_tasklet_stru *task = (oal_tasklet_stru *)info;
188     oal_task_sched(task);
189 }
190 
191 /* ****************************************************************************
192  功能描述  : 使用IPI中断,调度目标core上的tasklet执行处理事件
193 **************************************************************************** */
frw_task_sched_on_cpu(oal_tasklet_stru * task)194 hi_void frw_task_sched_on_cpu(oal_tasklet_stru *task)
195 {
196     oal_smp_call_function_single(0, frw_remote_task_receive, (hi_void *)task, 0);
197 }
198 #endif
199 
200 #if (_PRE_OS_VERSION_LINUX == _PRE_OS_VERSION)
frw_task_thread(hi_void * ul_bind_cpu)201 static hi_s32 frw_task_thread(hi_void *ul_bind_cpu)
202 {
203     hi_s32 ret;
204 #if (_PRE_FRW_FEATURE_PROCESS_ENTITY_TYPE == _PRE_FRW_FEATURE_PROCESS_ENTITY_THREAD)
205     hi_u32 ul_empty_count = 0;
206 #endif
207     g_frw_exit = HI_FALSE; /* 线程初始化时为此全局变量赋值 */
208     g_frw_stop = HI_FALSE; /* 线程初始化时为此全局变量赋值 */
209 #if (_PRE_OS_VERSION_LINUX == _PRE_OS_VERSION)
210     allow_signal(SIGTERM);
211 #endif
212     for (;;) {
213 #if (_PRE_FRW_FEATURE_PROCESS_ENTITY_TYPE == _PRE_FRW_FEATURE_PROCESS_ENTITY_THREAD)
214         hi_u32 ul_event_count;
215 #endif
216         if (oal_kthread_should_stop()) {
217             break;
218         }
219 
220         /* state为TASK_INTERRUPTIBLE,condition不成立则线程阻塞,直到被唤醒进入waitqueue */
221         /*lint -e730*/
222 #ifdef _PRE_FRW_EVENT_PROCESS_TRACE_DEBUG
223         frw_event_last_pc_trace(__FUNCTION__, __LINE__, (hi_u32)(unsigned long)ul_bind_cpu);
224 #endif
225         ret = hi_wait_event_interruptible(g_ast_event_task.frw_wq,
226             (HI_TRUE == frw_task_thread_condition_check() || g_frw_exit));
227         /*lint +e730*/
228         if (oal_unlikely(ret == -ERESTARTSYS)) {
229             oal_io_print1("wifi task %s was interrupted by a signal\n", oal_get_current_task_name());
230             break;
231         }
232         if (g_frw_exit == HI_TRUE) {
233             break;
234         }
235 #if (_PRE_FRW_FEATURE_PROCESS_ENTITY_TYPE == _PRE_FRW_FEATURE_PROCESS_ENTITY_THREAD)
236         g_ast_event_task.ul_total_loop_cnt++;
237 
238         ul_event_count = g_ast_event_task.ul_total_event_cnt;
239 #endif
240         frw_event_process_all_event();
241 #if (_PRE_FRW_FEATURE_PROCESS_ENTITY_TYPE == _PRE_FRW_FEATURE_PROCESS_ENTITY_THREAD)
242         if (ul_event_count == g_ast_event_task.ul_total_event_cnt) {
243             /* 空转 */
244             ul_empty_count++;
245             if (ul_empty_count == 10000) { /* empty count 10000 */
246             }
247         } else {
248             if (ul_empty_count > g_ast_event_task.ul_max_empty_count) {
249                 g_ast_event_task.ul_max_empty_count = ul_empty_count;
250             }
251             ul_empty_count = 0;
252         }
253 #endif
254 #ifdef _PRE_FRW_EVENT_PROCESS_TRACE_DEBUG
255         frw_event_last_pc_trace(__FUNCTION__, __LINE__, (hi_u32)(unsigned long)ul_bind_cpu);
256 #endif
257 #if (!defined(CONFIG_PREEMPT) && (_PRE_OS_VERSION_LINUX == _PRE_OS_VERSION))
258         cond_resched();
259 #endif
260     }
261     g_frw_stop = HI_TRUE;
262     return 0;
263 }
264 
frw_task_init()265 hi_u32 frw_task_init()
266 {
267     oal_kthread_stru *kthread = HI_NULL;
268     oal_kthread_param_stru st_thread_param = { 0 };
269 
270     memset_s(&g_ast_event_task, sizeof(g_ast_event_task), 0, sizeof(g_ast_event_task));
271 
272     hi_wait_queue_init_head(&g_ast_event_task.frw_wq);
273 
274     st_thread_param.l_cpuid      = 0;
275     st_thread_param.l_policy     = OAL_SCHED_RR;
276     st_thread_param.l_prio       = FRW_TASK_PRIO;
277     st_thread_param.ul_stacksize = FRW_TASK_SIZE;
278 
279     kthread = oal_kthread_create(g_frw_thread_name, frw_task_thread,
280         (hi_void *)(st_thread_param.l_cpuid), &st_thread_param);
281     if (IS_ERR_OR_NULL(kthread)) {
282         return HI_FAIL;
283     }
284 
285     g_ast_event_task.pst_event_kthread = kthread;
286     g_ast_event_task.uc_task_state = FRW_TASK_STATE_IRQ_UNBIND;
287     return HI_SUCCESS;
288 }
289 
frw_task_exit(hi_void)290 hi_void frw_task_exit(hi_void)
291 {
292     int times = 0;
293     if (g_ast_event_task.pst_event_kthread != HI_NULL) {
294         g_frw_exit = HI_TRUE;
295         frw_task_sched();
296         while (!g_frw_stop && times < 10000) {
297             usleep_range(50, 100); /* 50 100 均为延时参数,最小延时50,最大100 */
298             times++;
299         }
300     }
301 }
frw_task_sched(hi_void)302 hi_void frw_task_sched(hi_void)
303 {
304     hi_wait_queue_wake_up_interrupt(&g_ast_event_task.frw_wq);
305 }
306 #endif /* #if (_PRE_OS_VERSION_LINUX == _PRE_OS_VERSION) */
307 
308 #ifdef __cplusplus
309 #if __cplusplus
310 }
311 #endif
312 #endif
313