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 *)(¶));
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(¶m, 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, ¶m);
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