• 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 /* ****************************************************************************
20   1 其他头文件包含
21 **************************************************************************** */
22 #include "hcc_host.h"
23 #include "hcc_task.h"
24 #include "oal_ext_if.h"
25 #include "oam_ext_if.h"
26 #include "hmac_ext_if.h"
27 #include "wal_main.h"
28 #ifdef CONFIG_MMC
29 #include "plat_pm_wlan.h"
30 #endif
31 #ifndef _PRE_FEATURE_HCC_TASK
32 #include "flow_control.h"
33 #endif
34 #ifdef __cplusplus
35 #if __cplusplus
36 extern "C" {
37 #endif
38 #endif
39 
40 /* ****************************************************************************
41   全局变量定义
42 **************************************************************************** */
43 hi_u32 g_hcc_rx_thread_enable = 1;
44 hi_u32 g_hcc_assemble_count = 8;
45 hi_u32 g_hcc_credit_bottom_value = 2;
46 hi_u32 g_ul_tcp_ack_wait_sche_cnt = 1;
47 oal_netbuf_head_stru g_hcc_hmac_rx_netbuf;
48 hcc_handler_stru *g_hcc_host_handler = HI_NULL;
49 hi_u32 g_hcc_flowctrl_detect_panic = 0;
50 
51 hi_u8 g_hcc_sched_stat[FRW_EVENT_TYPE_BUTT];
52 hi_u8 g_hcc_flowctrl_stat[FRW_EVENT_TYPE_BUTT];
53 static hi_u8 g_device_is_ready = HI_FALSE;
54 
55 #define  MIN_DATA_LO_QUEUE                   6
56 #define  MIN_DES_CNT                         12
57 #define THRESHOLD_SIZE_10_BYTES     10
58 #define THRESHOLD_SIZE_20_BYTES     20
59 #define THRESHOLD_SIZE_40_BYTES     40
60 #define THRESHOLD_SIZE_60_BYTES     60
61 #define THRESHOLD_SIZE_80_BYTES     80
62 #define THRESHOLD_SIZE_120_BYTES    120
63 #define THRESHOLD_SIZE_200_BYTES    200
64 #define THRESHOLD_SIZE_400_BYTES    400
65 
66 #define THRESHOLD_SIZE_128_BYTES    128
67 #define THRESHOLD_SIZE_256_BYTES    256
68 #define THRESHOLD_SIZE_512_BYTES    512
69 #define THRESHOLD_SIZE_1024_BYTES   1024
70 
71 #define MAX_TIMES                           1000
72 #define MAX_TIME_VALUE                      1
73 #define MIN_TIME_VALUE                      1
74 #if (_PRE_OS_VERSION_LINUX == _PRE_OS_VERSION)
75 #define PM_DISABLING_TIME                   1500
76 #else
77 #define PM_DISABLING_TIME                   2
78 #endif
79 #define LOW_PRIORITY_COUNT                  1000
80 #define KEY_FRAME_COUNT                     2000
81 
82 static hi_u8 g_abandon_key_frame = HI_FALSE;
83 static hi_u8 g_list_overflow_flag = HI_FALSE;
84 static hi_u32 g_lo_buf_times = 0;
85 
86 #define WLAN_HEART_BEAT_ENABLE_WAIT_TIMEOUT 200 /* 等待device回复心跳使能/禁用命令的超时时间:200 ms */
87 #define WLAN_HEART_BEAT_DEVICE_TIMEOUT (5 * 60 * 1000) /* device 5min没收到心跳报文,则复位 */
88 static oal_completion g_heart_beat_completion_ack;
89 hi_bool g_heart_beat_enable = HI_TRUE; /* 默认使能心跳 */
90 hi_u32 g_heart_beat_device_timeout = WLAN_HEART_BEAT_DEVICE_TIMEOUT;
91 hi_u32 g_priority_cnt = 0;
92 hi_u32 g_lopriority_cnt = 0;
93 hi_u32 g_des_cnt = 0;
94 /* ****************************************************************************
95   函数定义
96 **************************************************************************** */
97 /* interface for getting hcc host handler */
hcc_host_get_handler(hi_void)98 hcc_handler_stru *hcc_host_get_handler(hi_void)
99 {
100     return g_hcc_host_handler;
101 }
102 
103 /* init hcc transfer_queue */
hcc_transfer_queues_init(hcc_handler_stru * hcc_handler)104 hi_void hcc_transfer_queues_init(hcc_handler_stru *hcc_handler)
105 {
106     hi_s32 i, j;
107     for (i = 0; i < HCC_DIR_COUNT; i++) {
108         for (j = 0; j < HCC_QUEUE_COUNT; j++) {
109             oal_netbuf_head_init(&hcc_handler->hcc_transer_info.hcc_queues[i].queues[j].data_queue);
110         }
111     }
112 }
113 
114 static volatile hi_s32 g_flowctrl_info_flag = 0;
115 
116 #ifdef _PRE_HDF_LINUX
hcc_dev_flow_ctrl_timeout_isr(oal_timer_list_stru * timer)117 static hi_void hcc_dev_flow_ctrl_timeout_isr(oal_timer_list_stru *timer)
118 {
119     hi_unref_param(timer);
120 #else
121 static hi_void hcc_dev_flow_ctrl_timeout_isr(unsigned long arg)
122 {
123     hi_unref_param(arg);
124 #endif
125     hcc_handler_stru *hcc_handler = g_hcc_host_handler;
126     if (hcc_handler == HI_NULL) {
127         oam_error_log0(0, 0, "hcc is null");
128         return;
129     }
130     /* flowctrl lock too much time. */
131     oam_info_log1(0, 0, "{SDIO flow ctrl had off for %lu ms, it's a long time}",
132                   hcc_handler->hcc_transer_info.tx_flow_ctrl.timeout);
133     g_flowctrl_info_flag = 0;
134 
135     /* If work is idle,queue a new work. */
136     if (oal_work_is_busy(&hcc_handler->hcc_transer_info.tx_flow_ctrl.worker.work) == 0) {
137 #if (_PRE_OS_VERSION_LINUX == _PRE_OS_VERSION)
138         oal_queue_delayed_system_work(&hcc_handler->hcc_transer_info.tx_flow_ctrl.worker, 0);
139 #endif
140     }
141 }
142 
143 hi_void hcc_print_device_mem_info(hi_void)
144 {
145 #ifdef CONFIG_MMC
146     hi_wifi_plat_pm_disable();
147     oal_bus_send_msg(g_hcc_host_handler->bus, H2D_MSG_DEVICE_MEM_INFO);
148 
149     hi_wifi_plat_pm_enable();
150 #endif
151 }
152 
153 hi_void hcc_trigger_device_panic(hi_void)
154 {
155 #ifdef CONFIG_MMC
156     hi_wifi_plat_pm_disable();
157     oal_bus_send_msg(g_hcc_host_handler->bus, H2D_MSG_TEST);
158     hi_wifi_plat_pm_enable();
159 #endif
160 }
161 
162 hi_void hcc_flowctrl_deadlock_detect_worker(oal_work_stru *pst_flow_work)
163 {
164     hi_unref_param(pst_flow_work);
165     hcc_handler_stru *hcc_handle = hcc_host_get_handler();
166     if (hcc_handle == HI_NULL) {
167         oam_error_log0(0, 0, "hcc_flowctrl_deadlock_detect_worker hcc is null");
168         return;
169     }
170     oam_info_log1(0, 0, "{hcc_flowctrl_deadlock_detect_worker action,%d}",
171                   g_flowctrl_info_flag);
172     if (g_flowctrl_info_flag == 0) {
173         g_flowctrl_info_flag = 1;
174         oal_smp_mb();
175         /* queue system_wq delay work,and send other message 20ms later. */
176         /* print device mem */
177         hcc_print_device_mem_info();
178 #if (_PRE_OS_VERSION_LINUX == _PRE_OS_VERSION)
179         oal_queue_delayed_system_work(&hcc_handle->hcc_transer_info.tx_flow_ctrl.worker,
180                                       OAL_MSECS_TO_JIFFIES(20)); /* delay 20 jiffes */
181 #endif
182     } else if (g_flowctrl_info_flag == 1) {
183         /* print device mem */
184         if (g_hcc_flowctrl_detect_panic) {
185             hcc_trigger_device_panic();
186         } else {
187             hcc_print_device_mem_info();
188         }
189     }
190 
191     return;
192 }
193 
194 hi_void hcc_trans_flow_ctrl_info_init(hcc_handler_stru *hcc_handle)
195 {
196     hi_s32 i;
197 
198     hcc_handle->hcc_transer_info.tx_flow_ctrl.flowctrl_flag = D2H_MSG_FLOWCTRL_ON;
199     hcc_handle->hcc_transer_info.tx_flow_ctrl.flowctrl_off_count = 0;
200     hcc_handle->hcc_transer_info.tx_flow_ctrl.flowctrl_on_count = 0;
201     oal_spin_lock_init(&hcc_handle->hcc_transer_info.tx_flow_ctrl.lock);
202     hcc_handle->hcc_transer_info.tx_flow_ctrl.timeout = 20 * 1000; /* TIME 是 20 * 1000 ms */
203     INIT_DELAYED_WORK(&hcc_handle->hcc_transer_info.tx_flow_ctrl.worker, hcc_flowctrl_deadlock_detect_worker);
204     oal_timer_init(&hcc_handle->hcc_transer_info.tx_flow_ctrl.flow_timer,
205         hcc_handle->hcc_transer_info.tx_flow_ctrl.timeout, hcc_dev_flow_ctrl_timeout_isr, 0);
206 
207     hcc_handle->hcc_transer_info.tx_flow_ctrl.uc_hipriority_cnt = HCC_FLOW_HIGH_PRI_BUFF_CNT;
208     hcc_handle->hcc_transer_info.tx_flow_ctrl.uc_lopriority_cnt = HCC_FLOW_LOW_PRI_BUFF_CNT;
209     oal_spin_lock_init(&hcc_handle->hcc_transer_info.tx_flow_ctrl.st_hipri_lock);
210 
211     hcc_trans_queues_stru *hcc_tx_queues = &hcc_handle->hcc_transer_info.hcc_queues[HCC_TX];
212     hcc_trans_queues_stru *hcc_rx_queues = &hcc_handle->hcc_transer_info.hcc_queues[HCC_RX];
213 
214     for (i = 0; i < HCC_QUEUE_COUNT; i++) {
215         /* TX queue */
216         hcc_tx_queues->queues[i].flow_ctrl.enable = HI_TRUE;
217         hcc_tx_queues->queues[i].flow_ctrl.flow_type = HCC_FLOWCTRL_SDIO;
218         hcc_tx_queues->queues[i].flow_ctrl.is_stopped = HI_FALSE;
219         hcc_tx_queues->queues[i].flow_ctrl.low_waterline = THRESHOLD_SIZE_512_BYTES;
220         hcc_tx_queues->queues[i].flow_ctrl.high_waterline = THRESHOLD_SIZE_1024_BYTES;
221         hcc_tx_queues->queues[i].netbuf_pool_type = HCC_NETBUF_NORMAL_QUEUE;
222 
223         /* RX queue */
224         hcc_rx_queues->queues[i].flow_ctrl.enable = HI_TRUE;
225         hcc_rx_queues->queues[i].flow_ctrl.is_stopped = HI_FALSE;
226         hcc_rx_queues->queues[i].flow_ctrl.low_waterline = THRESHOLD_SIZE_128_BYTES;
227         hcc_rx_queues->queues[i].flow_ctrl.high_waterline = THRESHOLD_SIZE_512_BYTES;
228     }
229 
230     /* Additional high priority flow_ctrl settings */
231     hcc_tx_queues->queues[DATA_HI_QUEUE].flow_ctrl.flow_type = HCC_FLOWCTRL_CREDIT;
232     hcc_tx_queues->queues[DATA_HI_QUEUE].flow_ctrl.enable = HI_FALSE;
233     hcc_tx_queues->queues[DATA_HI_QUEUE].netbuf_pool_type = HCC_NETBUF_HIGH_QUEUE;
234 
235 #ifdef _PRE_WLAN_FEATURE_OFFLOAD_FLOWCTL
236     hcc_tx_queues->queues[CTRL_QUEUE].flow_ctrl.low_waterline = THRESHOLD_SIZE_128_BYTES;
237     hcc_tx_queues->queues[CTRL_QUEUE].flow_ctrl.high_waterline = THRESHOLD_SIZE_256_BYTES;
238     hcc_tx_queues->queues[CTRL_QUEUE].netbuf_pool_type = HCC_NETBUF_HIGH_QUEUE;
239 
240     hcc_tx_queues->queues[DATA_HI_QUEUE].flow_ctrl.low_waterline = THRESHOLD_SIZE_128_BYTES;
241     hcc_tx_queues->queues[DATA_HI_QUEUE].flow_ctrl.high_waterline = THRESHOLD_SIZE_256_BYTES;
242     hcc_tx_queues->queues[DATA_HI_QUEUE].netbuf_pool_type = HCC_NETBUF_HIGH_QUEUE;
243 
244     hcc_tx_queues->queues[DATA_LO_QUEUE].flow_ctrl.low_waterline = THRESHOLD_SIZE_128_BYTES;
245     hcc_tx_queues->queues[DATA_LO_QUEUE].flow_ctrl.high_waterline = THRESHOLD_SIZE_256_BYTES;
246 
247     hcc_tx_queues->queues[DATA_TCP_DATA_QUEUE].flow_ctrl.low_waterline = THRESHOLD_SIZE_128_BYTES;
248     hcc_tx_queues->queues[DATA_TCP_DATA_QUEUE].flow_ctrl.high_waterline = THRESHOLD_SIZE_256_BYTES;
249 
250     hcc_tx_queues->queues[DATA_TCP_ACK_QUEUE].flow_ctrl.low_waterline = THRESHOLD_SIZE_128_BYTES;
251     hcc_tx_queues->queues[DATA_TCP_ACK_QUEUE].flow_ctrl.high_waterline = THRESHOLD_SIZE_256_BYTES;
252 #if (_PRE_OS_VERSION_LINUX == _PRE_OS_VERSION)
253     hcc_tx_queues->queues[DATA_UDP_BK_QUEUE].flow_ctrl.low_waterline = THRESHOLD_SIZE_10_BYTES;
254     hcc_tx_queues->queues[DATA_UDP_BK_QUEUE].flow_ctrl.high_waterline = THRESHOLD_SIZE_20_BYTES;
255 
256     hcc_tx_queues->queues[DATA_UDP_BE_QUEUE].flow_ctrl.low_waterline = THRESHOLD_SIZE_20_BYTES;
257     hcc_tx_queues->queues[DATA_UDP_BE_QUEUE].flow_ctrl.high_waterline = THRESHOLD_SIZE_40_BYTES;
258 #elif (_PRE_OS_VERSION_LITEOS == _PRE_OS_VERSION)
259     hcc_tx_queues->queues[DATA_UDP_BK_QUEUE].flow_ctrl.low_waterline = THRESHOLD_SIZE_200_BYTES;
260     hcc_tx_queues->queues[DATA_UDP_BK_QUEUE].flow_ctrl.high_waterline = THRESHOLD_SIZE_400_BYTES;
261 
262     hcc_tx_queues->queues[DATA_UDP_BE_QUEUE].flow_ctrl.low_waterline = THRESHOLD_SIZE_200_BYTES;
263     hcc_tx_queues->queues[DATA_UDP_BE_QUEUE].flow_ctrl.high_waterline = THRESHOLD_SIZE_400_BYTES;
264 #endif
265     hcc_tx_queues->queues[DATA_UDP_VI_QUEUE].flow_ctrl.low_waterline = THRESHOLD_SIZE_40_BYTES;
266     hcc_tx_queues->queues[DATA_UDP_VI_QUEUE].flow_ctrl.high_waterline = THRESHOLD_SIZE_80_BYTES;
267 
268     hcc_tx_queues->queues[DATA_UDP_VO_QUEUE].flow_ctrl.low_waterline = THRESHOLD_SIZE_60_BYTES;
269     hcc_tx_queues->queues[DATA_UDP_VO_QUEUE].flow_ctrl.high_waterline = THRESHOLD_SIZE_120_BYTES;
270 #endif
271 }
272 
273 static hi_u32 hcc_host_check_header_vaild(const hcc_header_stru *hcc_hdr)
274 {
275     if ((hcc_hdr->main_type >= HCC_ACTION_TYPE_BUTT) ||
276         (HCC_HDR_LEN + hcc_hdr->pad_hdr + hcc_hdr->pad_payload > HCC_HDR_TOTAL_LEN)) {
277         oam_error_log4(0, 0,
278             "hcc_host_check_header_vaild:: hcc_hdr invalid!,main_type[%d],sub_type[%d],pad_hdr[%d],pad_payload[%d]",
279             hcc_hdr->main_type, hcc_hdr->sub_type, hcc_hdr->pad_hdr, hcc_hdr->pad_payload);
280         return HI_FALSE;
281     }
282     return HI_TRUE;
283 }
284 
285 static hi_s32 hcc_host_rx(const hcc_handler_stru *hcc_handler, oal_netbuf_stru *netbuf)
286 {
287     hcc_header_stru *hcc_hdr = HI_NULL;
288     hi_s32 extend_len;
289 
290     (void)hcc_handler;
291     hcc_hdr = (hcc_header_stru *)oal_netbuf_data(netbuf);
292     if (hcc_host_check_header_vaild(hcc_hdr) != HI_TRUE) {
293         oal_print_hex_dump((hi_u8 *)hcc_hdr, HCC_HDR_TOTAL_LEN, 16, "invalid hcc_rx header: "); /* 16进制 */
294         return -OAL_EFAIL;
295     }
296 
297     extend_len = HCC_HDR_TOTAL_LEN - HCC_HDR_LEN - hcc_hdr->pad_hdr;
298 
299     if (hcc_hdr->pad_payload) {
300         hi_u8 *extend_addr = (hi_u8 *)hcc_hdr + HCC_HDR_LEN + hcc_hdr->pad_hdr;
301         if (memmove_s(extend_addr + hcc_hdr->pad_payload, (hi_u32)extend_len, extend_addr,
302             (hi_u32)extend_len) != EOK) {
303             return -OAL_EFAIL;
304         }
305     }
306 
307     if (HCC_HDR_LEN + hcc_hdr->pad_hdr + hcc_hdr->pad_payload > oal_netbuf_len(netbuf)) {
308         oam_error_log1(0, 0, "hcc_host_rx:: hcc_hdr too long, netbuf_len[%d]", (hi_s32)oal_netbuf_len(netbuf));
309         oal_print_hex_dump((hi_u8 *)oal_netbuf_data(netbuf), (hi_s32)oal_netbuf_len(netbuf), 32,
310             "rx wrong data: "); /* group_size 等于 32 */
311         return -OAL_EINVAL;
312     }
313 
314 #ifdef CONFIG_HCC_DEBUG
315     oam_info_log1(0, 0, "hcc_host_rx:: seq_num[%d]", hcc_hdr->seq);
316     oal_print_hex_dump((hi_u8 *)hcc_hdr, HCC_HDR_TOTAL_LEN, 8, "hcc hdr:"); /* string len 8 */
317     oal_print_hex_dump(oal_netbuf_data(netbuf) + HCC_HDR_TOTAL_LEN + hcc_hdr->pad_payload, hcc_hdr->pay_len, 8,
318         "hcc payload:"); /* group_size 等于 8 */
319 #endif
320 
321     oal_netbuf_pull(netbuf, HCC_HDR_LEN + hcc_hdr->pad_hdr + hcc_hdr->pad_payload);
322 
323     /* 传出去的netbuf len 包含extend_len长度! */
324     oal_netbuf_trim(netbuf, oal_netbuf_len(netbuf) - hcc_hdr->pay_len - (hi_u32)extend_len);
325 
326     set_oal_netbuf_next(netbuf, HI_NULL);
327     set_oal_netbuf_prev(netbuf, HI_NULL);
328 
329     return HI_SUCCESS;
330 }
331 
332 hi_s32 hcc_host_proc_rx_queue_impl(oal_netbuf_head_stru *head, void *handler, int32_t type)
333 {
334     hcc_handler_stru *hcc_handler = (hcc_handler_stru *)handler;
335     hi_s32 count = 0;
336     hi_s32 pre_ret = HI_SUCCESS;
337     hi_u8 *pre_context = HI_NULL;
338     oal_netbuf_head_stru *netbuf_head = HI_NULL;
339     oal_netbuf_stru *netbuf = HI_NULL;
340     hcc_header_stru *hcc_hdr = HI_NULL;
341     hcc_netbuf_stru hcc_netbuf;
342     hcc_rx_action_stru *rx_action = HI_NULL;
343     netbuf_head = head;
344 
345     for (;;) {
346         netbuf = oal_netbuf_delist(netbuf_head);
347         if (netbuf == HI_NULL) {
348             break;
349         }
350         hcc_hdr = (hcc_header_stru *)oal_netbuf_data(netbuf);
351         if (hcc_host_check_header_vaild(hcc_hdr) != HI_TRUE) {
352             oal_print_hex_dump((hi_u8 *)hcc_hdr, HCC_HDR_TOTAL_LEN, 16, "invalid hcc header: "); /* 16进制 */
353             oam_error_log0(0, 0, "hcc_host_send_rx_queue:: invalid hcc_header");
354             count++;
355             oal_netbuf_free(netbuf);
356             return count;
357         }
358         rx_action = &hcc_handler->hcc_transer_info.rx_action_info.action[hcc_hdr->main_type];
359         pre_ret = HI_SUCCESS;
360         if (rx_action->pre_do != HI_NULL) {
361             hcc_netbuf.pst_netbuf = netbuf;
362             hcc_netbuf.len = (hi_s32)oal_netbuf_len(netbuf);
363             pre_ret = rx_action->pre_do(hcc_hdr->sub_type, &hcc_netbuf, &pre_context);
364         }
365         if (pre_ret == HI_SUCCESS) {
366             if (hcc_host_rx(hcc_handler, netbuf) == HI_SUCCESS) {
367                 if (rx_action->post_do != HI_NULL) {
368                     hcc_netbuf.pst_netbuf = netbuf;
369                     hcc_netbuf.len = (hi_s32)oal_netbuf_len(netbuf);
370                     rx_action->post_do(hcc_hdr->sub_type, &hcc_netbuf, pre_context);
371                 } else {
372                     oam_error_log2(0, 0, "hcc_host_send_rx_queue:: post_do is null, hcc_main_type[%d], sub_type[%d]",
373                         hcc_hdr->main_type, hcc_hdr->sub_type);
374                     oal_print_hex_dump((hi_u8 *)hcc_hdr, HCC_HDR_TOTAL_LEN, 32, "hcc invalid header: "); /* len 32 */
375                     oal_print_hex_dump(oal_netbuf_data(netbuf), (hi_s32)oal_netbuf_len(netbuf), 32,
376                         "hcc invalid header(payload): "); /* 32 进制 */
377                     oal_netbuf_free(netbuf);
378                 }
379             } else {
380                 oal_netbuf_free(netbuf);
381             }
382             hcc_handler->hcc_transer_info.hcc_queues[HCC_RX].queues[type].total_pkts++;
383             count++;
384         } else {
385             /* keep the netbuf in list and skip the loop */
386             oal_netbuf_addlist(netbuf_head, netbuf);
387             break;
388         }
389     }
390 
391     return count;
392 }
393 hi_s32 hcc_host_proc_rx_queue(hcc_handler_stru *hcc_handler, hcc_queue_type_enum type)
394 {
395     oal_netbuf_head_stru *netbuf_head = &hcc_handler->hcc_transer_info.hcc_queues[HCC_RX].queues[type].data_queue;
396     return hcc_host_proc_rx_queue_impl(netbuf_head, hcc_handler, type);
397 }
398 
399 static oal_netbuf_stru *hcc_tx_assem_descr_get(hcc_handler_stru *hcc_handler)
400 {
401     return oal_netbuf_delist(&hcc_handler->tx_descr_info.tx_assem_descr_hdr);
402 }
403 
404 static hi_void hcc_tx_assem_descr_put(hcc_handler_stru *hcc_handler, oal_netbuf_stru *netbuf)
405 {
406     oal_netbuf_list_tail(&hcc_handler->tx_descr_info.tx_assem_descr_hdr, netbuf);
407 }
408 
409 static hi_s32 hcc_send_single_descr(hcc_handler_stru *hcc_handler, oal_netbuf_stru *netbuf)
410 {
411     hi_s32 ret;
412     oal_netbuf_head_stru head_send;
413     OAL_REFERENCE(hcc_handler);
414     oal_netbuf_list_head_init(&head_send);
415     oal_netbuf_list_tail(&head_send, netbuf);
416     ret = oal_sdio_transfer_netbuf_list(hcc_handler->bus, &head_send, SDIO_WRITE);
417     return ret;
418 }
419 
420 hi_s32 hcc_send_descr_control_data(hcc_handler_stru *hcc_handler, hcc_descr_type descr_type, const hi_void *data,
421     hi_u32 ul_size)
422 {
423     hi_s32 ret;
424     oal_netbuf_stru *netbuf = HI_NULL;
425     struct hcc_descr_header *dscr_hdr = HI_NULL;
426     netbuf = hcc_tx_assem_descr_get(hcc_handler);
427     if (netbuf == HI_NULL) {
428         return -OAL_ENOMEM;
429     }
430 
431     dscr_hdr = (struct hcc_descr_header *)oal_netbuf_data(netbuf);
432     dscr_hdr->descr_type = descr_type;
433 
434     if (ul_size) {
435         if (OAL_WARN_ON(data == HI_NULL)) {
436             hcc_tx_assem_descr_put(hcc_handler, netbuf);
437             return -OAL_EINVAL;
438         }
439         if (OAL_WARN_ON(ul_size + sizeof(struct hcc_descr_header) > oal_netbuf_len(netbuf))) {
440             oal_io_print2("invalid request size:%u,max size:%u\r\n",
441                 (hi_u32)(ul_size + sizeof(struct hcc_descr_header)), (hi_u32)oal_netbuf_len(netbuf));
442             hcc_tx_assem_descr_put(hcc_handler, netbuf);
443             return -OAL_EINVAL;
444         }
445 
446         /* lint -e124 */
447         if (memcpy_s((hi_void *)((hi_u8 *)oal_netbuf_data(netbuf) + sizeof(struct hcc_descr_header)), ul_size, data,
448             ul_size) != EOK) {
449             return -OAL_EINVAL;
450         }
451     }
452     ret = hcc_send_single_descr(hcc_handler, netbuf);
453 
454     hcc_tx_assem_descr_put(hcc_handler, netbuf);
455     return ret;
456 }
457 
458 static hi_void hcc_restore_assemble_netbuf_list(hcc_handler_stru *hcc_handler, oal_netbuf_head_stru *head)
459 {
460     hcc_queue_type_enum type;
461     oal_netbuf_head_stru *assembled_head;
462 
463     type = hcc_handler->hcc_transer_info.tx_assem_info.assembled_queue_type;
464     assembled_head = &hcc_handler->hcc_transer_info.tx_assem_info.assembled_head;
465 
466     if (type >= HCC_QUEUE_COUNT) {
467         type = DATA_LO_QUEUE;
468     }
469 
470     if (!oal_netbuf_list_empty(assembled_head)) {
471         oal_netbuf_splice_sync(head, assembled_head);
472     }
473 }
474 
475 static hi_s32 hcc_send_assemble_reset(hcc_handler_stru *hcc_handler, oal_netbuf_head_stru *head)
476 {
477     hi_s32 ret;
478 
479     hcc_handler->hcc_transer_info.tx_flow_ctrl.flowctrl_reset_count++;
480 
481     /* 当只发送一个聚合描述符包,并且聚合个数为0描述通知Device 重置聚合信息 */
482     ret = hcc_send_descr_control_data(hcc_handler, HCC_DESCR_ASSEM_RESET, HI_NULL, 0);
483 
484     hcc_restore_assemble_netbuf_list(hcc_handler, head);
485 
486     return ret;
487 }
488 
489 
490 hi_s32 hcc_tx_netbuf_queue_switch(hcc_handler_stru *hcc_handler, hcc_netbuf_queue_type queue_type)
491 {
492     return hcc_send_descr_control_data(hcc_handler, HCC_NETBUF_QUEUE_SWITCH, &queue_type, sizeof(queue_type));
493 }
494 
495 hi_s32 hcc_tx_netbuf_test_and_switch_high_pri_queue(hcc_handler_stru *hcc_handler, hcc_netbuf_queue_type pool_type,
496     hi_u8 is_config_frame)
497 {
498     hi_s32 ret = OAL_EFAIL;
499     if (pool_type == HCC_NETBUF_HIGH_QUEUE) {
500         /* 此处在最高位表示是否是配置事件 */
501         if (is_config_frame == 1) {
502             ret = hcc_tx_netbuf_queue_switch(hcc_handler, ((hi_u8)HCC_NETBUF_HIGH_QUEUE) | HCC_CONFIG_FRAME);
503         } else {
504             ret = hcc_tx_netbuf_queue_switch(hcc_handler, HCC_NETBUF_HIGH_QUEUE);
505         }
506     }
507     return ret;
508 }
509 
510 hi_s32 hcc_tx_netbuf_restore_normal_pri_queue(hcc_handler_stru *hcc_handler, hcc_netbuf_queue_type pool_type)
511 {
512     hi_s32 ret = OAL_EFAIL;
513     if (pool_type == HCC_NETBUF_HIGH_QUEUE) {
514         ret = hcc_tx_netbuf_queue_switch(hcc_handler, HCC_NETBUF_NORMAL_QUEUE);
515     }
516     return ret;
517 }
518 
519 /* align_size must be power of 2 */
520 static oal_netbuf_stru *hcc_netbuf_len_align(oal_netbuf_stru *netbuf, hi_u32 align_size)
521 {
522     hi_s32 ret = HI_SUCCESS;
523     hi_u32 len_algin, tail_room_len;
524     hi_u32 len = oal_netbuf_len(netbuf);
525     if (oal_is_aligned(len, align_size)) {
526         return netbuf;
527     }
528     /* align the netbuf */
529     len_algin = oal_round_up(len, align_size);
530     if (len_algin < len) {
531         oam_error_log2(0, 0, "hcc_netbuf_len_align::len_aglin[%d],len[%d]", len_algin, len);
532         return HI_NULL;
533     }
534 
535     tail_room_len = len_algin - len;
536 
537     if (oal_unlikely(tail_room_len > oal_netbuf_tailroom(netbuf))) {
538 #ifdef _PRE_LWIP_ZERO_COPY_DEBUG
539         oam_error_log3(0, 0, "[hcc_send_tx_q_expand_tail] need_tail_room=len_aglin[%d]-len[%d], have_tail_room = %d",
540             len_algin, len, oal_netbuf_tailroom(netbuf));
541 #endif
542         /* tailroom not enough */
543         ret = oal_netbuf_expand_head(netbuf, 0, (hi_s32)tail_room_len, GFP_KERNEL);
544         if (OAL_WARN_ON(ret != HI_SUCCESS)) {
545             oal_io_print1("alloc head room failed,expand tail len=%d\n", tail_room_len);
546             return HI_NULL;
547         }
548     }
549 
550     oal_netbuf_put(netbuf, tail_room_len);
551     return netbuf;
552 }
553 
554 static hi_void hcc_build_next_assem_descr(hcc_handler_stru *hcc_handler, hcc_queue_type_enum type,
555     oal_netbuf_head_stru *head, oal_netbuf_head_stru *next_assembled_head, const oal_netbuf_stru *descr_netbuf,
556     hi_u32 remain_len)
557 {
558     hi_s32 i = 0;
559     hi_s32 len;
560     hi_u8 *buf = HI_NULL;
561     oal_netbuf_stru *netbuf = HI_NULL;
562     oal_netbuf_stru *netbuf_t = HI_NULL;
563     hi_u32 assemble_max_count, queue_len, current_trans_len;
564 
565     buf = (hi_u8 *)oal_netbuf_data(descr_netbuf);
566     len = (hi_s32)oal_netbuf_len(descr_netbuf);
567     assemble_max_count = oal_max(1, g_hcc_assemble_count);
568     queue_len = oal_netbuf_list_len(head);
569     current_trans_len = oal_min(queue_len, assemble_max_count);
570     current_trans_len = oal_min(current_trans_len, remain_len);
571 
572 #ifdef CONFIG_HCC_DEBUG
573     oal_io_print4("build next descr, queue:[remain_len:%u][len:%u][trans_len:%u][max_assem_len:%u]",
574                   remain_len, queue_len, current_trans_len, assemble_max_count);
575 #endif
576 
577     buf[0] = 0;
578 
579     if (current_trans_len == 0) {
580         return;
581     }
582 
583     for (; ;) {
584         /* move the netbuf from head queue to prepare-send queue, head->tail */
585         netbuf = oal_netbuf_delist(head);
586         if (netbuf == HI_NULL) {
587             oal_io_print1("why? this should never happaned! assem list len:%d\n",
588                           oal_netbuf_list_len(next_assembled_head));
589             break;
590         }
591 
592         /* align the buff len to 32B */
593         netbuf_t = hcc_netbuf_len_align(netbuf, HISDIO_H2D_SCATT_BUFFLEN_ALIGN);
594         if (netbuf_t == HI_NULL) {
595             /* return to the list */
596             oal_netbuf_addlist(head, netbuf);
597             break;
598         }
599 
600         current_trans_len--;
601 
602         oal_netbuf_list_tail(next_assembled_head, netbuf_t);
603         if (oal_likely(i >= len)) {
604             oal_io_print3("hcc tx scatt num :%d over buff len:%d,assem count:%u\n", i, len, g_hcc_assemble_count);
605             break;
606         }
607 
608         buf[i++] = (hi_u8)(oal_netbuf_len(netbuf) >> HISDIO_H2D_SCATT_BUFFLEN_ALIGN_BITS);
609         if (current_trans_len == 0) {
610             /* send empty */
611             if (i != len) {
612                 buf[i] = 0;
613             }
614             break;
615         }
616     }
617 
618     if (oal_likely(!oal_netbuf_list_empty(next_assembled_head))) {
619         hcc_handler->hcc_transer_info.tx_assem_info.assembled_queue_type = type;
620     }
621 }
622 
623 static hi_void hcc_tx_netbuf_free(oal_netbuf_stru *pst_netbuf)
624 {
625     hcc_tx_cb_stru *pst_cb_stru = HI_NULL;
626 
627     if (pst_netbuf == HI_NULL) {
628         oal_io_print0("hcc_tx_netbuf_free: pst_netbuf is null\r\n");
629         return;
630     }
631 
632     pst_cb_stru = (hcc_tx_cb_stru *)oal_netbuf_cb(pst_netbuf);
633     if (oal_unlikely(pst_cb_stru->magic != HCC_TX_WAKELOCK_MAGIC)) {
634 #ifdef CONFIG_PRINTK
635 #if (_PRE_OS_VERSION_LINUX == _PRE_OS_VERSION)
636 
637         printk(KERN_EMERG "BUG: tx netbuf:%p on CPU#%d,magic:%08x should be %08x\n", pst_cb_stru,
638             raw_smp_processor_id(), pst_cb_stru->magic, HCC_TX_WAKELOCK_MAGIC);
639         print_hex_dump(KERN_ERR, "tx_netbuf_magic", DUMP_PREFIX_ADDRESS, 16, 1, /* eveny line print 16 */
640             (hi_u8 *)pst_netbuf, sizeof(oal_netbuf_stru), true);
641         printk(KERN_ERR "\n");
642 #endif
643 #endif
644 #if (_PRE_OS_VERSION_LINUX == _PRE_OS_VERSION)
645         OAL_WARN_ON(1);
646 #endif
647         return;
648     }
649 
650     if (oal_likely(pst_cb_stru->destroy)) {
651         pst_cb_stru->destroy(hcc_host_get_handler());
652     }
653 
654     pst_cb_stru->magic = 0x0;
655 
656     oal_netbuf_free(pst_netbuf);
657 }
658 
659 static hi_void hcc_tx_netbuf_list_free(oal_netbuf_head_stru *pst_netbuf_hdr)
660 {
661     oal_netbuf_stru *pst_netbuf = HI_NULL;
662     for (; ;) {
663         pst_netbuf = oal_netbuf_delist(pst_netbuf_hdr);
664         if (pst_netbuf == HI_NULL) {
665             break;
666         }
667         hcc_tx_netbuf_free(pst_netbuf);
668     }
669 }
670 
671 static hi_s32 hcc_send_data_packet(hcc_handler_stru *hcc_handler,
672                                    oal_netbuf_head_stru *head,
673                                    hcc_queue_type_enum type,
674                                    oal_netbuf_head_stru *next_assembled_head,
675                                    hcc_send_mode mode,
676                                    hi_u32 *remain_len)
677 {
678     hi_u8 *buf = HI_NULL;
679     hi_u32 total_send;
680     hi_s32 ret = HI_SUCCESS;
681     oal_netbuf_head_stru head_send;
682     oal_netbuf_stru *netbuf = HI_NULL;
683     oal_netbuf_stru *descr_netbuf = HI_NULL;
684     oal_netbuf_stru *netbuf_t = HI_NULL;
685     hi_u32 *info = HI_NULL;
686 
687     if (*remain_len == 0) {
688         return HI_SUCCESS;
689     }
690 
691 #ifdef CONFIG_HCC_DEBUG
692     oal_io_print3("send queue:%d, mode:%d,next assem len:%d", type, mode, oal_netbuf_list_len(next_assembled_head));
693 #endif
694 
695     descr_netbuf = hcc_tx_assem_descr_get(hcc_handler);
696     if (descr_netbuf == HI_NULL) {
697         ret = -OAL_ENOMEM;
698         /*lint -e801*/
699         goto failed_get_assem_descr;
700     }
701 
702     info = hcc_handler->hcc_transer_info.tx_assem_info.info;
703 
704     oal_netbuf_list_head_init(&head_send);
705 
706     if (oal_netbuf_list_empty(next_assembled_head)) {
707         /* single send */
708         netbuf = oal_netbuf_delist(head);
709         if (netbuf == HI_NULL) {
710             oal_io_print1("netbuf is HI_NULL [len:%d]\n", oal_netbuf_list_len(head));
711             ret = HI_FAIL;
712             /*lint -e801*/
713             goto failed_get_sig_buff;
714         }
715 
716         netbuf_t = hcc_netbuf_len_align(netbuf, HISDIO_H2D_SCATT_BUFFLEN_ALIGN);
717         if (oal_unlikely(netbuf_t == HI_NULL)) {
718             /* return to the list */
719             oal_netbuf_addlist(head, netbuf);
720             ret = HI_FAIL;
721             goto failed_align_netbuf;
722         }
723         oal_netbuf_list_tail(&head_send, netbuf);
724         info[0]++;
725     } else {
726         hi_u32 assemble_len = oal_netbuf_list_len(next_assembled_head);
727         if (assemble_len > HISDIO_HOST2DEV_SCATT_SIZE) {
728             oam_error_log1(0, OAM_SF_ANY, "hcc_send_data_packet::assemble_len[%u] > HISDIO_HOST2DEV_SCATT_SIZE.",
729                 assemble_len);
730         } else {
731             /* move the assem list to send queue */
732             oal_netbuf_splice_init(next_assembled_head, &head_send);
733             info[assemble_len]++;
734         }
735     }
736 
737     total_send = oal_netbuf_list_len(&head_send);
738     if (*remain_len >= total_send) {
739         *remain_len -= total_send;
740     } else {
741         *remain_len = 0;
742     }
743 
744     if (oal_netbuf_list_empty(next_assembled_head) != HI_TRUE) {
745         oam_error_log0(0, 0, "hcc_send_data_packet::next_assembled_head empty.");
746     }
747 
748     if (mode == HCC_ASSEM_SEND) {
749         hcc_build_next_assem_descr(hcc_handler, type, head, next_assembled_head, descr_netbuf, *remain_len);
750     } else {
751         buf = oal_netbuf_data(descr_netbuf);
752         *((hi_u32 *)buf) = 0;
753     }
754 
755     /* add the assem descr buf */
756     oal_netbuf_addlist(&head_send, descr_netbuf);
757 
758     ret = oal_sdio_transfer_netbuf_list(hcc_handler->bus, &head_send, SDIO_WRITE);
759 
760 #ifdef _PRE_WLAN_FEATURE_AUTO_FREQ
761     if (HI_NULL != g_pst_alg_process_func.p_auto_freq_count_func) {
762         g_pst_alg_process_func.p_auto_freq_count_func(total_send);
763     }
764 #endif
765     wlan_pm_set_packet_cnt(total_send);
766     hcc_handler->hcc_transer_info.hcc_queues[HCC_TX].queues[type].total_pkts += total_send;
767 
768     descr_netbuf = oal_netbuf_delist(&head_send);
769     if (descr_netbuf == HI_NULL) {
770         oam_error_log0(0, OAM_SF_ANY, "hcc_send_data_packet::oal_netbuf_delist fail.descr_netbuf is HI_NULL.");
771         ret = HI_SUCCESS;
772         goto failed_get_assem_descr;
773     }
774 
775     hcc_tx_assem_descr_put(hcc_handler, descr_netbuf);
776 
777     /* free the sent netbuf,release the wakelock */
778     hcc_tx_netbuf_list_free(&head_send);
779 
780     return ret;
781 
782 failed_align_netbuf:
783 failed_get_sig_buff:
784     hcc_tx_assem_descr_put(hcc_handler, descr_netbuf);
785 
786 failed_get_assem_descr:
787     return ret;
788 }
789 
790 hi_u32 hcc_queues_flow_ctrl_len(hcc_handler_stru *hcc_handler, hcc_chan_type dir)
791 {
792     hi_s32 i;
793     hi_u32 total;
794     hcc_trans_queue_stru *p_queue;
795 
796     p_queue = hcc_handler->hcc_transer_info.hcc_queues[dir].queues;
797     for (i = 0, total = 0; i < HCC_QUEUE_COUNT; i++, p_queue++) {
798         if (p_queue->flow_ctrl.enable == HI_TRUE) {
799             total += oal_netbuf_list_len(&p_queue->data_queue);
800         }
801     }
802 
803     return total;
804 }
805 
806 hi_void hcc_tx_network_startall_queues(const hcc_handler_stru *hcc_handler)
807 {
808     if (oal_likely(hcc_handler->hcc_transer_info.tx_flow_ctrl.net_startall)) {
809         hcc_handler->hcc_transer_info.tx_flow_ctrl.net_startall();
810     }
811 }
812 
813 hi_void hcc_tx_sleep(hi_void)
814 {
815     g_lo_buf_times++;
816     if (g_lo_buf_times > MAX_TIMES) {
817 #if (_PRE_OS_VERSION_LINUX == _PRE_OS_VERSION)
818         usleep_range(MIN_TIME_VALUE, MAX_TIME_VALUE);
819 #else
820         hi_sleep(1);
821 #endif
822         g_lo_buf_times = 0;
823     }
824 }
825 
826 hi_u8 hcc_list_overflow(hi_void)
827 {
828     return g_list_overflow_flag;
829 }
830 
831 hi_void hcc_clear_tx_queues(hcc_handler_stru *hcc)
832 {
833     hi_s32 i;
834     oal_netbuf_head_stru *head = HI_NULL;
835     for (i = 0; i < HCC_QUEUE_COUNT; i++) {
836         head = &hcc->hcc_transer_info.hcc_queues[HCC_TX].queues[i].data_queue;
837         if (oal_netbuf_list_len(head) > 0) {
838             hcc_tx_netbuf_list_free(head);
839         }
840     }
841 }
842 
843 hi_u8 hcc_discard_key_frame(hi_void)
844 {
845     return g_abandon_key_frame;
846 }
847 
848 static hi_void hcc_delay_time(hi_void)
849 {
850 #if (_PRE_OS_VERSION_LINUX == _PRE_OS_VERSION)
851     usleep_range(MIN_TIME_VALUE, MAX_TIME_VALUE);
852 #else
853     hi_sleep(1);
854 #endif
855 }
856 
857 hi_u8 hcc_config_frame(oal_netbuf_head_stru *head)
858 {
859     unsigned long flags;
860     oal_netbuf_stru *netbuf = HI_NULL;
861     hi_u8 config_frame = 0;
862     oal_spin_lock_irq_save((oal_spin_lock_stru *)&head->lock, &flags);
863     if (!oal_netbuf_list_empty(head)) {
864         netbuf = (oal_netbuf_stru *)oal_netbuf_head_next(head);
865         hi_u8 *hcc_hdr = (hi_u8 *)oal_netbuf_data(netbuf);
866         frw_hcc_extend_hdr_stru* ext_hdr = (frw_hcc_extend_hdr_stru*)(hcc_hdr + HCC_HDR_LEN
867             + WLAN_MAX_MAC_HDR_LEN + HI_MAX_DEV_CB_LEN);
868         if (ext_hdr->config_frame == 1) {
869             config_frame = 1;
870         }
871     }
872     oal_spin_unlock_irq_restore((oal_spin_lock_stru *)&head->lock, &flags);
873     return config_frame;
874 }
875 
876 hi_s32 hcc_host_proc_tx_queue_impl(oal_netbuf_head_stru *buffQueue, void *handler, int32_t type)
877 {
878     hcc_handler_stru *hcc_handler = (hcc_handler_stru *)handler;
879     hi_s32 ret = 0;
880     hi_s32 count = 0;
881     hi_u32 remain_len, remain_len_t;
882     oal_netbuf_head_stru *head = HI_NULL;
883     oal_netbuf_head_stru *next_assembled_head = HI_NULL;
884     hcc_send_mode send_mode;
885     hcc_trans_queue_stru *hcc_queue = HI_NULL;
886     hcc_netbuf_queue_type pool_type;
887     hi_u32 priority_cnt = 0;
888     hi_u8 is_schedule = HI_TRUE;
889 #ifndef _PRE_FEATURE_HCC_TASK
890     struct FlowControlModule *fcm = HI_NULL;
891 #endif
892     if (type >= HCC_QUEUE_COUNT) {
893         oam_error_log1(0, 0, "hcc_send_tx_queue:: invalid hcc_queue type[%d]", type);
894         return count;
895     }
896     hcc_queue = &hcc_handler->hcc_transer_info.hcc_queues[HCC_TX].queues[type];
897     head = buffQueue;
898 #ifndef _PRE_FEATURE_HCC_TASK
899     fcm = GetFlowControlModule();
900 #endif
901     hcc_tx_transfer_lock(hcc_handler);
902 
903     if (oal_netbuf_list_empty(head)) {
904 #if (_PRE_OS_VERSION_LINUX == _PRE_OS_VERSION)
905         schedule();
906 #endif
907         goto sdio_tx_exit;
908     }
909 
910     if (hcc_handler->bus) {
911         ret = oal_sdio_get_credit(hcc_handler->bus, &priority_cnt);
912         if (ret < 0) {
913             hcc_tx_transfer_unlock(hcc_handler);
914             hcc_clear_tx_queues(hcc_handler);
915             hcc_delay_time();
916             return 0;
917         }
918     }
919     oal_spin_lock(&(hcc_handler->hcc_transer_info.tx_flow_ctrl.st_hipri_lock));
920     hcc_handler->hcc_transer_info.tx_flow_ctrl.uc_hipriority_cnt =
921         hisdio_large_pkt_get(priority_cnt) + hisdio_mgmt_pkt_get(priority_cnt);
922     hcc_handler->hcc_transer_info.tx_flow_ctrl.uc_lopriority_cnt = hisdio_large_pkt_get(priority_cnt);
923     hcc_handler->hcc_transer_info.tx_flow_ctrl.des_cnt = hisdio_comm_reg_seq_pkt_get(priority_cnt);
924     oal_spin_unlock(&(hcc_handler->hcc_transer_info.tx_flow_ctrl.st_hipri_lock));
925     remain_len = oal_netbuf_list_len(head);
926 
927     g_priority_cnt = hcc_handler->hcc_transer_info.tx_flow_ctrl.uc_hipriority_cnt;
928     g_lopriority_cnt = hcc_handler->hcc_transer_info.tx_flow_ctrl.uc_lopriority_cnt;
929     g_des_cnt = hcc_handler->hcc_transer_info.tx_flow_ctrl.des_cnt;
930 
931     if (type == DATA_LO_QUEUE) {
932         if (remain_len > LOW_PRIORITY_COUNT) {
933             g_list_overflow_flag = HI_TRUE;
934         } else {
935             g_list_overflow_flag = HI_FALSE;
936         }
937 
938         if (remain_len > KEY_FRAME_COUNT) {
939             g_abandon_key_frame = HI_TRUE;
940         } else {
941             g_abandon_key_frame = HI_FALSE;
942         }
943     }
944 
945     if (hcc_queue->flow_ctrl.flow_type == HCC_FLOWCTRL_CREDIT &&
946         hcc_handler->hcc_transer_info.tx_flow_ctrl.uc_hipriority_cnt <= MIN_DATA_LO_QUEUE) {
947         hcc_tx_sleep();
948         goto sdio_tx_exit;
949     }
950 
951     if (hcc_queue->flow_ctrl.flow_type == HCC_FLOWCTRL_SDIO &&
952         hcc_handler->hcc_transer_info.tx_flow_ctrl.uc_lopriority_cnt <= MIN_DATA_LO_QUEUE) {
953         hcc_tx_sleep();
954         goto sdio_tx_exit;
955     }
956 
957     if (hcc_queue->flow_ctrl.flow_type == HCC_FLOWCTRL_SDIO &&
958         hcc_handler->hcc_transer_info.tx_flow_ctrl.des_cnt < MIN_DES_CNT) {
959         hcc_tx_sleep();
960         goto sdio_tx_exit;
961     }
962     g_lo_buf_times = 0;
963 
964     if (hcc_queue->flow_ctrl.flow_type == HCC_FLOWCTRL_CREDIT) {
965         remain_len = oal_min(hcc_handler->hcc_transer_info.tx_flow_ctrl.uc_hipriority_cnt, remain_len);
966     } else if (hcc_queue->flow_ctrl.flow_type == HCC_FLOWCTRL_SDIO) {
967         remain_len = oal_min(hcc_handler->hcc_transer_info.tx_flow_ctrl.uc_lopriority_cnt, remain_len);
968     }
969 
970     remain_len_t = remain_len;
971     next_assembled_head = &hcc_handler->hcc_transer_info.tx_assem_info.assembled_head;
972 
973     if (!oal_netbuf_list_empty(next_assembled_head)) {
974         if (hcc_send_assemble_reset(hcc_handler, head) != HI_SUCCESS) {
975             /* send one pkt */
976             count = 1;
977             hcc_delay_time();
978             goto sdio_tx_exit;
979         }
980     }
981     send_mode = hcc_queue->send_mode;
982     pool_type = hcc_queue->netbuf_pool_type;
983 
984     while (remain_len != 0) {
985         if (hcc_queue->flow_ctrl.flow_type == HCC_FLOWCTRL_CREDIT) {
986             hi_u8 is_config_frame = hcc_config_frame(head);
987             ret = hcc_tx_netbuf_test_and_switch_high_pri_queue(hcc_handler, pool_type, is_config_frame);
988             if (ret != HI_SUCCESS) {
989                 break;
990             }
991         }
992 
993         ret = hcc_send_data_packet(hcc_handler, head, type, next_assembled_head, send_mode, &remain_len);
994         if (ret != HI_SUCCESS) {
995             break;
996         }
997         count += (hi_s32)(remain_len_t - remain_len);
998 
999 #if (!defined(CONFIG_PREEMPT) && (_PRE_OS_VERSION_LINUX == _PRE_OS_VERSION))
1000         cond_resched();
1001 #endif
1002     }
1003 
1004     if (ret != HI_SUCCESS) {
1005         hcc_delay_time();
1006     }
1007 
1008     /* 正常发送完成,不需要再调度一次 */
1009     is_schedule = HI_FALSE;
1010 
1011     if (hcc_queue->flow_ctrl.flow_type == HCC_FLOWCTRL_CREDIT) {
1012         hcc_tx_netbuf_restore_normal_pri_queue(hcc_handler, pool_type);
1013     }
1014 
1015 sdio_tx_exit:
1016     hcc_tx_transfer_unlock(hcc_handler);
1017     if (wlan_pm_is_disabling()) {
1018 #if (_PRE_OS_VERSION_LINUX == _PRE_OS_VERSION)
1019         usleep_range(PM_DISABLING_TIME, PM_DISABLING_TIME);
1020 #else
1021         hi_sleep(PM_DISABLING_TIME);
1022 #endif
1023     }
1024     /* 异常场景下才重新再调度一次 */
1025     if (is_schedule && !oal_netbuf_list_empty(head)) {
1026 #ifdef _PRE_FEATURE_HCC_TASK
1027         hcc_sched_transfer(hcc_handler);
1028 #else
1029         fcm->interface->schedFCM(fcm, FLOW_TX);
1030 #endif
1031     }
1032     return count;
1033 }
1034 
1035 hi_s32 hcc_host_proc_tx_queue(hcc_handler_stru *hcc_handler, hcc_queue_type_enum type)
1036 {
1037     oal_netbuf_head_stru *buffQueue =
1038         &((hcc_handler_stru *)hcc_handler)->hcc_transer_info.hcc_queues[HCC_TX].queues[type].data_queue;
1039     return hcc_host_proc_tx_queue_impl(buffQueue, hcc_handler, type);
1040 }
1041 #ifdef _PRE_FEATURE_HCC_TASK
1042 static hi_void hcc_transfer_rx_handler(hcc_handler_stru *hcc_handler, oal_netbuf_stru *netbuf)
1043 {
1044     /* get the rx buf and enqueue */
1045     oal_netbuf_list_tail(&hcc_handler->hcc_transer_info.hcc_queues[HCC_RX].queues[DATA_LO_QUEUE].data_queue, netbuf);
1046     if (0 == g_hcc_rx_thread_enable) {
1047         hcc_host_proc_rx_queue(hcc_handler, DATA_LO_QUEUE);
1048     }
1049 }
1050 
1051 static hi_void hcc_transfer_rx_handler_replace(hcc_handler_stru *hcc_handler, oal_netbuf_stru *netbuf_new)
1052 {
1053     oal_netbuf_stru *netbuf_old = HI_NULL;
1054     hcc_trans_queue_stru *hcc_queue = &hcc_handler->hcc_transer_info.hcc_queues[HCC_RX].queues[DATA_LO_QUEUE];
1055 
1056     netbuf_old = oal_netbuf_delist(&hcc_queue->data_queue);
1057     if (netbuf_old != HI_NULL) {
1058         hcc_queue->loss_pkts++;
1059         oal_netbuf_free(netbuf_old);
1060     }
1061 
1062     oal_netbuf_list_tail(&hcc_queue->data_queue, netbuf_new);
1063 
1064     if (g_hcc_rx_thread_enable == 0) {
1065         hcc_host_proc_rx_queue(hcc_handler, DATA_LO_QUEUE);
1066     }
1067 }
1068 #endif
1069 hi_void hcc_sched_transfer(hcc_handler_stru *hcc_handler)
1070 {
1071     if (OAL_WARN_ON(hcc_handler == HI_NULL)) {
1072         oam_error_log0(0, 0, "hcc_sched_transfer:: hcc_handler is null!");
1073         return;
1074     }
1075 
1076     hi_wait_queue_wake_up_interrupt(&hcc_handler->hcc_transer_info.hcc_transfer_wq);
1077 }
1078 
1079 hi_void hcc_rx_sched_transfer(hcc_handler_stru *hcc_handler)
1080 {
1081     if (OAL_WARN_ON(hcc_handler == HI_NULL)) {
1082         oam_error_log0(0, 0, "hcc_sched_transfer:: hcc_handler is null!");
1083         return;
1084     }
1085     hi_wait_queue_wake_up_interrupt(&hcc_handler->hcc_transer_info.hcc_rx_wq);
1086 }
1087 
1088 static hi_void hcc_rx_netbuf_list_handler(hcc_handler_stru *hcc_handler, oal_netbuf_head_stru *netbuf_head)
1089 {
1090     hi_u32 scatt_count;
1091     oal_netbuf_stru *netbuf = HI_NULL;
1092     hcc_header_stru *hcc_hdr = HI_NULL;
1093 #ifndef _PRE_FEATURE_HCC_TASK
1094     struct FlowControlModule *fcm = HI_NULL;
1095     hcc_convert_queue_para para;
1096 #endif
1097     scatt_count = oal_netbuf_list_len(netbuf_head);
1098     if (scatt_count > HISDIO_DEV2HOST_SCATT_MAX) {
1099         oam_error_log1(0, 0, "hcc_rx_netbuf_list_handler:: scatt buffs overflow, scatt_count[%d]", scatt_count);
1100         scatt_count = 0;
1101     }
1102 
1103     hcc_handler->hcc_transer_info.rx_assem_info.info[scatt_count]++;
1104 
1105 #ifdef _PRE_FEATURE_HCC_TASK
1106     hcc_trans_queues_stru *hcc_rx = &hcc_handler->hcc_transer_info.hcc_queues[HCC_RX];
1107 #else
1108     fcm = GetFlowControlModule();
1109 #endif
1110 
1111     for (;;) {
1112         netbuf = oal_netbuf_delist(netbuf_head);
1113         if (netbuf == HI_NULL) {
1114             break;
1115         }
1116         hcc_hdr = (hcc_header_stru *)oal_netbuf_data(netbuf);
1117         if (hcc_host_check_header_vaild(hcc_hdr) != HI_TRUE) {
1118             oal_print_hex_dump((hi_u8 *)hcc_hdr, HCC_HDR_TOTAL_LEN, 16, "invalid hcc header: "); /* group size 16 */
1119         }
1120 
1121 #ifdef _PRE_FEATURE_HCC_TASK
1122         if (hcc_rx->queues[DATA_LO_QUEUE].flow_ctrl.enable == HI_TRUE) {
1123             if (oal_netbuf_list_len(&hcc_rx->queues[DATA_LO_QUEUE].data_queue) >
1124                 hcc_rx->queues[DATA_LO_QUEUE].flow_ctrl.high_waterline) {
1125                 hcc_transfer_rx_handler_replace(hcc_handler, netbuf);
1126             } else {
1127                 hcc_transfer_rx_handler(hcc_handler, netbuf);
1128             }
1129         } else {
1130             hcc_transfer_rx_handler(hcc_handler, netbuf);
1131         }
1132 #else
1133         if (fcm != NULL && fcm->op != NULL && fcm->op->getRxQueueId != NULL) {
1134             para.queueType = DATA_LO_QUEUE;
1135             para.isVip = HI_FALSE;
1136             FlowControlQueueID id = fcm->op->getRxQueueId((void *)(&para));
1137             fcm->interface->sendBuffToFCM(fcm, netbuf, id, FLOW_RX);
1138         }
1139 #endif
1140     }
1141 #ifdef _PRE_FEATURE_HCC_TASK
1142     if (g_hcc_rx_thread_enable == 1) {
1143         hcc_rx_sched_transfer(hcc_handler);
1144     }
1145 #else
1146     fcm->interface->schedFCM(fcm, FLOW_RX);
1147 #endif
1148 }
1149 
1150 hi_s32 sdio_transfer_rx_handler(hi_void *data)
1151 {
1152     hi_s32 err_code;
1153     oal_netbuf_head_stru netbuf_head;
1154     hcc_handler_stru *hcc_handler = (hcc_handler_stru *)data;
1155 
1156     oal_netbuf_head_init(&netbuf_head);
1157 
1158     err_code = oal_sdio_build_rx_netbuf_list(hcc_handler->bus, &netbuf_head);
1159     if (err_code != HI_SUCCESS) {
1160         oam_error_log1(0, 0, "sdio_transfer_rx_handler:: sdio_build_rx_netbuf_list failed[%d]", err_code);
1161         return err_code;
1162     }
1163 
1164     err_code = oal_sdio_transfer_netbuf_list(hcc_handler->bus, &netbuf_head, SDIO_READ);
1165     if (err_code != HI_SUCCESS) {
1166         oal_netbuf_list_purge(&netbuf_head);
1167         oam_error_log1(0, 0, "sdio_transfer_rx_handler:: sdio_transfer_netbuf_list failed[%d]", err_code);
1168         return -OAL_EFAIL;
1169     }
1170 
1171     if (hcc_get_thread_exit_flag() == HI_TRUE || hi_wifi_get_host_exit_flag() == HI_TRUE) {
1172         oal_netbuf_list_purge(&netbuf_head);
1173         return -OAL_EFAIL;
1174     }
1175     hcc_rx_netbuf_list_handler(hcc_handler, &netbuf_head);
1176     return HI_SUCCESS;
1177 }
1178 
1179 hi_void hcc_tx_assem_descr_exit(hcc_handler_stru *hcc_handler)
1180 {
1181     oal_netbuf_list_purge(&hcc_handler->tx_descr_info.tx_assem_descr_hdr);
1182 }
1183 
1184 hi_void hcc_host_tx_assem_info_reset(hcc_handler_stru *hcc_handler)
1185 {
1186     memset_s(hcc_handler->hcc_transer_info.tx_assem_info.info, sizeof(hcc_handler->hcc_transer_info.tx_assem_info.info),
1187         0, sizeof(hcc_handler->hcc_transer_info.tx_assem_info.info));
1188 }
1189 
1190 hi_void hcc_host_rx_assem_info_reset(hcc_handler_stru *hcc_handler)
1191 {
1192     memset_s(hcc_handler->hcc_transer_info.rx_assem_info.info, sizeof(hcc_handler->hcc_transer_info.rx_assem_info.info),
1193         0, sizeof(hcc_handler->hcc_transer_info.rx_assem_info.info));
1194 }
1195 
1196 hi_void hcc_assem_info_init(hcc_handler_stru *hcc_handler)
1197 {
1198     hcc_handler->hcc_transer_info.tx_assem_info.assemble_max_count = g_hcc_assemble_count;
1199     hcc_host_tx_assem_info_reset(hcc_handler);
1200     hcc_host_rx_assem_info_reset(hcc_handler);
1201     oal_netbuf_list_head_init(&hcc_handler->hcc_transer_info.tx_assem_info.assembled_head);
1202 }
1203 
1204 hi_void hcc_trans_limit_parm_init(hcc_handler_stru *hcc_handler)
1205 {
1206 #ifdef _PRE_WLAN_FEATURE_OFFLOAD_FLOWCTL
1207     hi_s32 i;
1208     hcc_trans_queues_stru *pst_hcc_tx_queues = &hcc_handler->hcc_transer_info.hcc_queues[HCC_TX];
1209 
1210     for (i = 0; i < HCC_QUEUE_COUNT; i++) {
1211         hcc_handler->hcc_transer_info.hcc_queues[HCC_TX].queues[i].burst_limit = (hi_u32)HCC_FLUSH_ALL;
1212         hcc_handler->hcc_transer_info.hcc_queues[HCC_RX].queues[i].burst_limit = (hi_u32)HCC_FLUSH_ALL;
1213     }
1214 
1215     pst_hcc_tx_queues->queues[CTRL_QUEUE].burst_limit = 256;          /* CTRL_QUEUE burst_limit 256 */
1216     pst_hcc_tx_queues->queues[DATA_HI_QUEUE].burst_limit = 256;       /* DATA_HI_QUEUE burst_limit 256 */
1217     pst_hcc_tx_queues->queues[DATA_LO_QUEUE].burst_limit = 256;       /* DATA_LO_QUEUE burst_limit 256 */
1218     pst_hcc_tx_queues->queues[DATA_TCP_DATA_QUEUE].burst_limit = 256; /* DATA_TCP_DATA_QUEUE burst_limit 256 */
1219     pst_hcc_tx_queues->queues[DATA_TCP_ACK_QUEUE].burst_limit = 256;  /* DATA_TCP_ACK_QUEUE burst_limit 256 */
1220     pst_hcc_tx_queues->queues[DATA_UDP_BK_QUEUE].burst_limit = 10;    /* DATA_UDP_BK_QUEUE burst_limit 10 */
1221     pst_hcc_tx_queues->queues[DATA_UDP_BE_QUEUE].burst_limit = 20;    /* DATA_UDP_BE_QUEUE burst_limit 20 */
1222     pst_hcc_tx_queues->queues[DATA_UDP_VI_QUEUE].burst_limit = 40;    /* DATA_UDP_VI_QUEUE burst_limit 40 */
1223     pst_hcc_tx_queues->queues[DATA_UDP_VO_QUEUE].burst_limit = 60;    /* DATA_UDP_VO_QUEUE burst_limit 60 */
1224 #else
1225     hi_unref_param(hcc_handler);
1226 #endif
1227 }
1228 
1229 hi_void hcc_trans_send_mode_init(hcc_handler_stru *hcc_handler)
1230 {
1231     hi_s32 i;
1232 
1233     for (i = 0; i < HCC_QUEUE_COUNT; i++) {
1234         hcc_handler->hcc_transer_info.hcc_queues[HCC_TX].queues[i].send_mode = HCC_ASSEM_SEND;
1235     }
1236     hcc_handler->hcc_transer_info.hcc_queues[HCC_TX].queues[DATA_HI_QUEUE].send_mode = HCC_SINGLE_SEND;
1237 }
1238 
1239 hi_s32 hcc_tx_assem_descr_init(hcc_handler_stru *hcc_handler)
1240 {
1241     hi_s32 i;
1242     hi_s32 ret = HI_SUCCESS;
1243     oal_netbuf_stru *netbuf = HI_NULL;
1244 
1245     oal_netbuf_head_init(&hcc_handler->tx_descr_info.tx_assem_descr_hdr);
1246 
1247     /* assem descr ping-pong buff, 2 should be ok */
1248     hcc_handler->tx_descr_info.descr_num = 2;
1249 
1250     for (i = 0; i < hcc_handler->tx_descr_info.descr_num; i++) {
1251         netbuf = oal_netbuf_alloc(HISDIO_HOST2DEV_SCATT_SIZE, 0, 0);
1252         if (netbuf == HI_NULL) {
1253             /*lint -e801*/
1254             goto failed_netbuf_alloc;
1255         }
1256 
1257         oal_netbuf_put(netbuf, HISDIO_HOST2DEV_SCATT_SIZE);
1258         memset_s(oal_netbuf_data(netbuf), oal_netbuf_len(netbuf), 0, oal_netbuf_len(netbuf));
1259         oal_netbuf_list_tail(&hcc_handler->tx_descr_info.tx_assem_descr_hdr, netbuf);
1260         if (!oal_is_aligned(((uintptr_t)oal_netbuf_data(netbuf)), 4)) { /* 4 字节对齐 */
1261             oam_error_log0(0, 0, "hcc_tx_assem_descr_init:: 4 aligned failed!");
1262         }
1263     }
1264     return ret;
1265 failed_netbuf_alloc:
1266     oal_netbuf_list_purge(&hcc_handler->tx_descr_info.tx_assem_descr_hdr);
1267     return -OAL_ENOMEM;
1268 }
1269 
1270 static hi_void hcc_dev_flowctr_timer_del(hcc_handler_stru *hcc_handler)
1271 {
1272     if (oal_in_interrupt()) {
1273         oal_timer_delete(&hcc_handler->hcc_transer_info.tx_flow_ctrl.flow_timer);
1274     } else {
1275         oal_timer_delete_sync(&hcc_handler->hcc_transer_info.tx_flow_ctrl.flow_timer);
1276     }
1277 }
1278 
1279 hi_void hcc_dev_flowctrl_on(hcc_handler_stru *hcc_handler, hi_u8 need_notify_dev)
1280 {
1281     hcc_handler->hcc_transer_info.tx_flow_ctrl.flowctrl_on_count++;
1282 #ifdef CONFIG_HCC_DEBUG
1283     oal_io_print("start tranferring to device\n");
1284 #endif
1285 
1286     if (hcc_handler->hcc_transer_info.tx_flow_ctrl.flowctrl_flag == D2H_MSG_FLOWCTRL_OFF) {
1287         hcc_dev_flowctr_timer_del(hcc_handler);
1288         hcc_handler->hcc_transer_info.tx_flow_ctrl.flowctrl_flag = D2H_MSG_FLOWCTRL_ON;
1289         hcc_sched_transfer(hcc_handler);
1290     }
1291 
1292     if (need_notify_dev) {
1293         oam_info_log0(0, 0, "hcc_dev_flowctrl_on:: Host turn on dev flow ctrl");
1294         oal_bus_send_msg(hcc_handler->bus, H2D_MSG_FLOWCTRL_ON);
1295     }
1296 }
1297 
1298 hi_void hi_wifi_device_deinit(const hcc_handler_stru *hcc_handler)
1299 {
1300     oal_bus_send_msg(hcc_handler->bus, H2D_MSG_PM_WLAN_OFF);
1301 }
1302 
1303 hi_void hcc_dev_flowctrl_off(hcc_handler_stru *hcc_handler)
1304 {
1305     if (hcc_handler->hcc_transer_info.tx_flow_ctrl.flowctrl_flag == D2H_MSG_FLOWCTRL_ON) {
1306         oal_timer_start(&hcc_handler->hcc_transer_info.tx_flow_ctrl.flow_timer,
1307             hcc_handler->hcc_transer_info.tx_flow_ctrl.timeout);
1308     }
1309 
1310     hcc_handler->hcc_transer_info.tx_flow_ctrl.flowctrl_flag = D2H_MSG_FLOWCTRL_OFF;
1311     hcc_handler->hcc_transer_info.tx_flow_ctrl.flowctrl_off_count++;
1312 #ifdef CONFIG_HCC_DEBUG
1313     oal_io_print("stop tranferring to device\n");
1314 #endif
1315 }
1316 
1317 hi_s32 hcc_flow_on_callback(hi_void *data)
1318 {
1319     hcc_dev_flowctrl_on((hcc_handler_stru *)data, 0);
1320     return HI_SUCCESS;
1321 }
1322 
1323 hi_s32 hcc_flow_off_callback(hi_void *data)
1324 {
1325     hcc_dev_flowctrl_off((hcc_handler_stru *)data);
1326     return HI_SUCCESS;
1327 }
1328 
1329 hi_s32 hcc_message_register(const hcc_handler_stru *hcc_handler, hi_u8 msg, hcc_msg_rx cb, hi_void *data)
1330 {
1331     return oal_bus_message_register(hcc_handler->bus, msg, cb, data);
1332 }
1333 
1334 hi_void hcc_message_unregister(const hcc_handler_stru *hcc_handler, hi_u8 msg)
1335 {
1336     oal_bus_message_unregister(hcc_handler->bus, msg);
1337 }
1338 
1339 hi_s32 hcc_credit_update_callback(hi_void *data)
1340 {
1341     hi_u8 large_cnt;
1342     hcc_handler_stru *hcc_handler = (hcc_handler_stru *)data;
1343     oal_channel_stru *hi_sdio = (oal_channel_stru *)hcc_handler->bus->priData.data;
1344 
1345     large_cnt = hisdio_large_pkt_get(hi_sdio->sdio_extend->credit_info);
1346     if (large_cnt == 0) {
1347         oam_info_log0(0, OAM_SF_PWR, "hcc_credit_update_callback:: credit updata zero!");
1348     }
1349 
1350     oal_spin_lock(&(hcc_handler->hcc_transer_info.tx_flow_ctrl.st_hipri_lock));
1351     hcc_handler->hcc_transer_info.tx_flow_ctrl.uc_hipriority_cnt = large_cnt;
1352     oal_spin_unlock(&(hcc_handler->hcc_transer_info.tx_flow_ctrl.st_hipri_lock));
1353     hcc_handler->hcc_transer_info.tx_flow_ctrl.flowctrl_hipri_update_count++;
1354     hcc_sched_transfer(hcc_handler);
1355     return HI_SUCCESS;
1356 }
1357 
1358 hi_s32 hcc_high_pkts_loss_callback(hi_void *data)
1359 {
1360     OAL_REFERENCE(data);
1361     return HI_SUCCESS;
1362 }
1363 
1364 hi_s32 hcc_hmac_rx_extend_hdr_vaild_check(const frw_hcc_extend_hdr_stru *hcc_ext_hdr)
1365 {
1366     if (hcc_ext_hdr->nest_type >= FRW_EVENT_TYPE_BUTT) {
1367         oam_error_log1(0, 0, "hcc_hmac_rx_extend_hdr_vaild_check:: invalid nest_type[%d]", hcc_ext_hdr->nest_type);
1368         return HI_FALSE;
1369     }
1370 
1371     return HI_TRUE;
1372 }
1373 
1374 hi_s32 hcc_hmac_rx_wifi_post_func(hi_u8 hcc_subtype, const hcc_netbuf_stru *hcc_netbuf, hi_u8 *context)
1375 {
1376     hi_unref_param(hcc_subtype);
1377     hi_unref_param(context);
1378     frw_hcc_extend_hdr_stru *hcc_ext_hdr = HI_NULL;
1379     hmac_vap_stru *hmac_vap = HI_NULL;
1380     frw_event_mem_stru *event_mem = HI_NULL;
1381     frw_event_stru *hcc_event = HI_NULL;
1382     hcc_event_stru *event_payload = HI_NULL;
1383     hi_s32 err_code;
1384 
1385     hcc_ext_hdr = (frw_hcc_extend_hdr_stru *)oal_netbuf_data(hcc_netbuf->pst_netbuf);
1386     if (hcc_hmac_rx_extend_hdr_vaild_check(hcc_ext_hdr) != HI_TRUE) {
1387         oal_netbuf_free(hcc_netbuf->pst_netbuf);
1388         return -OAL_EINVAL;
1389     }
1390 
1391     hmac_vap = hmac_vap_get_vap_stru(hcc_ext_hdr->vap_id);
1392     if (hmac_vap == HI_NULL) {
1393         oam_error_log1(0, 0, "hcc_hmac_rx_wifi_post_func:: hmac_vap is null, vap_id[%d]", hcc_ext_hdr->vap_id);
1394         oal_netbuf_free(hcc_netbuf->pst_netbuf);
1395         return -OAL_EINVAL;
1396     }
1397 
1398     event_mem = frw_event_alloc(sizeof(hcc_event_stru));
1399     if (event_mem == HI_NULL) {
1400         oam_error_log0(0, 0, "hcc_hmac_rx_wifi_post_func:: frw_event alloc failed!");
1401         oal_netbuf_free(hcc_netbuf->pst_netbuf);
1402         return -OAL_ENOMEM;
1403     }
1404 
1405     oal_netbuf_pull(hcc_netbuf->pst_netbuf, sizeof(frw_hcc_extend_hdr_stru));
1406 
1407     hcc_event = frw_get_event_stru(event_mem);
1408     frw_event_hdr_init(&(hcc_event->event_hdr), hcc_ext_hdr->nest_type, hcc_ext_hdr->nest_sub_type,
1409         sizeof(hcc_event_stru), FRW_EVENT_PIPELINE_STAGE_1, hcc_ext_hdr->vap_id);
1410 
1411     event_payload = (hcc_event_stru *)frw_get_event_payload(event_mem);
1412     event_payload->netbuf = hcc_netbuf->pst_netbuf;
1413     event_payload->buf_len = oal_netbuf_len(hcc_netbuf->pst_netbuf);
1414 
1415     frw_event_task_lock();
1416     /* 更改HCC发送RX事件由函数直接调用为event事件抛送,防止HCC中断frw任务的执行造成异常 */
1417     err_code = (hi_s32)frw_event_post_event(event_mem);
1418     frw_event_task_unlock();
1419     if (err_code != HI_SUCCESS) {
1420         oam_error_log3(0, 0, "hcc_hmac_rx_wifi_post_func:: post_event failed, err_code[%d], main_type[%d], subtype[%d]",
1421             err_code, hcc_ext_hdr->nest_type, hcc_ext_hdr->nest_sub_type);
1422         oal_netbuf_free(hcc_netbuf->pst_netbuf);
1423     }
1424 
1425     frw_event_free(event_mem);
1426 
1427     return err_code;
1428 }
1429 
1430 hi_void dev_dump_info(hi_char *buf, hi_s32 length)
1431 {
1432     hi_syserr_info *info = (hi_syserr_info *)buf;
1433     if (info == HI_NULL || length < (hi_s32)sizeof(hi_syserr_info)) {
1434         oam_error_log2(0, 0, "length = %d, %d", length, sizeof(hi_syserr_info));
1435         return;
1436     }
1437     oam_error_log0(0, 0, "==============device exception info=================");
1438     oam_error_log0(0, 0, "***Exc Info***");
1439     oam_error_log1(0, 0, "%s", (hi_u32)(uintptr_t)info->os_info.task.name);
1440     oam_error_log1(0, 0, "PC Task ID  = 0x%x", info->os_info.task.id);
1441     oam_error_log1(0, 0, "Cur Task ID = 0x%x", info->core_info.cur_task_id);
1442     oam_error_log0(0, 0, "***reg info***");
1443     oam_error_log1(0, 0, "mepc    = 0x%x", info->reg_info.mepc);
1444     oam_error_log1(0, 0, "mstatus = 0x%x", info->core_info.mstatus);
1445     oam_error_log1(0, 0, "mtval   = 0x%x", info->core_info.mtval);
1446     oam_error_log1(0, 0, "mcause  = 0x%x", info->core_info.mcause);
1447     oam_error_log1(0, 0, "ccause  = 0x%x", info->core_info.ccause);
1448     oam_error_log1(0, 0, "ra = 0x%x", info->reg_info.ra);
1449     oam_error_log1(0, 0, "sp = 0x%x", info->reg_info.sp);
1450     oam_error_log1(0, 0, "s0 = 0x%x", info->reg_info.s0);
1451     oam_error_log1(0, 0, "s1 = 0x%x", info->reg_info.s1);
1452     oam_error_log1(0, 0, "a0 = 0x%x", info->reg_info.a0);
1453     oam_error_log1(0, 0, "a1 = 0x%x", info->reg_info.a1);
1454     oam_error_log1(0, 0, "a2 = 0x%x", info->reg_info.a2);
1455     oam_error_log1(0, 0, "a3 = 0x%x", info->reg_info.a3);
1456     oam_error_log1(0, 0, "a4 = 0x%x", info->reg_info.a4);
1457     oam_error_log1(0, 0, "a5 = 0x%x", info->reg_info.a5);
1458     oam_error_log0(0, 0, "***memory***");
1459     oam_error_log1(0, 0, "Pool Size = 0x%x", info->os_info.mem.pool_size);
1460     oam_error_log1(0, 0, "Used Size = 0x%x", info->os_info.mem.cur_use_size);
1461     oam_error_log0(0, 0, "=====================================================");
1462 }
1463 
1464 hi_void dev_backtrace_info(const hi_char *buf, hi_s32 length)
1465 {
1466     int i;
1467 
1468     oam_error_log0(0, 0, "==============device backtrace=================");
1469     oam_error_log0(0, 0, "***code trace***");
1470     for (i = 0; i < length / WORD_WIDTH; i++) {
1471         oam_error_log2(0, 0, "code trace -- addr:%d   0x%x", i, *((hi_u32 *)buf + i));
1472     }
1473     oam_error_log0(0, 0, "***code trace end***");
1474     oam_error_log0(0, 0, "===============================================");
1475 }
1476 
1477 hi_s32 hcc_oam_rx_log_func(hi_u8 hcc_subtype, const hcc_netbuf_stru *hcc_netbuf, hi_u8 *context)
1478 {
1479     hi_unref_param(hcc_subtype);
1480     hi_unref_param(context);
1481     frw_hcc_extend_hdr_stru *hcc_ext_hdr = HI_NULL;
1482     hi_u16 buf_len;
1483     oal_netbuf_stru *netbuf = HI_NULL;
1484     hi_u32 *buf = HI_NULL;
1485     hi_s32 ret;
1486     hcc_ext_hdr = (frw_hcc_extend_hdr_stru *)oal_netbuf_data(hcc_netbuf->pst_netbuf);
1487     if (hcc_ext_hdr->nest_type != FRW_EVENT_TYPE_HCC) {
1488         ret = -OAL_EINVAL;
1489         goto end_oam_log;
1490     }
1491     netbuf = hcc_netbuf->pst_netbuf;
1492     buf_len = oal_netbuf_len(hcc_netbuf->pst_netbuf);
1493     if (buf_len <= HCC_EXTEND_TOTAL_SIZE) {
1494         ret = -OAL_EINVAL;
1495         goto end_oam_log;
1496     }
1497     buf = (hi_u32 *)((hi_u8 *)oal_netbuf_data(netbuf) + HCC_EXTEND_TOTAL_SIZE);
1498     switch (hcc_ext_hdr->nest_sub_type) {
1499         case OAM_DUMP_TYPE:
1500             dev_dump_info((hi_char *)buf, buf_len - HCC_EXTEND_TOTAL_SIZE);
1501             break;
1502         case OAM_BACK_TRACE_TYPE:
1503             dev_backtrace_info((hi_char *)buf, buf_len - HCC_EXTEND_TOTAL_SIZE);
1504             break;
1505         case OAM_LOG_TYPE:
1506             oam_info_log4(0, 0, "[CLIENT]id 0x%08x:0x%08x 0x%08x 0x%08x\n", buf[LOG_ID], buf[LOG_P0], buf[LOG_P1],
1507                 buf[LOG_P2]);
1508             break;
1509         case OAM_PM_TYPE:
1510             wlan_pm_dump_device_pm_info((hi_char *)buf, buf_len - HCC_EXTEND_TOTAL_SIZE);
1511             break;
1512         default:
1513             break;
1514     }
1515     ret = HI_SUCCESS;
1516 end_oam_log:
1517     if (netbuf != HI_NULL) {
1518         oal_netbuf_free(netbuf);
1519     }
1520     return ret;
1521 }
1522 
1523 static hi_s32 hcc_host_rx_register(hcc_handler_stru *hcc_handler, hcc_action_type_enum type, hcc_rx_post_do post_do,
1524     hcc_rx_pre_do pre_do)
1525 {
1526     hcc_rx_action_stru *rx_action = HI_NULL;
1527 
1528     if (hcc_handler == HI_NULL) {
1529         return -OAL_EINVAL;
1530     }
1531 
1532     rx_action = &(hcc_handler->hcc_transer_info.rx_action_info.action[type]);
1533 
1534     if (rx_action->post_do != HI_NULL) {
1535         oam_error_log0(0, 0, "post_do has already register");
1536         return -OAL_EBUSY;
1537     }
1538 
1539     rx_action->post_do = post_do;
1540     rx_action->pre_do = pre_do;
1541     return HI_SUCCESS;
1542 }
1543 
1544 static hi_void hcc_hmac_tx_sched_info_init(hi_void)
1545 {
1546     memset_s(g_hcc_sched_stat, sizeof(g_hcc_sched_stat), DATA_LO_QUEUE, sizeof(g_hcc_sched_stat));
1547 
1548     g_hcc_sched_stat[FRW_EVENT_TYPE_HIGH_PRIO] = DATA_HI_QUEUE;
1549     g_hcc_sched_stat[FRW_EVENT_TYPE_HOST_CRX] = DATA_HI_QUEUE;
1550     g_hcc_sched_stat[FRW_EVENT_TYPE_HOST_DRX] = DATA_LO_QUEUE;
1551     g_hcc_sched_stat[FRW_EVENT_TYPE_HOST_CTX] = DATA_HI_QUEUE;
1552     g_hcc_sched_stat[FRW_EVENT_TYPE_WLAN_CRX] = DATA_HI_QUEUE;
1553     g_hcc_sched_stat[FRW_EVENT_TYPE_WLAN_DRX] = DATA_LO_QUEUE;
1554     g_hcc_sched_stat[FRW_EVENT_TYPE_WLAN_CTX] = DATA_HI_QUEUE;
1555     g_hcc_sched_stat[FRW_EVENT_TYPE_WLAN_TX_COMP] = DATA_HI_QUEUE;
1556     g_hcc_sched_stat[FRW_EVENT_TYPE_TBTT] = DATA_HI_QUEUE;
1557     g_hcc_sched_stat[FRW_EVENT_TYPE_TIMEOUT] = DATA_HI_QUEUE;
1558     g_hcc_sched_stat[FRW_EVENT_TYPE_DMAC_MISC] = DATA_HI_QUEUE;
1559 
1560     memset_s(g_hcc_flowctrl_stat, sizeof(g_hcc_flowctrl_stat), HCC_FC_NONE, sizeof(g_hcc_flowctrl_stat));
1561 }
1562 
1563 hi_s32 hcc_hmac_adapt_init()
1564 {
1565     hi_s32 err_code;
1566     hcc_hmac_tx_sched_info_init();
1567     err_code = hcc_host_rx_register(hcc_host_get_handler(), HCC_ACTION_TYPE_WIFI, hcc_hmac_rx_wifi_post_func, HI_NULL);
1568     return err_code;
1569 }
1570 
1571 void set_device_is_ready(hi_u8 is_ready)
1572 {
1573     g_device_is_ready = is_ready;
1574 }
1575 
1576 hi_u8 get_device_is_ready(hi_void)
1577 {
1578     return g_device_is_ready;
1579 }
1580 
1581 hi_u32 hcc_send_control_msg(hcc_handler_stru *hcc_handler, hi_u8 sub_type, hi_u8 *buf, int len)
1582 {
1583     oal_netbuf_stru *netbuf = HI_NULL;
1584     hcc_transfer_param param = { 0 };
1585     frw_event_mem_stru *event_mem = HI_NULL;
1586     frw_event_stru *event = HI_NULL;
1587     hi_u8 *event_payload = HI_NULL;
1588     hi_u32 ret = HI_FAIL;
1589 
1590     frw_hcc_extend_hdr_stru *ext_hdr = HI_NULL;
1591     frw_event_hdr_stru *event_hdr = HI_NULL;
1592     if (hcc_handler == HI_NULL || get_device_is_ready() != HI_TRUE || len <= 0) {
1593         goto exit;
1594     }
1595     hcc_handler->hcc_transer_info.hcc_timer_status = TIMER_RUNING;
1596     event_mem = frw_event_alloc(len);
1597     if (oal_unlikely(event_mem == HI_NULL)) {
1598         goto exit;
1599     }
1600     event = (frw_event_stru *)event_mem->puc_data;
1601     /* 填写事件头 */
1602     frw_event_hdr_init(&(event->event_hdr), FRW_EVENT_TYPE_HCC, sub_type, len, FRW_EVENT_PIPELINE_STAGE_1, 0);
1603     event_payload = frw_get_event_payload(event_mem);
1604     if (event_payload == HI_NULL) {
1605         oam_error_log0(0, 0, "hcc_send_heartbeat:: event_payload is NULL");
1606         goto exit;
1607     }
1608 
1609     if (memcpy_s(event_payload, len, buf, len) != EOK) {
1610         goto exit;
1611     }
1612 
1613     netbuf = oal_netbuf_alloc(len + HCC_NETBUF_RESERVED_ROOM_SIZE, 0, 4); /* align 4 */
1614     if (netbuf == HI_NULL) {
1615         oam_error_log0(0, 0, "hcc_send_heartbeat:: netbuf_alloc failed!");
1616         goto exit;
1617     }
1618 
1619     oal_netbuf_put(netbuf, len);
1620     if (memcpy_s(oal_netbuf_data(netbuf), len, event_payload, len) != EOK) {
1621         oam_error_log0(0, 0, "hmac_hcc_tx_event_buf_to_netbuf:: memcpy_s failed!");
1622         oal_netbuf_free(netbuf);
1623         goto exit;
1624     }
1625     /* 1. 初始化HCC头 */
1626     hcc_hdr_param_init(&param, HCC_ACTION_TYPE_OAM, WIFI_CONTROL_TYPE, ((hi_u32)sizeof(frw_hcc_extend_hdr_stru)),
1627         HCC_FC_NONE, DATA_HI_QUEUE);
1628     /* 2. add extend area (extend head include HCC, MAC_HDR) */
1629     oal_netbuf_push(netbuf, sizeof(frw_hcc_extend_hdr_stru));
1630     /* 3. 初始化extent hdr */
1631     event_hdr = frw_get_event_hdr(event_mem);
1632     ext_hdr = (frw_hcc_extend_hdr_stru *)oal_netbuf_data(netbuf);
1633     ext_hdr->nest_type = event_hdr->type;
1634     ext_hdr->nest_sub_type = event_hdr->sub_type;
1635     ext_hdr->vap_id = event_hdr->vap_id;
1636     ext_hdr->config_frame = 1;
1637     /* 4. 插入高优先队列 */
1638     ret = hcc_host_tx(hcc_handler, netbuf, &param);
1639     if (ret != HI_SUCCESS) {
1640         oam_error_log1(0, 0, "hcc_tx_netbuf_normal:: hcc_host_tx fail[%d]", ret);
1641     }
1642 exit:
1643     if (event_mem != HI_NULL) {
1644         frw_event_free(event_mem);
1645     }
1646     return ret;
1647 }
1648 
1649 #ifdef _PRE_HDF_LINUX
1650 static void hcc_send_heartbeat(oal_timer_list_stru *timer)
1651 {
1652     hi_unref_param(timer);
1653 #else
1654 static void hcc_send_heartbeat(unsigned long data)
1655 {
1656     hi_unref_param(data);
1657 #endif
1658     hcc_handler_stru *hcc_handler = g_hcc_host_handler;
1659 
1660     if (hi_wifi_get_heart_beat_enable() == HI_TRUE) {
1661         hcc_heartbeat_stru heartbeat = { 0 };
1662         heartbeat.verify_code = VERIFY_CODE;
1663         heartbeat.timeout = g_heart_beat_device_timeout;
1664         hi_u32 ret = hcc_send_control_msg(hcc_handler, OAM_HEATBAET_TYPE, (hi_u8 *)&heartbeat, sizeof(heartbeat));
1665         if (ret != HI_SUCCESS) {
1666             oam_error_log1(0, 0, "hcc_send_heartbeat:: send heartbeat fail[%d]", ret);
1667         }
1668         oam_info_log3(0, 0, "g_priority_cnt=0x%x, g_lopriority_cnt=0x%x, g_des_cnt=0x%x", g_priority_cnt,
1669             g_lopriority_cnt, g_des_cnt);
1670     }
1671 
1672     if (hcc_handler != HI_NULL) {
1673         hi_u32 ret = oal_timer_start(&hcc_handler->hcc_transer_info.hcc_timer, HCC_HEARTBEAT_TIMEOUT);
1674         if (ret != 0 && ret != 1) {
1675             oam_error_log1(0, OAM_SF_FRW, "{hearbeat timer start fail: fail ret = %d}", ret);
1676         }
1677         hcc_handler->hcc_transer_info.hcc_timer_status = TIMER_STOP;
1678     }
1679 }
1680 
1681 hi_s32 hcc_heart_beat_enable_device_callback(hi_void *data)
1682 {
1683     hi_unref_param(data);
1684     OAL_COMPLETE(&g_heart_beat_completion_ack);
1685     return HI_SUCCESS;
1686 }
1687 #ifndef _PRE_FEATURE_HCC_TASK
1688 static FlowControlQueueID HccGetTxQueueId(const void *para)
1689 {
1690     hcc_convert_queue_para *input = (hcc_convert_queue_para *)para;
1691     if (input->queueType == DATA_HI_QUEUE) {
1692         return CTRL_QUEUE_ID;
1693     } else if (input->queueType == DATA_LO_QUEUE && input->isVip) {
1694         return VIP_QUEUE_ID;
1695     } else {
1696         return NORMAL_QUEUE_ID;
1697     }
1698 }
1699 static FlowControlQueueID HccGetRxQueueId(const void *para)
1700 {
1701     hcc_convert_queue_para *input = (hcc_convert_queue_para *)para;
1702     if (input->queueType == DATA_LO_QUEUE) {
1703         return VIP_QUEUE_ID;
1704     } else {
1705         return CTRL_QUEUE_ID;
1706     }
1707 }
1708 static int32_t HccGetFwPriorityId(FlowControlQueueID id)
1709 {
1710     if (id == CTRL_QUEUE_ID) {
1711         return DATA_HI_QUEUE;
1712     } else {
1713         return DATA_LO_QUEUE;
1714     }
1715 }
1716 static int32_t HccGetRxPriorityId(FlowControlQueueID id)
1717 {
1718     if (id == VIP_QUEUE_ID) {
1719         return DATA_LO_QUEUE;
1720     } else {
1721         return DATA_HI_QUEUE;
1722     }
1723 }
1724 struct FlowControlModule *g_fcm = NULL;
1725 static struct FlowControlOp g_flowControlOp = {
1726     .isDeviceStaOrP2PClient = NULL,
1727     .txDataPacket = hcc_host_proc_tx_queue_impl,
1728     .rxDataPacket = hcc_host_proc_rx_queue_impl,
1729     .getTxQueueId = HccGetTxQueueId,
1730     .getRxQueueId = HccGetRxQueueId,
1731     .getTxPriorityId = HccGetFwPriorityId,
1732     .getRxPriorityId = HccGetRxPriorityId,
1733 };
1734 #endif
1735 
1736 hi_u32 hcc_host_init(struct BusDev *bus)
1737 {
1738 #ifdef _PRE_FEATURE_HCC_TASK
1739     hi_u32 err_code;
1740 #endif
1741     hcc_handler_stru *hcc_handler = HI_NULL;
1742     g_list_overflow_flag = HI_FALSE;
1743     g_abandon_key_frame = HI_FALSE;
1744     g_hcc_host_handler = HI_NULL;
1745     hcc_handler = (hcc_handler_stru *)oal_memalloc(sizeof(hcc_handler_stru));
1746     if (hcc_handler == HI_NULL) {
1747         oam_error_log0(0, 0, "hcc_host_init:: malloc hcc_handler fail!");
1748         return HI_FAIL;
1749     }
1750     if (memset_s(hcc_handler, sizeof(hcc_handler_stru), 0, sizeof(hcc_handler_stru)) != EOK) {
1751         oal_free(hcc_handler);
1752         return HI_FAIL;
1753     }
1754 #ifndef _PRE_FEATURE_HCC_TASK
1755     g_fcm = InitFlowControl((void *)hcc_handler);
1756     if (g_fcm == HI_NULL) {
1757         oam_error_log0(0, 0, "hcc_host_init:: InitFlowControl failed!");
1758         goto flow_control_init_err;
1759     }
1760     oam_error_log0(0, 0, "hcc_host_init:: InitFlowControl success!");
1761     g_fcm->op = &g_flowControlOp;
1762 #endif
1763     hcc_handler->hdr_rever_max_len = HCC_HDR_RESERVED_MAX_LEN;
1764     bus->priData.data = (void *)oal_bus_init_module(bus, (hi_void *)hcc_handler);
1765     if (bus->priData.data == HI_NULL) {
1766         oam_error_log0(0, 0, "hcc_host_init:: channel_init failed!");
1767         goto sdio_init_err;
1768     }
1769     bus->priData.release = oal_sdio_exit_module;
1770     hcc_handler->bus = bus;
1771     if (oal_bus_func_init(bus)) {
1772         oam_error_log0(0, 0, "hcc_host_init:: sdio_probe failed!");
1773         goto sdio_probe_err;
1774     }
1775 
1776     oal_timer_init(&hcc_handler->hcc_transer_info.hcc_timer, HCC_HEARTBEAT_TIMEOUT, hcc_send_heartbeat, 0);
1777     set_device_is_ready(HI_FALSE);
1778     oal_timer_add(&hcc_handler->hcc_transer_info.hcc_timer);
1779     hcc_handler->hcc_transer_info.hcc_timer_status = TIMER_ADD;
1780     hcc_message_register(hcc_handler, D2H_MSG_HEART_BEAT_OPEN_ACK, hcc_heart_beat_enable_device_callback, HI_NULL);
1781     hcc_message_register(hcc_handler, D2H_MSG_HEART_BEAT_CLOSE_ACK, hcc_heart_beat_enable_device_callback, HI_NULL);
1782 
1783     /* disable hcc default */
1784     oal_atomic_set(&hcc_handler->state, HCC_OFF);
1785 
1786     hi_wait_queue_init_head(&hcc_handler->hcc_transer_info.hcc_transfer_wq); /* queues init */
1787     hi_wait_queue_init_head(&hcc_handler->hcc_transer_info.hcc_rx_wq);
1788     hcc_transfer_queues_init(hcc_handler);
1789     hcc_trans_flow_ctrl_info_init(hcc_handler);
1790 
1791     OAL_MUTEX_INIT(&hcc_handler->tx_transfer_lock);
1792 
1793     hi_wait_queue_init_head(&hcc_handler->hcc_transer_info.tx_flow_ctrl.wait_queue);
1794 
1795 #ifdef _PRE_FEATURE_HCC_TASK
1796     err_code = hcc_task_init(hcc_handler);
1797     if (err_code != HI_SUCCESS) {
1798         oam_error_log0(0, 0, "hcc_host_init:: hcc_task_init failed");
1799         goto hcc_tast_init_err;
1800     }
1801 #endif
1802 
1803     if (oal_bus_transfer_rx_register(bus, sdio_transfer_rx_handler) != HI_SUCCESS) {
1804         oam_error_log0(0, 0, "hcc_host_init:: sdio rx transfer callback register failed");
1805         goto rx_cb_reg_failed;
1806     }
1807 
1808     hcc_assem_info_init(hcc_handler);
1809     hcc_trans_limit_parm_init(hcc_handler);
1810     hcc_trans_send_mode_init(hcc_handler);
1811 
1812     if (!oal_is_aligned(HISDIO_HOST2DEV_SCATT_SIZE, HISDIO_H2D_SCATT_BUFFLEN_ALIGN)) {
1813         oam_error_log0(0, 0, "hcc_host_init:: HISDIO_HOST2DEV_SCATT_SIZE failed");
1814     }
1815 
1816     if (hcc_tx_assem_descr_init(hcc_handler) != HI_SUCCESS) {
1817         oam_error_log0(0, 0, "hcc_host_init:: hcc_tx_assem_descr_init failed");
1818         goto failed_tx_assem_descr_alloc;
1819     }
1820 
1821     if (hcc_message_register(hcc_handler, D2H_MSG_FLOWCTRL_ON, hcc_flow_on_callback, hcc_handler) != HI_SUCCESS) {
1822         oam_error_log0(0, 0, "hcc_host_init:: hcc_message_register_flowctrl_on failed!");
1823         goto failed_reg_flowon_msg;
1824     }
1825 
1826     if (hcc_message_register(hcc_handler, D2H_MSG_FLOWCTRL_OFF, hcc_flow_off_callback, hcc_handler) != HI_SUCCESS) {
1827         oam_error_log0(0, 0, "hcc_host_init:: hcc_message_register_flowctrl_off failed!");
1828         goto failed_reg_flowoff_msg;
1829     }
1830 
1831     hcc_message_register(hcc_handler, D2H_MSG_CREDIT_UPDATE, hcc_credit_update_callback, hcc_handler);
1832     hcc_message_register(hcc_handler, D2H_MSG_HIGH_PKT_LOSS, hcc_high_pkts_loss_callback, hcc_handler);
1833 
1834     /* 注册维测回调处理函数 */
1835     if (hcc_host_rx_register(hcc_handler, HCC_ACTION_TYPE_OAM, hcc_oam_rx_log_func, HI_NULL) != HI_SUCCESS) {
1836         goto failed_reg_oam_fuction;
1837     }
1838 
1839     oal_wake_lock_init(&hcc_handler->tx_wake_lock, "hcc_tx");
1840 
1841     g_hcc_host_handler = hcc_handler;
1842 
1843     return HI_SUCCESS;
1844 failed_reg_oam_fuction:
1845     hcc_message_unregister(hcc_handler, D2H_MSG_FLOWCTRL_OFF);
1846 failed_reg_flowoff_msg:
1847     hcc_message_unregister(hcc_handler, D2H_MSG_FLOWCTRL_ON);
1848 failed_reg_flowon_msg:
1849     hcc_tx_assem_descr_exit(hcc_handler);
1850 failed_tx_assem_descr_alloc:
1851     oal_bus_transfer_rx_unregister(bus);
1852 rx_cb_reg_failed:
1853 
1854 #ifdef _PRE_FEATURE_HCC_TASK
1855     oal_kthread_stop(hcc_handler->hcc_transer_info.hcc_transfer_thread);
1856     hcc_handler->hcc_transer_info.hcc_transfer_thread = HI_NULL;
1857 hcc_tast_init_err:
1858 #endif
1859     OAL_MUTEX_DESTROY(&hcc_handler->tx_transfer_lock);
1860     oal_timer_delete(&hcc_handler->hcc_transer_info.hcc_timer);
1861     hcc_handler->hcc_transer_info.hcc_timer_status = TIMER_DEL;
1862 sdio_probe_err:
1863     oal_bus_func_remove(bus);
1864 sdio_init_err:
1865 #ifndef _PRE_FEATURE_HCC_TASK
1866     DeInitFlowControl(g_fcm);
1867 flow_control_init_err:
1868 #endif
1869     oal_free(hcc_handler);
1870     return HI_FAIL;
1871 }
1872 
1873 hi_void hcc_clear_all_queues(hcc_handler_stru *hcc_handler, hi_s32 is_need_lock)
1874 {
1875     hi_s32 i;
1876     oal_netbuf_head_stru *pst_head = HI_NULL;
1877 
1878     if (hcc_handler == HI_NULL) {
1879         oam_error_log0(0, 0, "hcc_clear_all_queues:: hcc_handler is NULL");
1880         return;
1881     }
1882 
1883     if (is_need_lock == HI_TRUE) {
1884         hcc_tx_transfer_lock(hcc_handler);
1885     }
1886 
1887     /* Restore assem queues */
1888     hcc_queue_type_enum type = hcc_handler->hcc_transer_info.tx_assem_info.assembled_queue_type;
1889     hcc_restore_assemble_netbuf_list(hcc_handler,
1890         &hcc_handler->hcc_transer_info.hcc_queues[HCC_TX].queues[type].data_queue);
1891 
1892     /* Clear all tx queues */
1893     for (i = 0; i < HCC_QUEUE_COUNT; i++) {
1894         hi_u32 list_len;
1895         pst_head = &hcc_handler->hcc_transer_info.hcc_queues[HCC_TX].queues[i].data_queue;
1896         list_len = oal_netbuf_list_len(pst_head);
1897         hcc_tx_netbuf_list_free(pst_head);
1898         if (list_len != 0) {
1899             oam_info_log2(0, 0, "hcc_clear_all_queues:: Clear queue:%d,total %u hcc rx pkts!\n", i, list_len);
1900         }
1901     }
1902 
1903     if (is_need_lock == HI_TRUE) {
1904         hcc_tx_transfer_unlock(hcc_handler);
1905     }
1906 
1907     /* Clear all rx queues */
1908     if (is_need_lock == HI_TRUE) {
1909         hcc_rx_transfer_lock(hcc_handler);
1910     }
1911 
1912     for (i = 0; i < HCC_QUEUE_COUNT; i++) {
1913         hi_u32 list_len;
1914         pst_head = &hcc_handler->hcc_transer_info.hcc_queues[HCC_RX].queues[i].data_queue;
1915         list_len = oal_netbuf_list_len(pst_head);
1916         hcc_tx_netbuf_list_free(pst_head);
1917         if (list_len != 0) {
1918             oam_info_log2(0, 0, "hcc_clear_all_queues:: Clear queue:%d,total %u hcc rx pkts!\n", i, list_len);
1919         }
1920     }
1921 
1922     if (is_need_lock == HI_TRUE) {
1923         hcc_rx_transfer_unlock(hcc_handler);
1924     }
1925 }
1926 
1927 hi_void hcc_clear_rx_queues(hcc_handler_stru *hcc)
1928 {
1929     hi_s32 i;
1930     oal_netbuf_head_stru *head = HI_NULL;
1931     for (i = 0; i < HCC_QUEUE_COUNT; i++) {
1932         head = &hcc->hcc_transer_info.hcc_queues[HCC_RX].queues[i].data_queue;
1933         if (oal_netbuf_list_len(head) == 0) {
1934             continue;
1935         }
1936         for (; ;) {
1937             oal_netbuf_stru *netbuf = oal_netbuf_delist(head);
1938             if (netbuf == HI_NULL) {
1939                 break;
1940             }
1941             oal_netbuf_free(netbuf);
1942         }
1943     }
1944 }
1945 
1946 hi_void hcc_delete_hearbeat_timer(hcc_handler_stru *hcc)
1947 {
1948     hi_u16 retry_time = 10000;
1949     if (hcc == HI_NULL || hcc->hcc_transer_info.hcc_timer_status == TIMER_DEL) {
1950         return;
1951     }
1952 
1953     while (retry_time > 0 && hcc->hcc_transer_info.hcc_timer_status == TIMER_RUNING) {
1954         udelay(1);
1955         retry_time--;
1956     }
1957     printk("hcc_delete_hearbeat_timer\n");
1958     oal_timer_delete(&hcc->hcc_transer_info.hcc_timer);
1959     hcc->hcc_transer_info.hcc_timer_status = TIMER_DEL;
1960 }
1961 
1962 hi_void hcc_host_exit(hcc_handler_stru *hcc)
1963 {
1964     struct BusDev *bus = NULL;
1965     printk("hcc_host_exit start\n");
1966     if (hcc == HI_NULL) {
1967         return;
1968     }
1969     bus = hcc->bus;
1970     hcc_delete_hearbeat_timer(hcc);
1971     oal_unregister_sdio_intr(bus);
1972     oal_wake_lock_exit(&hcc->tx_wake_lock);
1973     hcc_message_unregister(hcc, D2H_MSG_FLOWCTRL_OFF);
1974     hcc_message_unregister(hcc, D2H_MSG_FLOWCTRL_ON);
1975     hcc_message_unregister(hcc, D2H_MSG_HEART_BEAT_OPEN_ACK);
1976     hcc_message_unregister(hcc, D2H_MSG_HEART_BEAT_CLOSE_ACK);
1977     hcc_tx_assem_descr_exit(hcc);
1978 #ifdef _PRE_FEATURE_HCC_TASK
1979     hcc_exit_task_thread(hcc);
1980     oal_kthread_stop(hcc->hcc_transer_info.hcc_transfer_thread);
1981     oal_kthread_stop(hcc->hcc_transer_info.hcc_rx_thread);
1982 #endif
1983     hcc_clear_tx_queues(hcc);
1984     hcc_clear_rx_queues(hcc);
1985     oal_bus_transfer_rx_unregister(bus);
1986     oal_bus_send_msg(oal_get_sdio_default_handler(), H2D_MSG_PM_WLAN_OFF);
1987     hcc->hcc_transer_info.hcc_transfer_thread = HI_NULL;
1988     OAL_MUTEX_DESTROY(&hcc->tx_transfer_lock);
1989     oal_timer_delete_sync(&hcc->hcc_transer_info.tx_flow_ctrl.flow_timer);
1990     oal_cancel_delayed_work_sync(&hcc->hcc_transer_info.tx_flow_ctrl.worker);
1991     oal_bus_func_remove(bus);
1992     bus->priData.release(bus->priData.data);
1993     oal_free(hcc);
1994     g_hcc_host_handler = HI_NULL;
1995     printk("hcc_host_exit finished\n");
1996 }
1997 
1998 hi_s32 queues_flow_ctrl_check(hcc_handler_stru *hcc_handler, hcc_chan_type dir)
1999 {
2000     hi_s32 i;
2001     hcc_trans_queue_stru *p_queue;
2002     hcc_tx_flow_ctrl_info_stru *p_flow_ctrl;
2003 
2004     p_queue = hcc_handler->hcc_transer_info.hcc_queues[dir].queues;
2005     p_flow_ctrl = &hcc_handler->hcc_transer_info.tx_flow_ctrl;
2006     for (i = 0; i < HCC_QUEUE_COUNT; i++, p_queue++) {
2007         /*
2008          * queue flow_ctrl function check
2009          * flow_ctrl function is enabled
2010          */
2011         if (p_queue->flow_ctrl.enable == HI_TRUE) {
2012             /*
2013              * Normal priority queue
2014              * flow_ctrl is disabled
2015              */
2016             if (p_queue->flow_ctrl.flow_type == HCC_FLOWCTRL_SDIO) {
2017                 if (oal_netbuf_list_len(&p_queue->data_queue) &&
2018                     (p_flow_ctrl->flowctrl_flag == D2H_MSG_FLOWCTRL_ON)) {
2019                     return HI_TRUE;
2020                 }
2021             }
2022         } else { /* flow_ctrl function is disabled */
2023             /* Normal priority queue */
2024             if (p_queue->flow_ctrl.flow_type == HCC_FLOWCTRL_SDIO) {
2025                 /* queue length is not zero */
2026                 if (oal_netbuf_list_len(&p_queue->data_queue)) {
2027                     return HI_TRUE;
2028                 }
2029             } else { /* credit queue */
2030                 /* queue length is not zero */
2031                 if (oal_netbuf_list_len(&p_queue->data_queue)) {
2032                     return HI_TRUE;
2033                 }
2034             }
2035         }
2036     }
2037 
2038     return HI_FALSE;
2039 }
2040 
2041 hi_s32 queues_len_check(hcc_handler_stru *hcc_handler, hcc_chan_type dir)
2042 {
2043     hi_s32 i;
2044     hcc_trans_queue_stru *p_queue;
2045 
2046     p_queue = hcc_handler->hcc_transer_info.hcc_queues[dir].queues;
2047 
2048     for (i = 0; i < HCC_QUEUE_COUNT; i++, p_queue++) {
2049         if (oal_netbuf_list_len(&p_queue->data_queue)) {
2050             return HI_TRUE;
2051         }
2052     }
2053     return HI_FALSE;
2054 }
2055 
2056 /* 是否正在进行心跳控制,防止重入 */
2057 hi_bool g_heart_beat_enabling = HI_FALSE;
2058 hi_s32 hi_wifi_enable_heart_beat(hi_bool enable)
2059 {
2060     if (g_heart_beat_enabling == HI_TRUE) {
2061         return HI_FAIL;
2062     }
2063 
2064     g_heart_beat_enabling = HI_TRUE;
2065     OAL_INIT_COMPLETION(&g_heart_beat_completion_ack);
2066     struct BusDev *bus = oal_get_bus_default_handler();
2067 
2068     hi_s32 ret = 0;
2069     if (enable) {
2070         ret = oal_bus_send_msg(bus, H2D_MSG_HEART_BEAT_OPEN);
2071     } else {
2072         ret = oal_bus_send_msg(bus, H2D_MSG_HEART_BEAT_CLOSE);
2073     }
2074 
2075     if (ret != HI_SUCCESS) {
2076         g_heart_beat_enabling = HI_FALSE;
2077         return HI_FAIL;
2078     }
2079 
2080     hi_u32 wait_ret = oal_wait_for_completion_timeout(&g_heart_beat_completion_ack,
2081         (hi_u32)OAL_MSECS_TO_JIFFIES(WLAN_HEART_BEAT_ENABLE_WAIT_TIMEOUT));
2082     if (wait_ret != 0) { /* 等于0表示等待回复失败 */
2083         g_heart_beat_enable = enable;
2084         g_heart_beat_enabling = HI_FALSE;
2085         return HI_SUCCESS;
2086     }
2087 
2088     g_heart_beat_enabling = HI_FALSE;
2089     return HI_FAIL;
2090 }
2091 
2092 hi_bool hi_wifi_get_heart_beat_enable(hi_void)
2093 {
2094     return g_heart_beat_enable;
2095 }
2096 
2097 #ifdef __cplusplus
2098 #if __cplusplus
2099 }
2100 #endif
2101 #endif
2102