• 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_slave.h"
23 #include "oal_net.h"
24 #include "oal_util.h"
25 #include "oal_mem.h"
26 #include "hcc_comm.h"
27 #include "hcc_task.h"
28 
29 #ifdef __cplusplus
30 #if __cplusplus
31 extern "C" {
32 #endif
33 #endif
34 
35 /* ****************************************************************************
36   1 全局变量定义
37 **************************************************************************** */
38 #define HCC_FRW_EVENT_SIZE           WLAN_MEM_EVENT_SIZE1
39 #define SHIF_8_BIT                   8
40 #define SHIF_16_BIT                  16
41 #define SHIF_24_BIT                  24
42 
43 voidfuncptr g_pm_wlan_forceslp_msg_proc = HI_NULL;
44 oal_dev_netbuf_stru *g_reserve_netbuff = HI_NULL; /* 用于内存申请不到时的备用内存 */
45 oal_dev_netbuf_head_stru g_hcc_tx_queue;
46 oal_dev_netbuf_head_stru g_hcc_rx_queue;
47 volatile hi_u8 g_sdio_init_ok = HI_FALSE;
48 struct hcc_handler g_hcc_slave_handler;
49 
50 typedef hi_void (*hcc_descr_ctrl_func)(hi_void *data);
51 hcc_descr_ctrl_func g_descr_control_func[HCC_DESCR_TYPE_BUTT];
52 hcc_netbuf_queue_type g_current_queue_type = HCC_NETBUF_NORMAL_QUEUE;
53 
54 hi_u32 g_hcc_panic_flag = 0;
55 hi_u16 g_used_mem_forstop = 20;
56 hi_u16 g_used_mem_forstart = 40;
57 hi_u32 g_flow_ctrl_reg_info = 0x0;
58 hi_u32 g_max_adma_descr_pkt_len = 0;
59 hi_u8 g_flowctrl_flashed = HI_FALSE;
60 hcc_msg_cb g_process_msg_callback = NULL;
61 
62 volatile hcc_slave_tx_info g_tx_aggr_info = { 0 };
63 volatile hcc_slave_rx_info g_rx_aggr_info = { 0 };
64 hi_u32 g_flowctrl_pending = 0;   /* 1 means pending, 0 means no pending */
65 hi_u8  g_h2d_assem_descr[HISDIO_HOST2DEV_SCATT_SIZE];  /* Used to receive the first assem info descr. */
66 hi_u8  g_thruput_bypass_enable[HCC_THRUPUT_BYPASS_BUTT] = {0};
67 
68 hi_u8  g_sdio_txpkt_index = 0;   /* 发送帧序号 */
69 
70 /* HOST下发数据过程标志,SDIO_RX_BUSY表示正在传输,SDIO_RX_IDLE表示传输结束 */
71 hi_u8  g_chan_write_flag = CHAN_RX_IDLE;
72 hi_u32 g_d2h_hcc_assemble_count = HISDIO_DEV2HOST_SCATT_MAX;
73 
74 
75 /* ****************************************************************************
76   2 函数实现
77 **************************************************************************** */
hcc_get_default_handler(hi_void)78 struct hcc_handler *hcc_get_default_handler(hi_void)
79 {
80     return &g_hcc_slave_handler;
81 }
82 
hcc_get_thruput_bypass_enable(hcc_thruput_bypass bypass_type)83 hi_u8 hcc_get_thruput_bypass_enable(hcc_thruput_bypass bypass_type)
84 {
85     if (bypass_type >= HCC_THRUPUT_BYPASS_BUTT) {
86         return 0;
87     }
88     return g_thruput_bypass_enable[bypass_type];
89 }
90 
hcc_set_thruput_bypass_enable(hcc_thruput_bypass bypass_type,hi_u8 value)91 hi_void hcc_set_thruput_bypass_enable(hcc_thruput_bypass bypass_type, hi_u8 value)
92 {
93     if (bypass_type >= HCC_THRUPUT_BYPASS_BUTT) {
94         return;
95     }
96 
97     g_thruput_bypass_enable[bypass_type] = value;
98 }
99 
100 /* ****************************************************************************
101  功能描述  : 获取hcc TCM头得扩展区有效数据首地址
102 
103  修改历史      :
104   1.日    期   : 2019-05-30
105     作    者   : HiSilicon
106     修改内容   : 新生成函数
107 **************************************************************************** */
hcc_get_extend_payload_addr(const oal_dev_netbuf_stru * dev_netbuf)108 hi_u8 *hcc_get_extend_payload_addr(const oal_dev_netbuf_stru *dev_netbuf)
109 {
110     hi_u8 *hdr = HI_NULL;
111     hcc_header_stru *hcc_hdr = HI_NULL;
112 
113     /* Device侧Netbuf 头/体分离,扩展区默认从高向低地址扩展! */
114     hdr = oal_dev_netbuf_hcchdr(dev_netbuf);
115     if (hdr == HI_NULL) {
116         return HI_NULL;
117     }
118     hcc_hdr = (hcc_header_stru *)hdr;
119     hdr += HCC_HDR_LEN;
120     hdr += hcc_hdr->pad_hdr;
121     if (hcc_hdr->pad_hdr > HCC_HDR_RESERVED_MAX_LEN) {
122         return HI_NULL;
123     }
124     return hdr;
125 }
126 
127 /* ****************************************************************************
128  功能描述  : 获取hcc TCM头得扩展区首地址
129 
130  修改历史      :
131   1.日    期   : 2019-05-30
132     作    者   : HiSilicon
133     修改内容   : 新生成函数
134 **************************************************************************** */
hcc_get_extend_addr(const oal_dev_netbuf_stru * dev_netbuf,hi_u32 extend_len)135 hi_u8 *hcc_get_extend_addr(const oal_dev_netbuf_stru *dev_netbuf, hi_u32 extend_len)
136 {
137     hi_u8 *hdr = HI_NULL;
138     /* Device侧Netbuf 头/体分离,扩展区默认从高向低地址扩展! */
139     if (extend_len > (hi_u32)HCC_HDR_RESERVED_MAX_LEN) {
140         return HI_NULL;
141     }
142 
143     hdr = oal_dev_netbuf_hcchdr(dev_netbuf);
144     hdr += HCC_HDR_LEN;
145     hdr += HCC_HDR_RESERVED_MAX_LEN - extend_len;
146     return hdr;
147 }
148 
hcc_delay_bug_on_detect(hi_void)149 hi_void hcc_delay_bug_on_detect(hi_void)
150 {
151     if (g_hcc_panic_flag != 0) {
152         g_hcc_panic_flag = 0;
153         hi_diag_log_msg_e0(0, "hcc panic detected.\n");
154     }
155 }
156 
157 #undef CONFIG_HCC_NETBUF_LIST_REPEAT_CHECK
158 #ifdef CONFIG_HCC_NETBUF_LIST_REPEAT_CHECK
hcc_netbuf_list_repeat_check(oal_dev_netbuf_stru * dev_netbuf,oal_dev_netbuf_head_stru * head)159 hi_u32 hcc_netbuf_list_repeat_check(oal_dev_netbuf_stru *dev_netbuf, oal_dev_netbuf_head_stru *head)
160 {
161     hi_u32 status;
162     oal_dev_netbuf_stru *dev_netbuf_temp = HI_NULL;
163 
164     status = hi_int_lock();
165     dev_netbuf_temp = head->next;
166     while ((hi_u32)dev_netbuf_temp != (hi_u32)head) {
167         if (dev_netbuf_temp == dev_netbuf) {
168             hi_int_restore(status);
169             return HI_FALSE;
170         }
171         dev_netbuf_temp = dev_netbuf_temp->next;
172     }
173 
174     hi_int_restore(status);
175     return HI_TRUE;
176 }
177 #endif
178 
hcc_netbuf_add_to_list_tail(oal_dev_netbuf_stru * dev_netbuf,oal_dev_netbuf_head_stru * head)179 hi_void hcc_netbuf_add_to_list_tail(oal_dev_netbuf_stru *dev_netbuf, oal_dev_netbuf_head_stru *head)
180 {
181     hi_u32 status;
182 
183 #ifdef CONFIG_HCC_NETBUF_LIST_REPEAT_CHECK
184     if (hcc_netbuf_list_repeat_check(dev_netbuf, head) != HI_TRUE) {
185         return;
186     }
187 #endif
188 
189     status = hi_int_lock();
190     head->prev->next = dev_netbuf;
191     dev_netbuf->next = (oal_dev_netbuf_stru *)head;
192     head->prev = dev_netbuf;
193     head->num++;
194     hi_int_restore(status);
195 }
196 
hcc_netbuf_delist(oal_dev_netbuf_head_stru * head)197 oal_dev_netbuf_stru *hcc_netbuf_delist(oal_dev_netbuf_head_stru *head)
198 {
199     hi_u32 status;
200     oal_dev_netbuf_stru *dev_netbuf = HI_NULL;
201 
202     status = hi_int_lock();
203     if (head->num == 0) {
204         hi_int_restore(status);
205         return HI_NULL;
206     }
207 
208     if ((uintptr_t)head->prev == (uintptr_t)head) {
209         hi_int_restore(status);
210         return HI_NULL;
211     }
212 
213     dev_netbuf = head->next;
214     if (head->num == 1) {
215         /* one node */
216         head->prev = (oal_dev_netbuf_stru *)head;
217     }
218     head->next = (oal_dev_netbuf_stru *)head->next->next;
219 
220     head->num--;
221     hi_int_restore(status);
222     return dev_netbuf;
223 }
224 
hcc_slave_get_netbuf_align_len(const oal_dev_netbuf_stru * dev_netbuf,hi_u32 align_size)225 hi_u32 hcc_slave_get_netbuf_align_len(const oal_dev_netbuf_stru *dev_netbuf, hi_u32 align_size)
226 {
227     hi_u32 send_len;
228     hi_u32 total_len;
229 
230     hcc_header_stru *hcc_hdr = (hcc_header_stru *)oal_dev_netbuf_hcchdr(dev_netbuf);
231     if (hcc_hdr == HI_NULL) {
232         hi_diag_log_msg_e0(0, "{hcc_slave_get_netbuf_align_len::hcc_hdr null.}");
233         return 0;
234     }
235     total_len = hcc_hdr->pay_len + HCC_HDR_TOTAL_LEN;
236 
237     send_len = hi_byte_align(total_len, align_size);
238     return send_len;
239 }
240 
hcc_slave_build_header(const oal_dev_netbuf_stru * dev_netbuf,hi_u16 pay_load_len,const hcc_transfer_param * param)241 hi_void hcc_slave_build_header(const oal_dev_netbuf_stru *dev_netbuf, hi_u16 pay_load_len,
242     const hcc_transfer_param *param)
243 {
244     hcc_header_stru *hcc_hdr = HI_NULL;
245 
246     if ((dev_netbuf == HI_NULL) || (param == HI_NULL)) {
247         hi_diag_log_msg_e0(0, "{hcc_slave_build_header:: net_buf/param null.}");
248         return;
249     }
250 
251     /* build hcc header */
252     hcc_hdr = (hcc_header_stru *)oal_dev_netbuf_hcchdr(dev_netbuf);
253     if (hcc_hdr == HI_NULL) {
254         hi_diag_log_msg_e0(0, "{hcc_slave_build_header:: hcc_hdr null.}");
255         return;
256     }
257     hcc_hdr->main_type   = param->main_type;
258     hcc_hdr->sub_type    = param->sub_type;
259     hcc_hdr->pay_len     = pay_load_len;
260     hcc_hdr->seq         = g_sdio_txpkt_index++;
261     hcc_hdr->pad_hdr     = HCC_HDR_RESERVED_MAX_LEN - param->extend_len;
262     hcc_hdr->pad_payload = 0;  /* Device alloc netbuf's payload all 4B aligned! */
263 }
264 
hcc_rx_process(oal_dev_netbuf_stru * dev_netbuf)265 hi_void hcc_rx_process(oal_dev_netbuf_stru *dev_netbuf)
266 {
267     hcc_netbuf_add_to_list_tail(dev_netbuf, &g_hcc_rx_queue);
268     /* sched the hcc rx */
269     hcc_task_sched();
270 }
271 
272 /* ****************************************************************************
273  功能描述  : 发送sdio 消息  低16 bits有效
274 
275  修改历史      :
276   1.日    期   : 2019-05-30
277     作    者   : HiSilicon
278     修改内容   : 新生成函数
279 **************************************************************************** */
hcc_send_msg2host(hi_u32 msg)280 hi_s32 hcc_send_msg2host(hi_u32 msg)
281 {
282     return hi_sdio_send_sync_msg(msg);
283 }
284 
hcc_device2host_netbuf_multi_post_check(oal_dev_netbuf_stru * dev_netbuf,hi_s32 num)285 hi_s32 hcc_device2host_netbuf_multi_post_check(oal_dev_netbuf_stru *dev_netbuf, hi_s32 num)
286 {
287 #ifdef CONFIG_HCC_TX_MULTI_BUF_CHECK
288     hi_s32 i;
289     hi_u32 status;
290 
291     status = hi_int_lock();
292     for (i = 0; i < num; i++) {
293         if (g_tx_aggr_info.hcc_tx_aggr[i].netbuf == dev_netbuf) {
294             hi_int_restore(status);
295             hi_diag_log_msg_i3(0, "[ERROR][d2h]netbuf[%d], num: %d[%p]multi post!\r\n", i, num,
296                 g_tx_aggr_info.hcc_tx_aggr[i].netbuf);
297             return HI_FAIL;
298         }
299     }
300     hi_int_restore(status);
301 #else
302     hi_unref_param(dev_netbuf);
303     hi_unref_param(num);
304 #endif
305     return HI_SUCCESS;
306 }
307 
308 /* ****************************************************************************
309  功能描述  : 发hcc消息到host侧,更新高优先级buffer credit值
310 
311  修改历史      :
312   1.日    期   : 2019-05-30
313     作    者   : HiSilicon
314     修改内容   : 新生成函数
315 **************************************************************************** */
hcc_update_high_priority_buffer_credit(hi_u8 free_large_buffer,hi_u8 free_mgmt_buffer,hi_u8 tx_dscr_free_cnt)316 hi_void hcc_update_high_priority_buffer_credit(hi_u8 free_large_buffer, hi_u8 free_mgmt_buffer, hi_u8 tx_dscr_free_cnt)
317 {
318     hi_sdio_extendfunc *hcc_extfunc = hi_sdio_get_extend_info();
319 
320     memset_s(hcc_extfunc, sizeof(hi_sdio_extendfunc), 0, sizeof(hi_sdio_extendfunc));
321     /* 8-15bit 大包free个数;16-23bit管理帧free个数 */
322     g_flow_ctrl_reg_info = ((g_flow_ctrl_reg_info & 0x000000FF) |
323         ((free_large_buffer & 0xFF) << SHIF_8_BIT) |
324         ((free_mgmt_buffer & 0xFF) << SHIF_16_BIT) |
325         ((tx_dscr_free_cnt & 0xFF) << SHIF_24_BIT));
326     if (hi_sdio_is_pending_msg(D2H_MSG_CREDIT_UPDATE) || hi_sdio_is_sending_msg(D2H_MSG_CREDIT_UPDATE)) {
327         g_flowctrl_flashed = HI_TRUE;
328         return;
329     }
330     /* 更新寄存器 */
331     hcc_extfunc->credit_info = g_flow_ctrl_reg_info;
332     hcc_extfunc->credit_isvalid = 1;
333     (hi_void)hi_sdio_write_extinfo(hcc_extfunc);
334     g_flowctrl_flashed = HI_FALSE;
335 }
336 
337 /* ****************************************************************************
338  功能描述  : 从netbuf创建DMA表
339 
340  修改历史      :
341   1.日    期   : 2019-05-30
342     作    者   : HiSilicon
343     修改内容   : 新生成函数
344 **************************************************************************** */
hcc_build_adma_descr_from_netbuf(hi_u8 * adma_table,hi_u32 * index,hi_u32 pkt_len,const oal_dev_netbuf_stru * dev_netbuf)345 hi_void hcc_build_adma_descr_from_netbuf(hi_u8 *adma_table, hi_u32 *index, hi_u32 pkt_len,
346     const oal_dev_netbuf_stru *dev_netbuf)
347 {
348     hi_u32 *hcc_hdr = HI_NULL;
349     hi_u32 *payload_hdr = HI_NULL;
350 
351     if (dev_netbuf == HI_NULL) {
352         return;
353     }
354 
355     hcc_hdr = (hi_u32 *)oal_dev_netbuf_hcchdr(dev_netbuf);
356     payload_hdr = (hi_u32 *)oal_dev_netbuf_get_payload(dev_netbuf);
357 
358     /* 填写MAC头传输DMA表 */
359     if (pkt_len >= HCC_HDR_TOTAL_LEN) {
360         (hi_void)hi_sdio_set_admatable(adma_table, (*index)++, (hi_u32 *)hcc_hdr, HCC_HDR_TOTAL_LEN);
361     }
362 
363     /* 填写Payload头传输DMA表 */
364     if (pkt_len > HCC_HDR_TOTAL_LEN) {
365         (hi_void)hi_sdio_set_admatable(adma_table, (*index)++, (hi_u32 *)payload_hdr, pkt_len - HCC_HDR_TOTAL_LEN);
366     }
367 
368     if (g_max_adma_descr_pkt_len < pkt_len) {
369         g_max_adma_descr_pkt_len = pkt_len;
370     }
371 }
372 
hcc_rx_assem_info_reset(hi_void * data)373 hi_void hcc_rx_assem_info_reset(hi_void *data)
374 {
375     hi_unref_param(data);
376     for (hi_u16 i = 0; i < g_rx_aggr_info.aggr_rx_num; i++) {
377         g_rx_aggr_info.hcc_rx_aggr[i].netbuf = HI_NULL;
378         g_rx_aggr_info.hcc_rx_aggr[i].rx_pkt_bytes = 0;
379     }
380 
381     /* Reset assem info package */
382     g_rx_aggr_info.aggr_rx_num = 0;
383     g_rx_aggr_info.rx_aggr_total_len = 0;
384 }
385 
hcc_rx_netbuf_queue_pri_switch(const hi_void * data)386 hi_void hcc_rx_netbuf_queue_pri_switch(const hi_void *data)
387 {
388     hcc_netbuf_queue_type queue_type = *(hcc_netbuf_queue_type *)data;
389 
390     if (queue_type >= HCC_NETBUF_QUEUE_BUTT) {
391         return;
392     }
393 
394     g_current_queue_type = queue_type;
395 }
396 
hcc_process_single_package(hi_u32 len)397 hi_void hcc_process_single_package(hi_u32 len)
398 {
399     hi_u32 pkt_len;
400     hi_u32 remain_len;
401     hi_u32 size = len;
402     hi_u32 ret;
403     oal_dev_netbuf_stru *dev_netbuf = HI_NULL;
404 
405     g_rx_aggr_info.aggr_rx_num = 1;
406     /* strip the assem info */
407     size -= HISDIO_HOST2DEV_SCATT_SIZE;
408     if (size > HCC_LONG_PACKAGE_SIZE + HCC_HDR_TOTAL_LEN) {
409         remain_len = size - HCC_LONG_PACKAGE_SIZE - HCC_HDR_TOTAL_LEN;
410         pkt_len = HCC_LONG_PACKAGE_SIZE;
411     } else {
412         remain_len = 0;
413         pkt_len = size - HCC_HDR_TOTAL_LEN;
414     }
415 
416     /* single package, we think it's one pkt assembled, and if the pkt is too long,
417        the pkt must algin to 512 */
418     g_rx_aggr_info.hcc_rx_aggr[0].rx_pkt_bytes = pkt_len + HCC_HDR_TOTAL_LEN;
419 
420     /* 高优先级队列调用高优先级buffer申请接口 */
421     if (g_current_queue_type == HCC_NETBUF_HIGH_QUEUE) {
422         dev_netbuf = oal_mem_dev_netbuf_alloc(OAL_NORMAL_NETBUF, (hi_u16)pkt_len, OAL_NETBUF_PRIORITY_HIGH);
423     } else {
424         dev_netbuf = oal_mem_dev_netbuf_alloc(OAL_NORMAL_NETBUF, (hi_u16)pkt_len, OAL_NETBUF_PRIORITY_MID);
425     }
426 
427     if (dev_netbuf == HI_NULL) {
428         ret = hi_sdio_procmem_alloc_fail(g_current_queue_type, (hi_void**) &(g_rx_aggr_info.hcc_rx_aggr[0].netbuf),
429                                          (hi_void*)g_reserve_netbuff);
430         if (ret != HI_SUCCESS) {
431             return;
432         }
433     } else {
434         g_rx_aggr_info.hcc_rx_aggr[0].netbuf = dev_netbuf;
435     }
436 
437     /* If single pkt too long? */
438     if (remain_len) {
439         g_rx_aggr_info.aggr_rx_num++;
440         g_rx_aggr_info.hcc_rx_aggr[1].netbuf = g_reserve_netbuff;
441         g_rx_aggr_info.hcc_rx_aggr[1].rx_pkt_bytes = remain_len;
442 
443         /* 单包过长,Host有下发限制,不应该走到这里。 */
444         if (remain_len > HCC_LONG_PACKAGE_SIZE) {
445             g_hcc_panic_flag = 1;
446             hi_diag_log_msg_e1(0, "ERROR: remain_len is %d\r\n", remain_len);
447         }
448     }
449     /* Total Len Useless!TBD */
450     g_rx_aggr_info.rx_aggr_total_len = size - HISDIO_HOST2DEV_SCATT_SIZE;
451 }
452 
hcc_process_multi_package(hi_void)453 hi_void hcc_process_multi_package(hi_void)
454 {
455     hi_u32 i;
456     hi_u16 rx_pkt_len = 0;
457     oal_dev_netbuf_stru *dev_netbuf = HI_NULL;
458 
459     /* assem transfer, host to device */
460     for (i = 0; i < g_rx_aggr_info.aggr_rx_num; i++) {
461         if (g_rx_aggr_info.hcc_rx_aggr[i].rx_pkt_bytes <= (HCC_LONG_PACKAGE_SIZE + HCC_HDR_TOTAL_LEN)) {
462             rx_pkt_len = (hi_u16)(g_rx_aggr_info.hcc_rx_aggr[i].rx_pkt_bytes - HCC_HDR_TOTAL_LEN);
463             dev_netbuf = oal_mem_dev_netbuf_alloc(OAL_NORMAL_NETBUF, rx_pkt_len, OAL_NETBUF_PRIORITY_HIGH);
464         } else {
465             dev_netbuf = HI_NULL;
466         }
467 
468         if (dev_netbuf == HI_NULL) {
469             hi_sdio_procmem_alloc_fail(g_current_queue_type,
470                                        (hi_void**) &(g_rx_aggr_info.hcc_rx_aggr[i].netbuf),
471                                        (hi_void*) g_reserve_netbuff);
472 
473             /* 聚合包每包大小超过了DEVICE最大内存池的长度,预留内存接收将会踩狗牌。 */
474             if (g_rx_aggr_info.hcc_rx_aggr[i].rx_pkt_bytes > HCC_LONG_PACKAGE_SIZE + HCC_HDR_TOTAL_LEN) {
475                 hi_diag_log_msg_e0(0, "rx_pkt is too large.\r\n");
476             }
477 #ifdef CONFIG_HCC_DEBUG
478             hi_diag_log_msg_i1(0, "netbuf fail,len:%d\n",
479                 g_rx_aggr_info.hcc_rx_aggr[i].rx_pkt_bytes - HCC_HDR_TOTAL_LEN);
480 #endif
481         } else {
482             g_rx_aggr_info.hcc_rx_aggr[i].netbuf = dev_netbuf;
483         }
484     }
485 }
486 
hcc_write_start_callback(hi_u32 len,hi_u8 * adma_table)487 hi_s32 hcc_write_start_callback(hi_u32 len, hi_u8 *adma_table)
488 {
489     hi_u32 index = 0;
490     hi_u32 pad_len = 0;
491     hi_u32 non_pad_total_len = 0;
492 
493     if (len < HISDIO_HOST2DEV_SCATT_SIZE) {
494         return 0;
495     }
496 
497     /* The flag protect sdio host to device transfer! */
498     g_chan_write_flag = CHAN_RX_BUSY;
499     g_rx_aggr_info.trans_len = len;
500 
501     /* The frist descr fixed to assem descr! */
502     (hi_void)hi_sdio_set_admatable(adma_table, index++, (hi_u32 *)g_h2d_assem_descr, HISDIO_HOST2DEV_SCATT_SIZE);
503 
504     non_pad_total_len += HISDIO_HOST2DEV_SCATT_SIZE;
505 
506     if (g_rx_aggr_info.trans_len == HISDIO_HOST2DEV_SCATT_SIZE) {
507         /* when transfer just assem scatt size buff, it's control message from host! */
508         (hi_void)hi_sdio_complete_send(adma_table, index);
509         return (hi_s32)index;
510     }
511 
512     if (g_rx_aggr_info.aggr_rx_num == 0) {
513         hcc_process_single_package(len);
514     } else {
515         hcc_process_multi_package();
516     }
517 
518     if (g_rx_aggr_info.aggr_rx_num > HISDIO_HOST2DEV_SCATT_MAX) {
519         g_hcc_panic_flag = 1;
520         hi_diag_log_msg_e1(0, "Error: rx_num(%d) more than SCATT_MAX\r\n", g_rx_aggr_info.aggr_rx_num);
521         return 0;
522     }
523 
524     for (hi_u32 i = 0; i < g_rx_aggr_info.aggr_rx_num; i++) {
525         non_pad_total_len += g_rx_aggr_info.hcc_rx_aggr[i].rx_pkt_bytes;
526         hcc_build_adma_descr_from_netbuf(adma_table,
527                                          &index,
528                                          g_rx_aggr_info.hcc_rx_aggr[i].rx_pkt_bytes,
529                                          g_rx_aggr_info.hcc_rx_aggr[i].netbuf);
530     }
531 
532     if (non_pad_total_len < len) {
533         pad_len = len - non_pad_total_len;
534     }
535 
536     if (pad_len != 0) {
537         (hi_void)hi_sdio_set_pad_admatab(pad_len, adma_table, index++);
538     }
539 
540     /* IP问题需多加一行无用数据,表示表格终止 */
541     (hi_void)hi_sdio_complete_send(adma_table, index);
542 
543     return (hi_s32)index;
544 }
545 
hcc_write_over_aggr_package(hi_void)546 hi_void hcc_write_over_aggr_package(hi_void)
547 {
548     hi_u32 i;
549     hi_u16 pkt_len;
550     hi_u16 total_len = 0;
551     hi_u8 *h2d_assem_descr = HI_NULL;
552 
553     for (i = 0; i < g_rx_aggr_info.aggr_rx_num; i++) {
554         if (((uintptr_t)g_rx_aggr_info.hcc_rx_aggr[i].netbuf != (uintptr_t)g_reserve_netbuff)) {
555             if (hcc_get_thruput_bypass_enable(HCC_TX_SDIO_SLAVE_BYPASS)) {
556                 oal_mem_dev_netbuf_free(g_rx_aggr_info.hcc_rx_aggr[i].netbuf);
557             } else {
558                 /* not reserved mem */
559                 hcc_rx_process(g_rx_aggr_info.hcc_rx_aggr[i].netbuf);
560             }
561         }
562 
563         g_rx_aggr_info.hcc_rx_aggr[i].netbuf = HI_NULL;
564         g_rx_aggr_info.hcc_rx_aggr[i].rx_pkt_bytes = 0;
565     }
566 
567     /* prepare the next assem info */
568     g_rx_aggr_info.aggr_rx_num = 0;
569     g_rx_aggr_info.rx_aggr_total_len = 0;
570 
571     /* assem info 64B */
572     h2d_assem_descr = (hi_u8 *)g_h2d_assem_descr;
573     for (i = 0; i < HISDIO_HOST2DEV_SCATT_MAX; i++) {
574         if (h2d_assem_descr[i] == 0) {
575             break;
576         }
577 
578         pkt_len = (h2d_assem_descr[i] << HISDIO_H2D_SCATT_BUFFLEN_ALIGN_BITS);
579 
580         g_rx_aggr_info.hcc_rx_aggr[i].netbuf = HI_NULL;
581         g_rx_aggr_info.hcc_rx_aggr[i].rx_pkt_bytes = pkt_len;
582         total_len += pkt_len;
583     }
584 
585     g_rx_aggr_info.aggr_rx_num = i;
586     g_rx_aggr_info.rx_aggr_total_len = total_len;
587 }
588 
589 
hcc_write_over_callback(hi_void)590 hi_s32 hcc_write_over_callback(hi_void)
591 {
592     struct hcc_descr_header *dscr_hdr = HI_NULL;
593     hi_void *h2d_ctrl_descr = (hi_void *)g_h2d_assem_descr;
594 
595     if (g_rx_aggr_info.trans_len == HISDIO_HOST2DEV_SCATT_SIZE) {
596         /* dscr control data */
597         dscr_hdr = (struct hcc_descr_header *)h2d_ctrl_descr;
598         if (dscr_hdr->descr_type < HCC_DESCR_TYPE_BUTT && g_descr_control_func[dscr_hdr->descr_type] != HI_NULL) {
599             g_descr_control_func[dscr_hdr->descr_type]((hi_u8 *)h2d_ctrl_descr + sizeof(struct hcc_descr_header));
600         }
601     } else {
602         hcc_write_over_aggr_package();
603     }
604 
605 #ifdef CONFIG_HCC_DEBUG
606     hi_diag_log_msg_i2(0, "h2d: next assem num: %d, totol: %d\r\n", g_rx_aggr_info.aggr_rx_num,
607         g_rx_aggr_info.rx_aggr_total_len);
608 #endif
609     g_chan_write_flag = CHAN_RX_IDLE;
610 
611     if (g_pm_wlan_forceslp_msg_proc != HI_NULL) {
612         g_pm_wlan_forceslp_msg_proc();
613     }
614     return HI_SUCCESS;
615 }
616 
hcc_read_start_callback(hi_u32 len,hi_u8 * adma_table)617 hi_s32 hcc_read_start_callback(hi_u32 len, hi_u8 *adma_table)
618 {
619     hi_u32 i;
620     hi_u32 index = 0;
621     hi_u32 total_pad;
622     hi_u32 pad_len;
623     hi_unref_param(len);
624 
625     if (g_tx_aggr_info.aggr_tx_num == 0) {
626         return 0;
627     }
628 
629     if (g_tx_aggr_info.tx_aggr_total_len < HISDIO_BLOCK_SIZE) {
630         pad_len = hi_byte_align(g_tx_aggr_info.tx_aggr_total_len, 4); /* 4 bytes align */
631     } else {
632         pad_len = hi_byte_align(g_tx_aggr_info.tx_aggr_total_len, HISDIO_BLOCK_SIZE);
633     }
634 
635     if (pad_len >= g_tx_aggr_info.tx_aggr_total_len) {
636         total_pad = pad_len - g_tx_aggr_info.tx_aggr_total_len;
637     } else {
638         total_pad = 0;
639     }
640 
641     if (g_tx_aggr_info.aggr_tx_num > HISDIO_DEV2HOST_SCATT_MAX) {
642 #ifdef CONFIG_HCC_DEBUG
643         hi_diag_log_msg_i1(0, "unvaild d2h aggr num: %d\r\n", g_tx_aggr_info.aggr_tx_num);
644 #endif
645     }
646 
647     for (i = 0; i < g_tx_aggr_info.aggr_tx_num; i++) {
648         if (g_tx_aggr_info.hcc_tx_aggr[i].netbuf == HI_NULL) {
649             return 0;
650         }
651 
652         hcc_build_adma_descr_from_netbuf(adma_table, &index,
653                                          g_tx_aggr_info.hcc_tx_aggr[i].tx_pkt_bytes,
654                                          g_tx_aggr_info.hcc_tx_aggr[i].netbuf);
655     }
656 
657     /* The padding descr */
658     if (total_pad != 0) {
659 #ifdef CONFIG_HCC_DEBUG
660         hi_diag_log_msg_i1(0, "add pad %u descr\r\n", total_pad);
661 #endif
662         (hi_void)hi_sdio_set_pad_admatab(total_pad, adma_table, index++);
663     }
664 
665     /* IP问题需多加一行无用数据,表示表格终止 */
666     (hi_void)hi_sdio_complete_send(adma_table, index);
667     return (hi_s32)index;
668 }
669 
hcc_read_over_callback(hi_void)670 hi_s32 hcc_read_over_callback(hi_void)
671 {
672     hi_sdio_status_info status_info;
673 
674     for (hi_u32 i = 0; i < g_tx_aggr_info.aggr_tx_num; i++) {
675         oal_mem_dev_netbuf_free(g_tx_aggr_info.hcc_tx_aggr[i].netbuf);
676         g_tx_aggr_info.hcc_tx_aggr[i].netbuf = HI_NULL;
677     }
678 
679     g_tx_aggr_info.tx_aggr_total_len = 0;
680     g_tx_aggr_info.aggr_tx_num = 0;
681 
682     (hi_void)hi_sdio_get_status(&status_info);
683     status_info.tx_status = CHAN_TX_IDLE;
684     (hi_void)hi_sdio_set_status(&status_info);
685 
686     if (g_pm_wlan_forceslp_msg_proc != HI_NULL) {
687         g_pm_wlan_forceslp_msg_proc();
688     }
689     return HI_SUCCESS;
690 }
691 
692 
hcc_slave_tx(oal_dev_netbuf_stru * dev_netbuf,hi_u16 pay_load_len,const hcc_transfer_param * param)693 hi_void hcc_slave_tx(oal_dev_netbuf_stru *dev_netbuf, hi_u16 pay_load_len, const hcc_transfer_param *param)
694 {
695     /* build the head */
696     hcc_slave_build_header(dev_netbuf, pay_load_len, param);
697 
698     /* put the pst_buf enqueue */
699     hcc_netbuf_add_to_list_tail(dev_netbuf, &g_hcc_tx_queue);
700 
701     /* sched the hcc tx */
702     hcc_task_sched();
703 }
704 
hcc_oam_fill_payload_data(const hi_u8 * data,hi_u16 pay_load_len,oal_dev_netbuf_stru ** dev_netbuf)705 hi_u32 hcc_oam_fill_payload_data(const hi_u8 *data, hi_u16 pay_load_len, oal_dev_netbuf_stru **dev_netbuf)
706 {
707     hi_u8 *cb = HI_NULL;
708     oal_dev_netbuf_stru *temp_netbuf;
709     temp_netbuf = oal_mem_dev_netbuf_alloc(OAL_NORMAL_NETBUF, (hi_u16)pay_load_len, OAL_NETBUF_PRIORITY_HIGH);
710     if (temp_netbuf == HI_NULL) {
711         return HI_ERR_FAILURE;
712     }
713     cb = oal_dev_netbuf_cb(temp_netbuf->us_index);
714     if (cb == HI_NULL) {
715         oal_mem_dev_netbuf_free(temp_netbuf);
716         return HI_ERR_FAILURE;
717     }
718     memset_s(cb, OAL_TX_CB_LEN, 0, OAL_TX_CB_LEN);
719     if (memcpy_s((hi_u8 *)(oal_dev_netbuf_get_payload(temp_netbuf)), pay_load_len,
720         (hi_u8 *)data, pay_load_len) != HI_SUCCESS) {
721         oal_mem_dev_netbuf_free(temp_netbuf);
722         return HI_ERR_FAILURE;
723     }
724     *dev_netbuf = temp_netbuf;
725     return HI_ERR_SUCCESS;
726 }
727 
hcc_oam_log_tx(const hi_u8 * data,hi_u16 data_len,hi_u16 cmd_id)728 hi_u32 hcc_oam_log_tx(const hi_u8 *data, hi_u16 data_len, hi_u16 cmd_id)
729 {
730     oal_dev_netbuf_stru *dev_netbuf = HI_NULL;
731     hcc_transfer_param param = { 0 };
732     hi_u16 pay_load_len;
733     frw_event_mem_stru *event_mem = HI_NULL;
734     frw_event_stru *event = HI_NULL;
735     frw_hcc_extend_hdr_stru *ext_hdr = HI_NULL;
736     frw_event_hdr_stru *event_hdr = HI_NULL;
737     if (g_sdio_init_ok == HI_FALSE) {
738         return HI_ERR_SUCCESS;
739     }
740     pay_load_len = data_len;
741     event_mem = frw_event_alloc(data_len);
742     if (oal_unlikely(event_mem == HI_NULL)) {
743         return HI_ERR_CODE_PTR_NULL;
744     }
745     event = (frw_event_stru *)event_mem->puc_data;
746     /* 需要把数据拷贝到event_mem中 */
747     frw_event_hdr_init(&(event->event_hdr), FRW_EVENT_TYPE_HCC, cmd_id, pay_load_len, FRW_EVENT_PIPELINE_STAGE_1, 0);
748     if (hcc_oam_fill_payload_data(data, pay_load_len, &dev_netbuf) != HI_ERR_SUCCESS) {
749         goto failed_netbuf;
750     }
751     ext_hdr = (frw_hcc_extend_hdr_stru *)hcc_get_extend_addr(dev_netbuf, HCC_EXTEND_TOTAL_SIZE);
752     event_hdr = frw_get_event_hdr(event_mem);
753     if (ext_hdr == HI_NULL || event_hdr == HI_NULL) {
754         goto failed_netbuf;
755     }
756     ext_hdr->nest_type = event_hdr->type;
757     ext_hdr->nest_sub_type = event_hdr->sub_type;
758     ext_hdr->vap_id = event_hdr->vap_id;
759     hcc_hdr_param_init(&param, HCC_ACTION_TYPE_OAM, WIFI_CONTROL_TYPE, HCC_EXTEND_TOTAL_SIZE, DATA_HI_QUEUE,
760         HCC_FC_NONE);
761     hcc_slave_tx(dev_netbuf, pay_load_len, &param);
762     frw_event_free(event_mem);
763     return HI_ERR_SUCCESS;
764 failed_netbuf:
765     if (dev_netbuf != HI_NULL) {
766         oal_mem_dev_netbuf_free(dev_netbuf);
767     }
768     if (event_mem != HI_NULL) {
769         frw_event_free(event_mem);
770     }
771     return HI_ERR_FAILURE;
772 }
773 
774 
hcc_get_extern_address(const oal_dev_netbuf_stru * dev_netbuf,hi_u32 extend_len)775 hi_void *hcc_get_extern_address(const oal_dev_netbuf_stru *dev_netbuf, hi_u32 extend_len)
776 {
777     if (extend_len > (HCC_HDR_TOTAL_LEN - HCC_HDR_LEN)) {
778         /* invalid extend len */
779 #ifdef CONFIG_HCC_DEBUG
780         hi_diag_log_msg_i1(0, "invalid extend len:%u\r\n", extend_len);
781 #endif
782         return HI_NULL;
783     }
784 
785     return (hi_void *)((uintptr_t)oal_dev_netbuf_hcchdr(dev_netbuf) + HCC_HDR_TOTAL_LEN - extend_len);
786 }
787 
hcc_check_header_vaild(const hcc_header_stru * hdr)788 hi_bool hcc_check_header_vaild(const hcc_header_stru *hdr)
789 {
790     if ((hdr->main_type >= HCC_ACTION_TYPE_BUTT) || (hdr->sub_type >= WIFI_SUB_TYPE_BUTT) ||
791         ((HCC_HDR_LEN + (hi_u16)(hdr->pad_hdr) + (hi_u16)(hdr->pad_payload)) > HCC_HDR_TOTAL_LEN)) {
792         return HI_FALSE;
793     }
794     return HI_TRUE;
795 }
796 
hcc_exec_action(oal_dev_netbuf_stru * nb_prefetch,const hcc_header_stru * hcc_head,oal_dev_netbuf_stru * nb_postdo)797 hi_bool hcc_exec_action(oal_dev_netbuf_stru *nb_prefetch, const hcc_header_stru *hcc_head,
798     oal_dev_netbuf_stru *nb_postdo)
799 {
800     hcc_slave_netbuf slave_netbuf;
801     hi_u8 *pre_context = HI_NULL;
802     hcc_rx_action *rx_action = &g_hcc_slave_handler.rx_action_info.action[hcc_head->main_type];
803 
804     /* prepare */
805     if (rx_action->pre_do) {
806         slave_netbuf.net_buf = nb_prefetch;
807         slave_netbuf.len = (hi_s32)hcc_head->pay_len;
808         if (rx_action->pre_do(hcc_head->sub_type, &slave_netbuf, &pre_context) != HI_SUCCESS) {
809             printf("rx_action->pre_do break\n");
810             return HI_FALSE;
811         }
812     }
813     /* prepare do ok,delist the netbuf. */
814     nb_postdo = hcc_netbuf_delist(&g_hcc_rx_queue);
815     if (nb_postdo == HI_NULL) {
816         printf("dev_netbuf_postdo break\n");
817         return HI_FALSE;
818     }
819 
820     if (rx_action->post_do != HI_NULL) {
821         nb_postdo->next = HI_NULL;
822         hcc_head = (hcc_header_stru *)oal_dev_netbuf_hcchdr(nb_postdo);
823         if (hcc_head == HI_NULL) {
824             hi_diag_log_msg_e0(0, "{hcc_slave_rx_queue_sched::pst_hcc_head null.}");
825             printf("dev_netbuf_postdo continue\n");
826             return HI_TRUE;
827         }
828         slave_netbuf.net_buf = nb_postdo;
829         slave_netbuf.len = (hi_s32)hcc_head->pay_len;
830         (hi_void)rx_action->post_do(hcc_head->sub_type, &slave_netbuf, pre_context);
831     } else {
832         /* Debug,unregistered mtype */
833         hi_diag_log_msg_e0(0, "rx_action->post_do is null\r\n");
834         oal_mem_dev_netbuf_free(nb_postdo);
835         printf("dev_netbuf_postdo else\n");
836     }
837     return HI_TRUE;
838 }
839 
hcc_slave_rx_queue_sched(hi_void)840 hi_void hcc_slave_rx_queue_sched(hi_void)
841 {
842     oal_dev_netbuf_stru *dev_netbuf_prefetch = HI_NULL;
843     oal_dev_netbuf_stru *dev_netbuf_postdo = HI_NULL;
844 
845     hcc_delay_bug_on_detect();
846 
847     for (hi_u32 i = 0; i < FRW_EVENT_HCC_BURST_COUNT; ++i) {
848         if (g_hcc_rx_queue.num == 0) {
849             break;
850         }
851 
852         /* action prepare, if failed keep the netbuf in the list */
853         dev_netbuf_prefetch = (oal_dev_netbuf_stru *)oal_netbuf_head_next(&g_hcc_rx_queue);
854         hcc_header_stru *hcc_head = (hcc_header_stru *)oal_dev_netbuf_hcchdr(dev_netbuf_prefetch);
855         if (hcc_head == HI_NULL) {
856             hi_diag_log_msg_e0(0, "{hcc_slave_rx_queue_sched::pst_hcc_head null.}");
857             continue;
858         }
859         if (hcc_check_header_vaild(hcc_head) != HI_TRUE) {
860             hi_diag_log_msg_e0(0, "hcc rx header valid\r\n");
861             dev_netbuf_postdo = hcc_netbuf_delist(&g_hcc_rx_queue);
862             oal_mem_dev_netbuf_free(dev_netbuf_postdo);
863             continue;
864         }
865 
866         if (!hcc_exec_action(dev_netbuf_prefetch, hcc_head, dev_netbuf_postdo)) {
867             break;
868         }
869     }
870 }
871 
hcc_slave_tx_queue_sched(hi_void)872 hi_void hcc_slave_tx_queue_sched(hi_void)
873 {
874     hi_u32 i;
875     hi_u32 total_len = 0;
876     hi_sdio_status_info status_info;
877     hi_sdio_extendfunc *hcc_extfunc = hi_sdio_get_extend_info();
878 
879     hi_u32 status = hi_int_lock();
880     (hi_void)hi_sdio_get_status(&status_info);
881     if ((status_info.tx_status == CHAN_TX_BUSY) || (status_info.allow_sleep == HI_TRUE) ||
882         (status_info.work_status != SDIO_CHAN_WORK) || (g_hcc_tx_queue.num == 0)) {
883         hi_int_restore(status);
884         return;
885     }
886 
887     status_info.tx_status = CHAN_TX_BUSY;
888     (hi_void)hi_sdio_set_status(&status_info);
889 
890     memset_s(hcc_extfunc, sizeof(hi_sdio_extendfunc), 0, sizeof(hi_sdio_extendfunc));
891 
892     /* 是否有高优先级buffer credit值要更新 */
893     if (g_flowctrl_flashed == HI_TRUE) {
894         if (!hi_sdio_is_sending_msg(D2H_MSG_CREDIT_UPDATE) && !hi_sdio_is_pending_msg(D2H_MSG_CREDIT_UPDATE)) {
895             /* 更新寄存器 */
896             hcc_extfunc->credit_info = g_flow_ctrl_reg_info;
897             hcc_extfunc->credit_isvalid = 1;
898             (hi_void)hi_sdio_write_extinfo(hcc_extfunc);
899             g_flowctrl_flashed = HI_FALSE;
900         }
901     }
902 
903     memset_s(hcc_extfunc, sizeof(hi_sdio_extendfunc), 0, sizeof(hi_sdio_extendfunc));
904 
905     for (i = 0; i < g_d2h_hcc_assemble_count; ++i) {
906         oal_dev_netbuf_stru *dev_netbuf = hcc_netbuf_delist(&g_hcc_tx_queue);
907         if (dev_netbuf == HI_NULL) {
908             break;
909         }
910 
911         /* set the tx aggr information */
912         hi_u32 send_len = hcc_slave_get_netbuf_align_len(dev_netbuf, HISDIO_D2H_SCATT_BUFFLEN_ALIGN);
913         total_len += send_len;
914         g_tx_aggr_info.hcc_tx_aggr[i].netbuf = dev_netbuf;
915         g_tx_aggr_info.hcc_tx_aggr[i].tx_pkt_bytes = send_len;
916         hcc_extfunc->comm_reg[i] = (send_len >> HISDIO_D2H_SCATT_BUFFLEN_ALIGN_BITS) & 0xFF;
917     }
918 
919     /* The sdio register must access by 4 bytes */
920     hcc_extfunc->valid_commreg_cnt = (hi_s32)(i & (~3)); /* 3 is used for 4 bytes down align. */
921     hcc_extfunc->commreg_isvalid = 1;
922     /* tx_aggr_total_len 32 B对齐,未作512对齐 */
923     g_tx_aggr_info.tx_aggr_total_len = total_len;
924     g_tx_aggr_info.aggr_tx_num = i;
925 
926     if (total_len < HISDIO_BLOCK_SIZE) {
927         hcc_extfunc->xfer_count = hi_byte_align(total_len, 4); /* 4 bytes align */
928     } else {
929         hcc_extfunc->xfer_count = hi_byte_align(total_len, HISDIO_BLOCK_SIZE); /* 4 bytes align */
930     }
931     /* write ext info */
932     (hi_void)hi_sdio_write_extinfo(hcc_extfunc);
933 
934     hi_sdio_send_data(hcc_extfunc->xfer_count);
935 
936     hi_int_restore(status);
937 }
938 
939 /* ****************************************************************************
940  功能描述  : 收到host的sleep request消息处理,应答允许或forbid sleep应答
941 
942  修改历史      :
943   1.日    期   : 2019-05-30
944     作    者   : HiSilicon
945     修改内容   : 新生成函数
946 **************************************************************************** */
hcc_sleep_request_msg_proc(hi_void)947 hi_void hcc_sleep_request_msg_proc(hi_void)
948 {
949     hi_u32 msg;
950     hi_sdio_status_info status_info;
951 
952     (hi_void)hi_sdio_get_status(&status_info);
953     if ((status_info.tx_status != CHAN_TX_BUSY) &&
954         (g_hcc_tx_queue.num == 0) &&
955         (g_chan_write_flag == CHAN_RX_IDLE)) {
956         msg = D2H_MSG_ALLOW_SLEEP;
957         status_info.sleep_status = SLEEP_ALLOW_SND;
958         status_info.allow_sleep = HI_TRUE;
959     } else {
960         msg = D2H_MSG_DISALLOW_SLEEP;
961         status_info.sleep_status = SLEEP_DISALLOW_SND;
962     }
963 
964     hi_sdio_send_sync_msg(msg);
965     (hi_void)hi_sdio_set_status(&status_info);
966 }
967 
hcc_msg_process(hi_u32 msg)968 hi_void hcc_msg_process(hi_u32 msg)
969 {
970     if (msg & (1 << H2D_MSG_PM_WLAN_OFF)) {
971         printf("reboot\n");
972         hi_diag_log_msg_i0(0, "recieve msg H2D_MSG_PM_WLAN_OFF, need reboot\n");
973         hi_reboot();
974     }
975 }
976 
hcc_msg_callback(hi_u32 msg)977 hi_void hcc_msg_callback(hi_u32 msg)
978 {
979     static hi_u8 msg_callback_flag = 0;
980     if (g_process_msg_callback != HI_NULL) {
981         g_process_msg_callback(msg);
982     } else {
983         if (msg_callback_flag == 0) { /* print related log every 256 messages. */
984             hi_diag_log_msg_e0(0, "call hcc_register_msg_callback to register callback firstly\r\n");
985         }
986         ++msg_callback_flag;
987     }
988 }
989 
hcc_read_err_callback(hi_void)990 hi_void hcc_read_err_callback(hi_void)
991 {
992     hi_diag_log_msg_i0(0, "hcc_read_err_callback occurs.\r\n");
993 }
994 
hcc_soft_rst_callback(hi_void)995 hi_void hcc_soft_rst_callback(hi_void)
996 {
997     sdio_soft_reset_valid(); /* must set before reinit. */
998     (hi_void)hi_sdio_reinit();
999 }
1000 
hcc_slave_clean(hi_void)1001 hi_void hcc_slave_clean(hi_void)
1002 {
1003     if (g_reserve_netbuff != HI_NULL) {
1004         oal_mem_dev_netbuf_free(g_reserve_netbuff);
1005         g_reserve_netbuff = HI_NULL;
1006     }
1007 }
1008 
1009 /* ****************************************************************************
1010  功能描述  : 注册消息处理中断函数
1011 
1012  修改历史      :
1013   1.日    期   : 2019-05-30
1014     作    者   : HiSilicon
1015     修改内容   : 新生成函数
1016 **************************************************************************** */
hcc_register_msg_callback(hcc_msg_cb msg_callback)1017 hi_void hcc_register_msg_callback(hcc_msg_cb msg_callback)
1018 {
1019     g_process_msg_callback = msg_callback;
1020 }
1021 
1022 /* ****************************************************************************
1023  功能描述  : HCC slave初始化
1024 
1025  修改历史      :
1026   1.日    期   : 2019-05-30
1027     作    者   : HiSilicon
1028     修改内容   : 新生成函数
1029 **************************************************************************** */
hcc_slave_init(hi_void)1030 hi_u32 hcc_slave_init(hi_void)
1031 {
1032     hi_sdio_intcallback callback;
1033     g_sdio_init_ok = HI_FALSE;
1034     /* 申请一个保留netbuff用来申请不到内存时使用 */
1035     g_reserve_netbuff = oal_mem_dev_netbuf_alloc(OAL_NORMAL_NETBUF, HCC_LONG_PACKAGE_SIZE, OAL_NETBUF_PRIORITY_HIGH);
1036     if (g_reserve_netbuff == HI_NULL) {
1037         return HI_FAIL;
1038     }
1039     /* 逻辑需要保证宏HCC_LONG_PACKAGE_SIZE是 4 字节整数倍 */
1040     if ((HCC_LONG_PACKAGE_SIZE % 4) != 0) {
1041         hi_diag_log_msg_e0(0, "must 4 bytes algin\r\n");
1042         return HI_FAIL;
1043     }
1044 
1045     /* 安全编程规则6.6例外(1) 对固定长度的数组进行初始化,或对固定长度的结构体进行内存初始化 */
1046     memset_s((hi_void *)&g_tx_aggr_info, sizeof(hcc_slave_tx_info), 0, sizeof(hcc_slave_tx_info));
1047     memset_s((hi_void *)&g_rx_aggr_info, sizeof(hcc_slave_rx_info), 0, sizeof(hcc_slave_rx_info));
1048     memset_s((hi_void *)g_h2d_assem_descr, HISDIO_HOST2DEV_SCATT_SIZE, 0, HISDIO_HOST2DEV_SCATT_SIZE);
1049     memset_s((hi_void *)&g_hcc_slave_handler, sizeof(struct hcc_handler), 0, sizeof(struct hcc_handler));
1050     memset_s((hi_void *)g_descr_control_func, sizeof(g_descr_control_func), 0, sizeof(g_descr_control_func));
1051 
1052     g_descr_control_func[HCC_DESCR_ASSEM_RESET] = hcc_rx_assem_info_reset;
1053     g_descr_control_func[HCC_NETBUF_QUEUE_SWITCH] = hcc_rx_netbuf_queue_pri_switch;
1054     g_current_queue_type = HCC_NETBUF_NORMAL_QUEUE;
1055 
1056     oal_dev_netbuf_list_head_init(&g_hcc_tx_queue);
1057     oal_dev_netbuf_list_head_init(&g_hcc_rx_queue);
1058 
1059     callback.rdover_callback     = hcc_read_over_callback;
1060     callback.rdstart_callback    = hcc_read_start_callback;
1061     callback.wrstart_callback    = hcc_write_start_callback;
1062     callback.wrover_callback     = hcc_write_over_callback;
1063     callback.processmsg_callback = hcc_msg_callback;
1064     callback.rderr_callback      = hcc_read_err_callback;
1065     callback.soft_rst_callback   = hcc_soft_rst_callback;
1066     (hi_void)hi_sdio_register_callback(&callback);
1067     (hi_void)hi_sdio_memory_init();
1068 
1069     hcc_register_msg_callback(hcc_msg_process);
1070 
1071     return HI_SUCCESS;
1072 }
1073 
1074 /* ****************************************************************************
1075  功能描述  : HCC slave重新初始化
1076 
1077  修改历史      :
1078   1.日    期   : 2019-05-30
1079     作    者   : HiSilicon
1080     修改内容   : 新生成函数
1081 **************************************************************************** */
hcc_slave_reinit(hi_void)1082 hi_u32 hcc_slave_reinit(hi_void)
1083 {
1084     hi_sdio_intcallback callback;
1085     hi_u32 ret;
1086 
1087     /* 申请一个保留netbuff用来申请不到内存时使用 */
1088     g_reserve_netbuff = oal_mem_dev_netbuf_alloc(OAL_NORMAL_NETBUF, HCC_LONG_PACKAGE_SIZE, OAL_NETBUF_PRIORITY_HIGH);
1089     if (g_reserve_netbuff == HI_NULL) {
1090         return HI_FAIL;
1091     }
1092     // 逻辑需要保证宏HCC_LONG_PACKAGE_SIZE是 4 字节整数倍,lin_t e506/e774告警屏蔽
1093     if ((HCC_LONG_PACKAGE_SIZE % 4) != 0) {
1094         hi_diag_log_msg_e0(0, "must 4 bytes algin\r\n");
1095         return HI_FAIL;
1096     }
1097 
1098     callback.rdover_callback        = hcc_read_over_callback;
1099     callback.rdstart_callback       = hcc_read_start_callback;
1100     callback.wrstart_callback       = hcc_write_start_callback;
1101     callback.wrover_callback        = hcc_write_over_callback;
1102     callback.processmsg_callback    = hcc_msg_callback;
1103     callback.rderr_callback         = hcc_read_err_callback;
1104     callback.soft_rst_callback      = hcc_soft_rst_callback;
1105 
1106     ret = hi_sdio_register_callback(&callback);
1107     if (ret != HI_SUCCESS) {
1108         return ret;
1109     }
1110     ret = hi_sdio_reinit();
1111     if (ret != HI_SUCCESS) {
1112         return ret;
1113     }
1114 
1115     return HI_SUCCESS;
1116 }
1117 
1118 /* ****************************************************************************
1119  功能描述  : HCC接收处理注册函数
1120 
1121  修改历史      :
1122   1.日    期   : 2019-05-30
1123     作    者   : HiSilicon
1124     修改内容   : 新生成函数
1125 **************************************************************************** */
hcc_rx_register(struct hcc_handler * hcc,hi_u8 mtype,hcc_rx_post_do post_do,hcc_rx_pre_do pre_do)1126 hi_u32 hcc_rx_register(struct hcc_handler *hcc, hi_u8 mtype, hcc_rx_post_do post_do, hcc_rx_pre_do pre_do)
1127 {
1128     hcc_rx_action *rx_action = HI_NULL;
1129 
1130     if ((hcc == HI_NULL) || (post_do == HI_NULL) || (mtype >= HCC_ACTION_TYPE_BUTT)) {
1131         return HI_FAIL;
1132     }
1133 
1134     rx_action = &hcc->rx_action_info.action[mtype];
1135 
1136     if (rx_action->post_do != HI_NULL) {
1137         return HI_FAIL;
1138     }
1139 
1140     rx_action->post_do = post_do;
1141     rx_action->pre_do = pre_do;
1142 
1143     return HI_SUCCESS;
1144 }
1145 
1146 #ifdef __cplusplus
1147 #if __cplusplus
1148 }
1149 #endif
1150 #endif
1151