2 ******************************************************************************
6 * @brief ECRNX sdio init and management function
8 * Copyright (C) ESWIN 2015-2020
10 ******************************************************************************
13 #include <linux/module.h>
14 #include <linux/kthread.h>
15 #include <linux/mmc/sdio_func.h>
16 #include <linux/mmc/sdio_ids.h>
19 #include "ecrnx_utils.h"
20 #include "ecrnx_cmds.h"
21 #include "ecrnx_defs.h"
22 #include "ecrnx_msg_rx.h"
24 #include "ipc_shared.h"
25 #include "ecrnx_events.h"
26 #include "ecrnx_sdio.h"
27 #ifdef CONFIG_TEST_ESWIN_SDIO
30 #ifdef CONFIG_ECRNX_WIFO_CAIL
31 #include "ecrnx_amt.h"
35 #define SDIO_ADDR_DATA (unsigned int)(0x200)
37 #ifdef CONFIG_ECRNX_SOFTMAC
39 #elif defined CONFIG_ECRNX_FULLMAC
43 sdio_rx_buf_t sdio_rx_buff;
45 extern const int nx_txdesc_cnt_msk[];
47 struct vendor_radiotap_hdr {
55 * @brief: sdio_rx_buf_init: Initialization the sdio rx buffer
59 static void sdio_rx_buf_init(void)
62 ECRNX_DBG("%s entry!!", __func__);
63 memset(&sdio_rx_buff, 0, sizeof(sdio_rx_buf_t));
65 for(i = 0; i < SDIO_RXBUF_CNT; i++)
67 sdio_rx_buff.ecrnx_sdio_rx_skb[i].skb = dev_alloc_skb(SDIO_RXBUF_SIZE);
68 skb_put(sdio_rx_buff.ecrnx_sdio_rx_skb[i].skb, SDIO_RXBUF_SIZE);
70 #ifdef CONFIG_TEST_ESWIN_SDIO
71 sdio_rx_tx_test_schedule();
73 ECRNX_DBG("%s exit!!", __func__);
77 * @brief: sdio_rx_buf_deinit: Deinitialization the sdio rx buffer
81 static void sdio_rx_buf_deinit(void)
85 memset(&sdio_rx_buff, 0, sizeof(sdio_rx_buf_t));
87 for(i = 0; i < SDIO_RXBUF_CNT; i++)
89 if(sdio_rx_buff.ecrnx_sdio_rx_skb[i].skb)
91 dev_kfree_skb(sdio_rx_buff.ecrnx_sdio_rx_skb[i].skb);
97 * @brief: sdio_rx_buf_push: push a skb element to sdio rx buffer
98 * @param {skb} skb data need to push
99 * @param {recv_len} skb data length
102 struct sk_buff * sdio_rx_buf_push(struct sk_buff *skb, uint16_t recv_len)
106 ECRNX_DBG("%s enter, skb: %d, skb_data:%d, skb_len:%d", __func__, skb, skb->data, recv_len);
107 if(atomic_read(&sdio_rx_buff.suspend))
112 if(sdio_rx_buff.sdio_host_rx_buff_used >= SDIO_RXBUF_CNT)
114 ECRNX_PRINT("no enough space \n");
118 if((!skb) || (!recv_len) || (recv_len > SDIO_RXBUF_SIZE))
120 ECRNX_PRINT("rx data is error \n");
124 atomic_set(&sdio_rx_buff.suspend, 1);
128 if(!sdio_rx_buff.ecrnx_sdio_rx_skb[index].flag) //find a index to store the data
133 }while(index < SDIO_RXBUF_CNT);
135 sdio_rx_buff.sdio_host_rx_buff_used++;
136 sdio_rx_buff.ecrnx_sdio_rx_skb[index].flag = true;
137 sdio_rx_buff.ecrnx_sdio_rx_skb[index].data_len = recv_len;
138 memcpy(sdio_rx_buff.ecrnx_sdio_rx_skb[index].skb->data, skb->data, recv_len);
139 atomic_set(&sdio_rx_buff.suspend, 0);
141 return sdio_rx_buff.ecrnx_sdio_rx_skb[index].skb;
145 * @brief: sdio_rx_buf_pop: pop a skb element from sdio rx buffer
149 struct sk_buff* sdio_rx_buf_pop(void)
152 struct sk_buff *skb= NULL;
154 if(atomic_read(&sdio_rx_buff.suspend))
156 ECRNX_PRINT("sdio suspend! \n");
160 if(sdio_rx_buff.sdio_host_rx_buff_used <= 0)
162 ECRNX_PRINT("no data in memory \n");
166 atomic_set(&sdio_rx_buff.suspend, 1);
170 if(sdio_rx_buff.ecrnx_sdio_rx_skb[index].flag) //find a index to pop the data
175 }while(index < SDIO_RXBUF_CNT);
177 if(index != SDIO_RXBUF_CNT)
179 skb = sdio_rx_buff.ecrnx_sdio_rx_skb[index].skb;
180 sdio_rx_buff.ecrnx_sdio_rx_skb[index].flag = false;
181 sdio_rx_buff.sdio_host_rx_buff_used = (sdio_rx_buff.sdio_host_rx_buff_used > 0)? sdio_rx_buff.sdio_host_rx_buff_used-1: 0;
183 atomic_set(&sdio_rx_buff.suspend, 0);
189 * @brief: ipc_host_rxdesc_handler: Handle the reception of a Rx Descriptor
190 * Called from general IRQ handler when status %IPC_IRQ_E2A_RXDESC is set
191 * @param {env} pointer to the sdio Host environment
192 * @param {skb} received skb data
195 static int sdio_host_rxdesc_handler(struct ipc_host_env_tag *env, struct sk_buff *skb)
198 // LMAC has triggered an IT saying that a reception has occurred.
199 // Then we first need to check the validity of the current hostbuf, and the validity
200 // of the next hostbufs too, because it is likely that several hostbufs have been
201 // filled within the time needed for this irq handling
202 #ifdef CONFIG_ECRNX_FULLMAC
203 // call the external function to indicate that a RX descriptor is received
204 ret = env->cb.recv_data_ind(env->pthis, skb);
206 // call the external function to indicate that a RX packet is received
207 ret = env->cb.recv_data_ind(env->pthis, skb);
208 #endif //(CONFIG_ECRNX_FULLMAC)
209 ECRNX_DBG("%s exit!!", __func__);
214 * @brief: sdio_host_radar_handler Handle the reception of radar events
215 * @param {env} pointer to the sdio Host environment
216 * @param {skb} received skb data
219 static int sdio_host_radar_handler(struct ipc_host_env_tag *env, struct sk_buff *skb)
223 #ifdef CONFIG_ECRNX_RADAR
224 // LMAC has triggered an IT saying that a radar event has been sent to upper layer.
225 // Then we first need to check the validity of the current msg buf, and the validity
226 // of the next buffers too, because it is likely that several buffers have been
227 // filled within the time needed for this irq handling
228 // call the external function to indicate that a RX packet is received
229 spin_lock(&((struct ecrnx_hw *)env->pthis)->radar.lock);
230 ret = env->cb.recv_radar_ind(env->pthis, skb);
231 spin_unlock(&((struct ecrnx_hw *)env->pthis)->radar.lock);
232 #endif /* CONFIG_ECRNX_RADAR */
237 * @brief: sdio_host_unsup_rx_vec_handler Handle the reception of unsupported rx vector
238 * @param {env} pointer to the sdio Host environment
239 * @param {skb} received skb data
242 static int sdio_host_unsup_rx_vec_handler(struct ipc_host_env_tag *env, struct sk_buff *skb)
244 return env->cb.recv_unsup_rx_vec_ind(env->pthis, skb);
248 * @brief: sdio_host_msg_handler Handler for firmware message
249 * @param {env} pointer to the sdio Host environment
250 * @param {skb} received skb data
253 static int sdio_host_msg_handler(struct ipc_host_env_tag *env, struct sk_buff *skb)
255 // LMAC has triggered an IT saying that a message has been sent to upper layer.
256 // Then we first need to check the validity of the current msg buf, and the validity
257 // of the next buffers too, because it is likely that several buffers have been
258 // filled within the time needed for this irq handling
259 // call the external function to indicate that a RX packet is received
260 return env->cb.recv_msg_ind(env->pthis, skb->data);
264 * @brief: sdio_host_msgack_handler Handle the reception of message acknowledgement
265 * @param {env} pointer to the sdio Host environment
266 * @param {skb} received skb data
269 static int sdio_host_msgack_handler(struct ipc_host_env_tag *env, struct sk_buff *skb)
271 uint64_t hostid = *(uint64_t *)skb->data;
275 env->msga2e_hostid = NULL;
276 env->cb.recv_msgack_ind(env->pthis, hostid);
282 * @brief: sdio_host_dbg_handler Handle the reception of Debug event
283 * @param {env} pointer to the sdio Host environment
284 * @param {skb} received skb data
287 static int sdio_host_dbg_handler(struct ipc_host_env_tag *env, struct sk_buff *skb)
289 // LMAC has triggered an IT saying that a DBG message has been sent to upper layer.
290 // Then we first need to check the validity of the current buffer, and the validity
291 // of the next buffers too, because it is likely that several buffers have been
292 // filled within the time needed for this irq handling
293 // call the external function to indicate that a RX packet is received
294 return env->cb.recv_dbg_ind(env->pthis, skb);
298 * @brief: sdio_host_tx_cfm_handler Handle the reception of TX confirmation
299 * @param {env} pointer to the sdio Host environment
300 * @param {queue_idx} index of the hardware on which the confirmation has been received
301 * @param {user_pos} index of the user position
304 static int sdio_host_tx_cfm_handler(struct ipc_host_env_tag *env, struct sk_buff *skb)
307 struct sk_buff *skb_cfm;
308 struct ecrnx_txhdr *txhdr;
310 ECRNX_DBG("%s, skb: 0x%08x \n", __func__, skb);
311 #ifdef CONFIG_ECRNX_FULLMAC
312 struct tx_cfm_tag *cfm;
314 cfm = (struct tx_cfm_tag *)skb->data;
315 memcpy((uint8_t *)&host_id, (uint8_t *)cfm->hostid, sizeof(ptr_addr));
316 ECRNX_DBG("--%s--hostid 0x%08x, skb: 0x%x \n", __func__, host_id, skb);
321 skb_cfm = (struct sk_buff *)host_id;
322 txhdr = (struct ecrnx_txhdr *)skb_cfm->data;
323 memcpy(&txhdr->hw_hdr.cfm, cfm, sizeof(*cfm));
324 #elif defined CONFIG_ECRNX_SOFTMAC
328 return env->cb.send_data_cfm(env->pthis, host_id);
332 #ifdef CONFIG_ECRNX_WIFO_CAIL
334 * @brief: sdio_host_rx_handler Handle the reception of rx frame
335 * @param {frm_type} received frame type
336 * @param {skb} received skb data
339 void sdio_host_amt_rx_handler(uint32_t frm_type, struct sk_buff *skb)
343 ECRNX_PRINT("%s enter, frame type: %d, len %d.!!", __func__, frm_type, skb->len);
344 if (frm_type != SDIO_FRM_TYPE_RXDESC)
346 skb_pull(skb, SKB_DATA_COM_HD_OFFSET); //delete the frame common header
351 case SDIO_FRM_TYPE_IWPRIV:
353 /*print_hex_dump(KERN_INFO, "iwpriv-cfm:", DUMP_PREFIX_ADDRESS, 32, 1,
354 skb->data, skb->len, false);*/
355 amt_vif.rxlen = skb->len;
356 memset(amt_vif.rxdata, 0, ECRNX_RXSIZE);
357 memcpy(amt_vif.rxdata, skb->data, skb->len > ECRNX_RXSIZE ? ECRNX_RXSIZE : skb->len);
359 wake_up(&amt_vif.rxdataq);
369 if (need_free && skb) { // free the skb
370 ECRNX_DBG("skb free: 0x%x, \n", skb);
373 ECRNX_DBG("%s exit!!", __func__);
379 * @brief: sdio_host_rx_handler Handle the reception of rx frame
380 * @param {frm_type} received frame type
381 * @param {env} pointer to the sdio Host environment
382 * @param {skb} received skb data
385 void sdio_host_rx_handler(uint32_t frm_type, struct ipc_host_env_tag *env, struct sk_buff *skb)
389 ECRNX_DBG("%s enter, frame type: %d!!", __func__, frm_type);
390 if (frm_type != SDIO_FRM_TYPE_RXDESC)
392 skb_pull(skb, SKB_DATA_COM_HD_OFFSET); //delete the frame common header
397 case SDIO_FRM_TYPE_RXDESC:
399 sdio_host_rxdesc_handler(env, skb);
403 case SDIO_FRM_TYPE_MSG_ACK:
405 ret = sdio_host_msgack_handler(env, skb);
409 case SDIO_FRM_TYPE_MSG:
411 ret = sdio_host_msg_handler(env, skb);
415 case SDIO_FRM_TYPE_TXCFM:
417 /* add the spinlock which was missed during porting. */
418 spin_lock_bh(&((struct ecrnx_hw *)env->pthis)->tx_lock);
419 while(skb->len > sizeof(struct tx_cfm_tag))
421 ret = sdio_host_tx_cfm_handler(env, skb);
422 skb_pull(skb, sizeof(struct tx_cfm_tag));
424 ret = sdio_host_tx_cfm_handler(env, skb);
425 spin_unlock_bh(&((struct ecrnx_hw *)env->pthis)->tx_lock);
429 case SDIO_FRM_TYPE_UNSUP_RX_VEC:
431 // handle the unsupported rx vector reception
432 ret = sdio_host_unsup_rx_vec_handler(env, skb);
436 case SDIO_FRM_TYPE_RADAR:
438 // handle the radar event reception
439 ret = sdio_host_radar_handler(env, skb);
443 case SDIO_FRM_TYPE_TBTT_SEC:
445 env->cb.sec_tbtt_ind(env->pthis);
449 case SDIO_FRM_TYPE_TBTT_PRIM:
451 env->cb.prim_tbtt_ind(env->pthis);
455 case SDIO_FRM_TYPE_DBG:
457 ret = sdio_host_dbg_handler(env, skb);
461 case SDIO_FRM_TYPE_UPDATE:
471 if (!ret && skb) { // free the skb
472 ECRNX_DBG("skb free: 0x%x, ret: %d!! \n", skb, ret);
475 ECRNX_DBG("%s exit!!", __func__);
480 * @brief: rcv_skb_convert convert the sdio received skb to the ecrnx handled skb.
481 * @param {src_rxu_state} received rxu state in skb
482 * @param {src_rxu_state} received rx header in skb
483 * @param {src_rxu_state} handled hw rxhdr in skb
484 * @param {src_rxu_state} handled rx desc tag in skb
487 u8 rcv_skb_convert(struct rxu_stat_mm* src_rxu_state, \
488 struct rx_hd* src_rx_hd, \
489 struct sk_buff *skb, \
490 struct hw_rxhdr* dst_hw_rxhdr,\
491 struct rxdesc_tag* dst_rxdesc_tag)
493 ECRNX_DBG("%s enter!!", __func__);
497 if (!skb || !skb->data){
498 ECRNX_PRINT("RX data invalid \n");
502 //copy the rxu state and rx header, repush process need to used them
503 memcpy(src_rxu_state, skb->data, sizeof(struct rxu_stat_mm));
504 memcpy(src_rx_hd, skb->data + sizeof(struct rxu_stat_mm), sizeof(struct rx_hd));
506 /*copy the hw vector and rxu state */
507 memcpy(dst_hw_rxhdr, skb->data + sizeof(struct rxu_stat_mm), sizeof(struct rx_hd));
508 memcpy(&dst_hw_rxhdr->phy_info, \
509 skb->data + SKB_DATA_TAG_OFFSET, \
510 sizeof(struct rxu_stat_mm) - SKB_DATA_TAG_OFFSET);
512 memcpy(dst_rxdesc_tag, skb->data + SKB_DATA_COM_HD_OFFSET + 2, sizeof(struct rxdesc_tag)); //two byte msdu_mode
513 /*recove the hdr to skb data*/
514 skb_pull(skb, SKB_DATA_HD_OFFSET); //delete the frame type and amsdu flag
515 skb_push(skb, sizeof(struct hw_rxhdr));
516 memcpy(skb->data, dst_hw_rxhdr, sizeof(struct hw_rxhdr)); //put hw header to skb
517 skb_push(skb, sizeof(struct rxdesc_tag));
518 memcpy(skb->data, dst_rxdesc_tag, sizeof(struct rxdesc_tag)); //put rx desc tag to skb
520 for(index = 0; index < sizeof(struct hw_rxhdr) + sizeof(struct rxdesc_tag); index++)
522 ECRNX_DBG("0x%x ", skb->data[index]);
525 ECRNX_DBG("%s exit!!", __func__);
530 * @brief: ecrnx_sdio_init Initialize sdio interface.
531 * @param {ecrnx_hw} Main driver data
534 u8 ecrnx_sdio_init(struct ecrnx_hw *ecrnx_hw)
536 ECRNX_DBG("%s entry!!", __func__);
537 // Save the pointer to the register base
538 ecrnx_hw->ipc_env->pthis = (void*)ecrnx_hw;
540 #ifdef CONFIG_TEST_ESWIN_SDIO
541 ecrnx_hw_set((void*)ecrnx_hw);
543 ECRNX_DBG("%s exit!!", __func__);
548 * @brief: ecrnx_sdio_deinit DeInitialize sdio interface.
549 * @param {ecrnx_hw} Main driver data
552 void ecrnx_sdio_deinit(struct ecrnx_hw *ecrnx_hw)
554 ECRNX_DBG(ECRNX_FN_ENTRY_STR);
556 sdio_rx_buf_deinit();
557 memset(ecrnx_hw, 0, sizeof(struct ecrnx_hw));
558 memset(&sdio_rx_buff, 0, sizeof(sdio_rx_buf_t));