s32 rtl8812au_xmitframe_complete(_adapter *padapter, struct xmit_priv *pxmitpriv, struct xmit_buf *pxmitbuf) { HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter); struct xmit_frame *pxmitframe = NULL; struct xmit_frame *pfirstframe = NULL; // aggregate variable struct hw_xmit *phwxmit; struct sta_info *psta = NULL; struct tx_servq *ptxservq = NULL; _irqL irqL; _list *xmitframe_plist = NULL, *xmitframe_phead = NULL; u32 pbuf; // next pkt address u32 pbuf_tail; // last pkt tail u32 len; // packet length, except TXDESC_SIZE and PKT_OFFSET u32 bulkSize = pHalData->UsbBulkOutSize; u8 descCount; u32 bulkPtr; // dump frame variable u32 ff_hwaddr; #ifndef IDEA_CONDITION int res = _SUCCESS; #endif RT_TRACE(_module_rtl8192c_xmit_c_, _drv_info_, ("+xmitframe_complete\n")); // check xmitbuffer is ok if (pxmitbuf == NULL) { pxmitbuf = rtw_alloc_xmitbuf(pxmitpriv); if (pxmitbuf == NULL){ //DBG_871X("%s #1, connot alloc xmitbuf!!!! \n",__FUNCTION__); return _FALSE; } } //DBG_8192C("%s ===================================== \n",__FUNCTION__); //3 1. pick up first frame do { rtw_free_xmitframe(pxmitpriv, pxmitframe); pxmitframe = rtw_dequeue_xframe(pxmitpriv, pxmitpriv->hwxmits, pxmitpriv->hwxmit_entry); if (pxmitframe == NULL) { // no more xmit frame, release xmit buffer //DBG_8192C("no more xmit frame ,return\n"); rtw_free_xmitbuf(pxmitpriv, pxmitbuf); return _FALSE; } #ifndef IDEA_CONDITION if (pxmitframe->frame_tag != DATA_FRAMETAG) { RT_TRACE(_module_rtl8192c_xmit_c_, _drv_err_, ("xmitframe_complete: frame tag(%d) is not DATA_FRAMETAG(%d)!\n", pxmitframe->frame_tag, DATA_FRAMETAG)); // rtw_free_xmitframe(pxmitpriv, pxmitframe); continue; } // TID 0~15 if ((pxmitframe->attrib.priority < 0) || (pxmitframe->attrib.priority > 15)) { RT_TRACE(_module_rtl8192c_xmit_c_, _drv_err_, ("xmitframe_complete: TID(%d) should be 0~15!\n", pxmitframe->attrib.priority)); // rtw_free_xmitframe(pxmitpriv, pxmitframe); continue; } #endif //DBG_8192C("==> pxmitframe->attrib.priority:%d\n",pxmitframe->attrib.priority); pxmitframe->pxmitbuf = pxmitbuf; pxmitframe->buf_addr = pxmitbuf->pbuf; pxmitbuf->priv_data = pxmitframe; pxmitframe->agg_num = 1; // alloc xmitframe should assign to 1. #ifdef CONFIG_TX_EARLY_MODE pxmitframe->pkt_offset = (PACKET_OFFSET_SZ/8)+1; // 2; // first frame of aggregation, reserve one offset for EM info ,another for usb bulk-out block check #else pxmitframe->pkt_offset = (PACKET_OFFSET_SZ/8); // 1; // first frame of aggregation, reserve offset #endif if (rtw_xmitframe_coalesce(padapter, pxmitframe->pkt, pxmitframe) == _FALSE) { DBG_871X("%s coalesce 1st xmitframe failed \n",__FUNCTION__); continue; } // always return ndis_packet after rtw_xmitframe_coalesce rtw_os_xmit_complete(padapter, pxmitframe); break; } while (1); //3 2. aggregate same priority and same DA(AP or STA) frames pfirstframe = pxmitframe; len = xmitframe_need_length(pfirstframe) + TXDESC_SIZE+(pfirstframe->pkt_offset*PACKET_OFFSET_SZ); pbuf_tail = len; pbuf = _RND8(pbuf_tail); // check pkt amount in one bulk descCount = 0; bulkPtr = bulkSize; if (pbuf < bulkPtr) descCount++; if (descCount == pHalData->UsbTxAggDescNum) goto agg_end; else { descCount = 0; bulkPtr = ((pbuf / bulkSize) + 1) * bulkSize; // round to next bulkSize } // dequeue same priority packet from station tx queue psta = pfirstframe->attrib.psta; switch (pfirstframe->attrib.priority) { case 1: case 2: ptxservq = &(psta->sta_xmitpriv.bk_q); phwxmit = pxmitpriv->hwxmits + 3; break; case 4: case 5: ptxservq = &(psta->sta_xmitpriv.vi_q); phwxmit = pxmitpriv->hwxmits + 1; break; case 6: case 7: ptxservq = &(psta->sta_xmitpriv.vo_q); phwxmit = pxmitpriv->hwxmits; break; case 0: case 3: default: ptxservq = &(psta->sta_xmitpriv.be_q); phwxmit = pxmitpriv->hwxmits + 2; break; } //DBG_8192C("==> pkt_no=%d,pkt_len=%d,len=%d,RND8_LEN=%d,pkt_offset=0x%02x\n", //pxmitframe->agg_num,pxmitframe->attrib.last_txcmdsz,len,pbuf,pxmitframe->pkt_offset ); _enter_critical_bh(&pxmitpriv->lock, &irqL); xmitframe_phead = get_list_head(&ptxservq->sta_pending); xmitframe_plist = get_next(xmitframe_phead); while (rtw_end_of_queue_search(xmitframe_phead, xmitframe_plist) == _FALSE) { pxmitframe = LIST_CONTAINOR(xmitframe_plist, struct xmit_frame, list); xmitframe_plist = get_next(xmitframe_plist); if(_FAIL == rtw_hal_busagg_qsel_check(padapter,pfirstframe->attrib.qsel,pxmitframe->attrib.qsel)) break; pxmitframe->agg_num = 0; // not first frame of aggregation #ifdef CONFIG_TX_EARLY_MODE pxmitframe->pkt_offset = 1;// not first frame of aggregation,reserve offset for EM Info #else pxmitframe->pkt_offset = 0; // not first frame of aggregation, no need to reserve offset #endif len = xmitframe_need_length(pxmitframe) + TXDESC_SIZE +(pxmitframe->pkt_offset*PACKET_OFFSET_SZ); if (_RND8(pbuf + len) > MAX_XMITBUF_SZ) //if (_RND8(pbuf + len) > (MAX_XMITBUF_SZ/2))//to do : for TX TP finial tune , Georgia 2012-0323 { //DBG_8192C("%s....len> MAX_XMITBUF_SZ\n",__FUNCTION__); pxmitframe->agg_num = 1; pxmitframe->pkt_offset = 1; break; } rtw_list_delete(&pxmitframe->list); ptxservq->qcnt--; phwxmit->accnt--; #ifndef IDEA_CONDITION // suppose only data frames would be in queue if (pxmitframe->frame_tag != DATA_FRAMETAG) { RT_TRACE(_module_rtl8192c_xmit_c_, _drv_err_, ("xmitframe_complete: frame tag(%d) is not DATA_FRAMETAG(%d)!\n", pxmitframe->frame_tag, DATA_FRAMETAG)); rtw_free_xmitframe(pxmitpriv, pxmitframe); continue; } // TID 0~15 if ((pxmitframe->attrib.priority < 0) || (pxmitframe->attrib.priority > 15)) { RT_TRACE(_module_rtl8192c_xmit_c_, _drv_err_, ("xmitframe_complete: TID(%d) should be 0~15!\n", pxmitframe->attrib.priority)); rtw_free_xmitframe(pxmitpriv, pxmitframe); continue; } #endif // pxmitframe->pxmitbuf = pxmitbuf; pxmitframe->buf_addr = pxmitbuf->pbuf + pbuf; if (rtw_xmitframe_coalesce(padapter, pxmitframe->pkt, pxmitframe) == _FALSE) { DBG_871X("%s coalesce failed \n",__FUNCTION__); rtw_free_xmitframe(pxmitpriv, pxmitframe); continue; } //DBG_8192C("==> pxmitframe->attrib.priority:%d\n",pxmitframe->attrib.priority); // always return ndis_packet after rtw_xmitframe_coalesce rtw_os_xmit_complete(padapter, pxmitframe); // (len - TXDESC_SIZE) == pxmitframe->attrib.last_txcmdsz update_txdesc(pxmitframe, pxmitframe->buf_addr, pxmitframe->attrib.last_txcmdsz,_TRUE); // don't need xmitframe any more rtw_free_xmitframe(pxmitpriv, pxmitframe); // handle pointer and stop condition pbuf_tail = pbuf + len; pbuf = _RND8(pbuf_tail); pfirstframe->agg_num++; #ifdef CONFIG_TX_EARLY_MODE pxmitpriv->agg_pkt[pfirstframe->agg_num-1].offset = _RND8(len); pxmitpriv->agg_pkt[pfirstframe->agg_num-1].pkt_len = pxmitframe->attrib.last_txcmdsz; #endif if (MAX_TX_AGG_PACKET_NUMBER == pfirstframe->agg_num) break; if (pbuf < bulkPtr) { descCount++; if (descCount == pHalData->UsbTxAggDescNum) break; } else { descCount = 0; bulkPtr = ((pbuf / bulkSize) + 1) * bulkSize; } }//end while( aggregate same priority and same DA(AP or STA) frames) if (_rtw_queue_empty(&ptxservq->sta_pending) == _TRUE) rtw_list_delete(&ptxservq->tx_pending); _exit_critical_bh(&pxmitpriv->lock, &irqL); agg_end: #ifdef CONFIG_80211N_HT if ((pfirstframe->attrib.ether_type != 0x0806) && (pfirstframe->attrib.ether_type != 0x888e) && (pfirstframe->attrib.ether_type != 0x88b4) && (pfirstframe->attrib.dhcp_pkt != 1)) { rtw_issue_addbareq_cmd(padapter, pfirstframe); } #endif //CONFIG_80211N_HT #ifndef CONFIG_USE_USB_BUFFER_ALLOC_TX //3 3. update first frame txdesc if ((PACKET_OFFSET_SZ != 0) && ((pbuf_tail % bulkSize) == 0)) { // remove pkt_offset pbuf_tail -= PACKET_OFFSET_SZ; pfirstframe->buf_addr += PACKET_OFFSET_SZ; pfirstframe->pkt_offset--; //DBG_8192C("$$$$$ buf size equal to USB block size $$$$$$\n"); } #endif // CONFIG_USE_USB_BUFFER_ALLOC_TX update_txdesc(pfirstframe, pfirstframe->buf_addr, pfirstframe->attrib.last_txcmdsz,_TRUE); #ifdef CONFIG_TX_EARLY_MODE //prepare EM info for first frame, agg_num value start from 1 pxmitpriv->agg_pkt[0].offset = _RND8(pfirstframe->attrib.last_txcmdsz +TXDESC_SIZE +(pfirstframe->pkt_offset*PACKET_OFFSET_SZ)); pxmitpriv->agg_pkt[0].pkt_len = pfirstframe->attrib.last_txcmdsz;//get from rtw_xmitframe_coalesce UpdateEarlyModeInfo8812(pxmitpriv,pxmitbuf ); #endif //3 4. write xmit buffer to USB FIFO ff_hwaddr = rtw_get_ff_hwaddr(pfirstframe); //DBG_8192C("%s ===================================== write port,buf_size(%d) \n",__FUNCTION__,pbuf_tail); // xmit address == ((xmit_frame*)pxmitbuf->priv_data)->buf_addr rtw_write_port(padapter, ff_hwaddr, pbuf_tail, (u8*)pxmitbuf); //3 5. update statisitc pbuf_tail -= (pfirstframe->agg_num * TXDESC_SIZE); pbuf_tail -= (pfirstframe->pkt_offset * PACKET_OFFSET_SZ); rtw_count_tx_stats(padapter, pfirstframe, pbuf_tail); rtw_free_xmitframe(pxmitpriv, pfirstframe); return _TRUE; }
static int recvbuf2recvframe(struct rtl_priv *rtlpriv, struct sk_buff *pskb) { uint8_t *pbuf; uint8_t pkt_cnt = 0; uint32_t pkt_offset; int32_t transfer_len; uint8_t *pphy_status = NULL; struct recv_frame *precvframe = NULL; struct rx_pkt_attrib *pattrib = NULL; struct _rtw_hal *pHalData = GET_HAL_DATA(rtlpriv); struct recv_priv *precvpriv = &rtlpriv->recvpriv; struct __queue *pfree_recv_queue = &precvpriv->free_recv_queue; transfer_len = (int32_t)pskb->len; pbuf = pskb->data; #ifdef CONFIG_USB_RX_AGGREGATION pkt_cnt = GET_RX_STATUS_DESC_USB_AGG_PKTNUM(pbuf); #endif do { precvframe = rtw_alloc_recvframe(pfree_recv_queue); if (precvframe == NULL) { DBG_8192C("%s()-%d: rtw_alloc_recvframe() failed! RX Drop!\n", __FUNCTION__, __LINE__); goto _exit_recvbuf2recvframe; } INIT_LIST_HEAD(&precvframe->list); precvframe->precvbuf = NULL; /* can't access the precvbuf for new arch. */ precvframe->len = 0; rtl8812_query_rx_desc_status(rtlpriv, &precvframe->attrib, precvframe, pbuf); pattrib = &precvframe->attrib; if ((pattrib->crc_err) || (pattrib->icv_err)) { DBG_8192C("%s: RX Warning! crc_err=%d icv_err=%d, skip!\n", __FUNCTION__, pattrib->crc_err, pattrib->icv_err); rtw_free_recvframe(precvframe, pfree_recv_queue); goto _exit_recvbuf2recvframe; } pkt_offset = RXDESC_SIZE + pattrib->drvinfo_sz + pattrib->shift_sz + pattrib->pkt_len; if ((pattrib->pkt_len <= 0) || (pkt_offset > transfer_len)) { DBG_8192C("%s()-%d: RX Warning!,pkt_len<=0 or pkt_offset> transfer_len \n", __FUNCTION__, __LINE__); rtw_free_recvframe(precvframe, pfree_recv_queue); goto _exit_recvbuf2recvframe; } if (rtw_os_alloc_recvframe(rtlpriv, precvframe, (pbuf+pattrib->shift_sz + pattrib->drvinfo_sz + RXDESC_SIZE), pskb) == _FAIL) { rtw_free_recvframe(precvframe, pfree_recv_queue); goto _exit_recvbuf2recvframe; } recvframe_put(precvframe, pattrib->pkt_len); /* recvframe_pull(precvframe, drvinfo_sz + RXDESC_SIZE); */ if (pattrib->pkt_rpt_type == NORMAL_RX) { /* Normal rx packet */ if (pattrib->physt) pphy_status = (pbuf + RXDESC_OFFSET); if (pattrib->physt && pphy_status) rtl8812_query_rx_phy_status(precvframe, pphy_status); if (rtw_recv_entry(precvframe) != _SUCCESS) { ; } } else { /* pkt_rpt_type == TX_REPORT1-CCX, TX_REPORT2-TX RTP,HIS_REPORT-USB HISR RTP */ if (pattrib->pkt_rpt_type == C2H_PACKET) { /* DBG_8192C("rx C2H_PACKET \n"); */ /* C2HPacketHandler_8812A(rtlpriv,precvframe->u.hdr.rx_data,pattrib->pkt_len); */ } /* enqueue recvframe to txrtp queue */ else if (pattrib->pkt_rpt_type == TX_REPORT1) { DBG_8192C("rx CCX \n"); } else if (pattrib->pkt_rpt_type == TX_REPORT2) { /* DBG_8192C("rx TX RPT \n"); */ } /*else if(pattrib->pkt_rpt_type == HIS_REPORT) { //DBG_8192C("%s , rx USB HISR \n",__FUNCTION__); }*/ rtw_free_recvframe(precvframe, pfree_recv_queue); } #ifdef CONFIG_USB_RX_AGGREGATION /* jaguar 8-byte alignment */ pkt_offset = (u16)_RND8(pkt_offset); pkt_cnt--; pbuf += pkt_offset; #endif transfer_len -= pkt_offset; precvframe = NULL; } while (transfer_len > 0); _exit_recvbuf2recvframe: return _SUCCESS; }
int recvbuf2recvframe(PADAPTER padapter, void *ptr) { u8 *pbuf; u8 pkt_cnt = 0; u32 pkt_offset; s32 transfer_len; u8 *pdata, *pphy_status; union recv_frame *precvframe = NULL; struct rx_pkt_attrib *pattrib = NULL; PHAL_DATA_TYPE pHalData; struct recv_priv *precvpriv; _queue *pfree_recv_queue; _pkt *pskb; pHalData = GET_HAL_DATA(padapter); precvpriv = &padapter->recvpriv; pfree_recv_queue = &precvpriv->free_recv_queue; #ifdef CONFIG_USE_USB_BUFFER_ALLOC_RX pskb = NULL; transfer_len = (s32)((struct recv_buf*)ptr)->transfer_len; pbuf = ((struct recv_buf*)ptr)->pbuf; #else // !CONFIG_USE_USB_BUFFER_ALLOC_RX pskb = (_pkt*)ptr; transfer_len = (s32)pskb->len; pbuf = pskb->data; #endif // !CONFIG_USE_USB_BUFFER_ALLOC_RX #ifdef CONFIG_USB_RX_AGGREGATION pkt_cnt = GET_RX_STATUS_DESC_USB_AGG_PKTNUM_8723B(pbuf); #endif do { precvframe = rtw_alloc_recvframe(pfree_recv_queue); if (precvframe == NULL) { DBG_8192C("%s: rtw_alloc_recvframe() failed! RX Drop!\n", __FUNCTION__); goto _exit_recvbuf2recvframe; } if (transfer_len >1500) _rtw_init_listhead(&precvframe->u.hdr.list); precvframe->u.hdr.precvbuf = NULL; //can't access the precvbuf for new arch. precvframe->u.hdr.len = 0; rtl8723b_query_rx_desc_status(precvframe, pbuf); pattrib = &precvframe->u.hdr.attrib; if ((padapter->registrypriv.mp_mode == 0) && ((pattrib->crc_err) || (pattrib->icv_err))) { DBG_8192C("%s: RX Warning! crc_err=%d icv_err=%d, skip!\n", __FUNCTION__, pattrib->crc_err, pattrib->icv_err); rtw_free_recvframe(precvframe, pfree_recv_queue); goto _exit_recvbuf2recvframe; } pkt_offset = RXDESC_SIZE + pattrib->drvinfo_sz + pattrib->shift_sz + pattrib->pkt_len; if ((pattrib->pkt_len <= 0) || (pkt_offset > transfer_len)) { DBG_8192C("%s: RX Error! pkt_len=%d pkt_offset=%d transfer_len=%d\n", __FUNCTION__, pattrib->pkt_len, pkt_offset, transfer_len); rtw_free_recvframe(precvframe, pfree_recv_queue); goto _exit_recvbuf2recvframe; } pdata = pbuf + RXDESC_SIZE + pattrib->drvinfo_sz + pattrib->shift_sz; if (rtw_os_alloc_recvframe(padapter, precvframe, pdata, pskb) == _FAIL) { DBG_8192C("%s: RX Error! rtw_os_alloc_recvframe FAIL!\n", __FUNCTION__); rtw_free_recvframe(precvframe, pfree_recv_queue); goto _exit_recvbuf2recvframe; } recvframe_put(precvframe, pattrib->pkt_len); if (pattrib->pkt_rpt_type == NORMAL_RX) { if (pattrib->physt) pphy_status = pbuf + RXDESC_OFFSET; else pphy_status = NULL; #ifdef CONFIG_CONCURRENT_MODE if (rtw_buddy_adapter_up(padapter)) { if (pre_recv_entry(precvframe, pphy_status) != _SUCCESS) { // Return fail except data frame //DBG_8192C("%s: RX Error! (concurrent)pre_recv_entry FAIL!\n", __FUNCTION__); } } #endif // CONFIG_CONCURRENT_MODE if (pphy_status) rx_query_phy_status(precvframe, pphy_status); if (rtw_recv_entry(precvframe) != _SUCCESS) { // Return fail except data frame //DBG_8192C("%s: RX Error! rtw_recv_entry FAIL!\n", __FUNCTION__); } } 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 // CONFIG_C2H_PACKET_EN rtw_free_recvframe(precvframe, pfree_recv_queue); } #ifdef CONFIG_USB_RX_AGGREGATION // jaguar 8-byte alignment pkt_offset = (u16)_RND8(pkt_offset); pkt_cnt--; pbuf += pkt_offset; #endif transfer_len -= pkt_offset; precvframe = NULL; } while (transfer_len > 0); _exit_recvbuf2recvframe: return _SUCCESS; }
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; _irqL irql; u8 *ptr; u32 pkt_len, pkt_offset, skb_len, alloc_sz; _pkt *pkt_copy = NULL; u8 shift_sz = 0, rx_report_sz = 0; 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) { DBG_8192C("%s: no enough recv frame!\n", __FUNCTION__); 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; } //rx desc parsing rtl8723b_query_rx_desc_status(precvframe, ptr); pattrib = &precvframe->u.hdr.attrib; // fix Hardware RX data error, drop whole recv_buffer if ((!(pHalData->ReceiveConfig & RCR_ACRC32)) && pattrib->crc_err) { #if !(MP_DRIVER==1) DBG_8192C("%s()-%d: RX Warning! rx CRC ERROR !!\n", __FUNCTION__, __LINE__); #endif rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue); break; } rx_report_sz = RXDESC_SIZE + pattrib->drvinfo_sz; pkt_offset = rx_report_sz + pattrib->shift_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)) { #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 { // Modified by Albert 20101213 // For 8 bytes IP header alignment. if (pattrib->qos) // Qos data, wireless lan header length is 26 { shift_sz = 6; } else { shift_sz = 0; } skb_len = pattrib->pkt_len; // for first fragment packet, driver need allocate 1536+drvinfo_sz+RXDESC_SIZE to defrag packet. // modify alloc_sz for recvive crc error packet by thomas 2011-06-02 if((pattrib->mfrag == 1)&&(pattrib->frag_num == 0)){ //alloc_sz = 1664; //1664 is 128 alignment. if(skb_len <= 1650) alloc_sz = 1664; else alloc_sz = skb_len + 14; } else { alloc_sz = skb_len; // 6 is for IP header 8 bytes alignment in QoS packet case. // 8 is for skb->data 4 bytes alignment. alloc_sz += 14; } pkt_copy = rtw_skb_alloc(alloc_sz); if (pkt_copy) { pkt_copy->dev = padapter->pnetdev; precvframe->u.hdr.pkt = pkt_copy; skb_reserve( pkt_copy, 8 - ((SIZE_PTR)( pkt_copy->data ) & 7 ));//force pkt_copy->data at 8-byte alignment address skb_reserve( pkt_copy, shift_sz );//force ip_hdr at 8-byte alignment address according to shift_sz. _rtw_memcpy(pkt_copy->data, (ptr + rx_report_sz + pattrib->shift_sz), skb_len); precvframe->u.hdr.rx_head = pkt_copy->head; precvframe->u.hdr.rx_data = precvframe->u.hdr.rx_tail = pkt_copy->data; precvframe->u.hdr.rx_end = skb_end_pointer(pkt_copy); } else { if((pattrib->mfrag == 1)&&(pattrib->frag_num == 0)) { DBG_8192C("%s: alloc_skb fail, drop frag frame\n", __FUNCTION__); rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue); break; } precvframe->u.hdr.pkt = rtw_skb_clone(precvbuf->pskb); if(precvframe->u.hdr.pkt) { _pkt *pkt_clone = precvframe->u.hdr.pkt; pkt_clone->data = ptr + rx_report_sz + pattrib->shift_sz; skb_reset_tail_pointer(pkt_clone); precvframe->u.hdr.rx_head = precvframe->u.hdr.rx_data = precvframe->u.hdr.rx_tail = pkt_clone->data; precvframe->u.hdr.rx_end = pkt_clone->data + skb_len; } else { DBG_8192C("%s: rtw_skb_clone fail\n", __FUNCTION__); rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue); break; } } recvframe_put(precvframe, skb_len); //recvframe_pull(precvframe, drvinfo_sz + RXDESC_SIZE); 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) { // skip the rx packet with abnormal length if (pattrib->pkt_len < 14 || pattrib->pkt_len > 8192) { DBG_8192C("skip abnormal rx packet(%d)\n", pattrib->pkt_len); rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue); break; } #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_dump_, ("%s: rtw_recv_entry(precvframe) != _SUCCESS\n",__FUNCTION__)); } } } 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; precvframe = NULL; pkt_copy = 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); }
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 rx_pkt_attrib *pattrib; u8 *ptr; u32 pkt_offset, skb_len, alloc_sz; _pkt *pkt_copy = NULL; u8 shift_sz = 0, rx_report_sz = 0; 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) { DBG_8192C("%s: no enough recv frame!\n", __FUNCTION__); 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. */ tasklet_schedule(&precvpriv->recv_tasklet); return; } /* rx desc parsing */ update_recvframe_attrib(padapter, precvframe, (struct recv_stat*)ptr); pattrib = &precvframe->u.hdr.attrib; /* 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; } rx_report_sz = RXDESC_SIZE + pattrib->drvinfo_sz; pkt_offset = rx_report_sz + pattrib->shift_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 { /* Modified by Albert 20101213 */ /* For 8 bytes IP header alignment. */ if (pattrib->qos) /* Qos data, wireless lan header length is 26 */ { shift_sz = 6; } else { shift_sz = 0; } skb_len = pattrib->pkt_len; /* for first fragment packet, driver need allocate 1536+drvinfo_sz+RXDESC_SIZE to defrag packet. */ /* modify alloc_sz for recvive crc error packet by thomas 2011-06-02 */ if ((pattrib->mfrag == 1)&&(pattrib->frag_num == 0)){ if (skb_len <= 1650) alloc_sz = 1664; else alloc_sz = skb_len + 14; } else { alloc_sz = skb_len; /* 6 is for IP header 8 bytes alignment in QoS packet case. */ /* 8 is for skb->data 4 bytes alignment. */ alloc_sz += 14; } pkt_copy = rtw_skb_alloc(alloc_sz); if (pkt_copy) { pkt_copy->dev = padapter->pnetdev; precvframe->u.hdr.pkt = pkt_copy; skb_reserve(pkt_copy, 8 - ((SIZE_PTR)(pkt_copy->data) & 7));/* force pkt_copy->data at 8-byte alignment address */ skb_reserve(pkt_copy, shift_sz);/* force ip_hdr at 8-byte alignment address according to shift_sz. */ memcpy(pkt_copy->data, (ptr + rx_report_sz + pattrib->shift_sz), skb_len); precvframe->u.hdr.rx_head = pkt_copy->head; precvframe->u.hdr.rx_data = precvframe->u.hdr.rx_tail = pkt_copy->data; precvframe->u.hdr.rx_end = skb_end_pointer(pkt_copy); } else { if ((pattrib->mfrag == 1)&&(pattrib->frag_num == 0)) { DBG_8192C("%s: alloc_skb fail, drop frag frame\n", __FUNCTION__); rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue); break; } precvframe->u.hdr.pkt = rtw_skb_clone(precvbuf->pskb); if (precvframe->u.hdr.pkt) { _pkt *pkt_clone = precvframe->u.hdr.pkt; pkt_clone->data = ptr + rx_report_sz + pattrib->shift_sz; skb_reset_tail_pointer(pkt_clone); precvframe->u.hdr.rx_head = precvframe->u.hdr.rx_data = precvframe->u.hdr.rx_tail = pkt_clone->data; precvframe->u.hdr.rx_end = pkt_clone->data + skb_len; } else { DBG_8192C("%s: rtw_skb_clone fail\n", __FUNCTION__); rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue); break; } } recvframe_put(precvframe, skb_len); /* recvframe_pull(precvframe, drvinfo_sz + RXDESC_SIZE); */ 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)/* Normal rx packet */ { if (pattrib->physt) update_recvframe_phyinfo(precvframe, (struct phy_stat*)ptr); if (rtw_recv_entry(precvframe) != _SUCCESS) { RT_TRACE(_module_rtl871x_recv_c_, _drv_dump_, ("%s: rtw_recv_entry(precvframe) != _SUCCESS\n", __FUNCTION__)); } } else if (pattrib->pkt_rpt_type == C2H_PACKET) { C2H_EVT_HDR C2hEvent; u16 len_c2h = pattrib->pkt_len; u8 *pbuf_c2h = precvframe->u.hdr.rx_data; u8 *pdata_c2h; C2hEvent.CmdID = pbuf_c2h[0]; C2hEvent.CmdSeq = pbuf_c2h[1]; C2hEvent.CmdLen = (len_c2h -2); pdata_c2h = pbuf_c2h+2; if (C2hEvent.CmdID == C2H_CCX_TX_RPT) { CCX_FwC2HTxRpt_8723b(padapter, pdata_c2h, C2hEvent.CmdLen); } else { rtl8723bs_c2h_packet_handler(padapter, precvframe->u.hdr.rx_data, pattrib->pkt_len); } rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue); } } pkt_offset = _RND8(pkt_offset); precvbuf->pdata += pkt_offset; ptr = precvbuf->pdata; precvframe = NULL; pkt_copy = NULL; } rtw_enqueue_recvbuf(precvbuf, &precvpriv->free_recv_buf_queue); } while (1); }
s32 rtl8188eu_xmitframe_complete(struct adapter *adapt, struct xmit_priv *pxmitpriv, struct xmit_buf *pxmitbuf) { struct hal_data_8188e *haldata = GET_HAL_DATA(adapt); struct xmit_frame *pxmitframe = NULL; struct xmit_frame *pfirstframe = NULL; /* aggregate variable */ struct hw_xmit *phwxmit; struct sta_info *psta = NULL; struct tx_servq *ptxservq = NULL; struct list_head *xmitframe_plist = NULL, *xmitframe_phead = NULL; u32 pbuf; /* next pkt address */ u32 pbuf_tail; /* last pkt tail */ u32 len; /* packet length, except TXDESC_SIZE and PKT_OFFSET */ u32 bulksize = haldata->UsbBulkOutSize; u8 desc_cnt; u32 bulkptr; /* dump frame variable */ u32 ff_hwaddr; RT_TRACE(_module_rtl8192c_xmit_c_, _drv_info_, ("+xmitframe_complete\n")); /* check xmitbuffer is ok */ if (pxmitbuf == NULL) { pxmitbuf = rtw_alloc_xmitbuf(pxmitpriv); if (pxmitbuf == NULL) return false; } /* 3 1. pick up first frame */ do { rtw_free_xmitframe(pxmitpriv, pxmitframe); pxmitframe = rtw_dequeue_xframe(pxmitpriv, pxmitpriv->hwxmits, pxmitpriv->hwxmit_entry); if (pxmitframe == NULL) { /* no more xmit frame, release xmit buffer */ rtw_free_xmitbuf(pxmitpriv, pxmitbuf); return false; } pxmitframe->pxmitbuf = pxmitbuf; pxmitframe->buf_addr = pxmitbuf->pbuf; pxmitbuf->priv_data = pxmitframe; pxmitframe->agg_num = 1; /* alloc xmitframe should assign to 1. */ pxmitframe->pkt_offset = 1; /* first frame of aggregation, reserve offset */ rtw_xmitframe_coalesce(adapt, pxmitframe->pkt, pxmitframe); /* always return ndis_packet after rtw_xmitframe_coalesce */ rtw_os_xmit_complete(adapt, pxmitframe); break; } while (1); /* 3 2. aggregate same priority and same DA(AP or STA) frames */ pfirstframe = pxmitframe; len = xmitframe_need_length(pfirstframe) + TXDESC_SIZE + (pfirstframe->pkt_offset*PACKET_OFFSET_SZ); pbuf_tail = len; pbuf = _RND8(pbuf_tail); /* check pkt amount in one bulk */ desc_cnt = 0; bulkptr = bulksize; if (pbuf < bulkptr) { desc_cnt++; } else { desc_cnt = 0; bulkptr = ((pbuf / bulksize) + 1) * bulksize; /* round to next bulksize */ } /* dequeue same priority packet from station tx queue */ psta = pfirstframe->attrib.psta; switch (pfirstframe->attrib.priority) { case 1: case 2: ptxservq = &(psta->sta_xmitpriv.bk_q); phwxmit = pxmitpriv->hwxmits + 3; break; case 4: case 5: ptxservq = &(psta->sta_xmitpriv.vi_q); phwxmit = pxmitpriv->hwxmits + 1; break; case 6: case 7: ptxservq = &(psta->sta_xmitpriv.vo_q); phwxmit = pxmitpriv->hwxmits; break; case 0: case 3: default: ptxservq = &(psta->sta_xmitpriv.be_q); phwxmit = pxmitpriv->hwxmits + 2; break; } spin_lock_bh(&pxmitpriv->lock); xmitframe_phead = get_list_head(&ptxservq->sta_pending); xmitframe_plist = xmitframe_phead->next; while (xmitframe_phead != xmitframe_plist) { pxmitframe = container_of(xmitframe_plist, struct xmit_frame, list); xmitframe_plist = xmitframe_plist->next; pxmitframe->agg_num = 0; /* not first frame of aggregation */ pxmitframe->pkt_offset = 0; /* not first frame of aggregation, no need to reserve offset */ len = xmitframe_need_length(pxmitframe) + TXDESC_SIZE + (pxmitframe->pkt_offset*PACKET_OFFSET_SZ); if (_RND8(pbuf + len) > MAX_XMITBUF_SZ) { pxmitframe->agg_num = 1; pxmitframe->pkt_offset = 1; break; } list_del_init(&pxmitframe->list); ptxservq->qcnt--; phwxmit->accnt--; pxmitframe->buf_addr = pxmitbuf->pbuf + pbuf; rtw_xmitframe_coalesce(adapt, pxmitframe->pkt, pxmitframe); /* always return ndis_packet after rtw_xmitframe_coalesce */ rtw_os_xmit_complete(adapt, pxmitframe); /* (len - TXDESC_SIZE) == pxmitframe->attrib.last_txcmdsz */ update_txdesc(pxmitframe, pxmitframe->buf_addr, pxmitframe->attrib.last_txcmdsz, true); /* don't need xmitframe any more */ rtw_free_xmitframe(pxmitpriv, pxmitframe); /* handle pointer and stop condition */ pbuf_tail = pbuf + len; pbuf = _RND8(pbuf_tail); pfirstframe->agg_num++; if (MAX_TX_AGG_PACKET_NUMBER == pfirstframe->agg_num) break; if (pbuf < bulkptr) { desc_cnt++; if (desc_cnt == haldata->UsbTxAggDescNum) break; } else { desc_cnt = 0; bulkptr = ((pbuf / bulksize) + 1) * bulksize; } } /* end while (aggregate same priority and same DA(AP or STA) frames) */ if (list_empty(&ptxservq->sta_pending.queue)) list_del_init(&ptxservq->tx_pending); spin_unlock_bh(&pxmitpriv->lock); if ((pfirstframe->attrib.ether_type != 0x0806) && (pfirstframe->attrib.ether_type != 0x888e) && (pfirstframe->attrib.ether_type != 0x88b4) && (pfirstframe->attrib.dhcp_pkt != 1)) rtw_issue_addbareq_cmd(adapt, pfirstframe); /* 3 3. update first frame txdesc */ if ((pbuf_tail % bulksize) == 0) { /* remove pkt_offset */ pbuf_tail -= PACKET_OFFSET_SZ; pfirstframe->buf_addr += PACKET_OFFSET_SZ; pfirstframe->pkt_offset--; } update_txdesc(pfirstframe, pfirstframe->buf_addr, pfirstframe->attrib.last_txcmdsz, true); /* 3 4. write xmit buffer to USB FIFO */ ff_hwaddr = rtw_get_ff_hwaddr(pfirstframe); rtw_write_port(adapt, ff_hwaddr, pbuf_tail, (u8 *)pxmitbuf); /* 3 5. update statisitc */ pbuf_tail -= (pfirstframe->agg_num * TXDESC_SIZE); pbuf_tail -= (pfirstframe->pkt_offset * PACKET_OFFSET_SZ); rtw_count_tx_stats(adapt, pfirstframe, pbuf_tail); rtw_free_xmitframe(pxmitpriv, pfirstframe); return true; }
s32 rtl8192cu_xmitframe_complete(_adapter *padapter, struct xmit_priv *pxmitpriv, struct xmit_buf *pxmitbuf) { HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter); struct xmit_frame *pxmitframe = NULL; struct xmit_frame *pfirstframe = NULL; // aggregate variable struct hw_xmit *phwxmit; struct sta_info *psta = NULL; struct tx_servq *ptxservq = NULL; _irqL irqL; _list *xmitframe_plist = NULL, *xmitframe_phead = NULL; u32 pbuf; // next pkt address u32 pbuf_tail; // last pkt tail u32 len; // packet length, except TXDESC_SIZE and PKT_OFFSET u32 bulkSize = pHalData->UsbBulkOutSize; u8 descCount; u32 bulkPtr; // dump frame variable u32 ff_hwaddr; #ifndef IDEA_CONDITION int res = _SUCCESS; #endif RT_TRACE(_module_rtl8192c_xmit_c_, _drv_info_, ("+xmitframe_complete\n")); // check xmitbuffer is ok if (pxmitbuf == NULL) { pxmitbuf = rtw_alloc_xmitbuf(pxmitpriv); if (pxmitbuf == NULL) return _FALSE; } //3 1. pick up first frame do { rtw_free_xmitframe(pxmitpriv, pxmitframe); pxmitframe = rtw_dequeue_xframe(pxmitpriv, pxmitpriv->hwxmits, pxmitpriv->hwxmit_entry); if (pxmitframe == NULL) { // no more xmit frame, release xmit buffer rtw_free_xmitbuf(pxmitpriv, pxmitbuf); return _FALSE; } #ifndef IDEA_CONDITION if (pxmitframe->frame_tag != DATA_FRAMETAG) { RT_TRACE(_module_rtl8192c_xmit_c_, _drv_err_, ("xmitframe_complete: frame tag(%d) is not DATA_FRAMETAG(%d)!\n", pxmitframe->frame_tag, DATA_FRAMETAG)); // rtw_free_xmitframe(pxmitpriv, pxmitframe); continue; } // TID 0~15 if ((pxmitframe->attrib.priority < 0) || (pxmitframe->attrib.priority > 15)) { RT_TRACE(_module_rtl8192c_xmit_c_, _drv_err_, ("xmitframe_complete: TID(%d) should be 0~15!\n", pxmitframe->attrib.priority)); // rtw_free_xmitframe(pxmitpriv, pxmitframe); continue; } #endif pxmitframe->pxmitbuf = pxmitbuf; pxmitframe->buf_addr = pxmitbuf->pbuf; pxmitbuf->priv_data = pxmitframe; //pxmitframe->agg_num = 1; // alloc xmitframe should assign to 1. pxmitframe->pkt_offset = 1; // first frame of aggregation, reserve offset #ifdef IDEA_CONDITION rtw_xmitframe_coalesce(padapter, pxmitframe->pkt, pxmitframe); #else res = rtw_xmitframe_coalesce(padapter, pxmitframe->pkt, pxmitframe); if (res == _FALSE) { // rtw_free_xmitframe(pxmitpriv, pxmitframe); continue; } #endif // always return ndis_packet after rtw_xmitframe_coalesce rtw_os_xmit_complete(padapter, pxmitframe); break; } while (1); //3 2. aggregate same priority and same DA(AP or STA) frames pfirstframe = pxmitframe; len = xmitframe_need_length(pfirstframe) + TXDESC_OFFSET; pbuf_tail = len; pbuf = _RND8(pbuf_tail); // check pkt amount in one bluk descCount = 0; bulkPtr = bulkSize; if (pbuf < bulkPtr) descCount++; else { descCount = 0; bulkPtr = ((pbuf / bulkSize) + 1) * bulkSize; // round to next bulkSize } // dequeue same priority packet from station tx queue psta = pfirstframe->attrib.psta; switch (pfirstframe->attrib.priority) { case 1: case 2: ptxservq = &(psta->sta_xmitpriv.bk_q); phwxmit = pxmitpriv->hwxmits + 3; break; case 4: case 5: ptxservq = &(psta->sta_xmitpriv.vi_q); phwxmit = pxmitpriv->hwxmits + 1; break; case 6: case 7: ptxservq = &(psta->sta_xmitpriv.vo_q); phwxmit = pxmitpriv->hwxmits; break; case 0: case 3: default: ptxservq = &(psta->sta_xmitpriv.be_q); phwxmit = pxmitpriv->hwxmits + 2; break; } _enter_critical_bh(&pxmitpriv->lock, &irqL); xmitframe_phead = get_list_head(&ptxservq->sta_pending); xmitframe_plist = get_next(xmitframe_phead); while (rtw_end_of_queue_search(xmitframe_phead, xmitframe_plist) == _FALSE) { pxmitframe = LIST_CONTAINOR(xmitframe_plist, struct xmit_frame, list); xmitframe_plist = get_next(xmitframe_plist); len = xmitframe_need_length(pxmitframe) + TXDESC_SIZE; // no offset if (pbuf + len > MAX_XMITBUF_SZ) break; rtw_list_delete(&pxmitframe->list); ptxservq->qcnt--; phwxmit->accnt--; #ifndef IDEA_CONDITION // suppose only data frames would be in queue if (pxmitframe->frame_tag != DATA_FRAMETAG) { RT_TRACE(_module_rtl8192c_xmit_c_, _drv_err_, ("xmitframe_complete: frame tag(%d) is not DATA_FRAMETAG(%d)!\n", pxmitframe->frame_tag, DATA_FRAMETAG)); rtw_free_xmitframe(pxmitpriv, pxmitframe); continue; } // TID 0~15 if ((pxmitframe->attrib.priority < 0) || (pxmitframe->attrib.priority > 15)) { RT_TRACE(_module_rtl8192c_xmit_c_, _drv_err_, ("xmitframe_complete: TID(%d) should be 0~15!\n", pxmitframe->attrib.priority)); rtw_free_xmitframe(pxmitpriv, pxmitframe); continue; } #endif // pxmitframe->pxmitbuf = pxmitbuf; pxmitframe->buf_addr = pxmitbuf->pbuf + pbuf; pxmitframe->agg_num = 0; // not first frame of aggregation pxmitframe->pkt_offset = 0; // not first frame of aggregation, no need to reserve offset #ifdef IDEA_CONDITION rtw_xmitframe_coalesce(padapter, pxmitframe->pkt, pxmitframe); #else res = rtw_xmitframe_coalesce(padapter, pxmitframe->pkt, pxmitframe); if (res == _FALSE) { rtw_free_xmitframe(pxmitpriv, pxmitframe); continue; } #endif // always return ndis_packet after rtw_xmitframe_coalesce rtw_os_xmit_complete(padapter, pxmitframe); // (len - TXDESC_SIZE) == pxmitframe->attrib.last_txcmdsz update_txdesc(pxmitframe, pxmitframe->buf_addr, pxmitframe->attrib.last_txcmdsz, _TRUE); // don't need xmitframe any more rtw_free_xmitframe(pxmitpriv, pxmitframe); // handle pointer and stop condition pbuf_tail = pbuf + len; pbuf = _RND8(pbuf_tail); pfirstframe->agg_num++; if (MAX_TX_AGG_PACKET_NUMBER == pfirstframe->agg_num) break; if (pbuf < bulkPtr) { descCount++; if (descCount == pHalData->UsbTxAggDescNum) break; } else { descCount = 0; bulkPtr = ((pbuf / bulkSize) + 1) * bulkSize; } } if (_rtw_queue_empty(&ptxservq->sta_pending) == _TRUE) rtw_list_delete(&ptxservq->tx_pending); _exit_critical_bh(&pxmitpriv->lock, &irqL); if ((pfirstframe->attrib.ether_type != 0x0806) && (pfirstframe->attrib.ether_type != 0x888e) && (pfirstframe->attrib.dhcp_pkt != 1)) { rtw_issue_addbareq_cmd(padapter, pfirstframe); } #ifndef CONFIG_USE_USB_BUFFER_ALLOC_TX //3 3. update first frame txdesc if ((pbuf_tail % bulkSize) == 0) { // remove pkt_offset pbuf_tail -= PACKET_OFFSET_SZ; pfirstframe->buf_addr += PACKET_OFFSET_SZ; pfirstframe->pkt_offset = 0; } #endif // CONFIG_USE_USB_BUFFER_ALLOC_TX update_txdesc(pfirstframe, pfirstframe->buf_addr, pfirstframe->attrib.last_txcmdsz, _TRUE); //3 4. write xmit buffer to USB FIFO ff_hwaddr = rtw_get_ff_hwaddr(pfirstframe); // xmit address == ((xmit_frame*)pxmitbuf->priv_data)->buf_addr rtw_write_port(padapter, ff_hwaddr, pbuf_tail, (u8*)pxmitbuf); //3 5. update statisitc pbuf_tail -= (pfirstframe->agg_num * TXDESC_SIZE); if (pfirstframe->pkt_offset == 1) pbuf_tail -= PACKET_OFFSET_SZ; rtw_count_tx_stats(padapter, pfirstframe, pbuf_tail); rtw_free_xmitframe(pxmitpriv, pfirstframe); return _TRUE; }
s32 rtl8192du_xmitframe_complete(_adapter *padapter, struct xmit_priv *pxmitpriv, struct xmit_buf *pxmitbuf) { HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter); struct xmit_frame *pxmitframe = NULL; struct xmit_frame *pfirstframe = NULL; // aggregate variable struct hw_xmit *phwxmit = pxmitpriv->hwxmits; struct tx_servq *ptxservq = NULL; _irqL irqL; _list *xmitframe_plist = NULL, *xmitframe_phead = NULL; u32 pbuf=0; // next pkt address u32 pbuf_tail; // last pkt tail u32 len=0; //packet length, except TXDESC_SIZE and PKT_OFFSET u32 aggMaxLength = MAX_XMITBUF_SZ; u32 bulkSize = pHalData->UsbBulkOutSize; u32 bulkPtr=0; u8 descCount=0; u8 ac_index; u8 bfirst = _TRUE;//first aggregation xmitframe u8 bulkstart = _FALSE; // dump frame variable u32 ff_hwaddr; #ifndef IDEA_CONDITION int res = _SUCCESS; #endif RT_TRACE(_module_rtl8192c_xmit_c_, _drv_info_, ("+xmitframe_complete\n")); // check xmitbuffer is ok if (pxmitbuf == NULL) { pxmitbuf = rtw_alloc_xmitbuf(pxmitpriv); if (pxmitbuf == NULL) return _FALSE; } if(pHalData->MacPhyMode92D==SINGLEMAC_SINGLEPHY) aggMaxLength = MAX_XMITBUF_SZ; else aggMaxLength = 0x3D00; do { //3 1. pick up first frame if(bfirst) { pxmitframe = rtw_dequeue_xframe(pxmitpriv, pxmitpriv->hwxmits, pxmitpriv->hwxmit_entry); if (pxmitframe == NULL) { // no more xmit frame, release xmit buffer rtw_free_xmitbuf(pxmitpriv, pxmitbuf); return _FALSE; } pxmitframe->pxmitbuf = pxmitbuf; pxmitframe->buf_addr = pxmitbuf->pbuf; pxmitbuf->priv_data = pxmitframe; //pxmitframe->agg_num = 1; // alloc xmitframe should assign to 1. pxmitframe->pkt_offset = USB_92D_DUMMY_OFFSET; // first frame of aggregation, reserve 2 offset for 512 alignment and early mode pfirstframe = pxmitframe; _enter_critical_bh(&pxmitpriv->lock, &irqL); ptxservq = rtw_get_sta_pending(padapter, pfirstframe->attrib.psta, pfirstframe->attrib.priority, (u8 *)(&ac_index)); _exit_critical_bh(&pxmitpriv->lock, &irqL); } //3 2. aggregate same priority and same DA(AP or STA) frames else { // dequeue same priority packet from station tx queue _enter_critical_bh(&pxmitpriv->lock, &irqL); if (_rtw_queue_empty(&ptxservq->sta_pending) == _FALSE) { xmitframe_phead = get_list_head(&ptxservq->sta_pending); xmitframe_plist = get_next(xmitframe_phead); pxmitframe = LIST_CONTAINOR(xmitframe_plist, struct xmit_frame, list); len = xmitframe_need_length(pxmitframe) + TXDESC_SIZE + ((USB_92D_DUMMY_OFFSET - 1) * PACKET_OFFSET_SZ); if (pbuf + _RND8(len) > aggMaxLength) { bulkstart = _TRUE; } else { rtw_list_delete(&pxmitframe->list); ptxservq->qcnt--; phwxmit[ac_index].accnt--; //Remove sta node when there is no pending packets. if (_rtw_queue_empty(&ptxservq->sta_pending) == _TRUE) rtw_list_delete(&ptxservq->tx_pending); } } else { bulkstart = _TRUE; } _exit_critical_bh(&pxmitpriv->lock, &irqL); if(bulkstart) { break; } pxmitframe->buf_addr = pxmitbuf->pbuf + pbuf; pxmitframe->agg_num = 0; // not first frame of aggregation pxmitframe->pkt_offset = USB_92D_DUMMY_OFFSET - 1; // not first frame of aggregation, reserve 1 offset for early mode }
int recvbuf2recvframe(PADAPTER padapter, void *ptr) { u8 *pbuf; u8 pkt_cnt = 0; u32 pkt_offset; s32 transfer_len; u8 *pphy_status = NULL; union recv_frame *precvframe = NULL; struct rx_pkt_attrib *pattrib = NULL; HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter); struct recv_priv *precvpriv = &padapter->recvpriv; _queue *pfree_recv_queue = &precvpriv->free_recv_queue; _pkt *pskb; #ifdef CONFIG_USE_USB_BUFFER_ALLOC_RX pskb = NULL; transfer_len = (s32)((struct recv_buf*)ptr)->transfer_len; pbuf = ((struct recv_buf*)ptr)->pbuf; #else pskb = (_pkt*)ptr; transfer_len = (s32)pskb->len; pbuf = pskb->data; #endif//CONFIG_USE_USB_BUFFER_ALLOC_RX #ifdef CONFIG_USB_RX_AGGREGATION pkt_cnt = GET_RX_STATUS_DESC_USB_AGG_PKTNUM_8812(pbuf); #endif do{ precvframe = rtw_alloc_recvframe(pfree_recv_queue); if(precvframe==NULL) { RT_TRACE(_module_rtl871x_recv_c_,_drv_err_,("recvbuf2recvframe: precvframe==NULL\n")); DBG_8192C("%s()-%d: rtw_alloc_recvframe() failed! RX Drop!\n", __FUNCTION__, __LINE__); goto _exit_recvbuf2recvframe; } _rtw_init_listhead(&precvframe->u.hdr.list); precvframe->u.hdr.precvbuf = NULL; //can't access the precvbuf for new arch. precvframe->u.hdr.len=0; rtl8812_query_rx_desc_status(precvframe, pbuf); pattrib = &precvframe->u.hdr.attrib; if ((padapter->registrypriv.mp_mode == 0) && ((pattrib->crc_err) || (pattrib->icv_err))) { DBG_8192C("%s: RX Warning! crc_err=%d icv_err=%d, skip!\n", __FUNCTION__, pattrib->crc_err, pattrib->icv_err); rtw_free_recvframe(precvframe, pfree_recv_queue); goto _exit_recvbuf2recvframe; } pkt_offset = RXDESC_SIZE + pattrib->drvinfo_sz + pattrib->shift_sz + pattrib->pkt_len; if((pattrib->pkt_len<=0) || (pkt_offset>transfer_len)) { RT_TRACE(_module_rtl871x_recv_c_,_drv_info_,("recvbuf2recvframe: pkt_len<=0\n")); DBG_8192C("%s()-%d: RX Warning!,pkt_len<=0 or pkt_offset> transfer_len \n", __FUNCTION__, __LINE__); rtw_free_recvframe(precvframe, pfree_recv_queue); goto _exit_recvbuf2recvframe; } #ifdef CONFIG_RX_PACKET_APPEND_FCS if(pattrib->pkt_rpt_type == NORMAL_RX) pattrib->pkt_len -= IEEE80211_FCS_LEN; #endif if(rtw_os_alloc_recvframe(padapter, precvframe, (pbuf + pattrib->shift_sz + pattrib->drvinfo_sz + RXDESC_SIZE), pskb) == _FAIL) { rtw_free_recvframe(precvframe, pfree_recv_queue); goto _exit_recvbuf2recvframe; } recvframe_put(precvframe, pattrib->pkt_len); //recvframe_pull(precvframe, drvinfo_sz + RXDESC_SIZE); if(pattrib->pkt_rpt_type == NORMAL_RX)//Normal rx packet { if(pattrib->physt) pphy_status = (pbuf + RXDESC_OFFSET); #ifdef CONFIG_CONCURRENT_MODE if(rtw_buddy_adapter_up(padapter)) { if(pre_recv_entry(precvframe, pphy_status) != _SUCCESS) { RT_TRACE(_module_rtl871x_recv_c_,_drv_err_, ("recvbuf2recvframe: recv_entry(precvframe) != _SUCCESS\n")); } } #endif //CONFIG_CONCURRENT_MODE if(pattrib->physt && pphy_status) rx_query_phy_status(precvframe, pphy_status); if(rtw_recv_entry(precvframe) != _SUCCESS) { RT_TRACE(_module_rtl871x_recv_c_,_drv_err_, ("recvbuf2recvframe: rtw_recv_entry(precvframe) != _SUCCESS\n")); } } else{ // pkt_rpt_type == TX_REPORT1-CCX, TX_REPORT2-TX RTP,HIS_REPORT-USB HISR RTP if (pattrib->pkt_rpt_type == C2H_PACKET) { //DBG_8192C("rx C2H_PACKET \n"); C2HPacketHandler_8812(padapter,precvframe->u.hdr.rx_data,pattrib->pkt_len); } rtw_free_recvframe(precvframe, pfree_recv_queue); } #ifdef CONFIG_USB_RX_AGGREGATION // jaguar 8-byte alignment pkt_offset = (u16)_RND8(pkt_offset); pkt_cnt--; pbuf += pkt_offset; #endif transfer_len -= pkt_offset; precvframe = NULL; }while(transfer_len>0); _exit_recvbuf2recvframe: return _SUCCESS; }