static void rtl8723as_recv_tasklet(void *priv) { PADAPTER padapter; PHAL_DATA_TYPE pHalData; struct recv_priv *precvpriv; struct recv_buf *precvbuf; union recv_frame *precvframe; struct recv_frame_hdr *phdr; struct rx_pkt_attrib *pattrib; u8 *ptr; _pkt *ppkt; u32 pkt_offset; _irqL irql; padapter = (PADAPTER)priv; pHalData = GET_HAL_DATA(padapter); precvpriv = &padapter->recvpriv; do { precvbuf = rtw_dequeue_recvbuf(&precvpriv->recv_buf_pending_queue); if (NULL == precvbuf) break; ptr = precvbuf->pdata; while (ptr < precvbuf->ptail) { precvframe = rtw_alloc_recvframe(&precvpriv->free_recv_queue); if (precvframe == NULL) { RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("rtl8723as_recv_tasklet: no enough recv frame!\n")); rtw_enqueue_recvbuf_to_head(precvbuf, &precvpriv->recv_buf_pending_queue); // The case of can't allocte recvframe should be temporary, // schedule again and hope recvframe is available next time. #ifdef PLATFORM_LINUX tasklet_schedule(&precvpriv->recv_tasklet); #endif return; } phdr = &precvframe->u.hdr; pattrib = &phdr->attrib; update_recvframe_attrib(precvframe, (struct recv_stat*)ptr); // fix Hardware RX data error, drop whole recv_buffer if ((!(pHalData->ReceiveConfig & RCR_ACRC32)) && pattrib->crc_err) { DBG_8192C("%s()-%d: RX Warning! rx CRC ERROR !!\n", __FUNCTION__, __LINE__); rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue); break; } pkt_offset = RXDESC_SIZE + pattrib->drvinfo_sz + pattrib->pkt_len; #if 0 // reduce check to speed up if ((ptr + pkt_offset) > precvbuf->ptail) { RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("%s: next pkt len(%p,%d) exceed ptail(%p)!\n", __FUNCTION__, ptr, pkt_offset, precvbuf->ptail)); rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue); break; } #endif if ((pattrib->crc_err) || (pattrib->icv_err)) { DBG_8192C("%s: crc_err=%d icv_err=%d, skip!\n", __FUNCTION__, pattrib->crc_err, pattrib->icv_err); rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue); } else { ppkt = skb_clone(precvbuf->pskb, GFP_ATOMIC); if (ppkt == NULL) { RT_TRACE(_module_rtl871x_recv_c_, _drv_crit_, ("rtl8723as_recv_tasklet: no enough memory to allocate SKB!\n")); rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue); rtw_enqueue_recvbuf_to_head(precvbuf, &precvpriv->recv_buf_pending_queue); // The case of can't allocte skb is serious and may never be recovered, // once bDriverStopped is enable, this task should be stopped. if (padapter->bDriverStopped == _FALSE) { #ifdef PLATFORM_LINUX tasklet_schedule(&precvpriv->recv_tasklet); #endif } return; } phdr->pkt = ppkt; phdr->len = 0; phdr->rx_head = precvbuf->phead; phdr->rx_data = phdr->rx_tail = precvbuf->pdata; phdr->rx_end = precvbuf->pend; recvframe_put(precvframe, pkt_offset); recvframe_pull(precvframe, RXDESC_SIZE + pattrib->drvinfo_sz); if (pHalData->ReceiveConfig & RCR_APPFCS) recvframe_pull_tail(precvframe, IEEE80211_FCS_LEN); // move to drv info position ptr += RXDESC_SIZE; // update drv info if (pHalData->ReceiveConfig & RCR_APP_BA_SSN) { // rtl8723s_update_bassn(padapter, pdrvinfo); ptr += 4; } #ifdef CONFIG_CONCURRENT_MODE if(rtw_buddy_adapter_up(padapter)) { if(pre_recv_entry(precvframe, precvbuf, (struct phy_stat*)ptr) != _SUCCESS) { RT_TRACE(_module_rtl871x_recv_c_,_drv_err_, ("recvbuf2recvframe: recv_entry(precvframe) != _SUCCESS\n")); } } else #endif { if (pattrib->physt) update_recvframe_phyinfo(precvframe, (struct phy_stat*)ptr); if (rtw_recv_entry(precvframe) != _SUCCESS) { RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("rtl8723as_recv_tasklet: rtw_recv_entry(precvframe) != _SUCCESS\n")); } } } // Page size of receive package is 128 bytes alignment => DMA agg // refer to _InitTransferPageSize() pkt_offset = _RND128(pkt_offset); precvbuf->pdata += pkt_offset; ptr = precvbuf->pdata; } dev_kfree_skb_any(precvbuf->pskb); precvbuf->pskb = NULL; rtw_enqueue_recvbuf(precvbuf, &precvpriv->free_recv_buf_queue); } while (1); }
static void rtl8188es_recv_tasklet(void *priv) { PADAPTER padapter; PHAL_DATA_TYPE pHalData; struct recv_priv *precvpriv; struct recv_buf *precvbuf; union recv_frame *precvframe; struct recv_frame_hdr *phdr; struct rx_pkt_attrib *pattrib; u8 *ptr; _pkt *ppkt; u32 pkt_offset; _irqL irql; padapter = (PADAPTER)priv; pHalData = GET_HAL_DATA(padapter); precvpriv = &padapter->recvpriv; do { precvbuf = rtw_dequeue_recvbuf(&precvpriv->recv_buf_pending_queue); if (NULL == precvbuf) break; ptr = precvbuf->pdata; while (ptr < precvbuf->ptail) { precvframe = rtw_alloc_recvframe(&precvpriv->free_recv_queue); if (precvframe == NULL) { RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("rtl8723as_recv_tasklet: no enough recv frame!\n")); rtw_enqueue_recvbuf_to_head(precvbuf, &precvpriv->recv_buf_pending_queue); // The case of can't allocte recvframe should be temporary, // schedule again and hope recvframe is available next time. #ifdef PLATFORM_LINUX tasklet_schedule(&precvpriv->recv_tasklet); #endif return; } phdr = &precvframe->u.hdr; pattrib = &phdr->attrib; //rx desc parsing update_recvframe_attrib_88e(precvframe, (struct recv_stat*)ptr); // fix Hardware RX data error, drop whole recv_buffer if ((!(pHalData->ReceiveConfig & RCR_ACRC32)) && pattrib->crc_err) { DBG_8192C("%s()-%d: RX Warning! rx CRC ERROR !!\n", __FUNCTION__, __LINE__); rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue); break; } pkt_offset = RXDESC_SIZE + pattrib->drvinfo_sz + pattrib->pkt_len; if ((ptr + pkt_offset) > precvbuf->ptail) { DBG_8192C("%s()-%d: : next pkt len(%p,%d) exceed ptail(%p)!\n", __FUNCTION__, __LINE__, ptr, pkt_offset, precvbuf->ptail); rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue); break; } if ((pattrib->crc_err) || (pattrib->icv_err)) { DBG_8192C("%s: crc_err=%d icv_err=%d, skip!\n", __FUNCTION__, pattrib->crc_err, pattrib->icv_err); rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue); } else { ppkt = skb_clone(precvbuf->pskb, GFP_ATOMIC); if (ppkt == NULL) { RT_TRACE(_module_rtl871x_recv_c_, _drv_crit_, ("rtl8723as_recv_tasklet: no enough memory to allocate SKB!\n")); rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue); rtw_enqueue_recvbuf_to_head(precvbuf, &precvpriv->recv_buf_pending_queue); // The case of can't allocte skb is serious and may never be recovered, // once bDriverStopped is enable, this task should be stopped. if (padapter->bDriverStopped == _FALSE) { #ifdef PLATFORM_LINUX tasklet_schedule(&precvpriv->recv_tasklet); #endif } return; } phdr->pkt = ppkt; phdr->len = 0; phdr->rx_head = precvbuf->phead; phdr->rx_data = phdr->rx_tail = precvbuf->pdata; phdr->rx_end = precvbuf->pend; recvframe_put(precvframe, pkt_offset); recvframe_pull(precvframe, RXDESC_SIZE + pattrib->drvinfo_sz); if (pHalData->ReceiveConfig & RCR_APPFCS) recvframe_pull_tail(precvframe, IEEE80211_FCS_LEN); // move to drv info position ptr += RXDESC_SIZE; // update drv info if (pHalData->ReceiveConfig & RCR_APP_BA_SSN) { // rtl8723s_update_bassn(padapter, pdrvinfo); ptr += 4; } if( (pattrib->physt) && (pattrib->pkt_rpt_type == NORMAL_RX)) update_recvframe_phyinfo_88e(precvframe, (struct phy_stat*)ptr); if(pattrib->pkt_rpt_type == NORMAL_RX)//Normal rx packet { //printk("rx normal pkt\n"); if (rtw_recv_entry(precvframe) != _SUCCESS) { RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("rtl8723as_recv_tasklet: rtw_recv_entry(precvframe) != _SUCCESS\n")); } } else{ // pkt_rpt_type == TX_REPORT1-CCX, TX_REPORT2-TX RTP,HIS_REPORT-USB HISR RTP //enqueue recvframe to txrtp queue if(pattrib->pkt_rpt_type == TX_REPORT1){ printk("rx CCX \n"); } else if(pattrib->pkt_rpt_type == TX_REPORT2){ //printk("rx TX RPT \n"); ODM_RA_TxRPT2Handle_8188E( &pHalData->odmpriv, precvframe->u.hdr.rx_data, pattrib->pkt_len, pattrib->MacIDValidEntry[0], pattrib->MacIDValidEntry[1] ); } else if(pattrib->pkt_rpt_type == TX_REPORT1){ printk("rx USB HISR \n"); } rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue); } } // Page size of receive package is 128 bytes alignment =>DMA AGG // refer to _InitTransferPageSize() pkt_offset = _RND128(pkt_offset); precvbuf->pdata += pkt_offset; ptr = precvbuf->pdata; } dev_kfree_skb_any(precvbuf->pskb); precvbuf->pskb = NULL; rtw_enqueue_recvbuf(precvbuf, &precvpriv->free_recv_buf_queue); } while (1); }
static void rtl8723bs_recv_tasklet(void *priv) { PADAPTER padapter; PHAL_DATA_TYPE pHalData; struct recv_priv *precvpriv; struct recv_buf *precvbuf; union recv_frame *precvframe; struct recv_frame_hdr *phdr; struct rx_pkt_attrib *pattrib; u8 *ptr; _pkt *ppkt; u32 pkt_offset; _irqL irql; padapter = (PADAPTER)priv; pHalData = GET_HAL_DATA(padapter); precvpriv = &padapter->recvpriv; do { precvbuf = rtw_dequeue_recvbuf(&precvpriv->recv_buf_pending_queue); if (NULL == precvbuf) break; ptr = precvbuf->pdata; while (ptr < precvbuf->ptail) { precvframe = rtw_alloc_recvframe(&precvpriv->free_recv_queue); if (precvframe == NULL) { RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("rtl8723bs_recv_tasklet: no enough recv frame!\n")); rtw_enqueue_recvbuf_to_head(precvbuf, &precvpriv->recv_buf_pending_queue); // The case of can't allocte recvframe should be temporary, // schedule again and hope recvframe is available next time. #ifdef PLATFORM_LINUX tasklet_schedule(&precvpriv->recv_tasklet); #endif return; } phdr = &precvframe->u.hdr; pattrib = &phdr->attrib; rtl8723b_query_rx_desc_status(precvframe, ptr); #if 0 { int i, len = 64; u8 *pptr = ptr; if((*(pptr + RXDESC_SIZE + pattrib->drvinfo_sz) != 0x80) && (*(pptr + RXDESC_SIZE + pattrib->drvinfo_sz) != 0x40)) { DBG_871X("##############RxDESC############### \n"); for(i=0; i<32;i=i+16) DBG_871X("%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:\n", *(pptr+i), *(pptr+i+1), *(pptr+i+2) ,*(pptr+i+3) ,*(pptr+i+4),*(pptr+i+5), *(pptr+i+6), *(pptr+i+7), *(pptr+i+8), *(pptr+i+9), *(pptr+i+10), *(pptr+i+11), *(pptr+i+12), *(pptr+i+13), *(pptr+i+14), *(pptr+i+15)); if(pattrib->pkt_len < 100) len = pattrib->pkt_len; pptr = ptr + RXDESC_SIZE + pattrib->drvinfo_sz; DBG_871X("##############Len=%d############### \n", pattrib->pkt_len); for(i=0; i<len;i=i+16) DBG_871X("%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:\n", *(pptr+i), *(pptr+i+1), *(pptr+i+2) ,*(pptr+i+3) ,*(pptr+i+4),*(pptr+i+5), *(pptr+i+6), *(pptr+i+7), *(pptr+i+8), *(pptr+i+9), *(pptr+i+10), *(pptr+i+11), *(pptr+i+12), *(pptr+i+13), *(pptr+i+14), *(pptr+i+15)); DBG_871X("############################# \n"); } } #endif // fix Hardware RX data error, drop whole recv_buffer if ((!(pHalData->ReceiveConfig & RCR_ACRC32)) && pattrib->crc_err) { DBG_8192C("%s()-%d: RX Warning! rx CRC ERROR !!\n", __FUNCTION__, __LINE__); rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue); break; } pkt_offset = RXDESC_SIZE + pattrib->drvinfo_sz + pattrib->pkt_len; #if 0 // reduce check to speed up if ((ptr + pkt_offset) > precvbuf->ptail) { RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("%s: next pkt len(%p,%d) exceed ptail(%p)!\n", __FUNCTION__, ptr, pkt_offset, precvbuf->ptail)); rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue); break; } #endif if ((pattrib->crc_err) || (pattrib->icv_err)) { #ifdef CONFIG_MP_INCLUDED if (padapter->registrypriv.mp_mode == 1) { if ((check_fwstate(&padapter->mlmepriv, WIFI_MP_STATE) == _TRUE))//&&(padapter->mppriv.check_mp_pkt == 0)) { if (pattrib->crc_err == 1) padapter->mppriv.rx_crcerrpktcount++; } } else #endif { DBG_8192C("%s: crc_err=%d icv_err=%d, skip!\n", __FUNCTION__, pattrib->crc_err, pattrib->icv_err); } rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue); } else { ppkt = rtw_skb_clone(precvbuf->pskb); if (ppkt == NULL) { DBG_8192C("%s: no enough memory to allocate SKB!\n", __FUNCTION__); rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue); rtw_enqueue_recvbuf_to_head(precvbuf, &precvpriv->recv_buf_pending_queue); // The case of can't allocte skb is serious and may never be recovered, // once bDriverStopped is enable, this task should be stopped. if (padapter->bDriverStopped == _FALSE) { #ifdef PLATFORM_LINUX tasklet_schedule(&precvpriv->recv_tasklet); #endif } return; } phdr->pkt = ppkt; phdr->len = 0; phdr->rx_head = precvbuf->phead; phdr->rx_data = phdr->rx_tail = precvbuf->pdata; phdr->rx_end = precvbuf->pend; recvframe_put(precvframe, pkt_offset); recvframe_pull(precvframe, RXDESC_SIZE + pattrib->drvinfo_sz); if (pHalData->ReceiveConfig & RCR_APPFCS) recvframe_pull_tail(precvframe, IEEE80211_FCS_LEN); // move to drv info position ptr += RXDESC_SIZE; // update drv info if (pHalData->ReceiveConfig & RCR_APP_BA_SSN) { //rtl8723s_update_bassn(padapter, pdrvinfo); ptr += 4; } if (pattrib->pkt_rpt_type == NORMAL_RX) { #ifdef CONFIG_CONCURRENT_MODE if (rtw_buddy_adapter_up(padapter)) { if (pre_recv_entry(precvframe, precvbuf, ptr) != _SUCCESS) { RT_TRACE(_module_rtl871x_recv_c_,_drv_err_, ("recvbuf2recvframe: recv_entry(precvframe) != _SUCCESS\n")); } } else #endif { if (pattrib->physt) rx_query_phy_status(precvframe, ptr); if (rtw_recv_entry(precvframe) != _SUCCESS) { RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, ("rtl8723bs_recv_tasklet: rtw_recv_entry(precvframe) != _SUCCESS\n")); } } } else { #ifdef CONFIG_C2H_PACKET_EN if (pattrib->pkt_rpt_type == C2H_PACKET) { rtl8723b_c2h_packet_handler(padapter, precvframe->u.hdr.rx_data, pattrib->pkt_len); } else { DBG_8192C("%s: [WARNNING] RX type(%d) not be handled!\n", __FUNCTION__, pattrib->pkt_rpt_type); } #endif rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue); } } pkt_offset = _RND8(pkt_offset); precvbuf->pdata += pkt_offset; ptr = precvbuf->pdata; } rtw_skb_free(precvbuf->pskb); precvbuf->pskb = NULL; rtw_enqueue_recvbuf(precvbuf, &precvpriv->free_recv_buf_queue); } while (1); }
int recvbuf2recvframe_s(_adapter *padapter, struct recv_buf *precvbuf) { // _irqL irql; u8 *pbuf; // u8 bsumbit = _FALSE; uint pkt_len, pkt_offset; int transfer_len; struct recv_stat *prxstat; u16 pkt_cnt, drvinfo_sz; _queue *pfree_recv_queue; union recv_frame *precvframe = NULL,*plast_recvframe = NULL; struct recv_priv *precvpriv = &padapter->recvpriv; // struct intf_hdl *pintfhdl = &padapter->pio_queue->intf; RT_TRACE(_module_rtl871x_recv_c_,_drv_info_,("+recvbuf2recvframe()\n")); pfree_recv_queue = &(precvpriv->free_recv_queue); pbuf = (u8*)precvbuf->pbuf; prxstat = (struct recv_stat *)pbuf; /* { u8 i; printk("\n-----recvbuf-----\n"); for (i=0;i<64;i=i+8) { printk("0x%.2x:0x%.2x:0x%.2x:0x%.2x:0x%.2x:0x%.2x:0x%.2x:0x%.2x\n",pbuf[i],pbuf[i+1],pbuf[i+2],pbuf[i+3],pbuf[i+4],pbuf[i+5],pbuf[i+6],pbuf[i+7]); } printk("\n-----recvbuf end-----\n"); }*/ transfer_len = precvbuf->len; precvbuf->ref_cnt = 1; do { precvframe = NULL; precvframe = rtw_alloc_recvframe(pfree_recv_queue); if (precvframe == NULL){ RT_TRACE(_module_rtl871x_recv_c_,_drv_err_,("recvbuf2recvframe(), precvframe==NULL\n")); break; } if (plast_recvframe != NULL) { if (rtw_recv_entry(plast_recvframe) != _SUCCESS) { RT_TRACE(_module_rtl871x_recv_c_,_drv_info_,("recvbuf2recvframe(), rtw_recv_entry(precvframe) != _SUCCESS\n")); } } prxstat = (struct recv_stat*)pbuf; pkt_len = le32_to_cpu(prxstat->rxdw0&0x00003fff); //pkt_len = prxstat->frame_length; RT_TRACE(_module_rtl871x_recv_c_,_drv_info_,("rxdesc: offsset0:0x%08x, offsset4:0x%08x, offsset8:0x%08x, offssetc:0x%08x\n",prxstat->rxdw0, prxstat->rxdw1, prxstat->rxdw2, prxstat->rxdw4)); drvinfo_sz = le16_to_cpu((prxstat->rxdw0&0x000f0000)>>16);//uint 2^3 = 8 bytes drvinfo_sz = drvinfo_sz << 3; RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, ("pkt_len=%d[0x%x] drvinfo_sz=%d[0x%x]\n", pkt_len, pkt_len, drvinfo_sz, drvinfo_sz)); precvframe->u.hdr.precvbuf = precvbuf; precvframe->u.hdr.adapter = padapter; rtw_init_recvframe(precvframe, precvpriv); precvframe->u.hdr.rx_head = precvframe->u.hdr.rx_data = precvframe->u.hdr.rx_tail = pbuf; precvframe->u.hdr.rx_end = precvbuf->pend; update_recvframe_attrib_from_recvstat(&precvframe->u.hdr.attrib, prxstat); pkt_offset = pkt_len + drvinfo_sz + RXDESC_SIZE; recvframe_put(precvframe, pkt_len + drvinfo_sz + RXDESC_SIZE); recvframe_pull(precvframe, drvinfo_sz + RXDESC_SIZE); /* { u8 i; printk("\n-----packet-----\n"); for(i=0;i<32;i++){ printk("0x%.2x:0x%.2x:0x%.2x:0x%.2x:0x%.2x:0x%.2x:0x%.2x:0x%.2x\n",precvframe->u.hdr.rx_data[i],precvframe->u.hdr.rx_data[i+1],precvframe->u.hdr.rx_data[i+2],precvframe->u.hdr.rx_data[i+3],precvframe->u.hdr.rx_data[i+4],precvframe->u.hdr.rx_data[i+5],precvframe->u.hdr.rx_data[i+6],precvframe->u.hdr.rx_data[i+7]); } printk("\n-----packet end-----\n"); }*/ RT_TRACE(_module_rtl871x_recv_c_,_drv_info_,("\n precvframe->u.hdr.rx_head=%p precvframe->u.hdr.rx_data=%p precvframe->u.hdr.rx_tail=%p precvframe->u.hdr.rx_end=%p\n",precvframe->u.hdr.rx_head,precvframe->u.hdr.rx_data,precvframe->u.hdr.rx_tail,precvframe->u.hdr.rx_end)); RT_TRACE(_module_rtl871x_recv_c_,_drv_info_,("\npkt_offset=%d [1]\n",pkt_offset)); pkt_offset = _RND512(pkt_offset); RT_TRACE(_module_rtl871x_recv_c_,_drv_info_,("\npkt_offset=%d [2] transfer_len=%d\n",pkt_offset,transfer_len)); transfer_len -= pkt_offset; RT_TRACE(_module_rtl871x_recv_c_,_drv_info_,("\n transfer_len=%d \n",transfer_len)); pbuf += pkt_offset; if (transfer_len > 0) precvbuf->ref_cnt++; plast_recvframe = precvframe; precvframe = NULL; } while (transfer_len > 0); if (plast_recvframe != NULL) { if (rtw_recv_entry(plast_recvframe) != _SUCCESS) { RT_TRACE(_module_rtl871x_recv_c_,_drv_info_,("recvbuf2recvframe(), rtw_recv_entry(precvframe) != _SUCCESS\n")); } } dev_kfree_skb_any(precvbuf->pskb); precvbuf->pskb = NULL; return _SUCCESS; }