/* * peer_config - configure a new association */ struct peer * peer_config( sockaddr_u * srcadr, const char * hostname, endpt * dstadr, u_char hmode, u_char version, u_char minpoll, u_char maxpoll, u_int flags, u_int32 ttl, keyid_t key, const char * ident /* autokey group */ ) { u_char cast_flags; /* * We do a dirty little jig to figure the cast flags. This is * probably not the best place to do this, at least until the * configure code is rebuilt. Note only one flag can be set. */ switch (hmode) { case MODE_BROADCAST: if (IS_MCAST(srcadr)) cast_flags = MDF_MCAST; else cast_flags = MDF_BCAST; break; case MODE_CLIENT: if (hostname != NULL && SOCK_UNSPEC(srcadr)) cast_flags = MDF_POOL; else if (IS_MCAST(srcadr)) cast_flags = MDF_ACAST; else cast_flags = MDF_UCAST; break; default: cast_flags = MDF_UCAST; } /* * Mobilize the association and initialize its variables. If * emulating ntpdate, force iburst. For pool and manycastclient * strip FLAG_PREEMPT as the prototype associations are not * themselves preemptible, though the resulting associations * are. */ flags |= FLAG_CONFIG; if (mode_ntpdate) flags |= FLAG_IBURST; if ((MDF_ACAST | MDF_POOL) & cast_flags) flags &= ~FLAG_PREEMPT; return newpeer(srcadr, hostname, dstadr, hmode, version, minpoll, maxpoll, flags, cast_flags, ttl, key, ident); }
/* * [IMPORTANT] This function would be run in interrupt context. */ s32 rtw_hal_mgnt_xmit(struct adapter *padapter, struct xmit_frame *pmgntframe) { s32 ret = _FAIL; update_mgntframe_attrib_addr(padapter, pmgntframe); /* pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET; */ /* pwlanhdr = (struct rtw_ieee80211_hdr *)pframe; */ /* memcpy(pmgntframe->attrib.ra, pwlanhdr->addr1, ETH_ALEN); */ if (padapter->securitypriv.binstallBIPkey == true) { if (IS_MCAST(pmgntframe->attrib.ra)) { pmgntframe->attrib.encrypt = _BIP_; /* pmgntframe->attrib.bswenc = true; */ } else { pmgntframe->attrib.encrypt = _AES_; pmgntframe->attrib.bswenc = true; } rtw_mgmt_xmitframe_coalesce(padapter, pmgntframe->pkt, pmgntframe); } if (padapter->HalFunc.mgnt_xmit) ret = padapter->HalFunc.mgnt_xmit(padapter, pmgntframe); return ret; }
/* * [IMPORTANT] This function would be run in interrupt context. */ s32 rtw_hal_mgnt_xmit(_adapter *padapter, struct xmit_frame *pmgntframe) { s32 ret = _FAIL; unsigned char *pframe; struct rtw_ieee80211_hdr *pwlanhdr; update_mgntframe_attrib_addr(padapter, pmgntframe); //pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET; //pwlanhdr = (struct rtw_ieee80211_hdr *)pframe; //_rtw_memcpy(pmgntframe->attrib.ra, pwlanhdr->addr1, ETH_ALEN); #ifdef CONFIG_IEEE80211W if(padapter->securitypriv.binstallBIPkey == _TRUE) { if(IS_MCAST(pmgntframe->attrib.ra)) { pmgntframe->attrib.encrypt = _BIP_; //pmgntframe->attrib.bswenc = _TRUE; } else { pmgntframe->attrib.encrypt = _AES_; pmgntframe->attrib.bswenc = _TRUE; } rtw_mgmt_xmitframe_coalesce(padapter, pmgntframe->pkt, pmgntframe); } #endif //CONFIG_IEEE80211W if(padapter->HalFunc.mgnt_xmit) ret = padapter->HalFunc.mgnt_xmit(padapter, pmgntframe); return ret; }
void UpdateEarlyModeInfo8192D(_adapter *padapter, struct xmit_frame *pxmitframe,struct tx_servq *ptxservq) { _irqL irqL; u32 len; struct xmit_priv *pxmitpriv = &padapter->xmitpriv; struct pkt_attrib *pattrib = &pxmitframe->attrib; _list *xmitframe_plist = NULL, *xmitframe_phead = NULL; //Some macaddr can't do early mode. if(MacAddr_isBcst(pattrib->dst) ||IS_MCAST(pattrib->dst) || !!pattrib->qos_en) return; pxmitframe->EMPktNum = 0; // dequeue same priority packet from station tx queue _enter_critical_bh(&pxmitpriv->lock, &irqL); xmitframe_phead = get_list_head(&ptxservq->sta_pending); xmitframe_plist = get_next(xmitframe_phead); while ((rtw_end_of_queue_search(xmitframe_phead, xmitframe_plist) == _FALSE)&&(pxmitframe->EMPktNum < 5)) { pxmitframe = LIST_CONTAINOR(xmitframe_plist, struct xmit_frame, list); xmitframe_plist = get_next(xmitframe_plist); len = xmitframe_need_length(pxmitframe); pxmitframe->EMPktLen[pxmitframe->EMPktNum] = len; pxmitframe->EMPktNum++; } _exit_critical_bh(&pxmitpriv->lock, &irqL); }
/* * restrict_source - maintains dynamic "restrict source ..." entries as * peers come and go. */ void restrict_source( sockaddr_u * addr, int farewell, /* 0 to add, 1 to remove */ u_long expire /* 0 is infinite, valid until */ ) { sockaddr_u onesmask; restrict_u * res; int found_specific; if (!restrict_source_enabled || SOCK_UNSPEC(addr) || IS_MCAST(addr) || ISREFCLOCKADR(addr)) return; REQUIRE(AF_INET == AF(addr) || AF_INET6 == AF(addr)); SET_HOSTMASK(&onesmask, AF(addr)); if (farewell) { hack_restrict(RESTRICT_REMOVE, addr, &onesmask, 0, 0, 0); DPRINTF(1, ("restrict_source: %s removed", stoa(addr))); return; } /* * If there is a specific entry for this address, hands * off, as it is condidered more specific than "restrict * server ...". * However, if the specific entry found is a fleeting one * added by pool_xmit() before soliciting, replace it * immediately regardless of the expire value to make way * for the more persistent entry. */ if (IS_IPV4(addr)) { res = match_restrict4_addr(SRCADR(addr), SRCPORT(addr)); INSIST(res != NULL); found_specific = (SRCADR(&onesmask) == res->u.v4.mask); } else { res = match_restrict6_addr(&SOCK_ADDR6(addr), SRCPORT(addr)); INSIST(res != NULL); found_specific = ADDR6_EQ(&res->u.v6.mask, &SOCK_ADDR6(&onesmask)); } if (!expire && found_specific && res->expire) { found_specific = 0; free_res(res, IS_IPV6(addr)); } if (found_specific) return; hack_restrict(RESTRICT_FLAGS, addr, &onesmask, restrict_source_mflags, restrict_source_flags, expire); DPRINTF(1, ("restrict_source: %s host restriction added\n", stoa(addr))); }
/* any station allocated can be searched by hash list */ struct sta_info *rtw_get_stainfo(struct sta_priv *pstapriv, u8 *hwaddr) { _irqL irqL; _list *plist, *phead; struct sta_info *psta = NULL; u32 index; u8 *addr; u8 bc_addr[ETH_ALEN] = {0xff,0xff,0xff,0xff,0xff,0xff}; _func_enter_; if(hwaddr==NULL) return NULL; if(IS_MCAST(hwaddr)) { addr = bc_addr; } else { addr = hwaddr; } index = wifi_mac_hash(addr); _enter_critical_bh(&pstapriv->sta_hash_lock, &irqL); phead = &(pstapriv->sta_hash[index]); plist = get_next(phead); while ((rtw_end_of_queue_search(phead, plist)) == _FALSE) { psta = LIST_CONTAINOR(plist, struct sta_info, hash_list); if ((_rtw_memcmp(psta->hwaddr, addr, ETH_ALEN))== _TRUE) { // if found the matched address break; } psta=NULL; plist = get_next(plist); } _exit_critical_bh(&pstapriv->sta_hash_lock, &irqL); _func_exit_; return psta; }
VOID odm_RefreshRateAdaptiveMaskCE( IN PVOID pDM_VOID ) { PDM_ODM_T pDM_Odm = (PDM_ODM_T)pDM_VOID; u1Byte i; PADAPTER pAdapter = pDM_Odm->Adapter; PODM_RATE_ADAPTIVE pRA = &pDM_Odm->RateAdaptive; if(pAdapter->bDriverStopped) { ODM_RT_TRACE(pDM_Odm, ODM_COMP_RA_MASK, ODM_DBG_TRACE, ("<---- odm_RefreshRateAdaptiveMask(): driver is going to unload\n")); return; } if(!pDM_Odm->bUseRAMask) { ODM_RT_TRACE(pDM_Odm, ODM_COMP_RA_MASK, ODM_DBG_LOUD, ("<---- odm_RefreshRateAdaptiveMask(): driver does not control rate adaptive mask\n")); return; } for(i=0; i<ODM_ASSOCIATE_ENTRY_NUM; i++){ PSTA_INFO_T pstat = pDM_Odm->pODM_StaInfo[i]; if(IS_STA_VALID(pstat) ) { if(IS_MCAST( pstat->hwaddr)) //if(psta->mac_id ==1) continue; if(IS_MCAST( pstat->hwaddr)) continue; if( TRUE == ODM_RAStateCheck(pDM_Odm, pstat->rssi_stat.UndecoratedSmoothedPWDB, FALSE , &pstat->rssi_level) ) { ODM_RT_TRACE(pDM_Odm, ODM_COMP_RA_MASK, ODM_DBG_LOUD, ("RSSI:%d, RSSI_LEVEL:%d\n", pstat->rssi_stat.UndecoratedSmoothedPWDB, pstat->rssi_level)); rtw_hal_update_ra_mask(pstat, pstat->rssi_level); } } } }
/* any station allocated can be searched by hash list */ struct sta_info *rtw_get_stainfo(struct sta_priv *pstapriv, u8 *hwaddr) { _list *plist, *phead; struct sta_info *psta = NULL; u32 index; u8 *addr; u8 bc_addr[ETH_ALEN] = {0xff,0xff,0xff,0xff,0xff,0xff}; _func_enter_; if(hwaddr==NULL) return NULL; if(IS_MCAST(hwaddr)) { addr = bc_addr; } else { addr = hwaddr; } index = wifi_mac_hash(addr); spin_lock_bh(&pstapriv->sta_hash_lock); phead = &(pstapriv->sta_hash[index]); plist = get_next(phead); while (phead != plist) { psta = LIST_CONTAINOR(plist, struct sta_info, hash_list); if ((!memcmp(psta->hwaddr, addr, ETH_ALEN))) { // if found the matched address break; } psta=NULL; plist = get_next(plist); } spin_unlock_bh(&pstapriv->sta_hash_lock); _func_exit_; return psta; }
s32 rtw_update_txdesc(struct xmit_frame *pxmitframe, u32 *pmem, s32 sz) { int pull=0; uint qsel; _adapter *padapter = pxmitframe->padapter; struct mlme_priv *pmlmepriv = &padapter->mlmepriv; struct pkt_attrib *pattrib = &pxmitframe->attrib; struct tx_desc *ptxdesc = (struct tx_desc *)pmem; sint bmcst = IS_MCAST(pattrib->ra); struct ht_priv *phtpriv = &pmlmepriv->htpriv; struct mlme_ext_info *pmlmeinfo = &padapter->mlmeextpriv.mlmext_info; if(urb_zero_packet_chk(padapter, sz)==0) { ptxdesc = (struct tx_desc *)(pmem+(PACKET_OFFSET_SZ>>2)); pull = 1; }
sint recvframe_chkmic(_adapter *adapter, union recv_frame *precvframe){ sint i,res=_SUCCESS; u32 datalen; u8 miccode[8]; u8 bmic_err=_FALSE; u8 *pframe, *payload,*pframemic; u8 *mickey,idx,*iv; struct sta_info *stainfo; struct rx_pkt_attrib *prxattrib=&precvframe->u.hdr.attrib; struct security_priv *psecuritypriv=&adapter->securitypriv; //struct recv_stat *prxstat=(struct recv_stat *)precvframe->u.hdr.rx_head; _func_enter_; stainfo=get_stainfo(&adapter->stapriv ,&prxattrib->ta[0] ); if(prxattrib->encrypt ==_TKIP_) { RT_TRACE(_module_rtl871x_recv_c_,_drv_info_,("\n recvframe_chkmic:prxattrib->encrypt ==_TKIP_\n")); RT_TRACE(_module_rtl871x_recv_c_,_drv_info_,("\n recvframe_chkmic:da=0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x\n", prxattrib->ra[0],prxattrib->ra[1],prxattrib->ra[2],prxattrib->ra[3],prxattrib->ra[4],prxattrib->ra[5])); //calculate mic code if(stainfo!= NULL) { if(IS_MCAST(prxattrib->ra)) { iv=precvframe->u.hdr.rx_data+prxattrib->hdrlen; idx=iv[3]; mickey=&psecuritypriv->dot118021XGrprxmickey[(( (idx>>6)&0x3 ))-1].skey[0]; RT_TRACE(_module_rtl871x_recv_c_,_drv_info_,("\n recvframe_chkmic: bcmc key \n")); if(psecuritypriv->binstallGrpkey==_FALSE) { res=_FAIL; RT_TRACE(_module_rtl871x_recv_c_,_drv_err_,("\n recvframe_chkmic:didn't install group key!!!!!!!!!!\n")); goto exit; } } else{
/* * [IMPORTANT] This function would be run in interrupt context. */ s32 rtw_hal_mgnt_xmit(_adapter *padapter, struct xmit_frame *pmgntframe) { s32 ret = _FAIL; u8 *pframe, subtype; struct rtw_ieee80211_hdr *pwlanhdr; struct sta_info *psta; struct sta_priv *pstapriv = &padapter->stapriv; update_mgntframe_attrib_addr(padapter, pmgntframe); pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET; subtype = GetFrameSubType(pframe); /* bit(7)~bit(2) */ //pwlanhdr = (struct rtw_ieee80211_hdr *)pframe; //_rtw_memcpy(pmgntframe->attrib.ra, pwlanhdr->addr1, ETH_ALEN); #ifdef CONFIG_IEEE80211W if (padapter->securitypriv.binstallBIPkey == _TRUE && (subtype == WIFI_DEAUTH || subtype == WIFI_DISASSOC || subtype == WIFI_ACTION)) { if (IS_MCAST(pmgntframe->attrib.ra) && pmgntframe->attrib.key_type != IEEE80211W_NO_KEY) { pmgntframe->attrib.encrypt = _BIP_; /* pmgntframe->attrib.bswenc = _TRUE; */ } else if (pmgntframe->attrib.key_type != IEEE80211W_NO_KEY) { psta = rtw_get_stainfo(pstapriv, pmgntframe->attrib.ra); if (psta && psta->bpairwise_key_installed == _TRUE) { pmgntframe->attrib.encrypt = _AES_; pmgntframe->attrib.bswenc = _TRUE; } else { DBG_871X("%s, %d, bpairwise_key_installed is FALSE\n", __func__, __LINE__); goto no_mgmt_coalesce; } } DBG_871X("encrypt=%d, bswenc=%d\n", pmgntframe->attrib.encrypt, pmgntframe->attrib.bswenc); rtw_mgmt_xmitframe_coalesce(padapter, pmgntframe->pkt, pmgntframe); } #endif //CONFIG_IEEE80211W no_mgmt_coalesce: ret = padapter->HalFunc.mgnt_xmit(padapter, pmgntframe); return ret; }
/* any station allocated can be searched by hash list */ struct sta_info *rtw_get_stainfo(struct sta_priv *pstapriv, u8 *hwaddr) { struct list_head *plist, *phead; struct sta_info *psta = NULL; u32 index; u8 *addr; u8 bc_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; if (!hwaddr) return NULL; if (IS_MCAST(hwaddr)) addr = bc_addr; else addr = hwaddr; index = wifi_mac_hash(addr); spin_lock_bh(&pstapriv->sta_hash_lock); phead = &(pstapriv->sta_hash[index]); plist = get_next(phead); while (phead != plist) { psta = LIST_CONTAINOR(plist, struct sta_info, hash_list); if ((!memcmp(psta->hwaddr, addr, ETH_ALEN))) /* if found the matched address */ break; psta = NULL; plist = get_next(plist); } spin_unlock_bh(&pstapriv->sta_hash_lock); return psta; }
/* * Will enqueue pxmitframe to the proper queue, and indicate it * to xx_pending list..... */ sint r8712_xmit_classifier(struct _adapter *padapter, struct xmit_frame *pxmitframe) { unsigned long irqL0; struct __queue *pstapending; struct sta_info *psta; struct tx_servq *ptxservq; struct pkt_attrib *pattrib = &pxmitframe->attrib; struct sta_priv *pstapriv = &padapter->stapriv; struct mlme_priv *pmlmepriv = &padapter->mlmepriv; sint bmcst = IS_MCAST(pattrib->ra); if (pattrib->psta) { psta = pattrib->psta; } else { if (bmcst) { psta = r8712_get_bcmc_stainfo(padapter); } else { if (check_fwstate(pmlmepriv, WIFI_MP_STATE)) psta = r8712_get_stainfo(pstapriv, get_bssid(pmlmepriv)); else psta = r8712_get_stainfo(pstapriv, pattrib->ra); } } if (psta == NULL) return _FAIL; ptxservq = get_sta_pending(padapter, &pstapending, psta, pattrib->priority); spin_lock_irqsave(&pstapending->lock, irqL0); if (list_empty(&ptxservq->tx_pending)) list_add_tail(&ptxservq->tx_pending, &pstapending->queue); list_add_tail(&pxmitframe->list, &ptxservq->sta_pending.queue); ptxservq->qcnt++; spin_unlock_irqrestore(&pstapending->lock, irqL0); return _SUCCESS; }
void fill_txdesc_for_mp(struct xmit_frame *pxmitframe, struct tx_desc *ptxdesc) { #ifdef CONFIG_MP_INCLUDED struct pkt_attrib *pattrib = &pxmitframe->attrib; sint bmcst = IS_MCAST(pattrib->ra); if (pattrib->pctrl == 1) // mp tx packets { struct tx_desc txdesc, *ptxdesc_mp; struct pkt_file pktfile; ptxdesc_mp = &txdesc; _rtw_open_pktfile(pxmitframe->pkt, &pktfile); _rtw_pktfile_read(&pktfile, NULL, ETH_HLEN); _rtw_pktfile_read(&pktfile, (u8*)ptxdesc_mp, TXDESC_SIZE); //offset 8 ptxdesc->txdw2 = cpu_to_le32(ptxdesc_mp->txdw2); if (bmcst) ptxdesc->txdw2 |= cpu_to_le32(BMC); ptxdesc->txdw2 |= cpu_to_le32(BK); //RT_TRACE(_module_rtl871x_xmit_c_,_drv_alert_,("mp pkt offset8-txdesc=0x%8x\n", ptxdesc->txdw2)); ptxdesc->txdw4 = cpu_to_le32(ptxdesc_mp->txdw4); //RT_TRACE(_module_rtl871x_xmit_c_,_drv_alert_,("mp pkt offset16-txdesc=0x%8x\n", ptxdesc->txdw4)); //offset 20 ptxdesc->txdw5 = cpu_to_le32(ptxdesc_mp->txdw5); //RT_TRACE(_module_rtl871x_xmit_c_,_drv_alert_,("mp pkt offset20-txdesc=0x%8x\n", ptxdesc->txdw5)); pattrib->pctrl = 0;//reset to zero; } #endif }
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; }
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; }
static s32 update_txdesc(struct xmit_frame *pxmitframe, u8 *pmem, s32 sz ,u8 bagg_pkt) { int pull=0; uint qsel; u8 data_rate,pwr_status,offset; _adapter *padapter = pxmitframe->padapter; struct mlme_priv *pmlmepriv = &padapter->mlmepriv; struct pkt_attrib *pattrib = &pxmitframe->attrib; HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter); struct dm_priv *pdmpriv = &pHalData->dmpriv; u8 *ptxdesc = pmem; struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); sint bmcst = IS_MCAST(pattrib->ra); #ifndef CONFIG_USE_USB_BUFFER_ALLOC_TX if (padapter->registrypriv.mp_mode == 0) { if((PACKET_OFFSET_SZ != 0) && (!bagg_pkt) &&(rtw_usb_bulk_size_boundary(padapter,TXDESC_SIZE+sz)==_FALSE)) { ptxdesc = (pmem+PACKET_OFFSET_SZ); //DBG_8192C("==> non-agg-pkt,shift pointer...\n"); pull = 1; } } #endif // CONFIG_USE_USB_BUFFER_ALLOC_TX _rtw_memset(ptxdesc, 0, TXDESC_SIZE); //4 offset 0 SET_TX_DESC_FIRST_SEG_8812(ptxdesc, 1); SET_TX_DESC_LAST_SEG_8812(ptxdesc, 1); SET_TX_DESC_OWN_8812(ptxdesc, 1); //DBG_8192C("%s==> pkt_len=%d,bagg_pkt=%02x\n",__FUNCTION__,sz,bagg_pkt); SET_TX_DESC_PKT_SIZE_8812(ptxdesc, sz); offset = TXDESC_SIZE + OFFSET_SZ; #ifdef CONFIG_TX_EARLY_MODE if(bagg_pkt){ offset += EARLY_MODE_INFO_SIZE ;//0x28 } #endif //DBG_8192C("%s==>offset(0x%02x) \n",__FUNCTION__,offset); SET_TX_DESC_OFFSET_8812(ptxdesc, offset); if (bmcst) { SET_TX_DESC_BMC_8812(ptxdesc, 1); } #ifndef CONFIG_USE_USB_BUFFER_ALLOC_TX if (padapter->registrypriv.mp_mode == 0) { if((PACKET_OFFSET_SZ != 0) && (!bagg_pkt)){ if((pull) && (pxmitframe->pkt_offset>0)) { pxmitframe->pkt_offset = pxmitframe->pkt_offset -1; } } } #endif //DBG_8192C("%s, pkt_offset=0x%02x\n",__FUNCTION__,pxmitframe->pkt_offset); // pkt_offset, unit:8 bytes padding if (pxmitframe->pkt_offset > 0) { SET_TX_DESC_PKT_OFFSET_8812(ptxdesc, pxmitframe->pkt_offset); } SET_TX_DESC_MACID_8812(ptxdesc, pattrib->mac_id); SET_TX_DESC_RATE_ID_8812(ptxdesc, pattrib->raid); SET_TX_DESC_QUEUE_SEL_8812(ptxdesc, pattrib->qsel); //offset 12 if (!pattrib->qos_en) { SET_TX_DESC_HWSEQ_EN_8812(ptxdesc, 1); // Hw set sequence number } else { SET_TX_DESC_SEQ_8812(ptxdesc, pattrib->seqnum); } if((pxmitframe->frame_tag&0x0f) == DATA_FRAMETAG) { //DBG_8192C("pxmitframe->frame_tag == DATA_FRAMETAG\n"); rtl8812a_fill_txdesc_sectype(pattrib, ptxdesc); //offset 20 #ifdef CONFIG_USB_TX_AGGREGATION if (pxmitframe->agg_num > 1){ //DBG_8192C("%s agg_num:%d\n",__FUNCTION__,pxmitframe->agg_num ); SET_TX_DESC_USB_TXAGG_NUM_8812(ptxdesc, pxmitframe->agg_num); } #endif rtl8812a_fill_txdesc_vcs(padapter, pattrib, ptxdesc); if ((pattrib->ether_type != 0x888e) && (pattrib->ether_type != 0x0806) && (pattrib->ether_type != 0x88b4) && (pattrib->dhcp_pkt != 1) #ifdef CONFIG_AUTO_AP_MODE && (pattrib->pctrl != _TRUE) #endif ) { //Non EAP & ARP & DHCP type data packet if (pattrib->ampdu_en==_TRUE) { SET_TX_DESC_AGG_ENABLE_8812(ptxdesc, 1); SET_TX_DESC_MAX_AGG_NUM_8812(ptxdesc, 0x1f); // Set A-MPDU aggregation. SET_TX_DESC_AMPDU_DENSITY_8812(ptxdesc, pattrib->ampdu_spacing); } else { SET_TX_DESC_AGG_BREAK_8812(ptxdesc, 1); } rtl8812a_fill_txdesc_phy(padapter, pattrib, ptxdesc); //DATA Rate FB LMT SET_TX_DESC_DATA_RATE_FB_LIMIT_8812(ptxdesc, 0x1f); if (pHalData->fw_ractrl == _FALSE) { SET_TX_DESC_USE_RATE_8812(ptxdesc, 1); if(pdmpriv->INIDATA_RATE[pattrib->mac_id] & BIT(7)) SET_TX_DESC_DATA_SHORT_8812(ptxdesc, 1); SET_TX_DESC_TX_RATE_8812(ptxdesc, (pdmpriv->INIDATA_RATE[pattrib->mac_id] & 0x7F)); } if (padapter->fix_rate != 0xFF) { // modify data rate by iwpriv SET_TX_DESC_USE_RATE_8812(ptxdesc, 1); if(padapter->fix_rate & BIT(7)) SET_TX_DESC_DATA_SHORT_8812(ptxdesc, 1); SET_TX_DESC_TX_RATE_8812(ptxdesc, (padapter->fix_rate & 0x7F)); if (!padapter->data_fb) SET_TX_DESC_DISABLE_FB_8812(ptxdesc,1); } if (pattrib->ldpc) SET_TX_DESC_DATA_LDPC_8812(ptxdesc, 1); if (pattrib->stbc) SET_TX_DESC_DATA_STBC_8812(ptxdesc, 1); } else { // EAP data packet and ARP packet and DHCP. // Use the 1M data rate to send the EAP/ARP packet. // This will maybe make the handshake smooth. SET_TX_DESC_USE_RATE_8812(ptxdesc, 1); SET_TX_DESC_AGG_BREAK_8812(ptxdesc, 1); // HW will ignore this setting if the transmission rate is legacy OFDM. if (pmlmeinfo->preamble_mode == PREAMBLE_SHORT) { SET_TX_DESC_DATA_SHORT_8812(ptxdesc, 1); } SET_TX_DESC_TX_RATE_8812(ptxdesc, MRateToHwRate(pmlmeext->tx_rate)); } #ifdef CONFIG_TDLS #ifdef CONFIG_XMIT_ACK /* CCX-TXRPT ack for xmit mgmt frames. */ if (pxmitframe->ack_report) { SET_TX_DESC_SPE_RPT_8812(ptxdesc, 1); #ifdef DBG_CCX DBG_871X("%s set tx report\n", __func__); #endif } #endif /* CONFIG_XMIT_ACK */ #endif } else if((pxmitframe->frame_tag&0x0f)== MGNT_FRAMETAG) { //DBG_8192C("pxmitframe->frame_tag == MGNT_FRAMETAG\n"); if(IS_HARDWARE_TYPE_8821(padapter)) SET_TX_DESC_MBSSID_8821(ptxdesc, pattrib->mbssid); SET_TX_DESC_USE_RATE_8812(ptxdesc, 1); #ifdef CONFIG_INTEL_PROXIM if((padapter->proximity.proxim_on==_TRUE)&&(pattrib->intel_proxim==_TRUE)){ DBG_871X("\n %s pattrib->rate=%d\n",__FUNCTION__,pattrib->rate); SET_TX_DESC_TX_RATE_8812(ptxdesc, pattrib->rate); } else #endif { SET_TX_DESC_TX_RATE_8812(ptxdesc, MRateToHwRate(pattrib->rate)); } // VHT NDPA or HT NDPA Packet for Beamformer. if((pattrib->subtype == WIFI_NDPA) || ((pattrib->subtype == WIFI_ACTION_NOACK) && (pattrib->order == 1))) { SET_TX_DESC_NAV_USE_HDR_8812(ptxdesc, 1); SET_TX_DESC_DATA_BW_8812(ptxdesc, BWMapping_8812(padapter,pattrib)); SET_TX_DESC_RTS_SC_8812(ptxdesc, SCMapping_8812(padapter,pattrib)); SET_TX_DESC_RETRY_LIMIT_ENABLE_8812(ptxdesc, 1); SET_TX_DESC_DATA_RETRY_LIMIT_8812(ptxdesc, 5); SET_TX_DESC_DISABLE_FB_8812(ptxdesc, 1); //if(pattrib->rts_cca) //{ // SET_TX_DESC_NDPA_8812(ptxdesc, 2); //} //else { SET_TX_DESC_NDPA_8812(ptxdesc, 1); } } else { SET_TX_DESC_RETRY_LIMIT_ENABLE_8812(ptxdesc, 1); if (pattrib->retry_ctrl == _TRUE) { SET_TX_DESC_DATA_RETRY_LIMIT_8812(ptxdesc, 6); } else { SET_TX_DESC_DATA_RETRY_LIMIT_8812(ptxdesc, 12); } } #ifdef CONFIG_XMIT_ACK //CCX-TXRPT ack for xmit mgmt frames. if (pxmitframe->ack_report) { SET_TX_DESC_SPE_RPT_8812(ptxdesc, 1); #ifdef DBG_CCX DBG_871X("%s set tx report\n", __func__); #endif } #endif //CONFIG_XMIT_ACK } else if((pxmitframe->frame_tag&0x0f) == TXAGG_FRAMETAG) { DBG_8192C("pxmitframe->frame_tag == TXAGG_FRAMETAG\n"); } #ifdef CONFIG_MP_INCLUDED else if(((pxmitframe->frame_tag&0x0f) == MP_FRAMETAG) && (padapter->registrypriv.mp_mode == 1)) { fill_txdesc_for_mp(padapter, ptxdesc); } #endif else { DBG_8192C("pxmitframe->frame_tag = %d\n", pxmitframe->frame_tag); SET_TX_DESC_USE_RATE_8812(ptxdesc, 1); SET_TX_DESC_TX_RATE_8812(ptxdesc, MRateToHwRate(pmlmeext->tx_rate)); } rtl8812a_cal_txdesc_chksum(ptxdesc); _dbg_dump_tx_info(padapter,pxmitframe->frame_tag,ptxdesc); return pull; }
void rtw_os_recv_indicate_pkt(_adapter *padapter, _pkt *pkt, struct rx_pkt_attrib *pattrib) { struct mlme_priv*pmlmepriv = &padapter->mlmepriv; int ret; /* Indicat the packets to upper layer */ if (pkt) { if (check_fwstate(pmlmepriv, WIFI_AP_STATE) == true) { _pkt *pskb2 =NULL; struct sta_info *psta = NULL; struct sta_priv *pstapriv = &padapter->stapriv; int bmcast = IS_MCAST(pattrib->dst); /* DBG_871X("bmcast =%d\n", bmcast); */ if (memcmp(pattrib->dst, myid(&padapter->eeprompriv), ETH_ALEN)) { /* DBG_871X("not ap psta =%p, addr =%pM\n", psta, pattrib->dst); */ if (bmcast) { psta = rtw_get_bcmc_stainfo(padapter); pskb2 = rtw_skb_clone(pkt); } 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; */ pkt->dev = pnetdev; skb_set_queue_mapping(pkt, rtw_recv_select_queue(pkt)); _rtw_xmit_entry(pkt, pnetdev); if (bmcast && (pskb2 != NULL)) { pkt = pskb2; DBG_COUNTER(padapter->rx_logs.os_indicate_ap_mcast); } else { DBG_COUNTER(padapter->rx_logs.os_indicate_ap_forward); return; } } } else/* to APself */ { /* DBG_871X("to APSelf\n"); */ DBG_COUNTER(padapter->rx_logs.os_indicate_ap_self); } } pkt->protocol = eth_type_trans(pkt, padapter->pnetdev); pkt->dev = padapter->pnetdev; #ifdef CONFIG_TCP_CSUM_OFFLOAD_RX if ((pattrib->tcpchk_valid == 1) && (pattrib->tcp_chkrpt == 1)) { pkt->ip_summed = CHECKSUM_UNNECESSARY; } else { pkt->ip_summed = CHECKSUM_NONE; } #else /* !CONFIG_TCP_CSUM_OFFLOAD_RX */ pkt->ip_summed = CHECKSUM_NONE; #endif /* CONFIG_TCP_CSUM_OFFLOAD_RX */ ret = rtw_netif_rx(padapter->pnetdev, pkt); if (ret == NET_RX_SUCCESS) DBG_COUNTER(padapter->rx_logs.os_netif_ok); else DBG_COUNTER(padapter->rx_logs.os_netif_err); } }
u32 usb_write_port(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *wmem) { _irqL irqL; unsigned int pipe; int status; u32 ret = _FAIL, bwritezero = _FALSE; PURB purb = NULL; _adapter *padapter = (_adapter *)pintfhdl->padapter; struct dvobj_priv *pdvobj = adapter_to_dvobj(padapter); struct xmit_priv *pxmitpriv = &padapter->xmitpriv; struct xmit_buf *pxmitbuf = (struct xmit_buf *)wmem; struct xmit_frame *pxmitframe = (struct xmit_frame *)pxmitbuf->priv_data; struct usb_device *pusbd = pdvobj->pusbdev; struct pkt_attrib *pattrib = &pxmitframe->attrib; _func_enter_; RT_TRACE(_module_hci_ops_os_c_,_drv_err_,("+usb_write_port\n")); if ((padapter->bDriverStopped) || (padapter->bSurpriseRemoved) ||(dvobj_to_pwrctl(pdvobj)->pnp_bstop_trx)) { #ifdef DBG_TX DBG_871X(" DBG_TX %s:%d bDriverStopped%d, bSurpriseRemoved:%d, pnp_bstop_trx:%d\n",__FUNCTION__, __LINE__ ,padapter->bDriverStopped, padapter->bSurpriseRemoved, dvobj_to_pwrctl(pdvobj)->pnp_bstop_trx ); #endif RT_TRACE(_module_hci_ops_os_c_,_drv_err_,("usb_write_port:( padapter->bDriverStopped ||padapter->bSurpriseRemoved ||pwrctl->pnp_bstop_trx)!!!\n")); rtw_sctx_done_err(&pxmitbuf->sctx, RTW_SCTX_DONE_TX_DENY); goto exit; } _enter_critical(&pxmitpriv->lock, &irqL); switch(addr) { case VO_QUEUE_INX: pxmitpriv->voq_cnt++; pxmitbuf->flags = VO_QUEUE_INX; break; case VI_QUEUE_INX: pxmitpriv->viq_cnt++; pxmitbuf->flags = VI_QUEUE_INX; break; case BE_QUEUE_INX: pxmitpriv->beq_cnt++; pxmitbuf->flags = BE_QUEUE_INX; break; case BK_QUEUE_INX: pxmitpriv->bkq_cnt++; pxmitbuf->flags = BK_QUEUE_INX; break; case HIGH_QUEUE_INX: pxmitbuf->flags = HIGH_QUEUE_INX; break; default: pxmitbuf->flags = MGT_QUEUE_INX; break; } _exit_critical(&pxmitpriv->lock, &irqL); #ifdef DBG_TRX_STA_PKTS { struct sta_info *psta = NULL; struct sta_priv *pstapriv = &padapter->stapriv; int bmcast = IS_MCAST(pattrib->dst); u8 agg_num = 1; #ifdef CONFIG_USB_HCI #ifdef CONFIG_USB_TX_AGGREGATION if(pxmitframe->agg_num>1) agg_num = pxmitframe->agg_num; #endif #endif #if defined(CONFIG_SDIO_HCI) || defined(CONFIG_GSPI_HCI) if(pxmitframe->agg_num>1) agg_num = pxmitframe->agg_num; #endif if(bmcast) { psta = rtw_get_bcmc_stainfo(padapter); } else { psta = rtw_get_stainfo(pstapriv, pattrib->dst); } if(psta) { switch(pattrib->priority) { case 1: case 2: psta->tx_bk_cnt += agg_num; break; case 4: case 5: psta->tx_vi_cnt += agg_num; break; case 6: case 7: psta->tx_vo_cnt += agg_num; break; case 0: case 3: default: psta->tx_be_cnt += agg_num; break; } } } #endif purb = pxmitbuf->pxmit_urb[0]; #if 0 if(pdvobj->ishighspeed) { if(cnt> 0 && cnt%512 == 0) { //DBG_8192C("ishighspeed, cnt=%d\n", cnt); bwritezero = _TRUE; } } else { if(cnt > 0 && cnt%64 == 0) { //DBG_8192C("cnt=%d\n", cnt); bwritezero = _TRUE; } } #endif //translate DMA FIFO addr to pipehandle pipe = ffaddr2pipehdl(pdvobj, addr); #ifdef CONFIG_REDUCE_USB_TX_INT if ( (pxmitpriv->free_xmitbuf_cnt%NR_XMITBUFF == 0) || (pxmitbuf->ext_tag == _TRUE) ) { purb->transfer_flags &= (~URB_NO_INTERRUPT); } else { purb->transfer_flags |= URB_NO_INTERRUPT; //DBG_8192C("URB_NO_INTERRUPT "); } #endif usb_fill_bulk_urb(purb, pusbd, pipe, pxmitframe->buf_addr, //= pxmitbuf->pbuf cnt, usb_write_port_complete, pxmitbuf);//context is pxmitbuf #ifdef CONFIG_USE_USB_BUFFER_ALLOC_TX purb->transfer_dma = pxmitbuf->dma_transfer_addr; purb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; purb->transfer_flags |= URB_ZERO_PACKET; #endif // CONFIG_USE_USB_BUFFER_ALLOC_TX #ifdef USB_PACKET_OFFSET_SZ #if (USB_PACKET_OFFSET_SZ == 0) purb->transfer_flags |= URB_ZERO_PACKET; #endif #endif #if 0 if (bwritezero) { purb->transfer_flags |= URB_ZERO_PACKET; } #endif status = usb_submit_urb(purb, GFP_ATOMIC); if (!status) { #ifdef DBG_CONFIG_ERROR_DETECT { HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter); pHalData->srestpriv.last_tx_time = rtw_get_current_time(); } #endif } else { rtw_sctx_done_err(&pxmitbuf->sctx, RTW_SCTX_DONE_WRITE_PORT_ERR); DBG_871X("usb_write_port, status=%d\n", status); RT_TRACE(_module_hci_ops_os_c_,_drv_err_,("usb_write_port(): usb_submit_urb, status=%x\n", status)); switch (status) { case -ENODEV: padapter->bDriverStopped=_TRUE; break; default: break; } goto exit; } ret= _SUCCESS; // Commented by Albert 2009/10/13 // We add the URB_ZERO_PACKET flag to urb so that the host will send the zero packet automatically. /* if(bwritezero == _TRUE) { usb_bulkout_zero(pintfhdl, addr); } */ RT_TRACE(_module_hci_ops_os_c_,_drv_err_,("-usb_write_port\n")); exit: if (ret != _SUCCESS) rtw_free_xmitbuf(pxmitpriv, pxmitbuf); _func_exit_; return ret; }
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 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 s32 update_txdesc(struct xmit_frame *pxmitframe, u8 *pmem, s32 sz, u8 bagg_pkt) { int pull = 0; uint qsel; u8 data_rate, pwr_status, offset; struct adapter *adapt = pxmitframe->padapter; struct pkt_attrib *pattrib = &pxmitframe->attrib; struct hal_data_8188e *haldata = GET_HAL_DATA(adapt); struct tx_desc *ptxdesc = (struct tx_desc *)pmem; struct mlme_ext_priv *pmlmeext = &adapt->mlmeextpriv; struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); int bmcst = IS_MCAST(pattrib->ra); if (adapt->registrypriv.mp_mode == 0) { if ((!bagg_pkt) && (urb_zero_packet_chk(adapt, sz) == 0)) { ptxdesc = (struct tx_desc *)(pmem+PACKET_OFFSET_SZ); pull = 1; } } memset(ptxdesc, 0, sizeof(struct tx_desc)); /* 4 offset 0 */ ptxdesc->txdw0 |= cpu_to_le32(OWN | FSG | LSG); ptxdesc->txdw0 |= cpu_to_le32(sz & 0x0000ffff);/* update TXPKTSIZE */ offset = TXDESC_SIZE + OFFSET_SZ; ptxdesc->txdw0 |= cpu_to_le32(((offset) << OFFSET_SHT) & 0x00ff0000);/* 32 bytes for TX Desc */ if (bmcst) ptxdesc->txdw0 |= cpu_to_le32(BMC); if (adapt->registrypriv.mp_mode == 0) { if (!bagg_pkt) { if ((pull) && (pxmitframe->pkt_offset > 0)) pxmitframe->pkt_offset = pxmitframe->pkt_offset - 1; } } /* pkt_offset, unit:8 bytes padding */ if (pxmitframe->pkt_offset > 0) ptxdesc->txdw1 |= cpu_to_le32((pxmitframe->pkt_offset << 26) & 0x7c000000); /* driver uses rate */ ptxdesc->txdw4 |= cpu_to_le32(USERATE);/* rate control always by driver */ if ((pxmitframe->frame_tag & 0x0f) == DATA_FRAMETAG) { /* offset 4 */ ptxdesc->txdw1 |= cpu_to_le32(pattrib->mac_id & 0x3F); qsel = (uint)(pattrib->qsel & 0x0000001f); ptxdesc->txdw1 |= cpu_to_le32((qsel << QSEL_SHT) & 0x00001f00); ptxdesc->txdw1 |= cpu_to_le32((pattrib->raid << RATE_ID_SHT) & 0x000F0000); fill_txdesc_sectype(pattrib, ptxdesc); if (pattrib->ampdu_en) { ptxdesc->txdw2 |= cpu_to_le32(AGG_EN);/* AGG EN */ ptxdesc->txdw6 = cpu_to_le32(0x6666f800); } else { ptxdesc->txdw2 |= cpu_to_le32(AGG_BK);/* AGG BK */ } /* offset 8 */ /* offset 12 */ ptxdesc->txdw3 |= cpu_to_le32((pattrib->seqnum << SEQ_SHT) & 0x0FFF0000); /* offset 16 , offset 20 */ if (pattrib->qos_en) ptxdesc->txdw4 |= cpu_to_le32(QOS);/* QoS */ /* offset 20 */ if (pxmitframe->agg_num > 1) ptxdesc->txdw5 |= cpu_to_le32((pxmitframe->agg_num << USB_TXAGG_NUM_SHT) & 0xFF000000); if ((pattrib->ether_type != 0x888e) && (pattrib->ether_type != 0x0806) && (pattrib->ether_type != 0x88b4) && (pattrib->dhcp_pkt != 1)) { /* Non EAP & ARP & DHCP type data packet */ fill_txdesc_vcs(pattrib, &ptxdesc->txdw4); fill_txdesc_phy(pattrib, &ptxdesc->txdw4); ptxdesc->txdw4 |= cpu_to_le32(0x00000008);/* RTS Rate=24M */ ptxdesc->txdw5 |= cpu_to_le32(0x0001ff00);/* DATA/RTS Rate FB LMT */ if (pattrib->ht_en) { if (ODM_RA_GetShortGI_8188E(&haldata->odmpriv, pattrib->mac_id)) ptxdesc->txdw5 |= cpu_to_le32(SGI);/* SGI */ } data_rate = ODM_RA_GetDecisionRate_8188E(&haldata->odmpriv, pattrib->mac_id); ptxdesc->txdw5 |= cpu_to_le32(data_rate & 0x3F); pwr_status = ODM_RA_GetHwPwrStatus_8188E(&haldata->odmpriv, pattrib->mac_id); ptxdesc->txdw4 |= cpu_to_le32((pwr_status & 0x7) << PWR_STATUS_SHT); } else { /* EAP data packet and ARP packet and DHCP. */ /* Use the 1M data rate to send the EAP/ARP packet. */ /* This will maybe make the handshake smooth. */ ptxdesc->txdw2 |= cpu_to_le32(AGG_BK);/* AGG BK */ if (pmlmeinfo->preamble_mode == PREAMBLE_SHORT) ptxdesc->txdw4 |= cpu_to_le32(BIT(24));/* DATA_SHORT */ ptxdesc->txdw5 |= cpu_to_le32(MRateToHwRate(pmlmeext->tx_rate)); } } else if ((pxmitframe->frame_tag&0x0f) == MGNT_FRAMETAG) { /* offset 4 */ ptxdesc->txdw1 |= cpu_to_le32(pattrib->mac_id & 0x3f); qsel = (uint)(pattrib->qsel&0x0000001f); ptxdesc->txdw1 |= cpu_to_le32((qsel << QSEL_SHT) & 0x00001f00); ptxdesc->txdw1 |= cpu_to_le32((pattrib->raid << RATE_ID_SHT) & 0x000f0000); /* offset 8 */ /* CCX-TXRPT ack for xmit mgmt frames. */ if (pxmitframe->ack_report) ptxdesc->txdw2 |= cpu_to_le32(BIT(19)); /* offset 12 */ ptxdesc->txdw3 |= cpu_to_le32((pattrib->seqnum<<SEQ_SHT)&0x0FFF0000); /* offset 20 */ ptxdesc->txdw5 |= cpu_to_le32(RTY_LMT_EN);/* retry limit enable */ if (pattrib->retry_ctrl) ptxdesc->txdw5 |= cpu_to_le32(0x00180000);/* retry limit = 6 */ else ptxdesc->txdw5 |= cpu_to_le32(0x00300000);/* retry limit = 12 */ ptxdesc->txdw5 |= cpu_to_le32(MRateToHwRate(pmlmeext->tx_rate)); } else if ((pxmitframe->frame_tag&0x0f) == TXAGG_FRAMETAG) { DBG_88E("pxmitframe->frame_tag == TXAGG_FRAMETAG\n"); } else { DBG_88E("pxmitframe->frame_tag = %d\n", pxmitframe->frame_tag); /* offset 4 */ ptxdesc->txdw1 |= cpu_to_le32((4) & 0x3f);/* CAM_ID(MAC_ID) */ ptxdesc->txdw1 |= cpu_to_le32((6 << RATE_ID_SHT) & 0x000f0000);/* raid */ /* offset 8 */ /* offset 12 */ ptxdesc->txdw3 |= cpu_to_le32((pattrib->seqnum<<SEQ_SHT)&0x0fff0000); /* offset 20 */ ptxdesc->txdw5 |= cpu_to_le32(MRateToHwRate(pmlmeext->tx_rate)); } /* 2009.11.05. tynli_test. Suggested by SD4 Filen for FW LPS. */ /* (1) The sequence number of each non-Qos frame / broadcast / multicast / */ /* mgnt frame should be controlled by Hw because Fw will also send null data */ /* which we cannot control when Fw LPS enable. */ /* --> default enable non-Qos data sequense number. 2010.06.23. by tynli. */ /* (2) Enable HW SEQ control for beacon packet, because we use Hw beacon. */ /* (3) Use HW Qos SEQ to control the seq num of Ext port non-Qos packets. */ /* 2010.06.23. Added by tynli. */ if (!pattrib->qos_en) { ptxdesc->txdw3 |= cpu_to_le32(EN_HWSEQ); /* Hw set sequence number */ ptxdesc->txdw4 |= cpu_to_le32(HW_SSN); /* Hw set sequence number */ } rtl88eu_dm_set_tx_ant_by_tx_info(&haldata->odmpriv, pmem, pattrib->mac_id); rtl8188eu_cal_txdesc_chksum(ptxdesc); _dbg_dump_tx_info(adapt, pxmitframe->frame_tag, ptxdesc); return pull; }
static s32 update_txdesc(struct xmit_frame *pxmitframe, u32 *pmem, s32 sz) { uint qsel; _adapter *padapter = pxmitframe->padapter; struct mlme_priv *pmlmepriv = &padapter->mlmepriv; struct dvobj_priv *pdvobjpriv = &padapter->dvobjpriv; struct pkt_attrib *pattrib = &pxmitframe->attrib; struct ht_priv *phtpriv = &pmlmepriv->htpriv; struct mlme_ext_info *pmlmeinfo = &padapter->mlmeextpriv.mlmext_info; HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter); struct dm_priv *pdmpriv = &pHalData->dmpriv; struct tx_desc *ptxdesc = (struct tx_desc *)pmem; sint bmcst = IS_MCAST(pattrib->ra); #ifdef CONFIG_P2P struct wifidirect_info* pwdinfo = &padapter->wdinfo; #endif //CONFIG_P2P dma_addr_t mapping = pci_map_single(pdvobjpriv->ppcidev, pxmitframe->buf_addr , sz, PCI_DMA_TODEVICE); _rtw_memset(ptxdesc, 0, TX_DESC_NEXT_DESC_OFFSET); if((pxmitframe->frame_tag&0x0f) == DATA_FRAMETAG) { //DBG_8192C("pxmitframe->frame_tag == DATA_FRAMETAG\n"); //offset 4 ptxdesc->txdw1 |= cpu_to_le32((pattrib->mac_id)&0x1f); qsel = (uint)(pattrib->qsel & 0x0000001f); ptxdesc->txdw1 |= cpu_to_le32((qsel << QSEL_SHT) & 0x00001f00); ptxdesc->txdw1 |= cpu_to_le32((pattrib->raid<< 16) & 0x000f0000); fill_txdesc_sectype(pattrib, ptxdesc); if(pattrib->ampdu_en==_TRUE) ptxdesc->txdw1 |= cpu_to_le32(BIT(5));//AGG EN else ptxdesc->txdw1 |= cpu_to_le32(BIT(6));//AGG BK //offset 8 //offset 12 ptxdesc->txdw3 |= cpu_to_le32((pattrib->seqnum<<16)&0xffff0000); //offset 16 , offset 20 if (pattrib->qos_en) ptxdesc->txdw4 |= cpu_to_le32(BIT(6));//QoS if ((pattrib->ether_type != 0x888e) && (pattrib->ether_type != 0x0806) && (pattrib->dhcp_pkt != 1)) { //Non EAP & ARP & DHCP type data packet fill_txdesc_vcs(pattrib, &ptxdesc->txdw4); fill_txdesc_phy(pattrib, &ptxdesc->txdw4); ptxdesc->txdw4 |= cpu_to_le32(0x00000008);//RTS Rate=24M ptxdesc->txdw5 |= cpu_to_le32(0x0001ff00);// //ptxdesc->txdw5 |= cpu_to_le32(0x0000000b);//DataRate - 54M //use REG_INIDATA_RATE_SEL value ptxdesc->txdw5 |= cpu_to_le32(pdmpriv->INIDATA_RATE[pattrib->mac_id]); if(0)//for driver dbg { ptxdesc->txdw4 |= cpu_to_le32(BIT(8));//driver uses rate if(pattrib->ht_en) ptxdesc->txdw5 |= cpu_to_le32(BIT(6));//SGI ptxdesc->txdw5 |= cpu_to_le32(0x00000013);//init rate - mcs7 } } else { // EAP data packet and ARP packet. // Use the 1M data rate to send the EAP/ARP packet. // This will maybe make the handshake smooth. ptxdesc->txdw1 |= cpu_to_le32(BIT(6));//AGG BK ptxdesc->txdw4 |= cpu_to_le32(BIT(8));//driver uses rate if (pmlmeinfo->preamble_mode == PREAMBLE_SHORT) ptxdesc->txdw4 |= cpu_to_le32(BIT(24));// DATA_SHORT } //offset 24 #ifdef CONFIG_TCP_CSUM_OFFLOAD_TX if ( pattrib->hw_tcp_csum == 1 ) { // ptxdesc->txdw6 = 0; // clear TCP_CHECKSUM and IP_CHECKSUM. It's zero already!! u8 ip_hdr_offset = 32 + pattrib->hdrlen + pattrib->iv_len + 8; ptxdesc->txdw7 = (1 << 31) | (ip_hdr_offset << 16); DBG_8192C("ptxdesc->txdw7 = %08x\n", ptxdesc->txdw7); } #endif } else if((pxmitframe->frame_tag&0x0f)== MGNT_FRAMETAG) { //DBG_8192C("pxmitframe->frame_tag == MGNT_FRAMETAG\n"); //offset 4 ptxdesc->txdw1 |= cpu_to_le32((pattrib->mac_id)&0x1f); qsel = (uint)(pattrib->qsel&0x0000001f); ptxdesc->txdw1 |= cpu_to_le32((qsel<<QSEL_SHT)&0x00001f00); ptxdesc->txdw1 |= cpu_to_le32((pattrib->raid<< 16) & 0x000f0000); //fill_txdesc_sectype(pattrib, ptxdesc); //offset 8 //offset 12 ptxdesc->txdw3 |= cpu_to_le32((pattrib->seqnum<<16)&0xffff0000); //offset 16 ptxdesc->txdw4 |= cpu_to_le32(BIT(8));//driver uses rate //offset 20 } else if((pxmitframe->frame_tag&0x0f) == TXAGG_FRAMETAG) { DBG_8192C("pxmitframe->frame_tag == TXAGG_FRAMETAG\n"); } #ifdef CONFIG_MP_INCLUDED else if((pxmitframe->frame_tag&0x0f) == MP_FRAMETAG) { fill_txdesc_for_mp(padapter, ptxdesc); } #endif else { DBG_8192C("pxmitframe->frame_tag = %d\n", pxmitframe->frame_tag); //offset 4 ptxdesc->txdw1 |= cpu_to_le32((4)&0x1f);//CAM_ID(MAC_ID) ptxdesc->txdw1 |= cpu_to_le32((6<< 16) & 0x000f0000);//raid //offset 8 //offset 12 ptxdesc->txdw3 |= cpu_to_le32((pattrib->seqnum<<16)&0xffff0000); //offset 16 ptxdesc->txdw4 |= cpu_to_le32(BIT(8));//driver uses rate //offset 20 ptxdesc->txdw5 |= cpu_to_le32(BIT(17));//retry limit enable ptxdesc->txdw5 |= cpu_to_le32(0x00180000);//retry limit = 6 #ifdef CONFIG_P2P // Added by Albert 2011/03/17 // In the P2P mode, the driver should not support the b mode. // So, the Tx packet shouldn't use the CCK rate if(!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)) { ptxdesc->txdw5 |= cpu_to_le32( 0x04 ); // Use the 6M data rate. } #endif //CONFIG_P2P } //offset 28 ptxdesc->txdw7 |= cpu_to_le32(sz&0x0000ffff); //offset 32 ptxdesc->txdw8 = cpu_to_le32(mapping); // 2009.11.05. tynli_test. Suggested by SD4 Filen for FW LPS. // (1) The sequence number of each non-Qos frame / broadcast / multicast / // mgnt frame should be controled by Hw because Fw will also send null data // which we cannot control when Fw LPS enable. // --> default enable non-Qos data sequense number. 2010.06.23. by tynli. // (2) Enable HW SEQ control for beacon packet, because we use Hw beacon. // (3) Use HW Qos SEQ to control the seq num of Ext port non-Qos packets. // 2010.06.23. Added by tynli. if(!pattrib->qos_en) { 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. } //offset 0 if(bmcst) { ptxdesc->txdw0 |= cpu_to_le32(BIT(24)); } ptxdesc->txdw0 |= cpu_to_le32(sz&0x0000ffff); ptxdesc->txdw0 |= cpu_to_le32(FSG | LSG); ptxdesc->txdw0 |= cpu_to_le32(((TXDESC_SIZE+OFFSET_SZ)<<OFFSET_SHT)&0x00ff0000);//32 bytes for TX Desc // ptxdesc->txdw0 |= cpu_to_le32(OWN); RT_TRACE(_module_rtl871x_xmit_c_,_drv_info_,("offset0-txdesc=0x%x\n", ptxdesc->txdw0)); return 0; }
void rtl8188es_fill_default_txdesc( struct xmit_frame *pxmitframe, u8 *pbuf) { PADAPTER padapter; HAL_DATA_TYPE *pHalData; struct mlme_ext_priv *pmlmeext; struct mlme_ext_info *pmlmeinfo; struct dm_priv *pdmpriv; struct pkt_attrib *pattrib; PTXDESC_8188E ptxdesc; s32 bmcst; padapter = pxmitframe->padapter; pHalData = GET_HAL_DATA(padapter); //pdmpriv = &pHalData->dmpriv; pmlmeext = &padapter->mlmeextpriv; pmlmeinfo = &(pmlmeext->mlmext_info); pattrib = &pxmitframe->attrib; bmcst = IS_MCAST(pattrib->ra); ptxdesc = (PTXDESC_8188E)pbuf; if (pxmitframe->frame_tag == DATA_FRAMETAG) { ptxdesc->macid = pattrib->mac_id; // CAM_ID(MAC_ID) if (pattrib->ampdu_en == _TRUE) ptxdesc->agg_en = 1; // AGG EN else ptxdesc->bk = 1; // AGG BK ptxdesc->qsel = pattrib->qsel; ptxdesc->rate_id = pattrib->raid; fill_txdesc_sectype(pattrib, ptxdesc); ptxdesc->seq = pattrib->seqnum; //todo: qos_en ptxdesc->userate = 1; // driver uses rate if ((pattrib->ether_type != 0x888e) && (pattrib->ether_type != 0x0806) && (pattrib->dhcp_pkt != 1)) { // Non EAP & ARP & DHCP type data packet fill_txdesc_vcs(pattrib, ptxdesc); fill_txdesc_phy(pattrib, ptxdesc); ptxdesc->rtsrate = 8; // RTS Rate=24M ptxdesc->data_ratefb_lmt = 0x1F; ptxdesc->rts_ratefb_lmt = 0xF; #if (RATE_ADAPTIVE_SUPPORT == 1) /* driver-based RA*/ if (pattrib->ht_en) ptxdesc->sgi = ODM_RA_GetShortGI_8188E(&pHalData->odmpriv,pattrib->mac_id); ptxdesc->datarate = ODM_RA_GetDecisionRate_8188E(&pHalData->odmpriv,pattrib->mac_id); #if (POWER_TRAINING_ACTIVE==1) ptxdesc->pwr_status = ODM_RA_GetHwPwrStatus_8188E(&pHalData->odmpriv,pattrib->mac_id); #endif #else /* (RATE_ADAPTIVE_SUPPORT == 1) */ /* FW-based RA, TODO */ if(pattrib->ht_en) ptxdesc->sgi = 1; ptxdesc->datarate = 0x13; //MCS7 #endif /* (RATE_ADAPTIVE_SUPPORT == 1) */ if (padapter->fix_rate != 0xFF) { ptxdesc->userate = 1; ptxdesc->datarate = padapter->fix_rate; ptxdesc->disdatafb = 1; ptxdesc->sgi = (padapter->fix_rate & BIT(7))?1:0; } } else { // EAP data packet and ARP and DHCP packet. // Use the 1M or 6M data rate to send the EAP/ARP packet. // This will maybe make the handshake smooth. ptxdesc->bk = 1; // AGG BK if (pmlmeinfo->preamble_mode == PREAMBLE_SHORT) ptxdesc->data_short = 1;// DATA_SHORT ptxdesc->datarate = MRateToHwRate(pmlmeext->tx_rate); } ptxdesc->usb_txagg_num = pxmitframe->agg_num; } else if (pxmitframe->frame_tag == MGNT_FRAMETAG) { // RT_TRACE(_module_hal_xmit_c_, _drv_notice_, ("%s: MGNT_FRAMETAG\n", __FUNCTION__)); ptxdesc->macid = pattrib->mac_id; // CAM_ID(MAC_ID) ptxdesc->qsel = pattrib->qsel; ptxdesc->rate_id = pattrib->raid; // Rate ID ptxdesc->seq = pattrib->seqnum; ptxdesc->userate = 1; // driver uses rate, 1M ptxdesc->rty_lmt_en = 1; // retry limit enable ptxdesc->data_rt_lmt = 6; // retry limit = 6 #ifdef CONFIG_XMIT_ACK //CCX-TXRPT ack for xmit mgmt frames. if (pxmitframe->ack_report) { #ifdef DBG_CCX static u16 ccx_sw = 0x123; txdesc_set_ccx_sw_88e(ptxdesc, ccx_sw); DBG_871X("%s set ccx, sw:0x%03x\n", __func__, ccx_sw); ccx_sw = (ccx_sw+1)%0xfff; #endif ptxdesc->ccx = 1; } #endif //CONFIG_XMIT_ACK #ifdef CONFIG_INTEL_PROXIM if((padapter->proximity.proxim_on==_TRUE)&&(pattrib->intel_proxim==_TRUE)){ DBG_871X("\n %s pattrib->rate=%d\n",__FUNCTION__,pattrib->rate); ptxdesc->datarate = pattrib->rate; } else #endif { ptxdesc->datarate = MRateToHwRate(pmlmeext->tx_rate); } } else if (pxmitframe->frame_tag == TXAGG_FRAMETAG) { RT_TRACE(_module_hal_xmit_c_, _drv_warning_, ("%s: TXAGG_FRAMETAG\n", __FUNCTION__)); } #ifdef CONFIG_MP_INCLUDED else if (pxmitframe->frame_tag == MP_FRAMETAG) { struct tx_desc *pdesc; pdesc = (struct tx_desc*)ptxdesc; RT_TRACE(_module_hal_xmit_c_, _drv_notice_, ("%s: MP_FRAMETAG\n", __FUNCTION__)); fill_txdesc_for_mp(padapter, (u8 *)pdesc); pdesc->txdw0 = le32_to_cpu(pdesc->txdw0); pdesc->txdw1 = le32_to_cpu(pdesc->txdw1); pdesc->txdw2 = le32_to_cpu(pdesc->txdw2); pdesc->txdw3 = le32_to_cpu(pdesc->txdw3); pdesc->txdw4 = le32_to_cpu(pdesc->txdw4); pdesc->txdw5 = le32_to_cpu(pdesc->txdw5); pdesc->txdw6 = le32_to_cpu(pdesc->txdw6); pdesc->txdw7 = le32_to_cpu(pdesc->txdw7); } #endif // CONFIG_MP_INCLUDED else { RT_TRACE(_module_hal_xmit_c_, _drv_warning_, ("%s: frame_tag=0x%x\n", __FUNCTION__, pxmitframe->frame_tag)); ptxdesc->macid = 4; // CAM_ID(MAC_ID) ptxdesc->rate_id = 6; // Rate ID ptxdesc->seq = pattrib->seqnum; ptxdesc->userate = 1; // driver uses rate ptxdesc->datarate = MRateToHwRate(pmlmeext->tx_rate); } ptxdesc->pktlen = pattrib->last_txcmdsz; if (pxmitframe->frame_tag == DATA_FRAMETAG){ #ifdef CONFIG_TX_EARLY_MODE ptxdesc->offset = TXDESC_SIZE +EARLY_MODE_INFO_SIZE ; ptxdesc->pkt_offset = 0x01; #else ptxdesc->offset = TXDESC_SIZE ; ptxdesc->pkt_offset = 0; #endif } else{ ptxdesc->offset = TXDESC_SIZE ; } if (bmcst) ptxdesc->bmc = 1; ptxdesc->ls = 1; ptxdesc->fs = 1; ptxdesc->own = 1; // 2009.11.05. tynli_test. Suggested by SD4 Filen for FW LPS. // (1) The sequence number of each non-Qos frame / broadcast / multicast / // mgnt frame should be controled by Hw because Fw will also send null data // which we cannot control when Fw LPS enable. // --> default enable non-Qos data sequense number. 2010.06.23. by tynli. // (2) Enable HW SEQ control for beacon packet, because we use Hw beacon. // (3) Use HW Qos SEQ to control the seq num of Ext port non-Qos packets. // 2010.06.23. Added by tynli. if (!pattrib->qos_en) { // Hw set sequence number ptxdesc->hwseq_en = 1; // HWSEQ_EN ptxdesc->hwseq_sel = 0; // HWSEQ_SEL } }
static s32 update_txdesc(struct xmit_frame *pxmitframe, u8 *pmem, s32 sz ,u8 bagg_pkt) { int pull=0; uint qsel; u8 data_rate,pwr_status,offset; _adapter *padapter = pxmitframe->padapter; struct mlme_priv *pmlmepriv = &padapter->mlmepriv; struct pkt_attrib *pattrib = &pxmitframe->attrib; HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter); //struct dm_priv *pdmpriv = &pHalData->dmpriv; u8 *ptxdesc = pmem; struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); sint bmcst = IS_MCAST(pattrib->ra); #ifdef CONFIG_P2P struct wifidirect_info* pwdinfo = &padapter->wdinfo; #endif //CONFIG_P2P #ifndef CONFIG_USE_USB_BUFFER_ALLOC_TX if (padapter->registrypriv.mp_mode == 0) { //if((!bagg_pkt) &&(urb_zero_packet_chk(padapter, sz)==0))//(sz %512) != 0 if((PACKET_OFFSET_SZ != 0) && (!bagg_pkt) && (rtw_usb_bulk_size_boundary(padapter,TXDESC_SIZE+sz)==_FALSE)) { ptxdesc = (pmem+PACKET_OFFSET_SZ); //DBG_8192C("==> non-agg-pkt,shift pointer...\n"); pull = 1; } } #endif // CONFIG_USE_USB_BUFFER_ALLOC_TX _rtw_memset(ptxdesc, 0, TXDESC_SIZE); //4 offset 0 //DBG_8192C("%s==> pkt_len=%d,bagg_pkt=%02x\n",__FUNCTION__,sz,bagg_pkt); SET_TX_DESC_PKT_SIZE_92E(ptxdesc, sz); offset = TXDESC_SIZE + OFFSET_SZ; #ifdef CONFIG_TX_EARLY_MODE if(bagg_pkt){ offset += EARLY_MODE_INFO_SIZE ;//0x28 } #endif //DBG_8192C("%s==>offset(0x%02x) \n",__FUNCTION__,offset); SET_TX_DESC_OFFSET_92E(ptxdesc, offset); if (bmcst) { SET_TX_DESC_BMC_92E(ptxdesc, 1); } #ifndef CONFIG_USE_USB_BUFFER_ALLOC_TX if (padapter->registrypriv.mp_mode == 0) { if((PACKET_OFFSET_SZ != 0) && (!bagg_pkt)){ if((pull) && (pxmitframe->pkt_offset>0)) { pxmitframe->pkt_offset = pxmitframe->pkt_offset -1; } } } #endif //DBG_8192C("%s, pkt_offset=0x%02x\n",__FUNCTION__,pxmitframe->pkt_offset); // pkt_offset, unit:8 bytes padding if (pxmitframe->pkt_offset > 0) { SET_TX_DESC_PKT_OFFSET_92E(ptxdesc, pxmitframe->pkt_offset); } SET_TX_DESC_MACID_92E(ptxdesc, pattrib->mac_id); SET_TX_DESC_RATE_ID_92E(ptxdesc, pattrib->raid); SET_TX_DESC_QUEUE_SEL_92E(ptxdesc, pattrib->qsel); //offset 12 if (!pattrib->qos_en) { SET_TX_DESC_EN_HWSEQ_92E(ptxdesc, 1); // Hw set sequence number } else { SET_TX_DESC_SEQ_92E(ptxdesc, pattrib->seqnum); } if((pxmitframe->frame_tag&0x0f) == DATA_FRAMETAG) { //DBG_8192C("pxmitframe->frame_tag == DATA_FRAMETAG\n"); fill_txdesc_sectype(pattrib, ptxdesc); if (pattrib->ampdu_en==_TRUE) { SET_TX_DESC_AGG_ENABLE_92E(ptxdesc, 1); SET_TX_DESC_MAX_AGG_NUM_92E(ptxdesc, 0x1f); // Set A-MPDU aggregation. SET_TX_DESC_AMPDU_DENSITY_92E(ptxdesc, pHalData->AMPDUDensity); } else { SET_TX_DESC_BK_92E(ptxdesc, 1); } //offset 20 #ifdef CONFIG_USB_TX_AGGREGATION if (pxmitframe->agg_num > 1){ //DBG_8192C("%s agg_num:%d\n",__FUNCTION__,pxmitframe->agg_num ); SET_TX_DESC_USB_TXAGG_NUM_92E(ptxdesc, pxmitframe->agg_num); } #endif if ((pattrib->ether_type != 0x888e) && (pattrib->ether_type != 0x0806) && (pattrib->ether_type != 0x88b4) && (pattrib->dhcp_pkt != 1) #ifdef CONFIG_AUTO_AP_MODE && (pattrib->pctrl != _TRUE) #endif ) { //Non EAP & ARP & DHCP type data packet fill_txdesc_vcs(pattrib, ptxdesc); fill_txdesc_phy(padapter, pattrib, ptxdesc); SET_TX_DESC_RTS_RATE_92E(ptxdesc, 0x8);//RTS Rate=24M //DATA/RTS Rate FB LMT SET_TX_DESC_DATA_RATE_FB_LIMIT_92E(ptxdesc, 0x1f); SET_TX_DESC_RTS_RATE_FB_LIMIT_92E(ptxdesc, 0xf); if(pHalData->fw_ractrl == _FALSE) { struct dm_priv *pdmpriv = &pHalData->dmpriv; SET_TX_DESC_USE_RATE_92E(ptxdesc, 1); if(pdmpriv->INIDATA_RATE[pattrib->mac_id] & BIT(7)) SET_TX_DESC_DATA_SHORT_92E(ptxdesc, 1); SET_TX_DESC_TX_RATE_92E(ptxdesc, (pdmpriv->INIDATA_RATE[pattrib->mac_id] & 0x7F)); } //for debug #if 1 if(padapter->fix_rate!= 0xFF){ struct dm_priv *pdmpriv = &pHalData->dmpriv; SET_TX_DESC_USE_RATE_92E(ptxdesc, 1); //if(pdmpriv->INIDATA_RATE[pattrib->mac_id] & BIT(7)) { if(padapter->fix_rate & BIT(7)) SET_TX_DESC_DATA_SHORT_92E(ptxdesc, 1); } SET_TX_DESC_TX_RATE_92E(ptxdesc, (padapter->fix_rate & 0x7F)); SET_TX_DESC_DISABLE_FB_92E(ptxdesc,1); //ptxdesc->datarate = padapter->fix_rate; } #endif } else { // EAP data packet and ARP packet and DHCP. // Use the 1M data rate to send the EAP/ARP packet. // This will maybe make the handshake smooth. SET_TX_DESC_USE_RATE_92E(ptxdesc, 1); SET_TX_DESC_BK_92E(ptxdesc, 1); // HW will ignore this setting if the transmission rate is legacy OFDM. if (pmlmeinfo->preamble_mode == PREAMBLE_SHORT) { SET_TX_DESC_DATA_SHORT_92E(ptxdesc, 1); } SET_TX_DESC_TX_RATE_92E(ptxdesc, MRateToHwRate(pmlmeext->tx_rate)); } } else if((pxmitframe->frame_tag&0x0f)== MGNT_FRAMETAG) { //DBG_8192C("pxmitframe->frame_tag == MGNT_FRAMETAG\n"); SET_TX_DESC_MBSSID_92E(ptxdesc, pattrib->mbssid);//for issue port1/mbssid beacon //offset 20 SET_TX_DESC_RETRY_LIMIT_ENABLE_92E(ptxdesc, 1); if (pattrib->retry_ctrl == _TRUE) { SET_TX_DESC_DATA_RETRY_LIMIT_92E(ptxdesc, 6); } else { SET_TX_DESC_DATA_RETRY_LIMIT_92E(ptxdesc, 12); } SET_TX_DESC_USE_RATE_92E(ptxdesc, 1); #ifdef CONFIG_INTEL_PROXIM if((padapter->proximity.proxim_on==_TRUE)&&(pattrib->intel_proxim==_TRUE)){ DBG_871X("\n %s pattrib->rate=%d\n",__FUNCTION__,pattrib->rate); SET_TX_DESC_TX_RATE_92E(ptxdesc, pattrib->rate); } else #endif { SET_TX_DESC_TX_RATE_92E(ptxdesc, MRateToHwRate(pmlmeext->tx_rate)); } #ifdef CONFIG_XMIT_ACK //CCX-TXRPT ack for xmit mgmt frames. if (pxmitframe->ack_report) { SET_TX_DESC_SPE_RPT_92E(ptxdesc, 1); #ifdef DBG_CCX DBG_871X("%s set tx report\n", __func__); #endif } #endif //CONFIG_XMIT_ACK } else if((pxmitframe->frame_tag&0x0f) == TXAGG_FRAMETAG) { DBG_8192C("pxmitframe->frame_tag == TXAGG_FRAMETAG\n"); } #ifdef CONFIG_MP_INCLUDED else if(((pxmitframe->frame_tag&0x0f) == MP_FRAMETAG) && (padapter->registrypriv.mp_mode == 1)) { fill_txdesc_for_mp(padapter, ptxdesc); } #endif else { DBG_8192C("pxmitframe->frame_tag = %d\n", pxmitframe->frame_tag); SET_TX_DESC_USE_RATE_92E(ptxdesc, 1); SET_TX_DESC_TX_RATE_92E(ptxdesc, MRateToHwRate(pmlmeext->tx_rate)); } rtl8192e_cal_txdesc_chksum(ptxdesc); _dbg_dump_tx_info(padapter,pxmitframe->frame_tag,ptxdesc); return pull; }
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_; }
static s32 update_txdesc(struct xmit_frame *pxmitframe, u8 *pmem, s32 sz, u8 bagg_pkt) { int pull=0; uint qsel; _adapter *padapter = pxmitframe->padapter; struct mlme_priv *pmlmepriv = &padapter->mlmepriv; struct pkt_attrib *pattrib = &pxmitframe->attrib; HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter); struct dm_priv *pdmpriv = &pHalData->dmpriv; struct tx_desc *ptxdesc = (struct tx_desc *)pmem; struct ht_priv *phtpriv = &pmlmepriv->htpriv; struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); sint bmcst = IS_MCAST(pattrib->ra); #ifdef CONFIG_P2P struct wifidirect_info* pwdinfo = &padapter->wdinfo; #endif //CONFIG_P2P #ifndef CONFIG_USE_USB_BUFFER_ALLOC_TX if((_FALSE == bagg_pkt) && (urb_zero_packet_chk(padapter, sz)==0)) { ptxdesc = (struct tx_desc *)(pmem+PACKET_OFFSET_SZ); pull = 1; pxmitframe->pkt_offset --; } #endif // CONFIG_USE_USB_BUFFER_ALLOC_TX _rtw_memset(ptxdesc, 0, sizeof(struct tx_desc)); if((pxmitframe->frame_tag&0x0f) == DATA_FRAMETAG) { //DBG_8192C("pxmitframe->frame_tag == DATA_FRAMETAG\n"); //offset 4 ptxdesc->txdw1 |= cpu_to_le32(pattrib->mac_id&0x1f); qsel = (uint)(pattrib->qsel & 0x0000001f); ptxdesc->txdw1 |= cpu_to_le32((qsel << QSEL_SHT) & 0x00001f00); ptxdesc->txdw1 |= cpu_to_le32((pattrib->raid<< 16) & 0x000f0000); fill_txdesc_sectype(pattrib, ptxdesc); if(pattrib->ampdu_en==_TRUE) ptxdesc->txdw1 |= cpu_to_le32(BIT(5));//AGG EN else ptxdesc->txdw1 |= cpu_to_le32(BIT(6));//AGG BK //offset 8 //offset 12 ptxdesc->txdw3 |= cpu_to_le32((pattrib->seqnum<<16)&0xffff0000); //offset 16 , offset 20 if (pattrib->qos_en) ptxdesc->txdw4 |= cpu_to_le32(BIT(6));//QoS if ((pattrib->ether_type != 0x888e) && (pattrib->ether_type != 0x0806) && (pattrib->dhcp_pkt != 1)) { //Non EAP & ARP & DHCP type data packet fill_txdesc_vcs(pattrib, &ptxdesc->txdw4); fill_txdesc_phy(pattrib, &ptxdesc->txdw4); ptxdesc->txdw4 |= cpu_to_le32(0x00000008);//RTS Rate=24M ptxdesc->txdw5 |= cpu_to_le32(0x0001ff00);// //ptxdesc->txdw5 |= cpu_to_le32(0x0000000b);//DataRate - 54M //use REG_INIDATA_RATE_SEL value ptxdesc->txdw5 |= cpu_to_le32(pdmpriv->INIDATA_RATE[pattrib->mac_id]); if(0)//for driver dbg { ptxdesc->txdw4 |= cpu_to_le32(BIT(8));//driver uses rate if(pattrib->ht_en) ptxdesc->txdw5 |= cpu_to_le32(BIT(6));//SGI ptxdesc->txdw5 |= cpu_to_le32(0x00000013);//init rate - mcs7 } } else { // EAP data packet and ARP packet. // Use the 1M data rate to send the EAP/ARP packet. // This will maybe make the handshake smooth. ptxdesc->txdw1 |= cpu_to_le32(BIT(6));//AGG BK ptxdesc->txdw4 |= cpu_to_le32(BIT(8));//driver uses rate if (pmlmeinfo->preamble_mode == PREAMBLE_SHORT) ptxdesc->txdw4 |= cpu_to_le32(BIT(24));// DATA_SHORT ptxdesc->txdw5 |= cpu_to_le32(MRateToHwRate(pmlmeext->tx_rate)); } //offset 24 #ifdef CONFIG_TCP_CSUM_OFFLOAD_TX if ( pattrib->hw_tcp_csum == 1 ) { // ptxdesc->txdw6 = 0; // clear TCP_CHECKSUM and IP_CHECKSUM. It's zero already!! u8 ip_hdr_offset = 32 + pattrib->hdrlen + pattrib->iv_len + 8; ptxdesc->txdw7 = (1 << 31) | (ip_hdr_offset << 16); DBG_8192C("ptxdesc->txdw7 = %08x\n", ptxdesc->txdw7); } #endif } else if((pxmitframe->frame_tag&0x0f)== MGNT_FRAMETAG) { //DBG_8192C("pxmitframe->frame_tag == MGNT_FRAMETAG\n"); //offset 4 ptxdesc->txdw1 |= cpu_to_le32(pattrib->mac_id&0x1f); qsel = (uint)(pattrib->qsel&0x0000001f); ptxdesc->txdw1 |= cpu_to_le32((qsel<<QSEL_SHT)&0x00001f00); ptxdesc->txdw1 |= cpu_to_le32((pattrib->raid<< 16) & 0x000f0000); //fill_txdesc_sectype(pattrib, ptxdesc); //offset 8 #ifdef CONFIG_XMIT_ACK //CCX-TXRPT ack for xmit mgmt frames. if (pxmitframe->ack_report) { ptxdesc->txdw2 |= cpu_to_le32(BIT(19)); #ifdef DBG_CCX DBG_871X("%s set ccx\n", __func__); #endif } #endif //CONFIG_XMIT_ACK //offset 12 ptxdesc->txdw3 |= cpu_to_le32((pattrib->seqnum<<16)&0xffff0000); //offset 16 ptxdesc->txdw4 |= cpu_to_le32(BIT(8));//driver uses rate //offset 20 ptxdesc->txdw5 |= cpu_to_le32(BIT(17));//retry limit enable if(pattrib->retry_ctrl == _TRUE) { #ifdef CONFIG_P2P if(!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)) { ptxdesc->txdw5 |= cpu_to_le32(0x00080000);//retry limit = 2 } else #endif //CONFIG_P2P ptxdesc->txdw5 |= cpu_to_le32(0x00180000);//retry limit = 6 } else ptxdesc->txdw5 |= cpu_to_le32(0x00300000);//retry limit = 12 #ifdef CONFIG_INTEL_PROXIM if((padapter->proximity.proxim_on==_TRUE)&&(pattrib->intel_proxim==_TRUE)){ printk("\n %s pattrib->rate=%d\n",__FUNCTION__,pattrib->rate); ptxdesc->txdw5 |= cpu_to_le32( pattrib->rate); } else #endif { ptxdesc->txdw5 |= cpu_to_le32(MRateToHwRate(pmlmeext->tx_rate)); } } else if((pxmitframe->frame_tag&0x0f) == TXAGG_FRAMETAG) { DBG_8192C("pxmitframe->frame_tag == TXAGG_FRAMETAG\n"); } #ifdef CONFIG_MP_INCLUDED else if((pxmitframe->frame_tag&0x0f) == MP_FRAMETAG) { fill_txdesc_for_mp(padapter, ptxdesc); } #endif else { DBG_8192C("pxmitframe->frame_tag = %d\n", pxmitframe->frame_tag); //offset 4 ptxdesc->txdw1 |= cpu_to_le32((4)&0x1f);//CAM_ID(MAC_ID) ptxdesc->txdw1 |= cpu_to_le32((6<< 16) & 0x000f0000);//raid //offset 8 //offset 12 ptxdesc->txdw3 |= cpu_to_le32((pattrib->seqnum<<16)&0xffff0000); //offset 16 ptxdesc->txdw4 |= cpu_to_le32(BIT(8));//driver uses rate //offset 20 ptxdesc->txdw5 |= cpu_to_le32(MRateToHwRate(pmlmeext->tx_rate)); } // 2009.11.05. tynli_test. Suggested by SD4 Filen for FW LPS. // (1) The sequence number of each non-Qos frame / broadcast / multicast / // mgnt frame should be controled by Hw because Fw will also send null data // which we cannot control when Fw LPS enable. // --> default enable non-Qos data sequense number. 2010.06.23. by tynli. // (2) Enable HW SEQ control for beacon packet, because we use Hw beacon. // (3) Use HW Qos SEQ to control the seq num of Ext port non-Qos packets. // 2010.06.23. Added by tynli. if(!pattrib->qos_en) { 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. } //offset 0 ptxdesc->txdw0 |= cpu_to_le32(sz&0x0000ffff); ptxdesc->txdw0 |= cpu_to_le32(OWN | FSG | LSG); ptxdesc->txdw0 |= cpu_to_le32(((TXDESC_SIZE+OFFSET_SZ)<<OFFSET_SHT)&0x00ff0000);//32 bytes for TX Desc if(bmcst) { ptxdesc->txdw0 |= cpu_to_le32(BIT(24)); } RT_TRACE(_module_rtl871x_xmit_c_,_drv_info_,("offset0-txdesc=0x%x\n", ptxdesc->txdw0)); //offset 4 // pkt_offset, unit:8 bytes padding if (pxmitframe->pkt_offset > 0) ptxdesc->txdw1 |= cpu_to_le32((pxmitframe->pkt_offset << 26) & 0x7c000000); #ifdef CONFIG_USB_TX_AGGREGATION if (pxmitframe->agg_num > 1) ptxdesc->txdw5 |= cpu_to_le32((pxmitframe->agg_num << 24) & 0xff000000); #endif rtl8192cu_cal_txdesc_chksum(ptxdesc); return pull; }
void rtw_os_recv_indicate_pkt(_adapter *padapter, _pkt *pkt, struct rx_pkt_attrib *pattrib) { struct mlme_priv*pmlmepriv = &padapter->mlmepriv; struct recv_priv *precvpriv = &(padapter->recvpriv); #ifdef CONFIG_BR_EXT void *br_port = NULL; #endif int ret; /* Indicat the packets to upper layer */ if (pkt) { if(check_fwstate(pmlmepriv, WIFI_AP_STATE) == _TRUE) { _pkt *pskb2=NULL; struct sta_info *psta = NULL; struct sta_priv *pstapriv = &padapter->stapriv; 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(pkt); } 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; pkt->dev = pnetdev; #if (LINUX_VERSION_CODE>=KERNEL_VERSION(2,6,35)) skb_set_queue_mapping(pkt, rtw_recv_select_queue(pkt)); #endif //LINUX_VERSION_CODE>=KERNEL_VERSION(2,6,35) _rtw_xmit_entry(pkt, pnetdev); if(bmcast && (pskb2 != NULL) ) { pkt = pskb2; DBG_COUNTER(padapter->rx_logs.os_indicate_ap_mcast); } else { DBG_COUNTER(padapter->rx_logs.os_indicate_ap_forward); return; } } } else// to APself { //DBG_871X("to APSelf\n"); DBG_COUNTER(padapter->rx_logs.os_indicate_ap_self); } } #ifdef CONFIG_BR_EXT // Insert NAT2.5 RX here! #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, pkt) == -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 rtw_skb_free(sub_skb); continue; #endif } } #endif // CONFIG_BR_EXT if( precvpriv->sink_udpport > 0) rtw_sink_rtp_seq_dbg(padapter,pkt); pkt->protocol = eth_type_trans(pkt, padapter->pnetdev); pkt->dev = padapter->pnetdev; #ifdef CONFIG_TCP_CSUM_OFFLOAD_RX if ( (pattrib->tcpchk_valid == 1) && (pattrib->tcp_chkrpt == 1) ) { pkt->ip_summed = CHECKSUM_UNNECESSARY; } else { pkt->ip_summed = CHECKSUM_NONE; } #else /* !CONFIG_TCP_CSUM_OFFLOAD_RX */ pkt->ip_summed = CHECKSUM_NONE; #endif //CONFIG_TCP_CSUM_OFFLOAD_RX ret = rtw_netif_rx(padapter->pnetdev, pkt); if (ret == NET_RX_SUCCESS) DBG_COUNTER(padapter->rx_logs.os_netif_ok); else DBG_COUNTER(padapter->rx_logs.os_netif_err); } }
static int mgnt_xmit_entry(struct sk_buff *skb, struct net_device *pnetdev) { u16 fc; int rc, len, pipe; unsigned int bmcst, tid, qsel; struct sk_buff *pxmit_skb; struct urb *urb; unsigned char *pxmitbuf; struct tx_desc *ptxdesc; struct ieee80211_hdr *tx_hdr; struct hostapd_priv *phostapdpriv = netdev_priv(pnetdev); _adapter *padapter = (_adapter *)phostapdpriv->padapter; HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter); struct dvobj_priv *pdvobj = &padapter->dvobjpriv; //printk("%s\n", __FUNCTION__); len = skb->len; tx_hdr = (struct ieee80211_hdr *)(skb->data); fc = le16_to_cpu(tx_hdr->frame_ctl); bmcst = IS_MCAST(tx_hdr->addr1); if ((fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_MGMT) goto _exit; #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18)) // http://www.mail-archive.com/[email protected]/msg17214.html pxmit_skb = dev_alloc_skb(len + TXDESC_SIZE); #else pxmit_skb = netdev_alloc_skb(pnetdev, len + TXDESC_SIZE); #endif 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; _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 cal_txdesc_chksum(ptxdesc); // ----- end of fill tx desc ----- // skb_put(pxmit_skb, len + TXDESC_SIZE); pxmitbuf = pxmitbuf + TXDESC_SIZE; _memcpy(pxmitbuf, skb->data, len); //printk("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, 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: dev_kfree_skb_any(skb); return 0; }
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_; }