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 "oal_ext_if.h"
20 #include "hcc_task.h"
21 #include "hcc_host.h"
22 #include "oam_ext_if.h"
23
24 #ifdef __cplusplus
25 #if __cplusplus
26 extern "C" {
27 #endif
28 #endif
29
30 #define HCC_TASK_PRIO 3
31 static volatile hi_u8 g_thread_exit_flag = HI_FALSE;
32 static hi_u8 g_thread_working = HI_FALSE;
33 hcc_task_stru g_hcc_task;
34
35 #define HCC_TASK_NAME "hisi_hcc0"
36 #define HCC_TASK_TX_NAME "hisi_hcc_tx"
37 #define HCC_TASK_RX_NAME "hisi_hcc_rx"
38 #define TX_WRITE 0
39 #define RX_READ 1
40 #define DELAY_10_US 10
41 #define HCC_TASK_SIZE 0x4000
42
hcc_thread_tx_wait_event_cond_check(hcc_handler_stru *hcc_handler)43 static hi_s32 hcc_thread_tx_wait_event_cond_check(hcc_handler_stru *hcc_handler)
44 {
45 hi_s32 ret;
46 /*
47 * please first check the condition
48 * which may be ok likely to reduce the cpu mips
49 */
50 ret = ((queues_len_check(hcc_handler, HCC_TX)) || ((hcc_handler->p_hmac_tcp_ack_need_schedule_func != HI_NULL) &&
51 hcc_handler->p_hmac_tcp_ack_need_schedule_func() == HI_TRUE));
52 #ifdef _PRE_CONFIG_WLAN_THRANS_THREAD_DEBUG
53 if (ret == HI_TRUE)
54 hcc_handler->hcc_transer_info.thread_stat.wait_event_run_count++;
55 if (ret == HI_FALSE)
56 hcc_handler->hcc_transer_info.thread_stat.wait_event_block_count++;
57 #endif
58 return ret;
59 }
60
hcc_thread_rx_wait_event_cond_check(hcc_handler_stru *hcc_handler)61 static hi_s32 hcc_thread_rx_wait_event_cond_check(hcc_handler_stru *hcc_handler)
62 {
63 hi_s32 ret;
64
65 /*
66 * please first check the condition
67 * which may be ok likely to reduce the cpu mips
68 */
69 ret = ((queues_len_check(hcc_handler, HCC_RX)) || ((hcc_handler->p_hmac_tcp_ack_need_schedule_func != HI_NULL) &&
70 hcc_handler->p_hmac_tcp_ack_need_schedule_func() == HI_TRUE));
71 #ifdef _PRE_CONFIG_WLAN_THRANS_THREAD_DEBUG
72 if (ret == HI_TRUE)
73 hcc_handler->hcc_transer_info.thread_stat.wait_event_run_count++;
74 if (ret == HI_FALSE)
75 hcc_handler->hcc_transer_info.thread_stat.wait_event_block_count++;
76 #endif
77 return ret;
78 }
79
hcc_thread_process(hcc_handler_stru *hcc_handler, hi_u8 wr)80 hi_s32 hcc_thread_process(hcc_handler_stru *hcc_handler, hi_u8 wr)
81 {
82 hi_s32 ret = 0;
83 #ifdef _PRE_WLAN_FEATURE_OFFLOAD_FLOWCTL
84 oal_bool_enum_uint8 en_device_is_sta;
85 OAL_STATIC oal_uint32 s_ul_schedule_cnt = 0;
86
87 en_device_is_sta = hcc_flowctl_get_device_mode(hcc);
88
89 s_ul_schedule_cnt++;
90
91 if (en_device_is_sta == OAL_TRUE) {
92 /* Tx Tcp Data queue > Rx Tcp Ack
93 Rx Tcp Data > Tx Tcp Ack
94 Tx Tcp Data queue > Rx Tcp Data queue */
95 ret += hcc_host_send_rx_queue(hcc, CTRL_QUEUE);
96 ret += hcc_host_send_tx_queue(hcc, CTRL_QUEUE);
97
98 ret += hcc_host_send_rx_queue(hcc, DATA_HI_QUEUE);
99 ret += hcc_host_send_tx_queue(hcc, DATA_HI_QUEUE);
100
101 if ((s_ul_schedule_cnt % LO_QUEUE_ADJUST_PRIORITY_PERIOD) == 0) {
102 /* Tx Lo < Rx Lo */
103 ret += hcc_host_send_rx_queue(hcc, DATA_LO_QUEUE);
104 ret += hcc_host_send_tx_queue(hcc, DATA_LO_QUEUE);
105
106 /* 下行TCP优先 */
107 ret += hcc_host_send_rx_queue(hcc, DATA_TCP_DATA_QUEUE);
108 ret += hcc_host_send_tx_queue(hcc, DATA_TCP_ACK_QUEUE);
109
110 ret += hcc_host_send_tx_queue(hcc, DATA_TCP_DATA_QUEUE);
111 ret += hcc_host_send_rx_queue(hcc, DATA_TCP_ACK_QUEUE);
112 } else {
113 /* 下行TCP优先 */
114 ret += hcc_host_send_rx_queue(hcc, DATA_TCP_DATA_QUEUE);
115 ret += hcc_host_send_tx_queue(hcc, DATA_TCP_ACK_QUEUE);
116
117 ret += hcc_host_send_tx_queue(hcc, DATA_TCP_DATA_QUEUE);
118 ret += hcc_host_send_rx_queue(hcc, DATA_TCP_ACK_QUEUE);
119
120 /* Tx Lo < Rx Lo */
121 ret += hcc_host_send_rx_queue(hcc, DATA_LO_QUEUE);
122 ret += hcc_host_send_tx_queue(hcc, DATA_LO_QUEUE);
123 }
124 ret += hcc_host_send_rx_queue(hcc, DATA_UDP_VO_QUEUE);
125 ret += hcc_host_send_tx_queue(hcc, DATA_UDP_VO_QUEUE);
126
127 ret += hcc_host_send_rx_queue(hcc, DATA_UDP_VI_QUEUE);
128 ret += hcc_host_send_tx_queue(hcc, DATA_UDP_VI_QUEUE);
129
130 ret += hcc_host_send_rx_queue(hcc, DATA_UDP_BE_QUEUE);
131 ret += hcc_host_send_tx_queue(hcc, DATA_UDP_BE_QUEUE);
132
133 ret += hcc_host_send_rx_queue(hcc, DATA_UDP_BK_QUEUE);
134 ret += hcc_host_send_tx_queue(hcc, DATA_UDP_BK_QUEUE);
135 } else {
136 /* Tx Tcp Data queue > Rx Tcp Ack
137 Rx Tcp Data > Tx Tcp Ack
138 Tx Tcp Data queue < Rx Tcp Data queue */
139 ret += hcc_host_send_tx_queue(hcc, CTRL_QUEUE);
140 ret += hcc_host_send_rx_queue(hcc, CTRL_QUEUE);
141
142 ret += hcc_host_send_tx_queue(hcc, DATA_HI_QUEUE);
143 ret += hcc_host_send_rx_queue(hcc, DATA_HI_QUEUE);
144
145 if ((s_ul_schedule_cnt % LO_QUEUE_ADJUST_PRIORITY_PERIOD) == 0) {
146 /* Tx Lo > Rx Lo */
147 ret += hcc_host_send_tx_queue(hcc, DATA_LO_QUEUE);
148 ret += hcc_host_send_rx_queue(hcc, DATA_LO_QUEUE);
149
150 ret += hcc_host_send_tx_queue(hcc, DATA_TCP_DATA_QUEUE);
151 ret += hcc_host_send_rx_queue(hcc, DATA_TCP_ACK_QUEUE);
152
153 ret += hcc_host_send_rx_queue(hcc, DATA_TCP_DATA_QUEUE);
154 ret += hcc_host_send_tx_queue(hcc, DATA_TCP_ACK_QUEUE);
155 } else {
156 ret += hcc_host_send_tx_queue(hcc, DATA_TCP_DATA_QUEUE);
157 ret += hcc_host_send_rx_queue(hcc, DATA_TCP_ACK_QUEUE);
158
159 ret += hcc_host_send_rx_queue(hcc, DATA_TCP_DATA_QUEUE);
160 ret += hcc_host_send_tx_queue(hcc, DATA_TCP_ACK_QUEUE);
161
162 /* Tx Lo > Rx Lo */
163 ret += hcc_host_send_tx_queue(hcc, DATA_LO_QUEUE);
164 ret += hcc_host_send_rx_queue(hcc, DATA_LO_QUEUE);
165 }
166
167 /* udp业务 */
168 ret += hcc_host_send_tx_queue(hcc, DATA_UDP_VO_QUEUE);
169 ret += hcc_host_send_rx_queue(hcc, DATA_UDP_VO_QUEUE);
170
171 ret += hcc_host_send_tx_queue(hcc, DATA_UDP_VI_QUEUE);
172 ret += hcc_host_send_rx_queue(hcc, DATA_UDP_VI_QUEUE);
173
174 ret += hcc_host_send_tx_queue(hcc, DATA_UDP_BE_QUEUE);
175 ret += hcc_host_send_rx_queue(hcc, DATA_UDP_BE_QUEUE);
176
177 ret += hcc_host_send_tx_queue(hcc, DATA_UDP_BK_QUEUE);
178 ret += hcc_host_send_rx_queue(hcc, DATA_UDP_BK_QUEUE);
179 }
180 #else
181 if (wr == TX_WRITE) {
182 ret += hcc_host_proc_tx_queue(hcc_handler, DATA_HI_QUEUE);
183 ret += hcc_host_proc_tx_queue(hcc_handler, DATA_LO_QUEUE);
184 } else {
185 ret += hcc_host_proc_rx_queue(hcc_handler, DATA_HI_QUEUE);
186 ret += hcc_host_proc_rx_queue(hcc_handler, DATA_LO_QUEUE);
187 }
188 #endif
189 return ret;
190 }
191
hcc_get_thread_exit_flagnull192 hi_u8 hcc_get_thread_exit_flag(hi_void)
193 {
194 return g_thread_exit_flag;
195 }
196
hcc_exit_task_thread(hcc_handler_stru *hcc)197 hi_void hcc_exit_task_thread(hcc_handler_stru *hcc)
198 {
199 hi_u16 retry_time = 10000;
200 g_thread_exit_flag = HI_TRUE;
201 hcc_sched_transfer(hcc);
202 while (g_thread_working && retry_time > 0) {
203 udelay(DELAY_10_US);
204 retry_time--;
205 }
206 }
207
hcc_task_rx_thread(hi_void *data)208 static hi_s32 hcc_task_rx_thread(hi_void *data)
209 {
210 hi_s32 hcc_ret = 0;
211 #ifdef _PRE_WLAN_TCP_OPT
212 static hi_u8 ack_loop_count = 0;
213 #endif
214 hcc_handler_stru *hcc_handler = (hcc_handler_stru *)data;
215
216 #if (_PRE_OS_VERSION_LINUX == _PRE_OS_VERSION)
217 allow_signal(SIGTERM);
218 #endif
219 oam_info_log0(0, 0, "hcc_task_rx_thread:: hcc_task_rx_thread enter");
220 g_thread_exit_flag = HI_FALSE;
221 for (; ;) {
222 if (g_thread_exit_flag == HI_TRUE || oal_kthread_should_stop()) {
223 oam_warning_log0(0, 0, "hcc_task_thread:: hcc_task leave");
224 break;
225 }
226 hcc_ret = hi_wait_event_interruptible(hcc_handler->hcc_transer_info.hcc_rx_wq,
227 (hcc_thread_rx_wait_event_cond_check(hcc_handler) == HI_TRUE));
228 if (hcc_ret == -ERESTARTSYS || g_thread_exit_flag == HI_TRUE) {
229 oam_warning_log0(0, 0, "hcc_task_rx_thread:: hcc_task was interupterd by a singnal");
230 break;
231 }
232 #ifdef _PRE_WLAN_TCP_OPT
233 if (hcc_handler->p_hmac_tcp_ack_process_func != HI_NULL) {
234 ack_loop_count++;
235 if (ack_loop_count >= g_ul_tcp_ack_wait_sche_cnt) {
236 ack_loop_count = 0;
237 hcc_handler->p_hmac_tcp_ack_process_func();
238 }
239 }
240 #endif
241 hcc_thread_process(hcc_handler, RX_READ);
242 }
243 return 0;
244 }
245
246 /* ****************************************************************************S
247 hcc task 线程主程序
248 **************************************************************************** */
hcc_task_tx_thread(hi_void *data)249 static hi_s32 hcc_task_tx_thread(hi_void *data)
250 {
251 hi_s32 hcc_ret = 0;
252 #ifdef _PRE_WLAN_TCP_OPT
253 static hi_u8 ack_loop_count = 0;
254 #endif
255 hcc_handler_stru *hcc_handler = (hcc_handler_stru *)data;
256
257 #if (_PRE_OS_VERSION_LINUX == _PRE_OS_VERSION)
258 allow_signal(SIGTERM);
259 #endif
260 oam_info_log0(0, 0, "hcc_task_tx_thread:: hcc_task_tx_thread enter");
261 g_thread_exit_flag = HI_FALSE;
262 g_thread_working = HI_TRUE;
263 for (; ;) {
264 if (g_thread_exit_flag == HI_TRUE || oal_kthread_should_stop()) {
265 oam_warning_log0(0, 0, "hcc_task_tx_thread:: hcc_task leave");
266 break;
267 }
268 hcc_ret = hi_wait_event_interruptible(hcc_handler->hcc_transer_info.hcc_transfer_wq,
269 (hcc_thread_tx_wait_event_cond_check(hcc_handler) == HI_TRUE));
270 if (hcc_ret == -ERESTARTSYS || g_thread_exit_flag == HI_TRUE) {
271 oam_warning_log0(0, 0, "hcc_task_tx_thread:: hcc_task was interupterd by a singnal");
272 break;
273 }
274 #ifdef _PRE_WLAN_TCP_OPT
275 if (hcc_handler->p_hmac_tcp_ack_process_func != HI_NULL) {
276 ack_loop_count++;
277 if (ack_loop_count >= g_ul_tcp_ack_wait_sche_cnt) {
278 ack_loop_count = 0;
279 hcc_handler->p_hmac_tcp_ack_process_func();
280 }
281 }
282 #endif
283 hcc_thread_process(hcc_handler, TX_WRITE);
284 }
285 g_thread_working = HI_FALSE;
286 return hcc_ret;
287 }
288
hcc_task_init(hcc_handler_stru *hcc_handler)289 hi_u32 hcc_task_init(hcc_handler_stru *hcc_handler)
290 {
291 oal_kthread_param_stru thread_param = { 0 };
292
293 memset_s(&g_hcc_task, sizeof(hcc_task_stru), 0, sizeof(hcc_task_stru));
294
295 hi_wait_queue_init_head(&g_hcc_task.hcc_wq);
296
297 memset_s(&thread_param, sizeof(oal_kthread_param_stru), 0, sizeof(oal_kthread_param_stru));
298 thread_param.l_cpuid = 0;
299 thread_param.l_policy = OAL_SCHED_FIFO;
300 thread_param.l_prio = HCC_TASK_PRIO;
301 thread_param.ul_stacksize = HCC_TASK_SIZE;
302
303 hcc_handler->hcc_transer_info.hcc_transfer_thread =
304 oal_kthread_create(HCC_TASK_TX_NAME, hcc_task_tx_thread, hcc_handler, &thread_param);
305 hcc_handler->hcc_transer_info.hcc_rx_thread =
306 oal_kthread_create(HCC_TASK_RX_NAME, hcc_task_rx_thread, hcc_handler, &thread_param);
307 if (IS_ERR_OR_NULL(hcc_handler->hcc_transer_info.hcc_transfer_thread) ||
308 IS_ERR_OR_NULL(hcc_handler->hcc_transer_info.hcc_rx_thread)) {
309 return HI_FAIL;
310 }
311 return HI_SUCCESS;
312 }
313
314 #ifdef __cplusplus
315 #if __cplusplus
316 }
317 #endif
318 #endif
319