static struct recv_buf *sd_recv_rxfifo(struct adapter *adapter, u32 size) { u32 readsize, ret; u8 *readbuf; struct recv_priv *recv_priv; struct recv_buf *recvbuf; /* Patch for some SDIO Host 4 bytes issue */ /* ex. RK3188 */ readsize = RND4(size); /* 3 1. alloc recvbuf */ recv_priv = &adapter->recvpriv; recvbuf = rtw_dequeue_recvbuf(&recv_priv->free_recv_buf_queue); if (!recvbuf) { DBG_871X_LEVEL(_drv_err_, "%s: alloc recvbuf FAIL!\n", __func__); return NULL; } /* 3 2. alloc skb */ if (!recvbuf->pskb) { SIZE_PTR tmpaddr = 0; SIZE_PTR alignment = 0; recvbuf->pskb = rtw_skb_alloc(MAX_RECVBUF_SZ + RECVBUFF_ALIGN_SZ); if (recvbuf->pskb) { recvbuf->pskb->dev = adapter->pnetdev; tmpaddr = (SIZE_PTR)recvbuf->pskb->data; alignment = tmpaddr & (RECVBUFF_ALIGN_SZ-1); skb_reserve(recvbuf->pskb, (RECVBUFF_ALIGN_SZ - alignment)); } if (!recvbuf->pskb) { DBG_871X("%s: alloc_skb fail! read =%d\n", __func__, readsize); return NULL; } } /* 3 3. read data from rxfifo */ readbuf = recvbuf->pskb->data; ret = sdio_read_port(&adapter->iopriv.intf, WLAN_RX0FF_DEVICE_ID, readsize, readbuf); if (ret == _FAIL) { RT_TRACE(_module_hci_ops_os_c_, _drv_err_, ("%s: read port FAIL!\n", __func__)); return NULL; } /* 3 4. init recvbuf */ recvbuf->len = size; recvbuf->phead = recvbuf->pskb->head; recvbuf->pdata = recvbuf->pskb->data; skb_set_tail_pointer(recvbuf->pskb, size); recvbuf->ptail = skb_tail_pointer(recvbuf->pskb); recvbuf->pend = skb_end_pointer(recvbuf->pskb); return recvbuf; }
static struct recv_buf* sd_recv_rxfifo(PADAPTER padapter, u32 size) { u32 readsize, ret; u8 *preadbuf; struct recv_priv *precvpriv; struct recv_buf *precvbuf; readsize = size; //3 1. alloc recvbuf precvpriv = &padapter->recvpriv; precvbuf = rtw_dequeue_recvbuf(&precvpriv->free_recv_buf_queue); if (precvbuf == NULL) { RT_TRACE(_module_hci_ops_os_c_, _drv_err_, ("%s: alloc recvbuf FAIL!\n", __FUNCTION__)); return NULL; } //3 2. alloc skb if (precvbuf->pskb == NULL) { SIZE_PTR tmpaddr=0; SIZE_PTR alignment=0; precvbuf->pskb = rtw_skb_alloc(MAX_RECVBUF_SZ + RECVBUFF_ALIGN_SZ); if(precvbuf->pskb) { precvbuf->pskb->dev = padapter->pnetdev; tmpaddr = (SIZE_PTR)precvbuf->pskb->data; alignment = tmpaddr & (RECVBUFF_ALIGN_SZ-1); skb_reserve(precvbuf->pskb, (RECVBUFF_ALIGN_SZ - alignment)); } if (precvbuf->pskb == NULL) { DBG_871X("%s: alloc_skb fail! read=%d\n", __FUNCTION__, readsize); return NULL; } } //3 3. read data from rxfifo preadbuf = precvbuf->pskb->data; // rtw_read_port(padapter, WLAN_RX0FF_DEVICE_ID, readsize, preadbuf); ret = sdio_read_port(&padapter->iopriv.intf, WLAN_RX0FF_DEVICE_ID, readsize, preadbuf); if (ret == _FAIL) { RT_TRACE(_module_hci_ops_os_c_, _drv_err_, ("%s: read port FAIL!\n", __FUNCTION__)); return NULL; } //3 4. init recvbuf precvbuf->len = readsize; precvbuf->phead = precvbuf->pskb->head; precvbuf->pdata = precvbuf->pskb->data; skb_set_tail_pointer(precvbuf->pskb, readsize); precvbuf->ptail = skb_tail_pointer(precvbuf->pskb); precvbuf->pend = skb_end_pointer(precvbuf->pskb); return precvbuf; }
_pkt *rtw_os_alloc_msdu_pkt(union recv_frame *prframe, u16 nSubframe_Length, u8 *pdata) { u16 eth_type; u8 *data_ptr; _pkt *sub_skb; struct rx_pkt_attrib *pattrib; pattrib = &prframe->u.hdr.attrib; #ifdef CONFIG_SKB_COPY sub_skb = rtw_skb_alloc(nSubframe_Length + 12); if(sub_skb) { skb_reserve(sub_skb, 12); data_ptr = (u8 *)skb_put(sub_skb, nSubframe_Length); _rtw_memcpy(data_ptr, (pdata + ETH_HLEN), nSubframe_Length); } else #endif // CONFIG_SKB_COPY { sub_skb = rtw_skb_clone(prframe->u.hdr.pkt); if(sub_skb) { sub_skb->data = pdata + ETH_HLEN; sub_skb->len = nSubframe_Length; skb_set_tail_pointer(sub_skb, nSubframe_Length); } else { DBG_871X("%s(): rtw_skb_clone() Fail!!!\n",__FUNCTION__); return NULL; } } eth_type = RTW_GET_BE16(&sub_skb->data[6]); if (sub_skb->len >= 8 && ((_rtw_memcmp(sub_skb->data, rtw_rfc1042_header, SNAP_SIZE) && eth_type != ETH_P_AARP && eth_type != ETH_P_IPX) || _rtw_memcmp(sub_skb->data, rtw_bridge_tunnel_header, SNAP_SIZE) )) { /* remove RFC1042 or Bridge-Tunnel encapsulation and replace EtherType */ skb_pull(sub_skb, SNAP_SIZE); _rtw_memcpy(skb_push(sub_skb, ETH_ALEN), pattrib->src, ETH_ALEN); _rtw_memcpy(skb_push(sub_skb, ETH_ALEN), pattrib->dst, ETH_ALEN); } else { u16 len; /* Leave Ethernet header part of hdr and full payload */ len = htons(sub_skb->len); _rtw_memcpy(skb_push(sub_skb, 2), &len, 2); _rtw_memcpy(skb_push(sub_skb, ETH_ALEN), pattrib->src, ETH_ALEN); _rtw_memcpy(skb_push(sub_skb, ETH_ALEN), pattrib->dst, ETH_ALEN); } return sub_skb; }
static struct recv_buf* sd_recv_rxfifo(PADAPTER padapter, u32 size) { u32 readsize, allocsize, ret; u8 *preadbuf; _pkt *ppkt; struct recv_priv *precvpriv; struct recv_buf *precvbuf; readsize = size; //3 1. alloc skb // align to block size allocsize = _RND(readsize, adapter_to_dvobj(padapter)->intf_data.block_transfer_len); ppkt = rtw_skb_alloc(allocsize); if (ppkt == NULL) { RT_TRACE(_module_hci_ops_os_c_, _drv_err_, ("%s: alloc_skb fail! alloc=%d read=%d\n", __FUNCTION__, allocsize, readsize)); return NULL; } //3 2. read data from rxfifo preadbuf = skb_put(ppkt, readsize); // rtw_read_port(padapter, WLAN_RX0FF_DEVICE_ID, readsize, preadbuf); ret = sdio_read_port(&padapter->iopriv.intf, WLAN_RX0FF_DEVICE_ID, readsize, preadbuf); if (ret == _FAIL) { rtw_skb_free(ppkt); RT_TRACE(_module_hci_ops_os_c_, _drv_err_, ("%s: read port FAIL!\n", __FUNCTION__)); return NULL; } //3 3. alloc recvbuf precvpriv = &padapter->recvpriv; precvbuf = rtw_dequeue_recvbuf(&precvpriv->free_recv_buf_queue); if (precvbuf == NULL) { rtw_skb_free(ppkt); RT_TRACE(_module_hci_ops_os_c_, _drv_err_, ("%s: alloc recvbuf FAIL!\n", __FUNCTION__)); return NULL; } //3 4. init recvbuf precvbuf->pskb = ppkt; precvbuf->len = ppkt->len; precvbuf->phead = ppkt->head; precvbuf->pdata = ppkt->data; precvbuf->ptail = skb_tail_pointer(precvbuf->pskb); precvbuf->pend = skb_end_pointer(precvbuf->pskb); return precvbuf; }
int rtw_os_alloc_recvframe(_adapter *padapter, union recv_frame *precvframe, u8 *pdata, _pkt *pskb) { int res = _SUCCESS; u8 shift_sz = 0; u32 skb_len, alloc_sz; _pkt *pkt_copy = NULL; struct rx_pkt_attrib *pattrib = &precvframe->u.hdr.attrib; if(pdata == NULL) { precvframe->u.hdr.pkt = NULL; res = _FAIL; return res; } // Modified by Albert 20101213 // For 8 bytes IP header alignment. shift_sz = pattrib->qos ? 6:0;// Qos data, wireless lan header length is 26 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. alloc_sz = (skb_len <= 1650) ? 1664:(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; precvframe->u.hdr.rx_head = pkt_copy->data; precvframe->u.hdr.rx_end = pkt_copy->data + alloc_sz; 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, pdata, skb_len); precvframe->u.hdr.rx_data = precvframe->u.hdr.rx_tail = pkt_copy->data; } else { #ifdef CONFIG_USE_USB_BUFFER_ALLOC_RX DBG_871X("%s:can not allocate memory for skb copy\n", __FUNCTION__); precvframe->u.hdr.pkt = NULL; //rtw_free_recvframe(precvframe, pfree_recv_queue); //goto _exit_recvbuf2recvframe; res = _FAIL; #else if((pattrib->mfrag == 1)&&(pattrib->frag_num == 0)) { DBG_871X("%s: alloc_skb fail , drop frag frame \n", __FUNCTION__); //rtw_free_recvframe(precvframe, pfree_recv_queue); res = _FAIL; goto exit_rtw_os_recv_resource_alloc; } if(pskb == NULL) { res = _FAIL; goto exit_rtw_os_recv_resource_alloc; } precvframe->u.hdr.pkt = rtw_skb_clone(pskb); if(precvframe->u.hdr.pkt) { precvframe->u.hdr.rx_head = precvframe->u.hdr.rx_data = precvframe->u.hdr.rx_tail = pdata; precvframe->u.hdr.rx_end = pdata + alloc_sz; } else { DBG_871X("%s: rtw_skb_clone fail\n", __FUNCTION__); //rtw_free_recvframe(precvframe, pfree_recv_queue); //goto _exit_recvbuf2recvframe; res = _FAIL; } #endif } exit_rtw_os_recv_resource_alloc: return res; }
s32 rtl8812au_hostap_mgnt_xmit_entry(_adapter *padapter, _pkt *pkt) { #ifdef PLATFORM_LINUX u16 fc; int rc, len, pipe; unsigned int bmcst, tid, qsel; struct sk_buff *skb, *pxmit_skb; struct urb *urb; unsigned char *pxmitbuf; struct tx_desc *ptxdesc; struct rtw_ieee80211_hdr *tx_hdr; struct hostapd_priv *phostapdpriv = padapter->phostapdpriv; struct net_device *pnetdev = padapter->pnetdev; HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter); struct dvobj_priv *pdvobj = adapter_to_dvobj(padapter); //DBG_8192C("%s\n", __FUNCTION__); skb = pkt; len = skb->len; tx_hdr = (struct rtw_ieee80211_hdr *)(skb->data); fc = le16_to_cpu(tx_hdr->frame_ctl); bmcst = IS_MCAST(tx_hdr->addr1); if ((fc & RTW_IEEE80211_FCTL_FTYPE) != RTW_IEEE80211_FTYPE_MGMT) goto _exit; pxmit_skb = rtw_skb_alloc(len + TXDESC_SIZE); if(!pxmit_skb) goto _exit; pxmitbuf = pxmit_skb->data; urb = usb_alloc_urb(0, GFP_ATOMIC); if (!urb) { goto _exit; } // ----- fill tx desc ----- ptxdesc = (struct tx_desc *)pxmitbuf; _rtw_memset(ptxdesc, 0, sizeof(*ptxdesc)); //offset 0 ptxdesc->txdw0 |= cpu_to_le32(len&0x0000ffff); ptxdesc->txdw0 |= cpu_to_le32(((TXDESC_SIZE+OFFSET_SZ)<<OFFSET_SHT)&0x00ff0000);//default = 32 bytes for TX Desc ptxdesc->txdw0 |= cpu_to_le32(OWN | FSG | LSG); if(bmcst) { ptxdesc->txdw0 |= cpu_to_le32(BIT(24)); } //offset 4 ptxdesc->txdw1 |= cpu_to_le32(0x00);//MAC_ID ptxdesc->txdw1 |= cpu_to_le32((0x12<<QSEL_SHT)&0x00001f00); ptxdesc->txdw1 |= cpu_to_le32((0x06<< 16) & 0x000f0000);//b mode //offset 8 //offset 12 ptxdesc->txdw3 |= cpu_to_le32((le16_to_cpu(tx_hdr->seq_ctl)<<16)&0xffff0000); //offset 16 ptxdesc->txdw4 |= cpu_to_le32(BIT(8));//driver uses rate //offset 20 //HW append seq ptxdesc->txdw4 |= cpu_to_le32(BIT(7)); // Hw set sequence number ptxdesc->txdw3 |= cpu_to_le32((8 <<28)); //set bit3 to 1. Suugested by TimChen. 2009.12.29. rtl8188eu_cal_txdesc_chksum(ptxdesc); // ----- end of fill tx desc ----- // skb_put(pxmit_skb, len + TXDESC_SIZE); pxmitbuf = pxmitbuf + TXDESC_SIZE; _rtw_memcpy(pxmitbuf, skb->data, len); //DBG_8192C("mgnt_xmit, len=%x\n", pxmit_skb->len); // ----- prepare urb for submit ----- //translate DMA FIFO addr to pipehandle //pipe = ffaddr2pipehdl(pdvobj, MGT_QUEUE_INX); pipe = usb_sndbulkpipe(pdvobj->pusbdev, pHalData->Queue2EPNum[(u8)MGT_QUEUE_INX]&0x0f); usb_fill_bulk_urb(urb, pdvobj->pusbdev, pipe, pxmit_skb->data, pxmit_skb->len, rtl8192cu_hostap_mgnt_xmit_cb, pxmit_skb); urb->transfer_flags |= URB_ZERO_PACKET; usb_anchor_urb(urb, &phostapdpriv->anchored); rc = usb_submit_urb(urb, GFP_ATOMIC); if (rc < 0) { usb_unanchor_urb(urb); kfree_skb(skb); } usb_free_urb(urb); _exit: rtw_skb_free(skb); #endif return 0; }
/* * Initialize recv private variable for hardware dependent * 1. recv buf * 2. recv tasklet * */ s32 rtl8723bs_init_recv_priv(PADAPTER padapter) { s32 res; u32 i, n; struct recv_priv *precvpriv; struct recv_buf *precvbuf; res = _SUCCESS; precvpriv = &padapter->recvpriv; //3 1. init recv buffer _rtw_init_queue(&precvpriv->free_recv_buf_queue); _rtw_init_queue(&precvpriv->recv_buf_pending_queue); n = NR_RECVBUFF * sizeof(struct recv_buf) + 4; precvpriv->pallocated_recv_buf = rtw_zmalloc(n); if (precvpriv->pallocated_recv_buf == NULL) { res = _FAIL; RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("alloc recv_buf fail!\n")); goto exit; } precvpriv->precv_buf = (u8*)N_BYTE_ALIGMENT((SIZE_PTR)(precvpriv->pallocated_recv_buf), 4); // init each recv buffer precvbuf = (struct recv_buf*)precvpriv->precv_buf; for (i = 0; i < NR_RECVBUFF; i++) { res = initrecvbuf(precvbuf, padapter); if (res == _FAIL) break; res = rtw_os_recvbuf_resource_alloc(padapter, precvbuf); if (res == _FAIL) { freerecvbuf(precvbuf); break; } #ifdef CONFIG_SDIO_RX_COPY if (precvbuf->pskb == NULL) { SIZE_PTR tmpaddr=0; SIZE_PTR alignment=0; precvbuf->pskb = rtw_skb_alloc(MAX_RECVBUF_SZ + RECVBUFF_ALIGN_SZ); if(precvbuf->pskb) { precvbuf->pskb->dev = padapter->pnetdev; tmpaddr = (SIZE_PTR)precvbuf->pskb->data; alignment = tmpaddr & (RECVBUFF_ALIGN_SZ-1); skb_reserve(precvbuf->pskb, (RECVBUFF_ALIGN_SZ - alignment)); } if (precvbuf->pskb == NULL) { DBG_871X("%s: alloc_skb fail!\n", __FUNCTION__); } } #endif rtw_list_insert_tail(&precvbuf->list, &precvpriv->free_recv_buf_queue.queue); precvbuf++; } precvpriv->free_recv_buf_queue_cnt = i; if (res == _FAIL) goto initbuferror; //3 2. init tasklet #ifdef PLATFORM_LINUX tasklet_init(&precvpriv->recv_tasklet, (void(*)(unsigned long))rtl8723bs_recv_tasklet, (unsigned long)padapter); #endif goto exit; initbuferror: precvbuf = (struct recv_buf*)precvpriv->precv_buf; if (precvbuf) { n = precvpriv->free_recv_buf_queue_cnt; precvpriv->free_recv_buf_queue_cnt = 0; for (i = 0; i < n ; i++) { rtw_list_delete(&precvbuf->list); rtw_os_recvbuf_resource_free(padapter, precvbuf); freerecvbuf(precvbuf); precvbuf++; } precvpriv->precv_buf = NULL; } if (precvpriv->pallocated_recv_buf) { n = NR_RECVBUFF * sizeof(struct recv_buf) + 4; rtw_mfree(precvpriv->pallocated_recv_buf, n); precvpriv->pallocated_recv_buf = NULL; } exit: return res; }
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 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); }
u32 usb_read_port(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *rmem) { int err; unsigned int pipe; u32 ret = _FAIL; PURB purb = NULL; struct recv_buf *precvbuf = (struct recv_buf *)rmem; _adapter *adapter = pintfhdl->padapter; struct dvobj_priv *pdvobj = adapter_to_dvobj(adapter); //struct pwrctrl_priv *pwrctl = dvobj_to_pwrctl(pdvobj); struct recv_priv *precvpriv = &adapter->recvpriv; struct usb_device *pusbd = pdvobj->pusbdev; _func_enter_; if (RTW_CANNOT_RX(adapter) || (precvbuf == NULL)) { RT_TRACE(_module_hci_ops_os_c_,_drv_err_,("usb_read_port:( RTW_CANNOT_RX ) || precvbuf == NULL!!!\n")); goto exit; } usb_init_recvbuf(adapter, precvbuf); if (precvbuf->pskb == NULL) { SIZE_PTR tmpaddr = 0; SIZE_PTR alignment = 0; if (NULL != (precvbuf->pskb = skb_dequeue(&precvpriv->free_recv_skb_queue))) goto recv_buf_hook; #ifndef CONFIG_FIX_NR_BULKIN_BUFFER precvbuf->pskb = rtw_skb_alloc(MAX_RECVBUF_SZ + RECVBUFF_ALIGN_SZ); #endif if (precvbuf->pskb == NULL) { if (0) DBG_871X("usb_read_port() enqueue precvbuf=%p \n", precvbuf); /* enqueue precvbuf and wait for free skb */ rtw_enqueue_recvbuf(precvbuf, &precvpriv->recv_buf_pending_queue); goto exit; } tmpaddr = (SIZE_PTR)precvbuf->pskb->data; alignment = tmpaddr & (RECVBUFF_ALIGN_SZ-1); skb_reserve(precvbuf->pskb, (RECVBUFF_ALIGN_SZ - alignment)); } recv_buf_hook: precvbuf->phead = precvbuf->pskb->head; precvbuf->pdata = precvbuf->pskb->data; precvbuf->ptail = skb_tail_pointer(precvbuf->pskb); precvbuf->pend = skb_end_pointer(precvbuf->pskb); precvbuf->pbuf = precvbuf->pskb->data; purb = precvbuf->purb; /* translate DMA FIFO addr to pipehandle */ pipe = ffaddr2pipehdl(pdvobj, addr); usb_fill_bulk_urb(purb, pusbd, pipe, precvbuf->pbuf, MAX_RECVBUF_SZ, usb_read_port_complete, precvbuf); err = usb_submit_urb(purb, GFP_ATOMIC); if (err && err != (-EPERM)) { DBG_871X("cannot submit rx in-token(err = 0x%08x),urb_status = %d\n" , err, purb->status); goto exit; } ATOMIC_INC(&(precvpriv->rx_pending_cnt)); ret = _SUCCESS; exit: _func_exit_; return ret; }
int rtl8188eu_init_recv_priv(_adapter *padapter) { struct recv_priv *precvpriv = &padapter->recvpriv; int i, res = _SUCCESS; struct recv_buf *precvbuf; #ifdef CONFIG_RECV_THREAD_MODE _rtw_init_sema(&precvpriv->recv_sema, 0);//will be removed _rtw_init_sema(&precvpriv->terminate_recvthread_sema, 0);//will be removed #endif tasklet_init(&precvpriv->recv_tasklet, (void(*)(unsigned long))rtl8188eu_recv_tasklet, (unsigned long)padapter); #ifdef CONFIG_USB_INTERRUPT_IN_PIPE precvpriv->int_in_urb = usb_alloc_urb(0, GFP_KERNEL); if(precvpriv->int_in_urb == NULL){ res= _FAIL; DBG_8192C("alloc_urb for interrupt in endpoint fail !!!!\n"); goto exit; } precvpriv->int_in_buf = rtw_zmalloc(INTERRUPT_MSG_FORMAT_LEN); if(precvpriv->int_in_buf == NULL){ res= _FAIL; DBG_8192C("alloc_mem for interrupt in endpoint fail !!!!\n"); goto exit; } #endif //init recv_buf _rtw_init_queue(&precvpriv->free_recv_buf_queue); #ifdef CONFIG_USE_USB_BUFFER_ALLOC_RX _rtw_init_queue(&precvpriv->recv_buf_pending_queue); #endif // CONFIG_USE_USB_BUFFER_ALLOC_RX precvpriv->pallocated_recv_buf = rtw_zmalloc(NR_RECVBUFF *sizeof(struct recv_buf) + 4); if(precvpriv->pallocated_recv_buf==NULL){ res= _FAIL; RT_TRACE(_module_rtl871x_recv_c_,_drv_err_,("alloc recv_buf fail!\n")); goto exit; } memset(precvpriv->pallocated_recv_buf, 0, NR_RECVBUFF *sizeof(struct recv_buf) + 4); precvpriv->precv_buf = (u8 *)N_BYTE_ALIGMENT((SIZE_PTR)(precvpriv->pallocated_recv_buf), 4); //precvpriv->precv_buf = precvpriv->pallocated_recv_buf + 4 - // ((uint) (precvpriv->pallocated_recv_buf) &(4-1)); precvbuf = (struct recv_buf*)precvpriv->precv_buf; for(i=0; i < NR_RECVBUFF ; i++) { _rtw_init_listhead(&precvbuf->list); _rtw_spinlock_init(&precvbuf->recvbuf_lock); precvbuf->alloc_sz = MAX_RECVBUF_SZ; res = rtw_os_recvbuf_resource_alloc(padapter, precvbuf); if(res==_FAIL) break; precvbuf->ref_cnt = 0; precvbuf->adapter =padapter; //rtw_list_insert_tail(&precvbuf->list, &(precvpriv->free_recv_buf_queue.queue)); precvbuf++; } precvpriv->free_recv_buf_queue_cnt = NR_RECVBUFF; skb_queue_head_init(&precvpriv->rx_skb_queue); #ifdef CONFIG_PREALLOC_RECV_SKB { int i; SIZE_PTR tmpaddr=0; SIZE_PTR alignment=0; struct sk_buff *pskb=NULL; skb_queue_head_init(&precvpriv->free_recv_skb_queue); for(i=0; i<NR_PREALLOC_RECV_SKB; i++) { pskb = rtw_skb_alloc(MAX_RECVBUF_SZ + RECVBUFF_ALIGN_SZ); if(pskb) { pskb->dev = padapter->pnetdev; tmpaddr = (SIZE_PTR)pskb->data; alignment = tmpaddr & (RECVBUFF_ALIGN_SZ-1); skb_reserve(pskb, (RECVBUFF_ALIGN_SZ - alignment)); skb_queue_tail(&precvpriv->free_recv_skb_queue, pskb); } pskb=NULL; } } #endif exit: return res; }
int usb_init_recv_priv(_adapter *padapter, u16 ini_in_buf_sz) { struct recv_priv *precvpriv = &padapter->recvpriv; int i, res = _SUCCESS; struct recv_buf *precvbuf; #ifdef CONFIG_RECV_THREAD_MODE _rtw_init_sema(&precvpriv->recv_sema, 0);//will be removed _rtw_init_sema(&precvpriv->terminate_recvthread_sema, 0);//will be removed #endif /* CONFIG_RECV_THREAD_MODE */ #ifdef PLATFORM_LINUX tasklet_init(&precvpriv->recv_tasklet, (void(*)(unsigned long))usb_recv_tasklet, (unsigned long)padapter); #endif /* PLATFORM_LINUX */ #ifdef PLATFORM_FREEBSD #ifdef CONFIG_RX_INDICATE_QUEUE TASK_INIT(&precvpriv->rx_indicate_tasklet, 0, rtw_rx_indicate_tasklet, padapter); #endif /* CONFIG_RX_INDICATE_QUEUE */ #endif /* PLATFORM_FREEBSD */ #ifdef CONFIG_USB_INTERRUPT_IN_PIPE #ifdef PLATFORM_LINUX precvpriv->int_in_urb = usb_alloc_urb(0, GFP_KERNEL); if(precvpriv->int_in_urb == NULL){ res = _FAIL; DBG_8192C("alloc_urb for interrupt in endpoint fail !!!!\n"); goto exit; } #endif /* PLATFORM_LINUX */ precvpriv->int_in_buf = rtw_zmalloc(ini_in_buf_sz); if(precvpriv->int_in_buf == NULL){ res = _FAIL; DBG_8192C("alloc_mem for interrupt in endpoint fail !!!!\n"); goto exit; } #endif /* CONFIG_USB_INTERRUPT_IN_PIPE */ /* init recv_buf */ _rtw_init_queue(&precvpriv->free_recv_buf_queue); _rtw_init_queue(&precvpriv->recv_buf_pending_queue); #ifndef CONFIG_USE_USB_BUFFER_ALLOC_RX /* this is used only when RX_IOBUF is sk_buff */ skb_queue_head_init(&precvpriv->free_recv_skb_queue); #endif DBG_871X("NR_RECVBUFF: %d\n", NR_RECVBUFF); DBG_871X("MAX_RECVBUF_SZ: %d\n", MAX_RECVBUF_SZ); precvpriv->pallocated_recv_buf = rtw_zmalloc(NR_RECVBUFF *sizeof(struct recv_buf) + 4); if(precvpriv->pallocated_recv_buf==NULL){ res= _FAIL; RT_TRACE(_module_rtl871x_recv_c_,_drv_err_,("alloc recv_buf fail!\n")); goto exit; } precvpriv->precv_buf = (u8 *)N_BYTE_ALIGMENT((SIZE_PTR)(precvpriv->pallocated_recv_buf), 4); precvbuf = (struct recv_buf*)precvpriv->precv_buf; for(i=0; i < NR_RECVBUFF ; i++) { _rtw_init_listhead(&precvbuf->list); _rtw_spinlock_init(&precvbuf->recvbuf_lock); precvbuf->alloc_sz = MAX_RECVBUF_SZ; res = rtw_os_recvbuf_resource_alloc(padapter, precvbuf); if(res==_FAIL) break; precvbuf->ref_cnt = 0; precvbuf->adapter =padapter; //rtw_list_insert_tail(&precvbuf->list, &(precvpriv->free_recv_buf_queue.queue)); precvbuf++; } precvpriv->free_recv_buf_queue_cnt = NR_RECVBUFF; #if defined(PLATFORM_LINUX) || defined(PLATFORM_FREEBSD) skb_queue_head_init(&precvpriv->rx_skb_queue); #ifdef CONFIG_RX_INDICATE_QUEUE memset(&precvpriv->rx_indicate_queue, 0, sizeof(struct ifqueue)); mtx_init(&precvpriv->rx_indicate_queue.ifq_mtx, "rx_indicate_queue", NULL, MTX_DEF); #endif /* CONFIG_RX_INDICATE_QUEUE */ #ifdef CONFIG_PREALLOC_RECV_SKB { int i; SIZE_PTR tmpaddr=0; SIZE_PTR alignment=0; struct sk_buff *pskb=NULL; DBG_871X("NR_PREALLOC_RECV_SKB: %d\n", NR_PREALLOC_RECV_SKB); #ifdef CONFIG_FIX_NR_BULKIN_BUFFER DBG_871X("Enable CONFIG_FIX_NR_BULKIN_BUFFER\n"); #endif for(i=0; i<NR_PREALLOC_RECV_SKB; i++) { #ifdef CONFIG_PREALLOC_RX_SKB_BUFFER pskb = rtw_alloc_skb_premem(MAX_RECVBUF_SZ); #else pskb = rtw_skb_alloc(MAX_RECVBUF_SZ + RECVBUFF_ALIGN_SZ); #endif //CONFIG_PREALLOC_RX_SKB_BUFFER if(pskb) { #ifdef PLATFORM_FREEBSD pskb->dev = padapter->pifp; #else pskb->dev = padapter->pnetdev; #endif //PLATFORM_FREEBSD #ifndef CONFIG_PREALLOC_RX_SKB_BUFFER tmpaddr = (SIZE_PTR)pskb->data; alignment = tmpaddr & (RECVBUFF_ALIGN_SZ-1); skb_reserve(pskb, (RECVBUFF_ALIGN_SZ - alignment)); #endif skb_queue_tail(&precvpriv->free_recv_skb_queue, pskb); } } } #endif /* CONFIG_PREALLOC_RECV_SKB */ #endif /* defined(PLATFORM_LINUX) || defined(PLATFORM_FREEBSD) */ exit: return res; }
void rtl8723as_recv(PADAPTER padapter, struct recv_buf *precvbuf) { //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; pHalData = GET_HAL_DATA(padapter); precvpriv = &padapter->recvpriv; 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__)); break; } //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 (padapter->registrypriv.mp_mode == 1) padapter->mppriv.rx_crcerrpktcount++; else DBG_8192C("%s()-%d: RX Warning! rx CRC ERROR !!\n", __FUNCTION__, __LINE__); 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)) { if (padapter->registrypriv.mp_mode == 0) 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), 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 = rtw_skb_clone(precvbuf->pskb); 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: rtw_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); }