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