int rtw_recv_indicatepkt(_adapter *padapter, union recv_frame *precv_frame) { struct recv_priv *precvpriv; _queue *pfree_recv_queue; _pkt *skb; struct rx_pkt_attrib *pattrib = &precv_frame->u.hdr.attrib; DBG_COUNTER(padapter->rx_logs.os_indicate); precvpriv = &(padapter->recvpriv); pfree_recv_queue = &(precvpriv->free_recv_queue); skb = precv_frame->u.hdr.pkt; if (skb == NULL) { RT_TRACE(_module_recv_osdep_c_, _drv_err_, ("rtw_recv_indicatepkt():skb ==NULL something wrong!!!!\n")); goto _recv_indicatepkt_drop; } RT_TRACE(_module_recv_osdep_c_, _drv_info_, ("rtw_recv_indicatepkt():skb != NULL !!!\n")); RT_TRACE(_module_recv_osdep_c_, _drv_info_, ("rtw_recv_indicatepkt():precv_frame->u.hdr.rx_head =%p precv_frame->hdr.rx_data =%p\n", precv_frame->u.hdr.rx_head, precv_frame->u.hdr.rx_data)); RT_TRACE(_module_recv_osdep_c_, _drv_info_, ("precv_frame->hdr.rx_tail =%p precv_frame->u.hdr.rx_end =%p precv_frame->hdr.len =%d \n", precv_frame->u.hdr.rx_tail, precv_frame->u.hdr.rx_end, precv_frame->u.hdr.len)); skb->data = precv_frame->u.hdr.rx_data; skb_set_tail_pointer(skb, precv_frame->u.hdr.len); skb->len = precv_frame->u.hdr.len; RT_TRACE(_module_recv_osdep_c_, _drv_info_, ("\n skb->head =%p skb->data =%p skb->tail =%p skb->end =%p skb->len =%d\n", skb->head, skb->data, skb_tail_pointer(skb), skb_end_pointer(skb), skb->len)); #ifdef CONFIG_AUTO_AP_MODE if (0x8899 == pattrib->eth_type) { rtw_os_ksocket_send(padapter, precv_frame); /* goto _recv_indicatepkt_drop; */ } #endif /* CONFIG_AUTO_AP_MODE */ rtw_os_recv_indicate_pkt(padapter, skb, pattrib); precv_frame->u.hdr.pkt = NULL; /* pointers to NULL before rtw_free_recvframe() */ rtw_free_recvframe(precv_frame, pfree_recv_queue); RT_TRACE(_module_recv_osdep_c_, _drv_info_, ("\n rtw_recv_indicatepkt :after rtw_os_recv_indicate_pkt!!!!\n")); return _SUCCESS; _recv_indicatepkt_drop: /* enqueue back to free_recv_queue */ if (precv_frame) rtw_free_recvframe(precv_frame, pfree_recv_queue); DBG_COUNTER(padapter->rx_logs.os_indicate_err); return _FAIL; }
void rtw_mi_buddy_clone_bcmc_packet(_adapter *padapter, union recv_frame *precvframe, u8 *pphy_status) { int i; s32 ret = _SUCCESS; _adapter *iface = NULL; union recv_frame *pcloneframe = NULL; struct recv_priv *precvpriv = &padapter->recvpriv;/*primary_padapter*/ _queue *pfree_recv_queue = &precvpriv->free_recv_queue; struct dvobj_priv *dvobj = adapter_to_dvobj(padapter); for (i = 0; i < dvobj->iface_nums; i++) { iface = dvobj->padapters[i]; if ((iface) && rtw_is_adapter_up(iface)) { if (iface == padapter) continue; pcloneframe = rtw_alloc_recvframe(pfree_recv_queue); if (pcloneframe) { ret = _rtw_mi_buddy_clone_bcmc_packet(iface, precvframe, pphy_status, pcloneframe); if (_SUCCESS != ret) { if (ret == -1) rtw_free_recvframe(pcloneframe, pfree_recv_queue); /*RTW_INFO(ADPT_FMT"-clone BC/MC frame failed\n", ADPT_ARG(iface));*/ } } } } }
int rtw_recv_monitor(_adapter *padapter, union recv_frame *precv_frame) { int ret = _FAIL; struct recv_priv *precvpriv; _queue *pfree_recv_queue; _pkt *skb; struct mlme_priv *pmlmepriv = &padapter->mlmepriv; struct rx_pkt_attrib *pattrib; if (NULL == precv_frame) goto _recv_drop; pattrib = &precv_frame->u.hdr.attrib; precvpriv = &(padapter->recvpriv); pfree_recv_queue = &(precvpriv->free_recv_queue); skb = precv_frame->u.hdr.pkt; if (skb == NULL) { DBG_871X("%s :skb==NULL something wrong!!!!\n", __func__); goto _recv_drop; } skb->data = precv_frame->u.hdr.rx_data; skb_set_tail_pointer(skb, precv_frame->u.hdr.len); skb->len = precv_frame->u.hdr.len; skb->ip_summed = CHECKSUM_NONE; skb->pkt_type = PACKET_OTHERHOST; skb->protocol = htons(0x0019); /* ETH_P_80211_RAW */ rtw_netif_rx(padapter->pnetdev, skb); /* pointers to NULL before rtw_free_recvframe() */ precv_frame->u.hdr.pkt = NULL; ret = _SUCCESS; _recv_drop: /* enqueue back to free_recv_queue */ if (precv_frame) rtw_free_recvframe(precv_frame, pfree_recv_queue); return ret; }
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; }
// using pstapriv->sta_hash_lock to protect u32 rtw_free_stainfo(_adapter *padapter , struct sta_info *psta) { int i; _queue *pfree_sta_queue; struct recv_reorder_ctrl *preorder_ctrl; struct sta_xmit_priv *pstaxmitpriv; struct xmit_priv *pxmitpriv= &padapter->xmitpriv; struct sta_priv *pstapriv = &padapter->stapriv; struct hw_xmit *phwxmit; _func_enter_; if (psta == NULL) goto exit; spin_lock_bh(&psta->lock); psta->state &= ~_FW_LINKED; spin_unlock_bh(&psta->lock); pfree_sta_queue = &pstapriv->free_sta_queue; pstaxmitpriv = &psta->sta_xmitpriv; //list_del_init(&psta->sleep_list); //list_del_init(&psta->wakeup_list); spin_lock_bh(&pxmitpriv->lock); rtw_free_xmitframe_queue(pxmitpriv, &psta->sleep_q); psta->sleepq_len = 0; //vo //spin_lock_bh(&(pxmitpriv->vo_pending.lock)); rtw_free_xmitframe_queue( pxmitpriv, &pstaxmitpriv->vo_q.sta_pending); list_del_init(&(pstaxmitpriv->vo_q.tx_pending)); phwxmit = pxmitpriv->hwxmits; phwxmit->accnt -= pstaxmitpriv->vo_q.qcnt; pstaxmitpriv->vo_q.qcnt = 0; //spin_unlock_bh(&(pxmitpriv->vo_pending.lock)); //vi //spin_lock_bh(&(pxmitpriv->vi_pending.lock)); rtw_free_xmitframe_queue( pxmitpriv, &pstaxmitpriv->vi_q.sta_pending); list_del_init(&(pstaxmitpriv->vi_q.tx_pending)); phwxmit = pxmitpriv->hwxmits+1; phwxmit->accnt -= pstaxmitpriv->vi_q.qcnt; pstaxmitpriv->vi_q.qcnt = 0; //spin_unlock_bh(&(pxmitpriv->vi_pending.lock)); //be //spin_lock_bh(&(pxmitpriv->be_pending.lock)); rtw_free_xmitframe_queue( pxmitpriv, &pstaxmitpriv->be_q.sta_pending); list_del_init(&(pstaxmitpriv->be_q.tx_pending)); phwxmit = pxmitpriv->hwxmits+2; phwxmit->accnt -= pstaxmitpriv->be_q.qcnt; pstaxmitpriv->be_q.qcnt = 0; //spin_unlock_bh(&(pxmitpriv->be_pending.lock)); //bk //spin_lock_bh(&(pxmitpriv->bk_pending.lock)); rtw_free_xmitframe_queue( pxmitpriv, &pstaxmitpriv->bk_q.sta_pending); list_del_init(&(pstaxmitpriv->bk_q.tx_pending)); phwxmit = pxmitpriv->hwxmits+3; phwxmit->accnt -= pstaxmitpriv->bk_q.qcnt; pstaxmitpriv->bk_q.qcnt = 0; //spin_unlock_bh(&(pxmitpriv->bk_pending.lock)); spin_unlock_bh(&pxmitpriv->lock); list_del_init(&psta->hash_list); RT_TRACE(_module_rtl871x_sta_mgt_c_,_drv_err_,("\n free number_%d stainfo with hwaddr = 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x \n",pstapriv->asoc_sta_count , psta->hwaddr[0], psta->hwaddr[1], psta->hwaddr[2],psta->hwaddr[3],psta->hwaddr[4],psta->hwaddr[5])); pstapriv->asoc_sta_count --; // re-init sta_info; 20061114 // will be init in alloc_stainfo //_rtw_init_sta_xmit_priv(&psta->sta_xmitpriv); //_rtw_init_sta_recv_priv(&psta->sta_recvpriv); _cancel_timer_ex(&psta->addba_retry_timer); //for A-MPDU Rx reordering buffer control, cancel reordering_ctrl_timer for(i=0; i < 16 ; i++) { _list *phead, *plist; union recv_frame *prframe; _queue *ppending_recvframe_queue; _queue *pfree_recv_queue = &padapter->recvpriv.free_recv_queue; preorder_ctrl = &psta->recvreorder_ctrl[i]; _cancel_timer_ex(&preorder_ctrl->reordering_ctrl_timer); ppending_recvframe_queue = &preorder_ctrl->pending_recvframe_queue; spin_lock_bh(&ppending_recvframe_queue->lock); phead = get_list_head(ppending_recvframe_queue); plist = get_next(phead); while(!list_empty(phead)) { prframe = LIST_CONTAINOR(plist, union recv_frame, u); plist = get_next(plist); list_del_init(&(prframe->u.hdr.list)); rtw_free_recvframe(prframe, pfree_recv_queue); } spin_unlock_bh(&ppending_recvframe_queue->lock); } if (!(psta->state & WIFI_AP_STATE)) rtw_hal_set_odm_var(padapter, HAL_ODM_STA_INFO, psta, false); //release mac id for non-bc/mc station, rtw_release_macid(pstapriv->padapter, psta); /* spin_lock_bh(&pstapriv->asoc_list_lock); list_del_init(&psta->asoc_list); spin_unlock_bh(&pstapriv->asoc_list_lock); */ spin_lock_bh(&pstapriv->auth_list_lock); if (!list_empty(&psta->auth_list)) { list_del_init(&psta->auth_list); pstapriv->auth_list_cnt--; } spin_unlock_bh(&pstapriv->auth_list_lock); psta->expire_to = 0; psta->sleepq_ac_len = 0; psta->qos_info = 0; psta->max_sp_len = 0; psta->uapsd_bk = 0; psta->uapsd_be = 0; psta->uapsd_vi = 0; psta->uapsd_vo = 0; psta->has_legacy_ac = 0; pstapriv->sta_dz_bitmap &=~BIT(psta->aid); pstapriv->tim_bitmap &=~BIT(psta->aid); if ((psta->aid >0)&&(pstapriv->sta_aid[psta->aid - 1] == psta)) { pstapriv->sta_aid[psta->aid - 1] = NULL; psta->aid = 0; } psta->under_exist_checking = 0; //spin_lock_bh(&(pfree_sta_queue->lock)); list_add_tail(&psta->list, get_list_head(pfree_sta_queue)); //spin_unlock_bh(&(pfree_sta_queue->lock)); exit: _func_exit_; return _SUCCESS; }
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; }
/* using pstapriv->sta_hash_lock to protect */ u32 rtw_free_stainfo(_adapter *padapter , struct sta_info *psta) { int i; unsigned long irqL0; struct __queue *pfree_sta_queue; struct recv_reorder_ctrl *preorder_ctrl; struct sta_xmit_priv *pstaxmitpriv; struct xmit_priv *pxmitpriv= &padapter->xmitpriv; struct sta_priv *pstapriv = &padapter->stapriv; _func_enter_; if (psta == NULL) goto exit; pfree_sta_queue = &pstapriv->free_sta_queue; pstaxmitpriv = &psta->sta_xmitpriv; _enter_critical_bh(&pxmitpriv->lock, &irqL0); rtw_free_xmitframe_queue(pxmitpriv, &psta->sleep_q); psta->sleepq_len = 0; rtw_free_xmitframe_queue( pxmitpriv, &pstaxmitpriv->vo_q.sta_pending); rtw_list_delete(&(pstaxmitpriv->vo_q.tx_pending)); rtw_free_xmitframe_queue( pxmitpriv, &pstaxmitpriv->vi_q.sta_pending); rtw_list_delete(&(pstaxmitpriv->vi_q.tx_pending)); rtw_free_xmitframe_queue( pxmitpriv, &pstaxmitpriv->bk_q.sta_pending); rtw_list_delete(&(pstaxmitpriv->bk_q.tx_pending)); rtw_free_xmitframe_queue( pxmitpriv, &pstaxmitpriv->be_q.sta_pending); rtw_list_delete(&(pstaxmitpriv->be_q.tx_pending)); _exit_critical_bh(&pxmitpriv->lock, &irqL0); rtw_list_delete(&psta->hash_list); RT_TRACE(_module_rtl871x_sta_mgt_c_,_drv_err_,("\n free number_%d stainfo with hwaddr = 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x\n",pstapriv->asoc_sta_count , psta->hwaddr[0], psta->hwaddr[1], psta->hwaddr[2],psta->hwaddr[3],psta->hwaddr[4],psta->hwaddr[5])); pstapriv->asoc_sta_count --; /* re-init sta_info; 20061114 */ _rtw_init_sta_xmit_priv(&psta->sta_xmitpriv); _rtw_init_sta_recv_priv(&psta->sta_recvpriv); _cancel_timer_ex(&psta->addba_retry_timer); /* for A-MPDU Rx reordering buffer control, cancel reordering_ctrl_timer */ for (i=0; i < 16 ; i++) { unsigned long irqL; struct list_head *phead, *plist; union recv_frame *prframe; struct __queue *ppending_recvframe_queue; struct __queue *pfree_recv_queue = &padapter->recvpriv.free_recv_queue; preorder_ctrl = &psta->recvreorder_ctrl[i]; _cancel_timer_ex(&preorder_ctrl->reordering_ctrl_timer); ppending_recvframe_queue = &preorder_ctrl->pending_recvframe_queue; _enter_critical_bh(&ppending_recvframe_queue->lock, &irqL); phead = get_list_head(ppending_recvframe_queue); plist = get_next(phead); while (!rtw_is_list_empty(phead)) { prframe = LIST_CONTAINOR(plist, union recv_frame, u); plist = get_next(plist); rtw_list_delete(&(prframe->u.hdr.list)); rtw_free_recvframe(prframe, pfree_recv_queue); } _exit_critical_bh(&ppending_recvframe_queue->lock, &irqL); } if (!(psta->state & WIFI_AP_STATE)) rtw_hal_set_odm_var(padapter, HAL_ODM_STA_INFO, psta, false); #ifdef CONFIG_AP_MODE _enter_critical_bh(&pstapriv->auth_list_lock, &irqL0); if (!rtw_is_list_empty(&psta->auth_list)) { rtw_list_delete(&psta->auth_list); pstapriv->auth_list_cnt--; } _exit_critical_bh(&pstapriv->auth_list_lock, &irqL0); psta->expire_to = 0; psta->sleepq_ac_len = 0; psta->qos_info = 0; psta->max_sp_len = 0; psta->uapsd_bk = 0; psta->uapsd_be = 0; psta->uapsd_vi = 0; psta->uapsd_vo = 0; psta->has_legacy_ac = 0; pstapriv->sta_dz_bitmap &=~BIT(psta->aid); pstapriv->tim_bitmap &=~BIT(psta->aid); if ((psta->aid >0)&&(pstapriv->sta_aid[psta->aid - 1] == psta)) { pstapriv->sta_aid[psta->aid - 1] = NULL; psta->aid = 0; } psta->under_exist_checking = 0; #endif /* CONFIG_AP_MODE */ _enter_critical_bh(&(pfree_sta_queue->lock), &irqL0); rtw_list_insert_tail(&psta->list, get_list_head(pfree_sta_queue)); _exit_critical_bh(&(pfree_sta_queue->lock), &irqL0); exit: _func_exit_; 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 s32 pre_recv_entry(union recv_frame *precvframe, u8 *pphy_status) { s32 ret=_SUCCESS; #ifdef CONFIG_CONCURRENT_MODE u8 *secondary_myid, *paddr1; union recv_frame *precvframe_if2 = NULL; _adapter *primary_padapter = precvframe->u.hdr.adapter; _adapter *secondary_padapter = primary_padapter->pbuddy_adapter; struct recv_priv *precvpriv = &primary_padapter->recvpriv; _queue *pfree_recv_queue = &precvpriv->free_recv_queue; HAL_DATA_TYPE *pHalData = GET_HAL_DATA(primary_padapter); if(!secondary_padapter) return ret; paddr1 = GetAddr1Ptr(precvframe->u.hdr.rx_data); if(IS_MCAST(paddr1) == _FALSE)//unicast packets { secondary_myid = adapter_mac_addr(secondary_padapter); if(_rtw_memcmp(paddr1, secondary_myid, ETH_ALEN)) { //change to secondary interface precvframe->u.hdr.adapter = secondary_padapter; } //ret = recv_entry(precvframe); } else // Handle BC/MC Packets { //clone/copy to if2 _pkt *pkt_copy = NULL; struct rx_pkt_attrib *pattrib = NULL; precvframe_if2 = rtw_alloc_recvframe(pfree_recv_queue); if(!precvframe_if2) return _FAIL; precvframe_if2->u.hdr.adapter = secondary_padapter; _rtw_memcpy(&precvframe_if2->u.hdr.attrib, &precvframe->u.hdr.attrib, sizeof(struct rx_pkt_attrib)); pattrib = &precvframe_if2->u.hdr.attrib; //driver need to set skb len for skb_copy(). //If skb->len is zero, skb_copy() will not copy data from original skb. skb_put(precvframe->u.hdr.pkt, pattrib->pkt_len); pkt_copy = rtw_skb_copy( precvframe->u.hdr.pkt); if (pkt_copy == NULL) { if((pattrib->mfrag == 1)&&(pattrib->frag_num == 0)) { DBG_8192C("pre_recv_entry(): rtw_skb_copy fail , drop frag frame \n"); rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue); return ret; } pkt_copy = rtw_skb_clone( precvframe->u.hdr.pkt); if(pkt_copy == NULL) { DBG_8192C("pre_recv_entry(): rtw_skb_clone fail , drop frame\n"); rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue); return ret; } } pkt_copy->dev = secondary_padapter->pnetdev; precvframe_if2->u.hdr.pkt = pkt_copy; precvframe_if2->u.hdr.rx_head = pkt_copy->head; precvframe_if2->u.hdr.rx_data = pkt_copy->data; precvframe_if2->u.hdr.rx_tail = skb_tail_pointer(pkt_copy); precvframe_if2->u.hdr.rx_end = skb_end_pointer(pkt_copy); precvframe_if2->u.hdr.len = pkt_copy->len; //recvframe_put(precvframe_if2, pattrib->pkt_len); if ( pHalData->ReceiveConfig & RCR_APPFCS) recvframe_pull_tail(precvframe_if2, IEEE80211_FCS_LEN); if (pattrib->physt) rx_query_phy_status(precvframe_if2, pphy_status); if(rtw_recv_entry(precvframe_if2) != _SUCCESS) { RT_TRACE(_module_rtl871x_recv_c_,_drv_err_, ("recvbuf2recvframe: rtw_recv_entry(precvframe) != _SUCCESS\n")); } } //if (precvframe->u.hdr.attrib.physt) // rx_query_phy_status(precvframe, pphy_status); //ret = rtw_recv_entry(precvframe); #endif return ret; }
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); }
// using pstapriv->sta_hash_lock to protect u32 rtw_free_stainfo(_adapter *padapter , struct sta_info *psta) { int i; _irqL irqL0; _queue *pfree_sta_queue; struct recv_reorder_ctrl *preorder_ctrl; struct sta_xmit_priv *pstaxmitpriv; struct xmit_priv *pxmitpriv= &padapter->xmitpriv; struct sta_priv *pstapriv = &padapter->stapriv; _func_enter_; if (psta == NULL) goto exit; pfree_sta_queue = &pstapriv->free_sta_queue; pstaxmitpriv = &psta->sta_xmitpriv; //rtw_list_delete(&psta->sleep_list); //rtw_list_delete(&psta->wakeup_list); _enter_critical_bh(&pxmitpriv->lock, &irqL0); rtw_free_xmitframe_queue(pxmitpriv, &psta->sleep_q); psta->sleepq_len = 0; //_enter_critical_bh(&(pxmitpriv->vo_pending.lock), &irqL0); rtw_free_xmitframe_queue( pxmitpriv, &pstaxmitpriv->vo_q.sta_pending); rtw_list_delete(&(pstaxmitpriv->vo_q.tx_pending)); //_exit_critical_bh(&(pxmitpriv->vo_pending.lock), &irqL0); //_enter_critical_bh(&(pxmitpriv->vi_pending.lock), &irqL0); rtw_free_xmitframe_queue( pxmitpriv, &pstaxmitpriv->vi_q.sta_pending); rtw_list_delete(&(pstaxmitpriv->vi_q.tx_pending)); //_exit_critical_bh(&(pxmitpriv->vi_pending.lock), &irqL0); //_enter_critical_bh(&(pxmitpriv->bk_pending.lock), &irqL0); rtw_free_xmitframe_queue( pxmitpriv, &pstaxmitpriv->bk_q.sta_pending); rtw_list_delete(&(pstaxmitpriv->bk_q.tx_pending)); //_exit_critical_bh(&(pxmitpriv->bk_pending.lock), &irqL0); //_enter_critical_bh(&(pxmitpriv->be_pending.lock), &irqL0); rtw_free_xmitframe_queue( pxmitpriv, &pstaxmitpriv->be_q.sta_pending); rtw_list_delete(&(pstaxmitpriv->be_q.tx_pending)); //_exit_critical_bh(&(pxmitpriv->be_pending.lock), &irqL0); _exit_critical_bh(&pxmitpriv->lock, &irqL0); rtw_list_delete(&psta->hash_list); RT_TRACE(_module_rtl871x_sta_mgt_c_,_drv_err_,("\n free number_%d stainfo with hwaddr = 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x \n",pstapriv->asoc_sta_count , psta->hwaddr[0], psta->hwaddr[1], psta->hwaddr[2],psta->hwaddr[3],psta->hwaddr[4],psta->hwaddr[5])); pstapriv->asoc_sta_count --; // re-init sta_info; 20061114 _rtw_init_sta_xmit_priv(&psta->sta_xmitpriv); _rtw_init_sta_recv_priv(&psta->sta_recvpriv); _cancel_timer_ex(&psta->addba_retry_timer); #ifdef CONFIG_TDLS _cancel_timer_ex(&psta->TPK_timer); _cancel_timer_ex(&psta->option_timer); _cancel_timer_ex(&psta->base_ch_timer); _cancel_timer_ex(&psta->off_ch_timer); _cancel_timer_ex(&psta->alive_timer1); _cancel_timer_ex(&psta->alive_timer2); #endif //CONFIG_TDLS //for A-MPDU Rx reordering buffer control, cancel reordering_ctrl_timer for(i=0; i < 16 ; i++) { _irqL irqL; _list *phead, *plist; union recv_frame *prframe; _queue *ppending_recvframe_queue; _queue *pfree_recv_queue = &padapter->recvpriv.free_recv_queue; preorder_ctrl = &psta->recvreorder_ctrl[i]; _cancel_timer_ex(&preorder_ctrl->reordering_ctrl_timer); ppending_recvframe_queue = &preorder_ctrl->pending_recvframe_queue; _enter_critical_bh(&ppending_recvframe_queue->lock, &irqL); phead = get_list_head(ppending_recvframe_queue); plist = get_next(phead); while(!rtw_is_list_empty(phead)) { prframe = LIST_CONTAINOR(plist, union recv_frame, u); plist = get_next(plist); rtw_list_delete(&(prframe->u.hdr.list)); rtw_free_recvframe(prframe, pfree_recv_queue); } _exit_critical_bh(&ppending_recvframe_queue->lock, &irqL); } DBG_871X("%s\n",__FUNCTION__); rtw_hal_set_odm_var(padapter,HAL_ODM_STA_INFO,psta,_FALSE); #ifdef CONFIG_AP_MODE /* _enter_critical_bh(&pstapriv->asoc_list_lock, &irqL0); rtw_list_delete(&psta->asoc_list); _exit_critical_bh(&pstapriv->asoc_list_lock, &irqL0); */ _enter_critical_bh(&pstapriv->auth_list_lock, &irqL0); rtw_list_delete(&psta->auth_list); _exit_critical_bh(&pstapriv->auth_list_lock, &irqL0); psta->expire_to = 0; psta->sleepq_ac_len = 0; psta->qos_info = 0; psta->max_sp_len = 0; psta->uapsd_bk = 0; psta->uapsd_be = 0; psta->uapsd_vi = 0; psta->uapsd_vo = 0; psta->has_legacy_ac = 0; #ifdef CONFIG_NATIVEAP_MLME pstapriv->sta_dz_bitmap &=~BIT(psta->aid); pstapriv->tim_bitmap &=~BIT(psta->aid); //rtw_indicate_sta_disassoc_event(padapter, psta); if ((psta->aid >0)&&(pstapriv->sta_aid[psta->aid - 1] == psta)) { pstapriv->sta_aid[psta->aid - 1] = NULL; psta->aid = 0; } #endif // CONFIG_NATIVEAP_MLME #ifdef CONFIG_TX_MCAST2UNI psta->under_exist_checking = 0; #endif // CONFIG_TX_MCAST2UNI #endif // CONFIG_AP_MODE _enter_critical_bh(&(pfree_sta_queue->lock), &irqL0); rtw_list_insert_tail(&psta->list, get_list_head(pfree_sta_queue)); _exit_critical_bh(&(pfree_sta_queue->lock), &irqL0); exit: _func_exit_; return _SUCCESS; }
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); }
void rtw_recv_indicatepkt(_adapter *padapter, union recv_frame *precv_frame) { struct recv_priv *precvpriv; _queue *pfree_recv_queue; _pkt *skb; struct mlme_priv*pmlmepriv = &padapter->mlmepriv; #ifdef CONFIG_RTL8712_TCP_CSUM_OFFLOAD_RX struct rx_pkt_attrib *pattrib = &precv_frame->u.hdr.attrib; #endif _func_enter_; precvpriv = &(padapter->recvpriv); pfree_recv_queue = &(precvpriv->free_recv_queue); #ifdef CONFIG_DRVEXT_MODULE if (drvext_rx_handler(padapter, precv_frame->u.hdr.rx_data, precv_frame->u.hdr.len) == _SUCCESS) { rtw_free_recvframe(precv_frame, pfree_recv_queue); return; } #endif skb = precv_frame->u.hdr.pkt; if(skb == NULL) { RT_TRACE(_module_recv_osdep_c_,_drv_err_,("rtw_recv_indicatepkt():skb==NULL something wrong!!!!\n")); goto _recv_indicatepkt_drop; } RT_TRACE(_module_recv_osdep_c_,_drv_info_,("rtw_recv_indicatepkt():skb != NULL !!!\n")); RT_TRACE(_module_recv_osdep_c_,_drv_info_,("rtw_recv_indicatepkt():precv_frame->u.hdr.rx_head=%p precv_frame->hdr.rx_data=%p\n", precv_frame->u.hdr.rx_head, precv_frame->u.hdr.rx_data)); RT_TRACE(_module_recv_osdep_c_,_drv_info_,("precv_frame->hdr.rx_tail=%p precv_frame->u.hdr.rx_end=%p precv_frame->hdr.len=%d \n", precv_frame->u.hdr.rx_tail, precv_frame->u.hdr.rx_end, precv_frame->u.hdr.len)); skb->data = precv_frame->u.hdr.rx_data; skb->tail = precv_frame->u.hdr.rx_tail; skb->len = precv_frame->u.hdr.len; RT_TRACE(_module_recv_osdep_c_,_drv_info_,("\n skb->head=%p skb->data=%p skb->tail=%p skb->end=%p skb->len=%d\n", skb->head, skb->data, skb->tail, skb->end, skb->len)); if(check_fwstate(pmlmepriv, WIFI_AP_STATE) == _TRUE) { _pkt *pskb2=NULL; struct sta_info *psta = NULL; struct sta_priv *pstapriv = &padapter->stapriv; struct rx_pkt_attrib *pattrib = &precv_frame->u.hdr.attrib; int bmcast = IS_MCAST(pattrib->dst); //DBG_871X("bmcast=%d\n", bmcast); if(_rtw_memcmp(pattrib->dst, myid(&padapter->eeprompriv), ETH_ALEN)==_FALSE) { psta = rtw_get_stainfo(pstapriv, pattrib->dst); //DBG_871X("not ap psta=%p, addr=%pM\n", psta, pattrib->dst); if(bmcast) { pskb2 = skb_clone(skb, GFP_ATOMIC); } if(psta) { //DBG_871X("directly forwarding to the xmit_entry\n"); //skb->ip_summed = CHECKSUM_NONE; //skb->protocol = eth_type_trans(skb, pnetdev); skb->dev = padapter->pnetdev; rtw_xmit_entry(skb, padapter->pnetdev); if(bmcast == _FALSE) goto _recv_indicatepkt_end; } if(bmcast) skb = pskb2; } else// to APself { //DBG_871X("to APSelf\n"); } } #ifdef CONFIG_RTL8712_TCP_CSUM_OFFLOAD_RX if ( (pattrib->tcpchk_valid == 1) && (pattrib->tcp_chkrpt == 1) ) { skb->ip_summed = CHECKSUM_UNNECESSARY; //printk("CHECKSUM_UNNECESSARY \n"); } else { skb->ip_summed = CHECKSUM_NONE; //printk("CHECKSUM_NONE(%d, %d) \n", pattrib->tcpchk_valid, pattrib->tcp_chkrpt); } #else /* !CONFIG_RTL8712_TCP_CSUM_OFFLOAD_RX */ skb->ip_summed = CHECKSUM_NONE; #endif skb->dev = padapter->pnetdev; skb->protocol = eth_type_trans(skb, padapter->pnetdev); netif_rx(skb); _recv_indicatepkt_end: precv_frame->u.hdr.pkt = NULL; // pointers to NULL before rtw_free_recvframe() rtw_free_recvframe(precv_frame, pfree_recv_queue); RT_TRACE(_module_recv_osdep_c_,_drv_info_,("\n rtw_recv_indicatepkt :after netif_rx!!!!\n")); _func_exit_; return; _recv_indicatepkt_drop: //enqueue back to free_recv_queue if(precv_frame) rtw_free_recvframe(precv_frame, pfree_recv_queue); precvpriv->rx_drop++; _func_exit_; }
int rtw_recv_indicatepkt(_adapter *padapter, union recv_frame *precv_frame) { struct recv_priv *precvpriv; _queue *pfree_recv_queue; _pkt *skb; struct mlme_priv*pmlmepriv = &padapter->mlmepriv; struct rx_pkt_attrib *pattrib; if(NULL == precv_frame) goto _recv_indicatepkt_drop; DBG_COUNTER(padapter->rx_logs.os_indicate); pattrib = &precv_frame->u.hdr.attrib; precvpriv = &(padapter->recvpriv); pfree_recv_queue = &(precvpriv->free_recv_queue); #ifdef CONFIG_DRVEXT_MODULE if (drvext_rx_handler(padapter, precv_frame->u.hdr.rx_data, precv_frame->u.hdr.len) == _SUCCESS) { goto _recv_indicatepkt_drop; } #endif #ifdef CONFIG_WAPI_SUPPORT if (rtw_wapi_check_for_drop(padapter,precv_frame)) { WAPI_TRACE(WAPI_ERR, "%s(): Rx Reorder Drop case!!\n", __FUNCTION__); goto _recv_indicatepkt_drop; } #endif skb = precv_frame->u.hdr.pkt; if(skb == NULL) { RT_TRACE(_module_recv_osdep_c_,_drv_err_,("rtw_recv_indicatepkt():skb==NULL something wrong!!!!\n")); goto _recv_indicatepkt_drop; } RT_TRACE(_module_recv_osdep_c_,_drv_info_,("rtw_recv_indicatepkt():skb != NULL !!!\n")); RT_TRACE(_module_recv_osdep_c_,_drv_info_,("rtw_recv_indicatepkt():precv_frame->u.hdr.rx_head=%p precv_frame->hdr.rx_data=%p\n", precv_frame->u.hdr.rx_head, precv_frame->u.hdr.rx_data)); RT_TRACE(_module_recv_osdep_c_,_drv_info_,("precv_frame->hdr.rx_tail=%p precv_frame->u.hdr.rx_end=%p precv_frame->hdr.len=%d \n", precv_frame->u.hdr.rx_tail, precv_frame->u.hdr.rx_end, precv_frame->u.hdr.len)); skb->data = precv_frame->u.hdr.rx_data; skb_set_tail_pointer(skb, precv_frame->u.hdr.len); skb->len = precv_frame->u.hdr.len; RT_TRACE(_module_recv_osdep_c_,_drv_info_,("\n skb->head=%p skb->data=%p skb->tail=%p skb->end=%p skb->len=%d\n", skb->head, skb->data, skb_tail_pointer(skb), skb_end_pointer(skb), skb->len)); if (pattrib->eth_type == 0x888e) DBG_871X_LEVEL(_drv_always_, "recv eapol packet\n"); #ifdef CONFIG_AUTO_AP_MODE #if 1 //for testing #if 1 if (0x8899 == pattrib->eth_type) { rtw_os_ksocket_send(padapter, precv_frame); //goto _recv_indicatepkt_drop; } #else if (0x8899 == pattrib->eth_type) { rtw_auto_ap_mode_rx(padapter, precv_frame); goto _recv_indicatepkt_end; } #endif #endif #endif //CONFIG_AUTO_AP_MODE /* TODO: move to core */ { _pkt *pkt = skb; struct ethhdr *etherhdr = (struct ethhdr *)pkt->data; struct sta_info *sta = precv_frame->u.hdr.psta; if (!sta) goto bypass_session_tracker; if (ntohs(etherhdr->h_proto) == ETH_P_IP) { u8 *ip = pkt->data + 14; if (GET_IPV4_PROTOCOL(ip) == 0x06 /* TCP */ && rtw_st_ctl_chk_reg_s_proto(&sta->st_ctl, 0x06) == _TRUE ) { u8 *tcp = ip + GET_IPV4_IHL(ip) * 4; if (rtw_st_ctl_chk_reg_rule(&sta->st_ctl, padapter, IPV4_DST(ip), TCP_DST(tcp), IPV4_SRC(ip), TCP_SRC(tcp)) == _TRUE) { if (GET_TCP_SYN(tcp) && GET_TCP_ACK(tcp)) { session_tracker_add_cmd(padapter, sta , IPV4_DST(ip), TCP_DST(tcp) , IPV4_SRC(ip), TCP_SRC(tcp)); if (DBG_SESSION_TRACKER) DBG_871X(FUNC_ADPT_FMT" local:"IP_FMT":"PORT_FMT", remote:"IP_FMT":"PORT_FMT" SYN-ACK\n" , FUNC_ADPT_ARG(padapter) , IP_ARG(IPV4_DST(ip)), PORT_ARG(TCP_DST(tcp)) , IP_ARG(IPV4_SRC(ip)), PORT_ARG(TCP_SRC(tcp))); } if (GET_TCP_FIN(tcp)) { session_tracker_del_cmd(padapter, sta , IPV4_DST(ip), TCP_DST(tcp) , IPV4_SRC(ip), TCP_SRC(tcp)); if (DBG_SESSION_TRACKER) DBG_871X(FUNC_ADPT_FMT" local:"IP_FMT":"PORT_FMT", remote:"IP_FMT":"PORT_FMT" FIN\n" , FUNC_ADPT_ARG(padapter) , IP_ARG(IPV4_DST(ip)), PORT_ARG(TCP_DST(tcp)) , IP_ARG(IPV4_SRC(ip)), PORT_ARG(TCP_SRC(tcp))); } } } } bypass_session_tracker: ; } rtw_os_recv_indicate_pkt(padapter, skb, pattrib); _recv_indicatepkt_end: precv_frame->u.hdr.pkt = NULL; // pointers to NULL before rtw_free_recvframe() rtw_free_recvframe(precv_frame, pfree_recv_queue); RT_TRACE(_module_recv_osdep_c_,_drv_info_,("\n rtw_recv_indicatepkt :after rtw_os_recv_indicate_pkt!!!!\n")); return _SUCCESS; _recv_indicatepkt_drop: //enqueue back to free_recv_queue if(precv_frame) rtw_free_recvframe(precv_frame, pfree_recv_queue); DBG_COUNTER(padapter->rx_logs.os_indicate_err); return _FAIL; }
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; _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) { RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("%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 update_recvframe_attrib(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) { #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; } if (pHalData->ReceiveConfig & RCR_APP_BA_SSN) rx_report_sz = RXDESC_SIZE + 4 + pattrib->drvinfo_sz; else rx_report_sz = RXDESC_SIZE + pattrib->drvinfo_sz; pkt_offset = rx_report_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)){ //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; } #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18)) // http://www.mail-archive.com/[email protected]/msg17214.html pkt_copy = dev_alloc_skb(alloc_sz); #else pkt_copy = netdev_alloc_skb(padapter->pnetdev, alloc_sz); #endif 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), 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("rtl8723as_recv_tasklet: alloc_skb fail , drop frag frame \n"); rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue); break; } precvframe->u.hdr.pkt = skb_clone(precvbuf->pskb, GFP_ATOMIC); if(precvframe->u.hdr.pkt) { _pkt *pkt_clone = precvframe->u.hdr.pkt; pkt_clone->data = ptr + rx_report_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("rtl8723as_recv_tasklet: skb_clone fail\n"); 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; } #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_, ("%s: rtw_recv_entry(precvframe) != _SUCCESS\n",__FUNCTION__)); } } } // 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; precvframe = NULL; pkt_copy = NULL; } rtw_enqueue_recvbuf(precvbuf, &precvpriv->free_recv_buf_queue); } while (1); }
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); }
// using pstapriv->sta_hash_lock to protect u32 rtw_free_stainfo(_adapter *padapter , struct sta_info *psta) { int i; _irqL irqL0; _queue *pfree_sta_queue; struct recv_reorder_ctrl *preorder_ctrl; struct sta_xmit_priv *pstaxmitpriv; struct xmit_priv *pxmitpriv= &padapter->xmitpriv; struct sta_priv *pstapriv = &padapter->stapriv; struct hw_xmit *phwxmit; int pending_qcnt[4]; _func_enter_; if (psta == NULL) goto exit; _enter_critical_bh(&(pstapriv->sta_hash_lock), &irqL0); rtw_list_delete(&psta->hash_list); RT_TRACE(_module_rtl871x_sta_mgt_c_,_drv_err_,("\n free number_%d stainfo with hwaddr = 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x \n",pstapriv->asoc_sta_count , psta->hwaddr[0], psta->hwaddr[1], psta->hwaddr[2],psta->hwaddr[3],psta->hwaddr[4],psta->hwaddr[5])); pstapriv->asoc_sta_count --; _exit_critical_bh(&(pstapriv->sta_hash_lock), &irqL0); _enter_critical_bh(&psta->lock, &irqL0); psta->state &= ~_FW_LINKED; _exit_critical_bh(&psta->lock, &irqL0); pfree_sta_queue = &pstapriv->free_sta_queue; pstaxmitpriv = &psta->sta_xmitpriv; //rtw_list_delete(&psta->sleep_list); //rtw_list_delete(&psta->wakeup_list); _enter_critical_bh(&pxmitpriv->lock, &irqL0); rtw_free_xmitframe_queue(pxmitpriv, &psta->sleep_q); psta->sleepq_len = 0; //vo //_enter_critical_bh(&(pxmitpriv->vo_pending.lock), &irqL0); rtw_free_xmitframe_queue( pxmitpriv, &pstaxmitpriv->vo_q.sta_pending); rtw_list_delete(&(pstaxmitpriv->vo_q.tx_pending)); phwxmit = pxmitpriv->hwxmits; phwxmit->accnt -= pstaxmitpriv->vo_q.qcnt; pending_qcnt[0] = pstaxmitpriv->vo_q.qcnt; pstaxmitpriv->vo_q.qcnt = 0; //_exit_critical_bh(&(pxmitpriv->vo_pending.lock), &irqL0); //vi //_enter_critical_bh(&(pxmitpriv->vi_pending.lock), &irqL0); rtw_free_xmitframe_queue( pxmitpriv, &pstaxmitpriv->vi_q.sta_pending); rtw_list_delete(&(pstaxmitpriv->vi_q.tx_pending)); phwxmit = pxmitpriv->hwxmits+1; phwxmit->accnt -= pstaxmitpriv->vi_q.qcnt; pending_qcnt[1] = pstaxmitpriv->vi_q.qcnt; pstaxmitpriv->vi_q.qcnt = 0; //_exit_critical_bh(&(pxmitpriv->vi_pending.lock), &irqL0); //be //_enter_critical_bh(&(pxmitpriv->be_pending.lock), &irqL0); rtw_free_xmitframe_queue( pxmitpriv, &pstaxmitpriv->be_q.sta_pending); rtw_list_delete(&(pstaxmitpriv->be_q.tx_pending)); phwxmit = pxmitpriv->hwxmits+2; phwxmit->accnt -= pstaxmitpriv->be_q.qcnt; pending_qcnt[2] = pstaxmitpriv->be_q.qcnt; pstaxmitpriv->be_q.qcnt = 0; //_exit_critical_bh(&(pxmitpriv->be_pending.lock), &irqL0); //bk //_enter_critical_bh(&(pxmitpriv->bk_pending.lock), &irqL0); rtw_free_xmitframe_queue( pxmitpriv, &pstaxmitpriv->bk_q.sta_pending); rtw_list_delete(&(pstaxmitpriv->bk_q.tx_pending)); phwxmit = pxmitpriv->hwxmits+3; phwxmit->accnt -= pstaxmitpriv->bk_q.qcnt; pending_qcnt[3] = pstaxmitpriv->bk_q.qcnt; pstaxmitpriv->bk_q.qcnt = 0; //_exit_critical_bh(&(pxmitpriv->bk_pending.lock), &irqL0); rtw_os_wake_queue_at_free_stainfo(padapter, pending_qcnt); _exit_critical_bh(&pxmitpriv->lock, &irqL0); // re-init sta_info; 20061114 // will be init in alloc_stainfo //_rtw_init_sta_xmit_priv(&psta->sta_xmitpriv); //_rtw_init_sta_recv_priv(&psta->sta_recvpriv); _cancel_timer_ex(&psta->addba_retry_timer); #ifdef CONFIG_TDLS rtw_free_tdls_timer(psta); #endif //CONFIG_TDLS //for A-MPDU Rx reordering buffer control, cancel reordering_ctrl_timer for(i=0; i < 16 ; i++) { _irqL irqL; _list *phead, *plist; union recv_frame *prframe; _queue *ppending_recvframe_queue; _queue *pfree_recv_queue = &padapter->recvpriv.free_recv_queue; preorder_ctrl = &psta->recvreorder_ctrl[i]; _cancel_timer_ex(&preorder_ctrl->reordering_ctrl_timer); ppending_recvframe_queue = &preorder_ctrl->pending_recvframe_queue; _enter_critical_bh(&ppending_recvframe_queue->lock, &irqL); phead = get_list_head(ppending_recvframe_queue); plist = get_next(phead); while(!rtw_is_list_empty(phead)) { prframe = LIST_CONTAINOR(plist, union recv_frame, u); plist = get_next(plist); rtw_list_delete(&(prframe->u.hdr.list)); rtw_free_recvframe(prframe, pfree_recv_queue); } _exit_critical_bh(&ppending_recvframe_queue->lock, &irqL); } if (!(psta->state & WIFI_AP_STATE)) rtw_hal_set_odm_var(padapter, HAL_ODM_STA_INFO, psta, _FALSE); //release mac id for non-bc/mc station, rtw_release_macid(pstapriv->padapter, psta); #ifdef CONFIG_AP_MODE /* _enter_critical_bh(&pstapriv->asoc_list_lock, &irqL0); rtw_list_delete(&psta->asoc_list); _exit_critical_bh(&pstapriv->asoc_list_lock, &irqL0); */ _enter_critical_bh(&pstapriv->auth_list_lock, &irqL0); if (!rtw_is_list_empty(&psta->auth_list)) { rtw_list_delete(&psta->auth_list); pstapriv->auth_list_cnt--; } _exit_critical_bh(&pstapriv->auth_list_lock, &irqL0); psta->expire_to = 0; #ifdef CONFIG_ATMEL_RC_PATCH psta->flag_atmel_rc = 0; #endif psta->sleepq_ac_len = 0; psta->qos_info = 0; psta->max_sp_len = 0; psta->uapsd_bk = 0; psta->uapsd_be = 0; psta->uapsd_vi = 0; psta->uapsd_vo = 0; psta->has_legacy_ac = 0; #ifdef CONFIG_NATIVEAP_MLME pstapriv->sta_dz_bitmap &=~BIT(psta->aid); pstapriv->tim_bitmap &=~BIT(psta->aid); //rtw_indicate_sta_disassoc_event(padapter, psta); if ((psta->aid >0)&&(pstapriv->sta_aid[psta->aid - 1] == psta)) { pstapriv->sta_aid[psta->aid - 1] = NULL; psta->aid = 0; } #endif // CONFIG_NATIVEAP_MLME #ifdef CONFIG_TX_MCAST2UNI psta->under_exist_checking = 0; #endif // CONFIG_TX_MCAST2UNI #endif // CONFIG_AP_MODE _rtw_spinlock_free(&psta->lock); //_enter_critical_bh(&(pfree_sta_queue->lock), &irqL0); _enter_critical_bh(&(pstapriv->sta_hash_lock), &irqL0); rtw_list_insert_tail(&psta->list, get_list_head(pfree_sta_queue)); _exit_critical_bh(&(pstapriv->sta_hash_lock), &irqL0); //_exit_critical_bh(&(pfree_sta_queue->lock), &irqL0); exit: _func_exit_; return _SUCCESS; }
static s32 pre_recv_entry(union recv_frame *precvframe, u8 *pphy_status) { s32 ret=_SUCCESS; #ifdef CONFIG_CONCURRENT_MODE u8 *secondary_myid, *paddr1; union recv_frame *precvframe_if2 = NULL; _adapter *primary_padapter = precvframe->u.hdr.adapter; _adapter *secondary_padapter = primary_padapter->pbuddy_adapter; struct recv_priv *precvpriv = &primary_padapter->recvpriv; _queue *pfree_recv_queue = &precvpriv->free_recv_queue; u8 *pbuf = precvframe->u.hdr.rx_data; if(!secondary_padapter) return ret; paddr1 = GetAddr1Ptr(pbuf); if(IS_MCAST(paddr1) == _FALSE)//unicast packets { secondary_myid = adapter_mac_addr(secondary_padapter); if(_rtw_memcmp(paddr1, secondary_myid, ETH_ALEN)) { //change to secondary interface precvframe->u.hdr.adapter = secondary_padapter; } //ret = recv_entry(precvframe); } else // Handle BC/MC Packets { u8 clone = _TRUE; #if 0 u8 type, subtype, *paddr2, *paddr3; type = GetFrameType(pbuf); subtype = GetFrameSubType(pbuf); //bit(7)~bit(2) switch (type) { case WIFI_MGT_TYPE: //Handle BC/MC mgnt Packets if(subtype == WIFI_BEACON) { paddr3 = GetAddr3Ptr(precvframe->u.hdr.rx_data); if (check_fwstate(&secondary_padapter->mlmepriv, _FW_LINKED) && _rtw_memcmp(paddr3, get_bssid(&secondary_padapter->mlmepriv), ETH_ALEN)) { //change to secondary interface precvframe->u.hdr.adapter = secondary_padapter; clone = _FALSE; } if(check_fwstate(&primary_padapter->mlmepriv, _FW_LINKED) && _rtw_memcmp(paddr3, get_bssid(&primary_padapter->mlmepriv), ETH_ALEN)) { if(clone==_FALSE) { clone = _TRUE; } else { clone = _FALSE; } precvframe->u.hdr.adapter = primary_padapter; } if(check_fwstate(&primary_padapter->mlmepriv, _FW_UNDER_SURVEY|_FW_UNDER_LINKING) || check_fwstate(&secondary_padapter->mlmepriv, _FW_UNDER_SURVEY|_FW_UNDER_LINKING)) { clone = _TRUE; precvframe->u.hdr.adapter = primary_padapter; } } else if(subtype == WIFI_PROBEREQ) { //probe req frame is only for interface2 //change to secondary interface precvframe->u.hdr.adapter = secondary_padapter; clone = _FALSE; } break; case WIFI_CTRL_TYPE: // Handle BC/MC ctrl Packets break; case WIFI_DATA_TYPE: //Handle BC/MC data Packets //Notes: AP MODE never rx BC/MC data packets paddr2 = GetAddr2Ptr(precvframe->u.hdr.rx_data); if(_rtw_memcmp(paddr2, get_bssid(&secondary_padapter->mlmepriv), ETH_ALEN)) { //change to secondary interface precvframe->u.hdr.adapter = secondary_padapter; clone = _FALSE; } break; default: break; } #endif if(_TRUE == clone) { //clone/copy to if2 struct rx_pkt_attrib *pattrib = NULL; precvframe_if2 = rtw_alloc_recvframe(pfree_recv_queue); if(precvframe_if2) { precvframe_if2->u.hdr.adapter = secondary_padapter; _rtw_init_listhead(&precvframe_if2->u.hdr.list); precvframe_if2->u.hdr.precvbuf = NULL; //can't access the precvbuf for new arch. precvframe_if2->u.hdr.len=0; _rtw_memcpy(&precvframe_if2->u.hdr.attrib, &precvframe->u.hdr.attrib, sizeof(struct rx_pkt_attrib)); pattrib = &precvframe_if2->u.hdr.attrib; if(rtw_os_alloc_recvframe(secondary_padapter, precvframe_if2, pbuf, NULL) == _SUCCESS) { recvframe_put(precvframe_if2, pattrib->pkt_len); //recvframe_pull(precvframe_if2, drvinfo_sz + RXDESC_SIZE); if (pattrib->physt && pphy_status) rx_query_phy_status(precvframe_if2, pphy_status); ret = rtw_recv_entry(precvframe_if2); } else { rtw_free_recvframe(precvframe_if2, pfree_recv_queue); DBG_8192C("%s()-%d: alloc_skb() failed!\n", __FUNCTION__, __LINE__); } } } } //if (precvframe->u.hdr.attrib.physt) // rx_query_phy_status(precvframe, pphy_status); //ret = rtw_recv_entry(precvframe); #endif return ret; }
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); }
int rtw_recv_indicatepkt(_adapter *padapter, union recv_frame *precv_frame) { struct recv_priv *precvpriv; _queue *pfree_recv_queue; _pkt *skb; struct mlme_priv*pmlmepriv = &padapter->mlmepriv; #ifdef CONFIG_TCP_CSUM_OFFLOAD_RX struct rx_pkt_attrib *pattrib = &precv_frame->u.hdr.attrib; #endif #ifdef CONFIG_BR_EXT void *br_port = NULL; #endif _func_enter_; precvpriv = &(padapter->recvpriv); pfree_recv_queue = &(precvpriv->free_recv_queue); #ifdef CONFIG_DRVEXT_MODULE if (drvext_rx_handler(padapter, precv_frame->u.hdr.rx_data, precv_frame->u.hdr.len) == _SUCCESS) { goto _recv_indicatepkt_drop; } #endif skb = precv_frame->u.hdr.pkt; if(skb == NULL) { RT_TRACE(_module_recv_osdep_c_,_drv_err_,("rtw_recv_indicatepkt():skb==NULL something wrong!!!!\n")); goto _recv_indicatepkt_drop; } RT_TRACE(_module_recv_osdep_c_,_drv_info_,("rtw_recv_indicatepkt():skb != NULL !!!\n")); RT_TRACE(_module_recv_osdep_c_,_drv_info_,("rtw_recv_indicatepkt():precv_frame->u.hdr.rx_head=%p precv_frame->hdr.rx_data=%p\n", precv_frame->u.hdr.rx_head, precv_frame->u.hdr.rx_data)); RT_TRACE(_module_recv_osdep_c_,_drv_info_,("precv_frame->hdr.rx_tail=%p precv_frame->u.hdr.rx_end=%p precv_frame->hdr.len=%d \n", precv_frame->u.hdr.rx_tail, precv_frame->u.hdr.rx_end, precv_frame->u.hdr.len)); skb->data = precv_frame->u.hdr.rx_data; skb_set_tail_pointer(skb, precv_frame->u.hdr.len); skb->len = precv_frame->u.hdr.len; RT_TRACE(_module_recv_osdep_c_,_drv_info_,("\n skb->head=%p skb->data=%p skb->tail=%p skb->end=%p skb->len=%d\n", skb->head, skb->data, skb->tail, skb->end, skb->len)); if(check_fwstate(pmlmepriv, WIFI_AP_STATE) == _TRUE) { _pkt *pskb2=NULL; struct sta_info *psta = NULL; struct sta_priv *pstapriv = &padapter->stapriv; struct rx_pkt_attrib *pattrib = &precv_frame->u.hdr.attrib; int bmcast = IS_MCAST(pattrib->dst); //DBG_871X("bmcast=%d\n", bmcast); if(_rtw_memcmp(pattrib->dst, myid(&padapter->eeprompriv), ETH_ALEN)==_FALSE) { //DBG_871X("not ap psta=%p, addr=%pM\n", psta, pattrib->dst); if(bmcast) { psta = rtw_get_bcmc_stainfo(padapter); pskb2 = rtw_skb_clone(skb); } else { psta = rtw_get_stainfo(pstapriv, pattrib->dst); } if(psta) { struct net_device *pnetdev= (struct net_device*)padapter->pnetdev; //DBG_871X("directly forwarding to the rtw_xmit_entry\n"); //skb->ip_summed = CHECKSUM_NONE; skb->dev = pnetdev; #if (LINUX_VERSION_CODE>=KERNEL_VERSION(2,6,35)) skb_set_queue_mapping(skb, rtw_recv_select_queue(skb)); #endif //LINUX_VERSION_CODE>=KERNEL_VERSION(2,6,35) _rtw_xmit_entry(skb, pnetdev); if(bmcast) skb = pskb2; else goto _recv_indicatepkt_end; } } else// to APself { //DBG_871X("to APSelf\n"); } } #ifdef CONFIG_BR_EXT #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 35)) br_port = padapter->pnetdev->br_port; #else // (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 35)) rcu_read_lock(); br_port = rcu_dereference(padapter->pnetdev->rx_handler_data); rcu_read_unlock(); #endif // (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 35)) if( br_port && (check_fwstate(pmlmepriv, WIFI_STATION_STATE|WIFI_ADHOC_STATE) == _TRUE) ) { int nat25_handle_frame(_adapter *priv, struct sk_buff *skb); if (nat25_handle_frame(padapter, skb) == -1) { //priv->ext_stats.rx_data_drops++; //DEBUG_ERR("RX DROP: nat25_handle_frame fail!\n"); //return FAIL; #if 1 // bypass this frame to upper layer!! #else goto _recv_indicatepkt_drop; #endif } } #endif // CONFIG_BR_EXT #ifdef CONFIG_TCP_CSUM_OFFLOAD_RX if ( (pattrib->tcpchk_valid == 1) && (pattrib->tcp_chkrpt == 1) ) { skb->ip_summed = CHECKSUM_UNNECESSARY; //DBG_871X("CHECKSUM_UNNECESSARY \n"); } else { skb->ip_summed = CHECKSUM_NONE; //DBG_871X("CHECKSUM_NONE(%d, %d) \n", pattrib->tcpchk_valid, pattrib->tcp_chkrpt); } #else /* !CONFIG_TCP_CSUM_OFFLOAD_RX */ skb->ip_summed = CHECKSUM_NONE; #endif skb->dev = padapter->pnetdev; skb->protocol = eth_type_trans(skb, padapter->pnetdev); rtw_netif_rx(padapter->pnetdev, skb); _recv_indicatepkt_end: precv_frame->u.hdr.pkt = NULL; // pointers to NULL before rtw_free_recvframe() rtw_free_recvframe(precv_frame, pfree_recv_queue); RT_TRACE(_module_recv_osdep_c_,_drv_info_,("\n rtw_recv_indicatepkt :after rtw_netif_rx!!!!\n")); _func_exit_; return _SUCCESS; _recv_indicatepkt_drop: //enqueue back to free_recv_queue if(precv_frame) rtw_free_recvframe(precv_frame, pfree_recv_queue); return _FAIL; _func_exit_; }
int rtw_recv_indicatepkt(struct adapter *padapter, struct recv_frame *precv_frame) { struct recv_priv *precvpriv; struct __queue *pfree_recv_queue; struct sk_buff *skb; struct mlme_priv *pmlmepriv = &padapter->mlmepriv; precvpriv = &(padapter->recvpriv); pfree_recv_queue = &(precvpriv->free_recv_queue); skb = precv_frame->pkt; if (!skb) { RT_TRACE(_module_recv_osdep_c_, _drv_err_, ("rtw_recv_indicatepkt():skb == NULL something wrong!!!!\n")); goto _recv_indicatepkt_drop; } RT_TRACE(_module_recv_osdep_c_, _drv_info_, ("rtw_recv_indicatepkt():skb != NULL !!!\n")); RT_TRACE(_module_recv_osdep_c_, _drv_info_, ("rtw_recv_indicatepkt():precv_frame->rx_head =%p precv_frame->hdr.rx_data =%p\n", precv_frame->rx_head, precv_frame->rx_data)); RT_TRACE(_module_recv_osdep_c_, _drv_info_, ("precv_frame->hdr.rx_tail =%p precv_frame->rx_end =%p precv_frame->hdr.len =%d\n", precv_frame->rx_tail, precv_frame->rx_end, precv_frame->len)); skb->data = precv_frame->rx_data; skb_set_tail_pointer(skb, precv_frame->len); skb->len = precv_frame->len; RT_TRACE(_module_recv_osdep_c_, _drv_info_, ("skb->head =%p skb->data =%p skb->tail =%p skb->end =%p skb->len =%d\n", skb->head, skb->data, skb_tail_pointer(skb), skb_end_pointer(skb), skb->len)); if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) { struct sk_buff *pskb2 = NULL; struct sta_info *psta = NULL; struct sta_priv *pstapriv = &padapter->stapriv; struct rx_pkt_attrib *pattrib = &precv_frame->attrib; int bmcast = IS_MCAST(pattrib->dst); if (memcmp(pattrib->dst, myid(&padapter->eeprompriv), ETH_ALEN)) { if (bmcast) { psta = rtw_get_bcmc_stainfo(padapter); pskb2 = skb_clone(skb, GFP_ATOMIC); } else { psta = rtw_get_stainfo(pstapriv, pattrib->dst); } if (psta) { struct net_device *pnetdev; pnetdev = (struct net_device *)padapter->pnetdev; skb->dev = pnetdev; skb_set_queue_mapping(skb, rtw_recv_select_queue(skb)); rtw_xmit_entry(skb, pnetdev); if (bmcast) skb = pskb2; else goto _recv_indicatepkt_end; } } } rcu_read_lock(); rcu_dereference(padapter->pnetdev->rx_handler_data); rcu_read_unlock(); skb->ip_summed = CHECKSUM_NONE; skb->dev = padapter->pnetdev; skb->protocol = eth_type_trans(skb, padapter->pnetdev); netif_rx(skb); _recv_indicatepkt_end: /* pointers to NULL before rtw_free_recvframe() */ precv_frame->pkt = NULL; rtw_free_recvframe(precv_frame, pfree_recv_queue); RT_TRACE(_module_recv_osdep_c_, _drv_info_, ("\n rtw_recv_indicatepkt :after netif_rx!!!!\n")); return _SUCCESS; _recv_indicatepkt_drop: /* enqueue back to free_recv_queue */ rtw_free_recvframe(precv_frame, pfree_recv_queue); return _FAIL; }
/* using pstapriv->sta_hash_lock to protect */ u32 rtw_free_stainfo(struct adapter *padapter, struct sta_info *psta) { int i; struct __queue *pfree_sta_queue; struct recv_reorder_ctrl *preorder_ctrl; struct sta_xmit_priv *pstaxmitpriv; struct xmit_priv *pxmitpriv = &padapter->xmitpriv; struct sta_priv *pstapriv = &padapter->stapriv; if (!psta) goto exit; pfree_sta_queue = &pstapriv->free_sta_queue; pstaxmitpriv = &psta->sta_xmitpriv; spin_lock_bh(&pxmitpriv->lock); rtw_free_xmitframe_queue(pxmitpriv, &psta->sleep_q); psta->sleepq_len = 0; rtw_free_xmitframe_queue(pxmitpriv, &pstaxmitpriv->vo_q.sta_pending); list_del_init(&pstaxmitpriv->vo_q.tx_pending); rtw_free_xmitframe_queue(pxmitpriv, &pstaxmitpriv->vi_q.sta_pending); list_del_init(&pstaxmitpriv->vi_q.tx_pending); rtw_free_xmitframe_queue(pxmitpriv, &pstaxmitpriv->bk_q.sta_pending); list_del_init(&pstaxmitpriv->bk_q.tx_pending); rtw_free_xmitframe_queue(pxmitpriv, &pstaxmitpriv->be_q.sta_pending); list_del_init(&pstaxmitpriv->be_q.tx_pending); spin_unlock_bh(&pxmitpriv->lock); list_del_init(&psta->hash_list); RT_TRACE(_module_rtl871x_sta_mgt_c_, _drv_err_, ("\n free number_%d stainfo with hwaddr=0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x\n", pstapriv->asoc_sta_count, psta->hwaddr[0], psta->hwaddr[1], psta->hwaddr[2], psta->hwaddr[3], psta->hwaddr[4], psta->hwaddr[5])); pstapriv->asoc_sta_count--; /* re-init sta_info; 20061114 */ _rtw_init_sta_xmit_priv(&psta->sta_xmitpriv); _rtw_init_sta_recv_priv(&psta->sta_recvpriv); del_timer_sync(&psta->addba_retry_timer); /* for A-MPDU Rx reordering buffer control, cancel reordering_ctrl_timer */ for (i = 0; i < 16; i++) { struct list_head *phead, *plist; struct recv_frame *prframe; struct __queue *ppending_recvframe_queue; struct __queue *pfree_recv_queue = &padapter->recvpriv.free_recv_queue; preorder_ctrl = &psta->recvreorder_ctrl[i]; del_timer_sync(&preorder_ctrl->reordering_ctrl_timer); ppending_recvframe_queue = &preorder_ctrl->pending_recvframe_queue; spin_lock_bh(&ppending_recvframe_queue->lock); phead = get_list_head(ppending_recvframe_queue); plist = phead->next; while (!list_empty(phead)) { prframe = container_of(plist, struct recv_frame, list); plist = plist->next; list_del_init(&prframe->list); rtw_free_recvframe(prframe, pfree_recv_queue); } spin_unlock_bh(&ppending_recvframe_queue->lock); } if (!(psta->state & WIFI_AP_STATE)) rtw_hal_set_odm_var(padapter, HAL_ODM_STA_INFO, psta, false); #ifdef CONFIG_88EU_AP_MODE spin_lock_bh(&pstapriv->auth_list_lock); if (!list_empty(&psta->auth_list)) { list_del_init(&psta->auth_list); pstapriv->auth_list_cnt--; } spin_unlock_bh(&pstapriv->auth_list_lock); psta->expire_to = 0; psta->sleepq_ac_len = 0; psta->qos_info = 0; psta->max_sp_len = 0; psta->uapsd_bk = 0; psta->uapsd_be = 0; psta->uapsd_vi = 0; psta->uapsd_vo = 0; psta->has_legacy_ac = 0; pstapriv->sta_dz_bitmap &= ~BIT(psta->aid); pstapriv->tim_bitmap &= ~BIT(psta->aid); if ((psta->aid > 0) && (pstapriv->sta_aid[psta->aid - 1] == psta)) { pstapriv->sta_aid[psta->aid - 1] = NULL; psta->aid = 0; } psta->under_exist_checking = 0; #endif /* CONFIG_88EU_AP_MODE */ spin_lock_bh(&pfree_sta_queue->lock); list_add_tail(&psta->list, get_list_head(pfree_sta_queue)); spin_unlock_bh(&pfree_sta_queue->lock); exit: return _SUCCESS; }
int rtw_recv_indicatepkt(_adapter *padapter, union recv_frame *precv_frame) { struct recv_priv *precvpriv; _queue *pfree_recv_queue; _pkt *skb; struct mlme_priv*pmlmepriv = &padapter->mlmepriv; struct rx_pkt_attrib *pattrib; if(NULL == precv_frame) goto _recv_indicatepkt_drop; DBG_COUNTER(padapter->rx_logs.os_indicate); pattrib = &precv_frame->u.hdr.attrib; precvpriv = &(padapter->recvpriv); pfree_recv_queue = &(precvpriv->free_recv_queue); #ifdef CONFIG_DRVEXT_MODULE if (drvext_rx_handler(padapter, precv_frame->u.hdr.rx_data, precv_frame->u.hdr.len) == _SUCCESS) { goto _recv_indicatepkt_drop; } #endif #ifdef CONFIG_WAPI_SUPPORT if (rtw_wapi_check_for_drop(padapter,precv_frame)) { WAPI_TRACE(WAPI_ERR, "%s(): Rx Reorder Drop case!!\n", __FUNCTION__); goto _recv_indicatepkt_drop; } #endif skb = precv_frame->u.hdr.pkt; if(skb == NULL) { RT_TRACE(_module_recv_osdep_c_,_drv_err_,("rtw_recv_indicatepkt():skb==NULL something wrong!!!!\n")); goto _recv_indicatepkt_drop; } RT_TRACE(_module_recv_osdep_c_,_drv_info_,("rtw_recv_indicatepkt():skb != NULL !!!\n")); RT_TRACE(_module_recv_osdep_c_,_drv_info_,("rtw_recv_indicatepkt():precv_frame->u.hdr.rx_head=%p precv_frame->hdr.rx_data=%p\n", precv_frame->u.hdr.rx_head, precv_frame->u.hdr.rx_data)); RT_TRACE(_module_recv_osdep_c_,_drv_info_,("precv_frame->hdr.rx_tail=%p precv_frame->u.hdr.rx_end=%p precv_frame->hdr.len=%d \n", precv_frame->u.hdr.rx_tail, precv_frame->u.hdr.rx_end, precv_frame->u.hdr.len)); skb->data = precv_frame->u.hdr.rx_data; skb_set_tail_pointer(skb, precv_frame->u.hdr.len); skb->len = precv_frame->u.hdr.len; RT_TRACE(_module_recv_osdep_c_,_drv_info_,("\n skb->head=%p skb->data=%p skb->tail=%p skb->end=%p skb->len=%d\n", skb->head, skb->data, skb_tail_pointer(skb), skb_end_pointer(skb), skb->len)); #ifdef CONFIG_AUTO_AP_MODE #if 1 //for testing #if 1 if (0x8899 == pattrib->eth_type) { rtw_os_ksocket_send(padapter, precv_frame); //goto _recv_indicatepkt_drop; } #else if (0x8899 == pattrib->eth_type) { rtw_auto_ap_mode_rx(padapter, precv_frame); goto _recv_indicatepkt_end; } #endif #endif #endif //CONFIG_AUTO_AP_MODE rtw_os_recv_indicate_pkt(padapter, skb, pattrib); _recv_indicatepkt_end: precv_frame->u.hdr.pkt = NULL; // pointers to NULL before rtw_free_recvframe() rtw_free_recvframe(precv_frame, pfree_recv_queue); RT_TRACE(_module_recv_osdep_c_,_drv_info_,("\n rtw_recv_indicatepkt :after rtw_os_recv_indicate_pkt!!!!\n")); return _SUCCESS; _recv_indicatepkt_drop: //enqueue back to free_recv_queue if(precv_frame) rtw_free_recvframe(precv_frame, pfree_recv_queue); DBG_COUNTER(padapter->rx_logs.os_indicate_err); return _FAIL; }
int rtw_recv_indicatepkt(struct adapter *padapter, struct recv_frame *precv_frame) { struct recv_priv *precvpriv; struct __queue *pfree_recv_queue; struct sk_buff *skb; struct mlme_priv *pmlmepriv = &padapter->mlmepriv; precvpriv = &padapter->recvpriv; pfree_recv_queue = &precvpriv->free_recv_queue; skb = precv_frame->pkt; if (!skb) { RT_TRACE(_module_recv_osdep_c_, _drv_err_, ("%s():skb == NULL something wrong!!!!\n", __func__)); goto _recv_indicatepkt_drop; } if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) { struct sk_buff *pskb2 = NULL; struct sta_info *psta = NULL; struct sta_priv *pstapriv = &padapter->stapriv; struct rx_pkt_attrib *pattrib = &precv_frame->attrib; bool mcast = is_multicast_ether_addr(pattrib->dst); if (memcmp(pattrib->dst, myid(&padapter->eeprompriv), ETH_ALEN)) { if (mcast) { psta = rtw_get_bcmc_stainfo(padapter); pskb2 = skb_clone(skb, GFP_ATOMIC); } else { psta = rtw_get_stainfo(pstapriv, pattrib->dst); } if (psta) { struct net_device *pnetdev; pnetdev = (struct net_device *)padapter->pnetdev; skb->dev = pnetdev; skb_set_queue_mapping(skb, rtw_recv_select_queue(skb)); rtw_xmit_entry(skb, pnetdev); if (mcast) skb = pskb2; else goto _recv_indicatepkt_end; } } } skb->ip_summed = CHECKSUM_NONE; skb->dev = padapter->pnetdev; skb->protocol = eth_type_trans(skb, padapter->pnetdev); netif_rx(skb); _recv_indicatepkt_end: /* pointers to NULL before rtw_free_recvframe() */ precv_frame->pkt = NULL; rtw_free_recvframe(precv_frame, pfree_recv_queue); RT_TRACE(_module_recv_osdep_c_, _drv_info_, ("\n %s :after netif_rx!!!!\n", __func__)); return _SUCCESS; _recv_indicatepkt_drop: /* enqueue back to free_recv_queue */ rtw_free_recvframe(precv_frame, pfree_recv_queue); return _FAIL; }