// 1: write RCR DATA BIT // 2: issue peer traffic indication // 3: go back to the channel linked with AP, terminating channel switch procedure // 4: init channel sensing, receive all data and mgnt frame // 5: channel sensing and report candidate channel // 6: first time set channel to off channel // 7: go back tp the channel linked with AP when set base channel as target channel void TDLS_option_workitem_callback(struct work_struct *work) { struct sta_info *ptdls_sta = container_of(work, struct sta_info, option_workitem); _adapter *padapter = ptdls_sta->padapter; struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; u32 bit_6=1<<6, bit_7=1<<7, bit_4=1<<4; u8 survey_channel, i, min; switch(ptdls_sta->option){ case 1: //As long as TDLS handshake success, we should set RCR_CBSSID_DATA bit to 0 //such we can receive all kinds of data frames. rtw_write32(padapter, 0x0608, rtw_read32(padapter, 0x0608)&(~bit_6)); DBG_8192C("wirte 0x0608, set bit6 off\n"); break; case 2: issue_tdls_peer_traffic_indication(padapter, ptdls_sta); break; case 3: _cancel_timer_ex(&ptdls_sta->base_ch_timer); _cancel_timer_ex(&ptdls_sta->off_ch_timer); SelectChannel(padapter, pmlmeext->cur_channel); ptdls_sta->state &= ~(TDLS_CH_SWITCH_ON_STATE | TDLS_PEER_AT_OFF_STATE | TDLS_AT_OFF_CH_STATE); DBG_8192C("go back to base channel\n "); issue_nulldata(padapter, 0); break; case 4: rtw_write32(padapter, 0x0608, rtw_read32(padapter, 0x0608)&(~bit_6)&(~bit_7)); rtw_write16(padapter, 0x06A4,0xffff); //maybe don't need to write here //disable update TSF rtw_write8(padapter, 0x0550, rtw_read8(padapter, 0x0550)|bit_4); pmlmeext->sitesurvey_res.channel_idx = 0; ptdls_sta->option = 5; _set_workitem(&ptdls_sta->option_workitem); break; case 5: survey_channel = pmlmeext->channel_set[pmlmeext->sitesurvey_res.channel_idx].ChannelNum; if(survey_channel){ SelectChannel(padapter, survey_channel); pmlmeinfo->tdls_cur_channel = survey_channel; pmlmeext->sitesurvey_res.channel_idx++; _set_timer(&ptdls_sta->option_timer, SURVEY_TO); }else{ SelectChannel(padapter, pmlmeext->cur_channel); //enable update TSF rtw_write8(padapter, 0x0550, rtw_read8(padapter, 0x0550)&(~bit_4)); rtw_write32(padapter, 0x0608, rtw_read32(padapter, 0x0608)|(bit_7)); if(pmlmeinfo->tdls_ch_sensing==1){ pmlmeinfo->tdls_ch_sensing=0; pmlmeinfo->tdls_cur_channel=1; min=pmlmeinfo->tdls_collect_pkt_num[0]; for(i=1; i<14-1; i++){ if(min > pmlmeinfo->tdls_collect_pkt_num[i]){ pmlmeinfo->tdls_cur_channel=i+1; min=pmlmeinfo->tdls_collect_pkt_num[i]; } pmlmeinfo->tdls_collect_pkt_num[i]=0; } pmlmeinfo->tdls_collect_pkt_num[0]=0; pmlmeinfo->tdls_candidate_ch=pmlmeinfo->tdls_cur_channel; DBG_8192C("TDLS channel sensing done, candidate channel: %02x\n", pmlmeinfo->tdls_candidate_ch); pmlmeinfo->tdls_cur_channel=0; } if(ptdls_sta->state & TDLS_PEER_SLEEP_STATE){ ptdls_sta->state |= TDLS_APSD_CHSW_STATE; }else{ //send null data with pwrbit==1 before send ch_switching_req to peer STA. issue_nulldata(padapter, 1); ptdls_sta->state |= TDLS_CH_SW_INITIATOR_STATE; issue_tdls_ch_switch_req(padapter, ptdls_sta->hwaddr); DBG_8192C("issue tdls ch switch req\n"); } } break; case 6: issue_nulldata(padapter, 1); SelectChannel(padapter, ptdls_sta->off_ch); DBG_8192C("change channel to tar ch:%02x\n", ptdls_sta->off_ch); ptdls_sta->state |= TDLS_AT_OFF_CH_STATE; ptdls_sta->state &= ~(TDLS_PEER_AT_OFF_STATE); _set_timer(&ptdls_sta->option_timer, (u32)ptdls_sta->ch_switch_time); break; case 7: _cancel_timer_ex(&ptdls_sta->base_ch_timer); _cancel_timer_ex(&ptdls_sta->off_ch_timer); SelectChannel(padapter, pmlmeext->cur_channel); ptdls_sta->state &= ~(TDLS_CH_SWITCH_ON_STATE | TDLS_PEER_AT_OFF_STATE | TDLS_AT_OFF_CH_STATE); DBG_8192C("go back to base channel\n "); issue_nulldata(padapter, 0); _set_timer(&ptdls_sta->option_timer, (u32)ptdls_sta->ch_switch_time); break; } }
static s32 pre_recv_entry(union recv_frame *precvframe, struct recv_buf *precvbuf, struct phy_stat *pphy_status) { s32 ret=_SUCCESS; #ifdef CONFIG_CONCURRENT_MODE u8 *primary_myid, *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 { //primary_myid = myid(&primary_padapter->eeprompriv); secondary_myid = myid(&secondary_padapter->eeprompriv); 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 rtw_skb_copy(). //If skb->len is zero, rtw_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) update_recvframe_phyinfo(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) update_recvframe_phyinfo(precvframe, pphy_status); ret = rtw_recv_entry(precvframe); #endif return ret; }
/***************************************** * H2C Msg format : * 0x1DF - 0x1D0 *| 31 - 8 | 7-5 4 - 0 | *| h2c_msg |Class_ID CMD_ID | * * Extend 0x1FF - 0x1F0 *|31 - 0 | *|ext_msg| ******************************************/ static s32 FillH2CCmd_8812(PADAPTER padapter, u8 ElementID, u32 CmdLen, u8 *pCmdBuffer) { u8 bcmd_down = _FALSE; s32 retry_cnts = 100; u8 h2c_box_num; u32 msgbox_addr; u32 msgbox_ex_addr; HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter); u8 cmd_idx,ext_cmd_len; u32 h2c_cmd = 0; u32 h2c_cmd_ex = 0; s32 ret = _FAIL; _func_enter_; padapter = GET_PRIMARY_ADAPTER(padapter); pHalData = GET_HAL_DATA(padapter); if(padapter->bFWReady == _FALSE) { //DBG_8192C("FillH2CCmd_8812(): return H2C cmd because fw is not ready\n"); return ret; } _enter_critical_mutex(&(adapter_to_dvobj(padapter)->h2c_fwcmd_mutex), NULL); if (!pCmdBuffer) { goto exit; } if (CmdLen > RTL8812_MAX_CMD_LEN) { goto exit; } if (padapter->bSurpriseRemoved == _TRUE) goto exit; //pay attention to if race condition happened in H2C cmd setting. do{ h2c_box_num = pHalData->LastHMEBoxNum; if(!_is_fw_read_cmd_down(padapter, h2c_box_num)){ DBG_8192C(" fw read cmd failed...\n"); goto exit; } *(u8*)(&h2c_cmd) = ElementID; if(CmdLen<=3) { _rtw_memcpy((u8*)(&h2c_cmd)+1, pCmdBuffer, CmdLen ); } else{ _rtw_memcpy((u8*)(&h2c_cmd)+1, pCmdBuffer,3); ext_cmd_len = CmdLen-3; _rtw_memcpy((u8*)(&h2c_cmd_ex), pCmdBuffer+3,ext_cmd_len ); //Write Ext command msgbox_ex_addr = REG_HMEBOX_EXT0_8812 + (h2c_box_num *RTL8812_EX_MESSAGE_BOX_SIZE); #ifdef CONFIG_H2C_EF for(cmd_idx=0;cmd_idx<ext_cmd_len;cmd_idx++ ){ rtw_write8(padapter,msgbox_ex_addr+cmd_idx,*((u8*)(&h2c_cmd_ex)+cmd_idx)); } #else h2c_cmd_ex = le32_to_cpu( h2c_cmd_ex ); rtw_write32(padapter, msgbox_ex_addr, h2c_cmd_ex); #endif } // Write command msgbox_addr =REG_HMEBOX_0 + (h2c_box_num *RTL8812_MESSAGE_BOX_SIZE); #ifdef CONFIG_H2C_EF for(cmd_idx=0;cmd_idx<RTL8812_MESSAGE_BOX_SIZE;cmd_idx++ ){ rtw_write8(padapter,msgbox_addr+cmd_idx,*((u8*)(&h2c_cmd)+cmd_idx)); } #else h2c_cmd = le32_to_cpu( h2c_cmd ); rtw_write32(padapter,msgbox_addr, h2c_cmd); #endif bcmd_down = _TRUE; // DBG_8192C("MSG_BOX:%d,CmdLen(%d), reg:0x%x =>h2c_cmd:0x%x, reg:0x%x =>h2c_cmd_ex:0x%x ..\n" // ,pHalData->LastHMEBoxNum ,CmdLen,msgbox_addr,h2c_cmd,msgbox_ex_addr,h2c_cmd_ex); pHalData->LastHMEBoxNum = (h2c_box_num+1) % RTL8812_MAX_H2C_BOX_NUMS; }while((!bcmd_down) && (retry_cnts--)); ret = _SUCCESS; exit: _exit_critical_mutex(&(adapter_to_dvobj(padapter)->h2c_fwcmd_mutex), NULL); _func_exit_; return ret; }
void interrupt_handler_8812au(_adapter *padapter,u16 pkt_len,u8 *pbuf) { HAL_DATA_TYPE *pHalData=GET_HAL_DATA(padapter); struct reportpwrstate_parm pwr_rpt; if ( pkt_len != INTERRUPT_MSG_FORMAT_LEN ) { DBG_8192C("%s Invalid interrupt content length (%d)!\n", __FUNCTION__, pkt_len); return ; } // HISR _rtw_memcpy(&(pHalData->IntArray[0]), &(pbuf[USB_INTR_CONTENT_HISR_OFFSET]), 4); _rtw_memcpy(&(pHalData->IntArray[1]), &(pbuf[USB_INTR_CONTENT_HISRE_OFFSET]), 4); #if 0 //DBG { u32 hisr=0 ,hisr_ex=0; _rtw_memcpy(&hisr,&(pHalData->IntArray[0]),4); hisr = le32_to_cpu(hisr); _rtw_memcpy(&hisr_ex,&(pHalData->IntArray[1]),4); hisr_ex = le32_to_cpu(hisr_ex); if((hisr != 0) || (hisr_ex!=0)) DBG_871X("===> %s hisr:0x%08x ,hisr_ex:0x%08x \n",__FUNCTION__,hisr,hisr_ex); } #endif #ifdef CONFIG_LPS_LCLK if( pHalData->IntArray[0] & IMR_CPWM_88E ) { _rtw_memcpy(&pwr_rpt.state, &(pbuf[USB_INTR_CONTENT_CPWM1_OFFSET]), 1); //_rtw_memcpy(&pwr_rpt.state2, &(pbuf[USB_INTR_CONTENT_CPWM2_OFFSET]), 1); //88e's cpwm value only change BIT0, so driver need to add PS_STATE_S2 for LPS flow. pwr_rpt.state |= PS_STATE_S2; _set_workitem(&(adapter_to_pwrctl(padapter)->cpwm_event)); } #endif//CONFIG_LPS_LCLK #ifdef CONFIG_INTERRUPT_BASED_TXBCN #ifdef CONFIG_INTERRUPT_BASED_TXBCN_EARLY_INT if (pHalData->IntArray[0] & IMR_BCNDMAINT0_88E) #endif #ifdef CONFIG_INTERRUPT_BASED_TXBCN_BCN_OK_ERR if (pHalData->IntArray[0] & (IMR_TBDER_88E|IMR_TBDOK_88E)) #endif { struct mlme_priv *pmlmepriv = &padapter->mlmepriv; #if 0 if(pHalData->IntArray[0] & IMR_BCNDMAINT0_88E) DBG_8192C("%s: HISR_BCNERLY_INT\n", __func__); if(pHalData->IntArray[0] & IMR_TBDOK_88E) DBG_8192C("%s: HISR_TXBCNOK\n", __func__); if(pHalData->IntArray[0] & IMR_TBDER_88E) DBG_8192C("%s: HISR_TXBCNERR\n", __func__); #endif if(check_fwstate(pmlmepriv, WIFI_AP_STATE)) { //send_beacon(padapter); if(pmlmepriv->update_bcn == _TRUE) { //tx_beacon_hdl(padapter, NULL); set_tx_beacon_cmd(padapter); } } #ifdef CONFIG_CONCURRENT_MODE if(check_buddy_fwstate(padapter, WIFI_AP_STATE)) { //send_beacon(padapter); if(padapter->pbuddy_adapter->mlmepriv.update_bcn == _TRUE) { //tx_beacon_hdl(padapter, NULL); set_tx_beacon_cmd(padapter->pbuddy_adapter); } } #endif } #endif //CONFIG_INTERRUPT_BASED_TXBCN #ifdef DBG_CONFIG_ERROR_DETECT_INT if( pHalData->IntArray[1] & IMR_TXERR_88E ) DBG_871X("===> %s Tx Error Flag Interrupt Status \n",__FUNCTION__); if( pHalData->IntArray[1] & IMR_RXERR_88E ) DBG_871X("===> %s Rx Error Flag INT Status \n",__FUNCTION__); if( pHalData->IntArray[1] & IMR_TXFOVW_88E ) DBG_871X("===> %s Transmit FIFO Overflow \n",__FUNCTION__); if( pHalData->IntArray[1] & IMR_RXFOVW_88E ) DBG_871X("===> %s Receive FIFO Overflow \n",__FUNCTION__); #endif//DBG_CONFIG_ERROR_DETECT_INT // C2H Event if(pbuf[0]!= 0){ _rtw_memcpy(&(pHalData->C2hArray[0]), &(pbuf[USB_INTR_CONTENT_C2H_OFFSET]), 16); //rtw_c2h_wk_cmd(padapter); to do.. } }
int usbctrl_vendorreq(struct intf_hdl *pintfhdl, u8 request, u16 value, u16 index, void *pdata, u16 len, u8 requesttype) { _adapter *padapter = pintfhdl->padapter; struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(padapter); struct pwrctrl_priv *pwrctl = dvobj_to_pwrctl(pdvobjpriv); struct usb_device *udev=pdvobjpriv->pusbdev; unsigned int pipe; int status = 0; u32 tmp_buflen=0; u8 reqtype; u8 *pIo_buf; int vendorreq_times = 0; #ifdef CONFIG_USB_VENDOR_REQ_BUFFER_DYNAMIC_ALLOCATE u8 *tmp_buf; #else // use stack memory u8 tmp_buf[MAX_USB_IO_CTL_SIZE]; #endif #ifdef CONFIG_CONCURRENT_MODE if(padapter->adapter_type > PRIMARY_ADAPTER) { padapter = padapter->pbuddy_adapter; pdvobjpriv = adapter_to_dvobj(padapter); udev = pdvobjpriv->pusbdev; } #endif //DBG_871X("%s %s:%d\n",__FUNCTION__, current->comm, current->pid); if (RTW_CANNOT_IO(padapter)){ RT_TRACE(_module_hci_ops_os_c_,_drv_err_,("usbctrl_vendorreq:(RTW_CANNOT_IO)!!!\n")); status = -EPERM; goto exit; } if(len>MAX_VENDOR_REQ_CMD_SIZE){ DBG_8192C( "[%s] Buffer len error ,vendor request failed\n", __FUNCTION__ ); status = -EINVAL; goto exit; } #ifdef CONFIG_USB_VENDOR_REQ_MUTEX _enter_critical_mutex(&pdvobjpriv->usb_vendor_req_mutex, NULL); #endif // Acquire IO memory for vendorreq #ifdef CONFIG_USB_VENDOR_REQ_BUFFER_PREALLOC pIo_buf = pdvobjpriv->usb_vendor_req_buf; #else #ifdef CONFIG_USB_VENDOR_REQ_BUFFER_DYNAMIC_ALLOCATE tmp_buf = rtw_malloc( (u32) len + ALIGNMENT_UNIT); tmp_buflen = (u32)len + ALIGNMENT_UNIT; #else // use stack memory tmp_buflen = MAX_USB_IO_CTL_SIZE; #endif // Added by Albert 2010/02/09 // For mstar platform, mstar suggests the address for USB IO should be 16 bytes alignment. // Trying to fix it here. pIo_buf = (tmp_buf==NULL)?NULL:tmp_buf + ALIGNMENT_UNIT -((SIZE_PTR)(tmp_buf) & 0x0f ); #endif if ( pIo_buf== NULL) { DBG_8192C( "[%s] pIo_buf == NULL \n", __FUNCTION__ ); status = -ENOMEM; goto release_mutex; } while(++vendorreq_times<= MAX_USBCTRL_VENDORREQ_TIMES) { _rtw_memset(pIo_buf, 0, len); if (requesttype == 0x01) { pipe = usb_rcvctrlpipe(udev, 0);//read_in reqtype = REALTEK_USB_VENQT_READ; } else { pipe = usb_sndctrlpipe(udev, 0);//write_out reqtype = REALTEK_USB_VENQT_WRITE; _rtw_memcpy( pIo_buf, pdata, len); } status = rtw_usb_control_msg(udev, pipe, request, reqtype, value, index, pIo_buf, len, RTW_USB_CONTROL_MSG_TIMEOUT); if ( status == len) // Success this control transfer. { rtw_reset_continual_io_error(pdvobjpriv); if ( requesttype == 0x01 ) { // For Control read transfer, we have to copy the read data from pIo_buf to pdata. _rtw_memcpy( pdata, pIo_buf, len ); } } else { // error cases DBG_8192C("reg 0x%x, usb %s %u fail, status:%d value=0x%x, vendorreq_times:%d\n" , value,(requesttype == 0x01)?"read":"write" , len, status, *(u32*)pdata, vendorreq_times); if (status < 0) { if(status == (-ESHUTDOWN) || status == -ENODEV ) { padapter->bSurpriseRemoved = _TRUE; } else { #ifdef DBG_CONFIG_ERROR_DETECT { HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter); pHalData->srestpriv.Wifi_Error_Status = USB_VEN_REQ_CMD_FAIL; } #endif } } else // status != len && status >= 0 { if(status > 0) { if ( requesttype == 0x01 ) { // For Control read transfer, we have to copy the read data from pIo_buf to pdata. _rtw_memcpy( pdata, pIo_buf, len ); } } } if(rtw_inc_and_chk_continual_io_error(pdvobjpriv) == _TRUE ){ padapter->bSurpriseRemoved = _TRUE; break; } } // firmware download is checksumed, don't retry if( (value >= FW_START_ADDRESS ) || status == len ) break; } // release IO memory used by vendorreq #ifdef CONFIG_USB_VENDOR_REQ_BUFFER_DYNAMIC_ALLOCATE rtw_mfree(tmp_buf, tmp_buflen); #endif release_mutex: #ifdef CONFIG_USB_VENDOR_REQ_MUTEX _exit_critical_mutex(&pdvobjpriv->usb_vendor_req_mutex, NULL); #endif exit: return status; }
s32 rtw_dump_xframe(_adapter *padapter, struct xmit_frame *pxmitframe) { s32 ret = _SUCCESS; s32 inner_ret = _SUCCESS; _irqL irqL; int t, sz, w_sz, pull=0; //u8 *mem_addr; u32 ff_hwaddr; struct xmit_buf *pxmitbuf = pxmitframe->pxmitbuf; struct pkt_attrib *pattrib = &pxmitframe->attrib; struct xmit_priv *pxmitpriv = &padapter->xmitpriv; struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(padapter); struct security_priv *psecuritypriv = &padapter->securitypriv; struct tx_desc *ptxdesc; if ((pxmitframe->frame_tag == DATA_FRAMETAG) && (pxmitframe->attrib.ether_type != 0x0806) && (pxmitframe->attrib.ether_type != 0x888e) && (pxmitframe->attrib.dhcp_pkt != 1)) { rtw_issue_addbareq_cmd(padapter, pxmitframe); } //mem_addr = pxmitframe->buf_addr; RT_TRACE(_module_rtl871x_xmit_c_,_drv_info_,("rtw_dump_xframe()\n")); for (t = 0; t < pattrib->nr_frags; t++) { if (inner_ret != _SUCCESS && ret == _SUCCESS) ret = _FAIL; if (t != (pattrib->nr_frags - 1)) { RT_TRACE(_module_rtl871x_xmit_c_,_drv_err_,("pattrib->nr_frags=%d\n", pattrib->nr_frags)); sz = pxmitpriv->frag_len; sz = sz - 4 - (psecuritypriv->sw_encrypt ? 0 : pattrib->icv_len); } else //no frag { sz = pattrib->last_txcmdsz; } ff_hwaddr = rtw_get_ff_hwaddr(pxmitframe); _enter_critical(&pdvobjpriv->irq_th_lock, &irqL); ptxdesc = get_txdesc(pxmitframe, ff_hwaddr); if(ptxdesc == NULL) { _exit_critical(&pdvobjpriv->irq_th_lock, &irqL); rtw_free_xmitbuf(pxmitpriv, pxmitbuf); DBG_8192C("##### Tx desc unavailable !#####\n"); break; } update_txdesc(pxmitframe, (uint*)ptxdesc, sz); rtl8192de_enqueue_xmitbuf(&pxmitpriv->tx_ring[ff_hwaddr], pxmitbuf); pxmitbuf->len = sz; _exit_critical(&pdvobjpriv->irq_th_lock, &irqL); w_sz = sz; rtw_write16(padapter, REG_PCIE_CTRL_REG, ffaddr2dma(ff_hwaddr)); inner_ret = rtw_write_port(padapter, ff_hwaddr, w_sz, (unsigned char*)pxmitbuf); rtw_count_tx_stats(padapter, pxmitframe, sz); RT_TRACE(_module_rtl871x_xmit_c_,_drv_info_,("rtw_write_port, w_sz=%d\n", w_sz)); //DBG_8192C("rtw_write_port, w_sz=%d, sz=%d, txdesc_sz=%d, tid=%d\n", w_sz, sz, w_sz-sz, pattrib->priority); //mem_addr += w_sz; //mem_addr = (u8 *)RND4(((SIZE_PTR)(mem_addr))); } rtw_free_xmitframe(pxmitpriv, pxmitframe); if (ret != _SUCCESS) rtw_sctx_done_err(&pxmitbuf->sctx, RTW_SCTX_DONE_UNKNOWN); return ret; }
void sd_int_dpc(PADAPTER padapter) { HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter); if (pHalData->sdio_hisr & SDIO_HISR_CPWM1) { struct reportpwrstate_parm report; _sdio_local_read(padapter, SDIO_REG_HCPWM1, 1, &report.state); #ifdef CONFIG_LPS_LCLK //88e's cpwm value only change BIT0, so driver need to add PS_STATE_S2 for LPS flow. //modify by Thomas. 2012/4/2. #ifdef CONFIG_EXT_CLK //for sprd if(report.state & BIT(4)) //indicate FW entering 32k { u8 chk_cnt = 0; do{ if(_sdio_read8(padapter, 0x90)&BIT(0))//FW in 32k already { struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv; if(pwrpriv->rpwm < PS_STATE_S2) { //DBG_871X("disable ext clk when FW in LPS-32K already!\n"); EnableGpio5ClockReq(padapter, _TRUE, 0); } break; } chk_cnt++; }while(chk_cnt<10); if(chk_cnt==10) { DBG_871X("polling fw in 32k already, fail!\n"); } } else //indicate fw leaving 32K #endif //CONFIG_EXT_CLK { report.state |= PS_STATE_S2; //cpwm_int_hdl(padapter, &report); _set_workitem(&padapter->pwrctrlpriv.cpwm_event); } #endif } #ifdef CONFIG_WOWLAN if (pHalData->sdio_hisr & SDIO_HISR_CPWM2) { u32 value; value = rtw_read32(padapter, SDIO_LOCAL_BASE+SDIO_REG_HISR); DBG_871X_LEVEL(_drv_always_, "Reset SDIO HISR(0x%08x) original:0x%08x\n", SDIO_LOCAL_BASE+SDIO_REG_HISR, value); value |= BIT19; rtw_write32(padapter, SDIO_LOCAL_BASE+SDIO_REG_HISR, value); value = rtw_read8(padapter, SDIO_LOCAL_BASE+SDIO_REG_HIMR+2); DBG_871X_LEVEL(_drv_always_, "Reset SDIO HIMR CPWM2(0x%08x) original:0x%02x\n", SDIO_LOCAL_BASE+SDIO_REG_HIMR + 2, value); } #endif if (pHalData->sdio_hisr & SDIO_HISR_TXERR) { u8 *status; u32 addr; status = _rtw_malloc(4); if (status) { addr = REG_TXDMA_STATUS; HalSdioGetCmdAddr8723ASdio(padapter, WLAN_IOREG_DEVICE_ID, addr, &addr); _sd_read(&adapter_to_dvobj(padapter)->intf_data, addr, 4, status); _sd_write(&adapter_to_dvobj(padapter)->intf_data, addr, 4, status); DBG_8192C("%s: SDIO_HISR_TXERR (0x%08x)\n", __func__, le32_to_cpu(*(u32*)status)); _rtw_mfree(status, 4); } else { DBG_8192C("%s: SDIO_HISR_TXERR, but can't allocate memory to read status!\n", __func__); } } #ifdef CONFIG_INTERRUPT_BASED_TXBCN #ifdef CONFIG_INTERRUPT_BASED_TXBCN_EARLY_INT if (pHalData->sdio_hisr & SDIO_HISR_BCNERLY_INT) #endif #ifdef CONFIG_INTERRUPT_BASED_TXBCN_BCN_OK_ERR if (pHalData->sdio_hisr & (SDIO_HISR_TXBCNOK|SDIO_HISR_TXBCNERR)) #endif { struct mlme_priv *pmlmepriv = &padapter->mlmepriv; #if 0 //for debug if (pHalData->sdio_hisr & SDIO_HISR_BCNERLY_INT) DBG_8192C("%s: SDIO_HISR_BCNERLY_INT\n", __func__); if (pHalData->sdio_hisr & SDIO_HISR_TXBCNOK) DBG_8192C("%s: SDIO_HISR_TXBCNOK\n", __func__); if (pHalData->sdio_hisr & SDIO_HISR_TXBCNERR) DBG_8192C("%s: SDIO_HISR_TXBCNERR\n", __func__); #endif if(check_fwstate(pmlmepriv, WIFI_AP_STATE)) { //send_beacon(padapter); if(pmlmepriv->update_bcn == _TRUE) { //tx_beacon_hdl(padapter, NULL); set_tx_beacon_cmd(padapter); } } #ifdef CONFIG_CONCURRENT_MODE if(check_buddy_fwstate(padapter, WIFI_AP_STATE)) { //send_beacon(padapter); if(padapter->pbuddy_adapter->mlmepriv.update_bcn == _TRUE) { //tx_beacon_hdl(padapter, NULL); set_tx_beacon_cmd(padapter->pbuddy_adapter); } } #endif } #endif //CONFIG_INTERRUPT_BASED_TXBCN #ifdef CONFIG_EXT_CLK if (pHalData->sdio_hisr & SDIO_HISR_BCNERLY_INT) { struct mlme_priv *pmlmepriv = &padapter->mlmepriv; if(check_fwstate(pmlmepriv, _FW_LINKED) && check_fwstate(pmlmepriv, WIFI_STATION_STATE)) { //DBG_8192C("BCNERLY_INT for enabling ext clk\n"); EnableGpio5ClockReq(padapter, _TRUE, 1); } } #endif //CONFIG_EXT_CLK if (pHalData->sdio_hisr & SDIO_HISR_C2HCMD) { DBG_8192C("%s: C2H Command\n", __func__); } if (pHalData->sdio_hisr & SDIO_HISR_RX_REQUEST) { struct recv_buf *precvbuf; //DBG_8192C("%s: RX Request, size=%d\n", __func__, phal->SdioRxFIFOSize); pHalData->sdio_hisr ^= SDIO_HISR_RX_REQUEST; #ifdef CONFIG_MAC_LOOPBACK_DRIVER sd_recv_loopback(padapter, pHalData->SdioRxFIFOSize); #else do { //Sometimes rx length will be zero. driver need to use cmd53 read again. if(pHalData->SdioRxFIFOSize == 0) { u8 data[4]; _sdio_local_read(padapter, SDIO_REG_RX0_REQ_LEN, 4, data); pHalData->SdioRxFIFOSize = le16_to_cpu(*(u16*)data); } if(pHalData->SdioRxFIFOSize) { precvbuf = sd_recv_rxfifo(padapter, pHalData->SdioRxFIFOSize); pHalData->SdioRxFIFOSize = 0; if (precvbuf) sd_rxhandler(padapter, precvbuf); else break; } else break; #ifdef CONFIG_SDIO_DISABLE_RXFIFO_POLLING_LOOP } while (0); #else } while (1); #endif #endif }
void rtw_ps_processor(_adapter*padapter) { #ifdef CONFIG_P2P struct wifidirect_info *pwdinfo = &( padapter->wdinfo ); #endif struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv; struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); int res; rt_rf_power_state rfpwrstate; #ifdef SUPPORT_HW_RFOFF_DETECTED if(pwrpriv->bips_processing == _TRUE) return; //DBG_8192C("==> fw report state(0x%x)\n",rtw_read8(padapter,0x1ca)); if(padapter->pwrctrlpriv.bHWPwrPindetect) { #ifdef CONFIG_AUTOSUSPEND if(padapter->registrypriv.usbss_enable) { if(padapter->net_closed == _TRUE) return; if(pwrpriv->current_rfpwrstate == rf_on) { rfpwrstate = RfOnOffDetect(padapter); DBG_8192C("@@@@- #1 %s==> rfstate:%s \n",__FUNCTION__,(rfpwrstate==rf_on)?"rf_on":"rf_off"); if(rfpwrstate!= pwrpriv->current_rfpwrstate) { if(rfpwrstate == rf_off) { pwrpriv->change_rfpwrstate = rf_off; pwrpriv->bkeepfwalive = _TRUE; pwrpriv->brfoffbyhw = _TRUE; autosuspend_enter(padapter); } } } } else #endif { rfpwrstate = RfOnOffDetect(padapter); DBG_8192C("@@@@- #2 %s==> rfstate:%s \n",__FUNCTION__,(rfpwrstate==rf_on)?"rf_on":"rf_off"); if(rfpwrstate!= pwrpriv->current_rfpwrstate) { if(rfpwrstate == rf_off) { pwrpriv->change_rfpwrstate = rf_off; pwrpriv->brfoffbyhw = _TRUE; padapter->bCardDisableWOHSM = _TRUE; rtw_hw_suspend(padapter ); } else { pwrpriv->change_rfpwrstate = rf_on; rtw_hw_resume(padapter ); } DBG_8192C("current_rfpwrstate(%s)\n",(pwrpriv->current_rfpwrstate == rf_off)?"rf_off":"rf_on"); } } pwrpriv->pwr_state_check_cnts ++; } #endif if( pwrpriv->power_mgnt == PS_MODE_ACTIVE ) return; if(padapter->net_closed == _TRUE) return; if((pwrpriv->current_rfpwrstate == rf_on) && ((pwrpriv->pwr_state_check_cnts%4)==0)) { if ( (check_fwstate(pmlmepriv, _FW_LINKED|_FW_UNDER_SURVEY|_FW_UNDER_LINKING) == _TRUE) || (check_fwstate(pmlmepriv, WIFI_AP_STATE) == _TRUE) || (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == _TRUE) || (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) == _TRUE) || (padapter->net_closed == _TRUE)|| (padapter->bup == _FALSE) #ifdef CONFIG_P2P || (pwdinfo->p2p_state != P2P_STATE_NONE) #endif ) { return; } DBG_8192C("==>%s .fw_state(%x)\n",__FUNCTION__,padapter->mlmepriv.fw_state); pwrpriv->change_rfpwrstate = rf_off; #ifdef CONFIG_AUTOSUSPEND if(padapter->registrypriv.usbss_enable) { if(padapter->pwrctrlpriv.bHWPwrPindetect) pwrpriv->bkeepfwalive = _TRUE; padapter->bCardDisableWOHSM = _TRUE; autosuspend_enter(padapter); } else if(padapter->pwrctrlpriv.bHWPwrPindetect) { } else #endif { #ifdef CONFIG_IPS ips_enter(padapter); #endif } } }
void rtw_set_ps_mode(_adapter * padapter, u8 ps_mode, u8 smart_ps) { struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv; #ifdef CONFIG_P2P struct wifidirect_info *pwdinfo = &( padapter->wdinfo ); #endif _func_enter_; RT_TRACE(_module_rtl871x_pwrctrl_c_,_drv_err_,("========= Power Mode is :%d, Smart_PS = %d\n", ps_mode,smart_ps)); //DBG_8192C("========= Power Mode is :%d, Smart_PS = %d\n", ps_mode,smart_ps); if(ps_mode > PM_Card_Disable) { RT_TRACE(_module_rtl871x_pwrctrl_c_,_drv_err_,("ps_mode:%d error\n", ps_mode)); return; } if((pwrpriv->pwr_mode == ps_mode) && (pwrpriv->smart_ps == smart_ps)){ return; } //if(pwrpriv->pwr_mode == PS_MODE_ACTIVE) if(ps_mode == PS_MODE_ACTIVE) { #ifdef CONFIG_P2P if(pwdinfo->opp_ps == 0) #endif { DBG_8192C("rtw_set_ps_mode(): Busy Traffic , Leave 802.11 power save..\n"); pwrpriv->smart_ps = smart_ps; pwrpriv->pwr_mode = ps_mode; rtw_set_rpwm(padapter, PS_STATE_S4); padapter->HalFunc.SetHwRegHandler(padapter, HW_VAR_H2C_FW_PWRMODE, (u8 *)(&ps_mode)); pwrpriv->bFwCurrentInPSMode = _FALSE; } } else { if(PS_RDY_CHECK(padapter)) { DBG_8192C("rtw_set_ps_mode(): Enter 802.11 power save mode...\n"); pwrpriv->smart_ps = smart_ps; pwrpriv->pwr_mode = ps_mode; pwrpriv->bFwCurrentInPSMode = _TRUE; padapter->HalFunc.SetHwRegHandler(padapter, HW_VAR_H2C_FW_PWRMODE, (u8 *)(&ps_mode)); #ifdef CONFIG_P2P // Set CTWindow after LPS if(pwdinfo->opp_ps == 1) //if(pwdinfo->p2p_ps_enable == _TRUE) p2p_ps_wk_cmd(padapter, P2P_PS_ENABLE, 0); #endif rtw_set_rpwm(padapter, PS_STATE_S2); } //else //{ // pwrpriv->pwr_mode = PS_MODE_ACTIVE; //} } _func_exit_; }
void sd_int_dpc(PADAPTER padapter) { PHAL_DATA_TYPE phal; struct dvobj_priv *dvobj; struct intf_hdl * pintfhdl=&padapter->iopriv.intf; struct pwrctrl_priv *pwrctl; phal = GET_HAL_DATA(padapter); dvobj = adapter_to_dvobj(padapter); pwrctl = dvobj_to_pwrctl(dvobj); if (phal->sdio_hisr & SDIO_HISR_CPWM1) { struct reportpwrstate_parm report; #ifdef CONFIG_LPS_RPWM_TIMER u8 bcancelled; _cancel_timer(&(pwrctl->pwr_rpwm_timer), &bcancelled); #endif // CONFIG_LPS_RPWM_TIMER report.state = SdioLocalCmd52Read1Byte(padapter, SDIO_REG_HCPWM1_8723B); #ifdef CONFIG_LPS_LCLK //cpwm_int_hdl(padapter, &report); _set_workitem(&(pwrctl->cpwm_event)); #endif } if (phal->sdio_hisr & SDIO_HISR_TXERR) { u8 *status; u32 addr; status = rtw_malloc(4); if (status) { addr = REG_TXDMA_STATUS; HalSdioGetCmdAddr8723BSdio(padapter, WLAN_IOREG_DEVICE_ID, addr, &addr); _sd_read(pintfhdl, addr, 4, status); _sd_write(pintfhdl, addr, 4, status); DBG_8192C("%s: SDIO_HISR_TXERR (0x%08x)\n", __func__, le32_to_cpu(*(u32*)status)); rtw_mfree(status, 4); } else { DBG_8192C("%s: SDIO_HISR_TXERR, but can't allocate memory to read status!\n", __func__); } } if (phal->sdio_hisr & SDIO_HISR_TXBCNOK) { DBG_8192C("%s: SDIO_HISR_TXBCNOK\n", __func__); } if (phal->sdio_hisr & SDIO_HISR_TXBCNERR) { DBG_8192C("%s: SDIO_HISR_TXBCNERR\n", __func__); } #ifndef CONFIG_C2H_PACKET_EN if (phal->sdio_hisr & SDIO_HISR_C2HCMD) { struct c2h_evt_hdr_88xx *c2h_evt; DBG_8192C("%s: C2H Command\n", __func__); if ((c2h_evt = (struct c2h_evt_hdr_88xx*)rtw_zmalloc(16)) != NULL) { if (rtw_hal_c2h_evt_read(padapter, (u8 *)c2h_evt) == _SUCCESS) { if (c2h_id_filter_ccx_8723b((u8 *)c2h_evt)) { /* Handle CCX report here */ rtw_hal_c2h_handler(padapter, (u8 *)c2h_evt); rtw_mfree((u8*)c2h_evt, 16); } else { rtw_c2h_wk_cmd(padapter, (u8 *)c2h_evt); } } } else { /* Error handling for malloc fail */ if (rtw_cbuf_push(padapter->evtpriv.c2h_queue, (void*)NULL) != _SUCCESS) DBG_871X("%s rtw_cbuf_push fail\n", __func__); _set_workitem(&padapter->evtpriv.c2h_wk); } } #endif if (phal->sdio_hisr & SDIO_HISR_RXFOVW) { DBG_8192C("%s: Rx Overflow\n", __func__); } if (phal->sdio_hisr & SDIO_HISR_RXERR) { DBG_8192C("%s: Rx Error\n", __func__); } if (phal->sdio_hisr & SDIO_HISR_RX_REQUEST) { struct recv_buf *precvbuf; int alloc_fail_time=0; u32 hisr; // DBG_8192C("%s: RX Request, size=%d\n", __func__, phal->SdioRxFIFOSize); phal->sdio_hisr ^= SDIO_HISR_RX_REQUEST; do { phal->SdioRxFIFOSize = SdioLocalCmd52Read2Byte(padapter, SDIO_REG_RX0_REQ_LEN); if (phal->SdioRxFIFOSize != 0) { #ifdef CONFIG_MAC_LOOPBACK_DRIVER sd_recv_loopback(padapter, phal->SdioRxFIFOSize); #else precvbuf = sd_recv_rxfifo(padapter, phal->SdioRxFIFOSize); if (precvbuf) sd_rxhandler(padapter, precvbuf); else { alloc_fail_time++; DBG_871X("precvbuf is Null for %d times because alloc memory failed\n", alloc_fail_time); if (alloc_fail_time >= 10) break; } phal->SdioRxFIFOSize = 0; #endif } else break; hisr = 0; ReadInterrupt8723BSdio(padapter, &hisr); hisr &= SDIO_HISR_RX_REQUEST; if (!hisr) break; } while (1); if(alloc_fail_time==10) DBG_871X("exit because alloc memory failed more than 10 times \n"); } }
u32 sdio_read32(struct intf_hdl *pintfhdl, u32 addr) { PADAPTER padapter; u8 bMacPwrCtrlOn; u8 deviceId; u16 offset; u32 ftaddr; u8 shift; u32 val; s32 err; _func_enter_; padapter = pintfhdl->padapter; ftaddr = _cvrt2ftaddr(addr, &deviceId, &offset); rtw_hal_get_hwreg(padapter, HW_VAR_APFM_ON_MAC, &bMacPwrCtrlOn); if (((deviceId == WLAN_IOREG_DEVICE_ID) && (offset < 0x100)) || (_FALSE == bMacPwrCtrlOn) #ifdef CONFIG_LPS_LCLK || (_TRUE == adapter_to_pwrctl(padapter)->bFwCurrentInPSMode) #endif ) { err = sd_cmd52_read(pintfhdl, ftaddr, 4, (u8*)&val); #ifdef SDIO_DEBUG_IO if (!err) { #endif val = le32_to_cpu(val); return val; #ifdef SDIO_DEBUG_IO } DBG_8192C(KERN_ERR "%s: Mac Power off, Read FAIL(%d)! addr=0x%x\n", __func__, err, addr); return SDIO_ERR_VAL32; #endif } // 4 bytes alignment shift = ftaddr & 0x3; if (shift == 0) { val = sd_read32(pintfhdl, ftaddr, NULL); } else { u8 *ptmpbuf; ptmpbuf = (u8*)rtw_malloc(8); if (NULL == ptmpbuf) { DBG_8192C(KERN_ERR "%s: Allocate memory FAIL!(size=8) addr=0x%x\n", __func__, addr); return SDIO_ERR_VAL32; } ftaddr &= ~(u16)0x3; sd_read(pintfhdl, ftaddr, 8, ptmpbuf); _rtw_memcpy(&val, ptmpbuf+shift, 4); val = le32_to_cpu(val); rtw_mfree(ptmpbuf, 8); } _func_exit_; return val; }
/* * Notice: * Before calling this function, * precvframe->u.hdr.rx_data should be ready! */ void update_recvframe_phyinfo( union recv_frame *precvframe, struct phy_stat *pphy_status) { PADAPTER padapter= precvframe->u.hdr.adapter; struct rx_pkt_attrib *pattrib = &precvframe->u.hdr.attrib; HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter); PODM_PHY_INFO_T pPHYInfo = (PODM_PHY_INFO_T)(&pattrib->phy_info); u8 *wlanhdr; ODM_PACKET_INFO_T pkt_info; u8 *sa; //_irqL irqL; struct sta_priv *pstapriv; struct sta_info *psta; pkt_info.bPacketMatchBSSID =_FALSE; pkt_info.bPacketToSelf = _FALSE; pkt_info.bPacketBeacon = _FALSE; wlanhdr = get_recvframe_data(precvframe); pkt_info.bPacketMatchBSSID = ((!IsFrameTypeCtrl(wlanhdr)) && !pattrib->icv_err && !pattrib->crc_err && _rtw_memcmp(get_hdr_bssid(wlanhdr), get_bssid(&padapter->mlmepriv), ETH_ALEN)); pkt_info.bPacketToSelf = pkt_info.bPacketMatchBSSID && (_rtw_memcmp(get_da(wlanhdr), myid(&padapter->eeprompriv), ETH_ALEN)); pkt_info.bPacketBeacon = pkt_info.bPacketMatchBSSID && (GetFrameSubType(wlanhdr) == WIFI_BEACON); if(pkt_info.bPacketBeacon){ if(check_fwstate(&padapter->mlmepriv, WIFI_STATION_STATE) == _TRUE){ sa = padapter->mlmepriv.cur_network.network.MacAddress; #if 0 { DBG_8192C("==> rx beacon from AP[%02x:%02x:%02x:%02x:%02x:%02x]\n", sa[0],sa[1],sa[2],sa[3],sa[4],sa[5]); } #endif } //to do Ad-hoc } else{ sa = get_sa(wlanhdr); } pkt_info.StationID = 0xFF; pstapriv = &padapter->stapriv; psta = rtw_get_stainfo(pstapriv, sa); if (psta) { pkt_info.StationID = psta->mac_id; //DBG_8192C("%s ==> StationID(%d)\n",__FUNCTION__,pkt_info.StationID); } pkt_info.Rate = pattrib->mcs_rate; //rtl8192c_query_rx_phy_status(precvframe, pphy_status); //_enter_critical_bh(&pHalData->odm_stainfo_lock, &irqL); ODM_PhyStatusQuery(&pHalData->odmpriv,pPHYInfo,(u8 *)pphy_status,&(pkt_info)); //_exit_critical_bh(&pHalData->odm_stainfo_lock, &irqL); precvframe->u.hdr.psta = NULL; if (pkt_info.bPacketMatchBSSID && (check_fwstate(&padapter->mlmepriv, WIFI_AP_STATE) == _TRUE)) { if (psta) { precvframe->u.hdr.psta = psta; rtl8192c_process_phy_info(padapter, precvframe); } } else if (pkt_info.bPacketToSelf || pkt_info.bPacketBeacon) { if (check_fwstate(&padapter->mlmepriv, WIFI_ADHOC_STATE|WIFI_ADHOC_MASTER_STATE) == _TRUE) { if (psta) { precvframe->u.hdr.psta = psta; } } rtl8192c_process_phy_info(padapter, precvframe); } }
static void rtl8723as_recv_tasklet(void *priv) { PADAPTER padapter; PHAL_DATA_TYPE pHalData; struct recv_priv *precvpriv; struct recv_buf *precvbuf; union recv_frame *precvframe; struct recv_frame_hdr *phdr; struct rx_pkt_attrib *pattrib; u8 *ptr; _pkt *ppkt; u32 pkt_offset; _irqL irql; padapter = (PADAPTER)priv; pHalData = GET_HAL_DATA(padapter); precvpriv = &padapter->recvpriv; do { precvbuf = rtw_dequeue_recvbuf(&precvpriv->recv_buf_pending_queue); if (NULL == precvbuf) break; ptr = precvbuf->pdata; while (ptr < precvbuf->ptail) { precvframe = rtw_alloc_recvframe(&precvpriv->free_recv_queue); if (precvframe == NULL) { RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("rtl8723as_recv_tasklet: no enough recv frame!\n")); rtw_enqueue_recvbuf_to_head(precvbuf, &precvpriv->recv_buf_pending_queue); // The case of can't allocte recvframe should be temporary, // schedule again and hope recvframe is available next time. #ifdef PLATFORM_LINUX tasklet_schedule(&precvpriv->recv_tasklet); #endif return; } phdr = &precvframe->u.hdr; pattrib = &phdr->attrib; update_recvframe_attrib(precvframe, (struct recv_stat*)ptr); // fix Hardware RX data error, drop whole recv_buffer if ((!(pHalData->ReceiveConfig & RCR_ACRC32)) && pattrib->crc_err) { 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; } pkt_offset = RXDESC_SIZE + pattrib->drvinfo_sz + pattrib->pkt_len; #if 0 // reduce check to speed up if ((ptr + pkt_offset) > precvbuf->ptail) { RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("%s: next pkt len(%p,%d) exceed ptail(%p)!\n", __FUNCTION__, ptr, pkt_offset, precvbuf->ptail)); rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue); break; } #endif if ((pattrib->crc_err) || (pattrib->icv_err)) { 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 { ppkt = rtw_skb_clone(precvbuf->pskb); if (ppkt == NULL) { RT_TRACE(_module_rtl871x_recv_c_, _drv_crit_, ("rtl8723as_recv_tasklet: no enough memory to allocate SKB!\n")); rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue); rtw_enqueue_recvbuf_to_head(precvbuf, &precvpriv->recv_buf_pending_queue); // The case of can't allocte skb is serious and may never be recovered, // once bDriverStopped is enable, this task should be stopped. if (padapter->bDriverStopped == _FALSE) { #ifdef PLATFORM_LINUX tasklet_schedule(&precvpriv->recv_tasklet); #endif } return; } phdr->pkt = ppkt; phdr->len = 0; phdr->rx_head = precvbuf->phead; phdr->rx_data = phdr->rx_tail = precvbuf->pdata; phdr->rx_end = precvbuf->pend; recvframe_put(precvframe, pkt_offset); recvframe_pull(precvframe, RXDESC_SIZE + pattrib->drvinfo_sz); if (pHalData->ReceiveConfig & RCR_APPFCS) recvframe_pull_tail(precvframe, IEEE80211_FCS_LEN); // move to drv info position ptr += RXDESC_SIZE; // update drv info if (pHalData->ReceiveConfig & RCR_APP_BA_SSN) { // rtl8723s_update_bassn(padapter, pdrvinfo); ptr += 4; } #ifdef CONFIG_CONCURRENT_MODE if(rtw_buddy_adapter_up(padapter)) { if(pre_recv_entry(precvframe, precvbuf, (struct phy_stat*)ptr) != _SUCCESS) { RT_TRACE(_module_rtl871x_recv_c_,_drv_err_, ("recvbuf2recvframe: recv_entry(precvframe) != _SUCCESS\n")); } } else #endif { if (pattrib->physt) update_recvframe_phyinfo(precvframe, (struct phy_stat*)ptr); if (rtw_recv_entry(precvframe) != _SUCCESS) { RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("rtl8723as_recv_tasklet: rtw_recv_entry(precvframe) != _SUCCESS\n")); } } } // Page size of receive package is 128 bytes alignment => DMA agg // refer to _InitTransferPageSize() pkt_offset = _RND128(pkt_offset); precvbuf->pdata += pkt_offset; ptr = precvbuf->pdata; } rtw_skb_free(precvbuf->pskb); precvbuf->pskb = NULL; rtw_enqueue_recvbuf(precvbuf, &precvpriv->free_recv_buf_queue); } while (1); }
static void rtl8723as_recv_tasklet(void *priv) { PADAPTER padapter; PHAL_DATA_TYPE pHalData; struct recv_priv *precvpriv; struct recv_buf *precvbuf; union recv_frame *precvframe; struct recv_frame_hdr *phdr; struct rx_pkt_attrib *pattrib; _irqL irql; u8 *ptr; u32 pkt_len, pkt_offset, skb_len, alloc_sz; _pkt *pkt_copy = NULL; u8 shift_sz = 0, rx_report_sz = 0; padapter = (PADAPTER)priv; pHalData = GET_HAL_DATA(padapter); precvpriv = &padapter->recvpriv; do { precvbuf = rtw_dequeue_recvbuf(&precvpriv->recv_buf_pending_queue); if (NULL == precvbuf) break; ptr = precvbuf->pdata; while (ptr < precvbuf->ptail) { precvframe = rtw_alloc_recvframe(&precvpriv->free_recv_queue); if (precvframe == NULL) { RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("%s: no enough recv frame!\n",__FUNCTION__)); rtw_enqueue_recvbuf_to_head(precvbuf, &precvpriv->recv_buf_pending_queue); // The case of can't allocte recvframe should be temporary, // schedule again and hope recvframe is available next time. #ifdef PLATFORM_LINUX tasklet_schedule(&precvpriv->recv_tasklet); #endif return; } //rx desc parsing update_recvframe_attrib(precvframe, (struct recv_stat*)ptr); pattrib = &precvframe->u.hdr.attrib; // fix Hardware RX data error, drop whole recv_buffer if ((!(pHalData->ReceiveConfig & RCR_ACRC32)) && pattrib->crc_err) { if (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); } while (1); }
int hostapd_mode_init(_adapter *padapter) { unsigned char mac[ETH_ALEN]; struct hostapd_priv *phostapdpriv; struct net_device *pnetdev; pnetdev = rtw_alloc_etherdev(sizeof(struct hostapd_priv)); if (!pnetdev) return -ENOMEM; //SET_MODULE_OWNER(pnetdev); ether_setup(pnetdev); //pnetdev->type = ARPHRD_IEEE80211; phostapdpriv = rtw_netdev_priv(pnetdev); phostapdpriv->pmgnt_netdev = pnetdev; phostapdpriv->padapter= padapter; padapter->phostapdpriv = phostapdpriv; //pnetdev->init = NULL; #if (LINUX_VERSION_CODE>=KERNEL_VERSION(2,6,29)) DBG_8192C("register rtl871x_mgnt_netdev_ops to netdev_ops\n"); pnetdev->netdev_ops = &rtl871x_mgnt_netdev_ops; #else pnetdev->open = mgnt_netdev_open; pnetdev->stop = mgnt_netdev_close; pnetdev->hard_start_xmit = mgnt_xmit_entry; //pnetdev->set_mac_address = r871x_net_set_mac_address; //pnetdev->get_stats = r871x_net_get_stats; //pnetdev->do_ioctl = r871x_mp_ioctl; #endif pnetdev->watchdog_timeo = HZ; /* 1 second timeout */ //pnetdev->wireless_handlers = NULL; #ifdef CONFIG_TCP_CSUM_OFFLOAD_TX pnetdev->features |= NETIF_F_IP_CSUM; #endif if(dev_alloc_name(pnetdev,"mgnt.wlan%d") < 0) { DBG_8192C("hostapd_mode_init(): dev_alloc_name, fail! \n"); } //SET_NETDEV_DEV(pnetdev, pintfpriv->udev); mac[0]=0x00; mac[1]=0xe0; mac[2]=0x4c; mac[3]=0x87; mac[4]=0x11; mac[5]=0x12; _rtw_memcpy(pnetdev->dev_addr, mac, ETH_ALEN); netif_carrier_off(pnetdev); /* Tell the network stack we exist */ if (register_netdev(pnetdev) != 0) { DBG_8192C("hostapd_mode_init(): register_netdev fail!\n"); if(pnetdev) { rtw_free_netdev(pnetdev); } } return 0; }
// // Description: Leave all power save mode: LPS, FwLPS, IPS if needed. // Move code to function by tynli. 2010.03.26. // void LeaveAllPowerSaveMode(IN PADAPTER Adapter) { struct mlme_priv *pmlmepriv = &(Adapter->mlmepriv); u32 LPSLeaveTimeOut = 10000; //u32 IPSLeaveTimeOut = 10000; _func_enter_; DBG_8192C("%s.....\n",__FUNCTION__); if (check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE) { //connect #ifdef CONFIG_P2P p2p_ps_wk_cmd(Adapter, P2P_PS_DISABLE, 0); #endif #ifdef CONFIG_LPS //DBG_8192C("==> leave LPS.......\n"); LPS_Leave(Adapter); if (Adapter->pwrctrlpriv.bLeisurePs) { BOOLEAN bAwake = _TRUE; Adapter->HalFunc.GetHwRegHandler(Adapter, HW_VAR_FWLPS_RF_ON, (u8 *)(&bAwake)); while(!bAwake) { rtw_usleep_os(100); LPSLeaveTimeOut--; if(LPSLeaveTimeOut <= 0) { DBG_8192C("Wait for FW LPS leave too long!!! LPSLeaveTimeOut = %d\n", LPSLeaveTimeOut ); break; } Adapter->HalFunc.GetHwRegHandler(Adapter, HW_VAR_FWLPS_RF_ON, (u8 *)(&bAwake)); } } #endif } else { if(Adapter->pwrctrlpriv.current_rfpwrstate== rf_off) { DBG_8192C("==> leave IPS.......\n"); #ifdef CONFIG_AUTOSUSPEND if(Adapter->registrypriv.usbss_enable) { #if (LINUX_VERSION_CODE>=KERNEL_VERSION(2,6,35)) usb_disable_autosuspend(Adapter->dvobjpriv.pusbdev); #elif (LINUX_VERSION_CODE>=KERNEL_VERSION(2,6,22) && LINUX_VERSION_CODE<=KERNEL_VERSION(2,6,34)) Adapter->dvobjpriv.pusbdev->autosuspend_disabled = Adapter->bDisableAutosuspend;//autosuspend disabled by the user #endif } else #endif { #ifdef CONFIG_IPS if(_FALSE == ips_leave(Adapter)) { DBG_8192C("======> ips_leave fail.............\n"); } #endif } } } _func_exit_; }
static s32 update_txdesc(struct xmit_frame *pxmitframe, u32 *pmem, s32 sz) { uint qsel; _adapter *padapter = pxmitframe->padapter; HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter); struct dm_priv *pdmpriv = &pHalData->dmpriv; struct mlme_priv *pmlmepriv = &padapter->mlmepriv; struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(padapter); struct pkt_attrib *pattrib = &pxmitframe->attrib; struct ht_priv *phtpriv = &pmlmepriv->htpriv; struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); struct tx_desc *ptxdesc = (struct tx_desc *)pmem; sint bmcst = IS_MCAST(pattrib->ra); 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 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 //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 #ifdef CONFIG_AP_MODE ptxdesc->txdw5 |= cpu_to_le32(BIT(17));//retry limit enable ptxdesc->txdw5 |= cpu_to_le32(0x00180000);//retry limit = 6 #endif #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)); } //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; }
/* * Description: * Aggregation packets and send to hardware * * Return: * 0 Success * -1 Hardware resource(TX FIFO) not ready * -2 Software resource(xmitbuf) not ready */ static s32 xmit_xmitframes(PADAPTER padapter, struct xmit_priv *pxmitpriv) { s32 err, ret; u32 k; struct hw_xmit *hwxmits; u8 no_res, idx, hwentry; _irqL irql; // _irqL irqL0, irqL1; struct tx_servq *ptxservq; _list *sta_plist, *sta_phead, *frame_plist, *frame_phead; struct xmit_frame *pxmitframe; _queue *pframe_queue; struct xmit_buf *pxmitbuf; u32 txlen; err = 0; no_res = _FALSE; hwxmits = pxmitpriv->hwxmits; hwentry = pxmitpriv->hwxmit_entry; ptxservq = NULL; pxmitframe = NULL; pframe_queue = NULL; pxmitbuf = NULL; // 0(VO), 1(VI), 2(BE), 3(BK) for (idx = 0; idx < hwentry; idx++, hwxmits++) { // _enter_critical(&hwxmits->sta_queue->lock, &irqL0); sta_phead = get_list_head(hwxmits->sta_queue); sta_plist = get_next(sta_phead); while (rtw_end_of_queue_search(sta_phead, sta_plist) == _FALSE) { ptxservq = LIST_CONTAINOR(sta_plist, struct tx_servq, tx_pending); sta_plist = get_next(sta_plist); pframe_queue = &ptxservq->sta_pending; // _enter_critical(&pframe_queue->lock, &irqL1); _enter_critical_bh(&pxmitpriv->lock, &irql); frame_phead = get_list_head(pframe_queue); while (rtw_is_list_empty(frame_phead) == _FALSE) { frame_plist = get_next(frame_phead); pxmitframe = LIST_CONTAINOR(frame_plist, struct xmit_frame, list); // check xmit_buf size enough or not txlen = TXDESC_SIZE + rtw_wlan_pkt_size(pxmitframe); if ((NULL == pxmitbuf) || ((pxmitbuf->ptail + txlen) > pxmitbuf->pend) #ifdef SDIO_TX_AGG_MAX || (k >= SDIO_TX_AGG_MAX) #endif ) { if (pxmitbuf) { struct xmit_frame *pframe; pframe = (struct xmit_frame*)pxmitbuf->priv_data; pframe->agg_num = k; pxmitbuf->agg_num = k; rtl8723a_update_txdesc(pframe, pframe->buf_addr); rtw_free_xmitframe(pxmitpriv, pframe); pxmitbuf->priv_data = NULL; enqueue_pending_xmitbuf(pxmitpriv, pxmitbuf); //rtw_yield_os(); } pxmitbuf = rtw_alloc_xmitbuf(pxmitpriv); if (pxmitbuf == NULL) { RT_TRACE(_module_hal_xmit_c_, _drv_err_, ("%s: xmit_buf is not enough!\n", __FUNCTION__)); err = -2; break; } k = 0; } // ok to send, remove frame from queue //_enter_critical_bh(&pxmitpriv->lock, &irql); #ifdef CONFIG_AP_MODE if (check_fwstate(&padapter->mlmepriv, WIFI_AP_STATE) == _TRUE) { if ((pxmitframe->attrib.psta->state & WIFI_SLEEP_STATE) && (pxmitframe->attrib.triggered == 0)) { //_exit_critical_bh(&pxmitpriv->lock, &irql); DBG_8192C("%s: one not triggered pkt in queue when STA sleep\n", __func__); break; } } #endif rtw_list_delete(&pxmitframe->list); ptxservq->qcnt--; hwxmits->accnt--; if (k == 0) { pxmitbuf->ff_hwaddr = rtw_get_ff_hwaddr(pxmitframe); pxmitbuf->priv_data = (u8*)pxmitframe; } // coalesce the xmitframe to xmitbuf pxmitframe->pxmitbuf = pxmitbuf; pxmitframe->buf_addr = pxmitbuf->ptail; ret = rtw_xmitframe_coalesce(padapter, pxmitframe->pkt, pxmitframe); if (ret == _FAIL) { RT_TRACE(_module_hal_xmit_c_, _drv_err_, ("%s: coalesce FAIL!", __FUNCTION__)); // Todo: error handler } else { k++; if (k != 1) rtl8723a_update_txdesc(pxmitframe, pxmitframe->buf_addr); rtw_count_tx_stats(padapter, pxmitframe, pxmitframe->attrib.last_txcmdsz); txlen = TXDESC_SIZE + pxmitframe->attrib.last_txcmdsz; pxmitframe->pg_num = (txlen + 127)/128; pxmitbuf->pg_num += (txlen + 127)/128; //if (k != 1) // ((struct xmit_frame*)pxmitbuf->priv_data)->pg_num += pxmitframe->pg_num; pxmitbuf->ptail += _RND(txlen, 8); // round to 8 bytes alignment pxmitbuf->len = _RND(pxmitbuf->len, 8) + txlen; } if (k != 1) rtw_free_xmitframe(pxmitpriv, pxmitframe); pxmitframe = NULL; } //_enter_critical_bh(&pxmitpriv->lock, &irql); if (_rtw_queue_empty(pframe_queue) == _TRUE) rtw_list_delete(&ptxservq->tx_pending); //_exit_critical_bh(&pxmitpriv->lock, &irql); // _exit_critical(&pframe_queue->lock, &irqL1); _exit_critical_bh(&pxmitpriv->lock, &irql); if (err) break; } // _exit_critical(&hwxmits->sta_queue->lock, &irqL0); // dump xmit_buf to hw tx fifo if (pxmitbuf) { RT_TRACE(_module_hal_xmit_c_, _drv_notice_, ("pxmitbuf->len=%d enqueue\n",pxmitbuf->len)); if (pxmitbuf->len > 0) { struct xmit_frame *pframe; pframe = (struct xmit_frame*)pxmitbuf->priv_data; pframe->agg_num = k; pxmitbuf->agg_num = k; rtl8723a_update_txdesc(pframe, pframe->buf_addr); rtw_free_xmitframe(pxmitpriv, pframe); pxmitbuf->priv_data = NULL; enqueue_pending_xmitbuf(pxmitpriv, pxmitbuf); rtw_yield_os(); } else rtw_free_xmitbuf(pxmitpriv, pxmitbuf); pxmitbuf = NULL; } if (err) break; } return err; }
void rtl8192de_xmitframe_resume(_adapter *padapter) { struct xmit_priv *pxmitpriv = &padapter->xmitpriv; struct xmit_frame *pxmitframe = NULL; struct xmit_buf *pxmitbuf = NULL; int res=_SUCCESS, xcnt = 0; RT_TRACE(_module_rtl871x_xmit_c_,_drv_info_,("rtl8192ce_xmitframe_resume()\n")); while(1) { if ((padapter->bDriverStopped == _TRUE)||(padapter->bSurpriseRemoved== _TRUE)) { DBG_8192C("rtl8192ce_xmitframe_resume => bDriverStopped or bSurpriseRemoved \n"); break; } pxmitbuf = rtw_alloc_xmitbuf(pxmitpriv); if(!pxmitbuf) { break; } pxmitframe = rtw_dequeue_xframe(pxmitpriv, pxmitpriv->hwxmits, pxmitpriv->hwxmit_entry); if(pxmitframe) { pxmitframe->pxmitbuf = pxmitbuf; pxmitframe->buf_addr = pxmitbuf->pbuf; pxmitbuf->priv_data = pxmitframe; if((pxmitframe->frame_tag&0x0f) == DATA_FRAMETAG) { if(pxmitframe->attrib.priority<=15)//TID0~15 { res = rtw_xmitframe_coalesce(padapter, pxmitframe->pkt, pxmitframe); } rtw_os_xmit_complete(padapter, pxmitframe);//always return ndis_packet after rtw_xmitframe_coalesce } RT_TRACE(_module_rtl871x_xmit_c_,_drv_info_,("rtl8192ce_xmitframe_resume(): rtw_dump_xframe\n")); if(res == _SUCCESS) { rtw_dump_xframe(padapter, pxmitframe); } else { rtw_free_xmitbuf(pxmitpriv, pxmitbuf); rtw_free_xmitframe(pxmitpriv, pxmitframe); } xcnt++; } else { rtw_free_xmitbuf(pxmitpriv, pxmitbuf); break; } } }
s32 rtl8723_dequeue_writeport(PADAPTER padapter, u8 *freePage) { struct mlme_priv *pmlmepriv = &padapter->mlmepriv; struct xmit_priv *pxmitpriv = &padapter->xmitpriv; struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(padapter); struct xmit_buf *pxmitbuf; //struct xmit_frame *pframe; PADAPTER pri_padapter = padapter; u32 deviceId; u32 requiredPage; u8 PageIdx; _irqL irql; u32 n; s32 ret = 0; //HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter); #ifdef CONFIG_CONCURRENT_MODE s32 buddy_rm_stop = _FAIL; #endif #ifdef CONFIG_CONCURRENT_MODE if(rtw_buddy_adapter_up(padapter)) ret = check_buddy_fwstate( padapter, _FW_UNDER_SURVEY); #endif ret = ret || check_fwstate(pmlmepriv, _FW_UNDER_SURVEY); if (_TRUE == ret) pxmitbuf = dequeue_pending_xmitbuf_under_survey(pxmitpriv); else pxmitbuf = dequeue_pending_xmitbuf(pxmitpriv); if (pxmitbuf == NULL) return _TRUE; //pframe = (struct xmit_frame*)pxmitbuf->priv_data; //requiredPage = pframe->pg_num; requiredPage = pxmitbuf->pg_num; //translate queue index to sdio fifo addr deviceId = pdvobjpriv->Queue2Pipe[pxmitbuf->ff_hwaddr]; // translate sdio fifo addr to tx fifo page index switch (deviceId) { case WLAN_TX_HIQ_DEVICE_ID: PageIdx = HI_QUEUE_IDX; break; case WLAN_TX_MIQ_DEVICE_ID: PageIdx = MID_QUEUE_IDX; break; case WLAN_TX_LOQ_DEVICE_ID: PageIdx = LOW_QUEUE_IDX; break; } // check if hardware tx fifo page is enough n = 0; // _enter_critical_bh(&phal->SdioTxFIFOFreePageLock, &irql); do { if (requiredPage <= freePage[PageIdx]) { freePage[PageIdx] -= requiredPage; break; } // The number of page which public page included is available. if ((freePage[PageIdx] + freePage[PUBLIC_QUEUE_IDX]) > (requiredPage + 1)) { u8 requiredPublicPage; requiredPublicPage = requiredPage - freePage[PageIdx]; freePage[PageIdx] = 0; freePage[PUBLIC_QUEUE_IDX] -= requiredPublicPage; break; } // _exit_critical_bh(&phal->SdioTxFIFOFreePageLock, &irql); ret = (padapter->bDriverStopped == _TRUE) || (padapter->bSurpriseRemoved == _TRUE); if (ret) { RT_TRACE(_module_hal_xmit_c_, _drv_notice_, ("%s: bSurpriseRemoved(update TX FIFO page)\n", __func__)); goto free_xmitbuf; } n++; //if ((n & 0x3FF) == 0) if ((n % 2) == 0) { if (n > 5000) { DBG_8192C(KERN_NOTICE "%s: FIFO starvation!(%d) len=%d agg=%d page=(R)%d(A)%d\n", __func__, n, pxmitbuf->len, pxmitbuf->agg_num, pxmitbuf->pg_num, freePage[PageIdx] + freePage[PUBLIC_QUEUE_IDX]); } else { //RT_TRACE(_module_hal_xmit_c_, _drv_notice_, // ("%s: FIFO starvation!(%d) len=%d agg=%d page=(R)%d(A)%d\n", // __FUNCTION__, n, pxmitbuf->len, pxmitbuf->agg_num, pxmitbuf->pg_num, freePage[PageIdx] + freePage[UBLIC_QUEUE_IDX])); } //rtw_yield_os(); rtw_msleep_os(1); } // Total number of page is NOT available, so update current FIFO status #ifdef CONFIG_CONCURRENT_MODE if (padapter->adapter_type > 0) pri_padapter = padapter->pbuddy_adapter; #endif HalQueryTxBufferStatus8723ASdio(pri_padapter); } while (1); if ((padapter->bSurpriseRemoved == _TRUE) #ifdef CONFIG_CONCURRENT_MODE ||((padapter->pbuddy_adapter)&& (padapter->pbuddy_adapter->bSurpriseRemoved)) #endif ){ RT_TRACE(_module_hal_xmit_c_, _drv_notice_, ("%s: bSurpriseRemoved(wirte port)\n", __FUNCTION__)); goto free_xmitbuf; } rtw_write_port(padapter, deviceId, pxmitbuf->len, (u8 *)pxmitbuf); free_xmitbuf: //rtw_free_xmitframe(pxmitpriv, pframe); //pxmitbuf->priv_data = NULL; rtw_free_xmitbuf(pxmitpriv, pxmitbuf); return _FAIL; }
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; _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((!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(!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)); //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)); } } 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, (struct tx_desc *)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; }
int recvbuf2recvframe(PADAPTER padapter, void *ptr) { u8 *pbuf; u8 pkt_cnt = 0; u32 pkt_offset; s32 transfer_len; u8 *pphy_status = NULL; union recv_frame *precvframe = NULL; struct rx_pkt_attrib *pattrib = NULL; HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter); struct recv_priv *precvpriv = &padapter->recvpriv; _queue *pfree_recv_queue = &precvpriv->free_recv_queue; _pkt *pskb; #ifdef CONFIG_USE_USB_BUFFER_ALLOC_RX pskb = NULL; transfer_len = (s32)((struct recv_buf*)ptr)->transfer_len; pbuf = ((struct recv_buf*)ptr)->pbuf; #else pskb = (_pkt*)ptr; transfer_len = (s32)pskb->len; pbuf = pskb->data; #endif//CONFIG_USE_USB_BUFFER_ALLOC_RX #ifdef CONFIG_USB_RX_AGGREGATION pkt_cnt = GET_RX_STATUS_DESC_USB_AGG_PKTNUM_8812(pbuf); #endif do{ precvframe = rtw_alloc_recvframe(pfree_recv_queue); if(precvframe==NULL) { RT_TRACE(_module_rtl871x_recv_c_,_drv_err_,("recvbuf2recvframe: precvframe==NULL\n")); DBG_8192C("%s()-%d: rtw_alloc_recvframe() failed! RX Drop!\n", __FUNCTION__, __LINE__); goto _exit_recvbuf2recvframe; } _rtw_init_listhead(&precvframe->u.hdr.list); precvframe->u.hdr.precvbuf = NULL; //can't access the precvbuf for new arch. precvframe->u.hdr.len=0; rtl8812_query_rx_desc_status(precvframe, pbuf); pattrib = &precvframe->u.hdr.attrib; if ((padapter->registrypriv.mp_mode == 0) && ((pattrib->crc_err) || (pattrib->icv_err))) { DBG_8192C("%s: RX Warning! crc_err=%d icv_err=%d, skip!\n", __FUNCTION__, pattrib->crc_err, pattrib->icv_err); rtw_free_recvframe(precvframe, pfree_recv_queue); goto _exit_recvbuf2recvframe; } pkt_offset = RXDESC_SIZE + pattrib->drvinfo_sz + pattrib->shift_sz + pattrib->pkt_len; if((pattrib->pkt_len<=0) || (pkt_offset>transfer_len)) { RT_TRACE(_module_rtl871x_recv_c_,_drv_info_,("recvbuf2recvframe: pkt_len<=0\n")); DBG_8192C("%s()-%d: RX Warning!,pkt_len<=0 or pkt_offset> transfer_len \n", __FUNCTION__, __LINE__); rtw_free_recvframe(precvframe, pfree_recv_queue); goto _exit_recvbuf2recvframe; } #ifdef CONFIG_RX_PACKET_APPEND_FCS if(pattrib->pkt_rpt_type == NORMAL_RX) pattrib->pkt_len -= IEEE80211_FCS_LEN; #endif if(rtw_os_alloc_recvframe(padapter, precvframe, (pbuf + pattrib->shift_sz + pattrib->drvinfo_sz + RXDESC_SIZE), pskb) == _FAIL) { rtw_free_recvframe(precvframe, pfree_recv_queue); goto _exit_recvbuf2recvframe; } recvframe_put(precvframe, pattrib->pkt_len); //recvframe_pull(precvframe, drvinfo_sz + RXDESC_SIZE); if(pattrib->pkt_rpt_type == NORMAL_RX)//Normal rx packet { if(pattrib->physt) pphy_status = (pbuf + RXDESC_OFFSET); #ifdef CONFIG_CONCURRENT_MODE if(rtw_buddy_adapter_up(padapter)) { if(pre_recv_entry(precvframe, pphy_status) != _SUCCESS) { RT_TRACE(_module_rtl871x_recv_c_,_drv_err_, ("recvbuf2recvframe: recv_entry(precvframe) != _SUCCESS\n")); } } #endif //CONFIG_CONCURRENT_MODE if(pattrib->physt && pphy_status) rx_query_phy_status(precvframe, pphy_status); if(rtw_recv_entry(precvframe) != _SUCCESS) { RT_TRACE(_module_rtl871x_recv_c_,_drv_err_, ("recvbuf2recvframe: rtw_recv_entry(precvframe) != _SUCCESS\n")); } } else{ // pkt_rpt_type == TX_REPORT1-CCX, TX_REPORT2-TX RTP,HIS_REPORT-USB HISR RTP if (pattrib->pkt_rpt_type == C2H_PACKET) { //DBG_8192C("rx C2H_PACKET \n"); C2HPacketHandler_8812(padapter,precvframe->u.hdr.rx_data,pattrib->pkt_len); } rtw_free_recvframe(precvframe, pfree_recv_queue); } #ifdef CONFIG_USB_RX_AGGREGATION // jaguar 8-byte alignment pkt_offset = (u16)_RND8(pkt_offset); pkt_cnt--; pbuf += pkt_offset; #endif transfer_len -= pkt_offset; precvframe = NULL; }while(transfer_len>0); _exit_recvbuf2recvframe: return _SUCCESS; }
// // Description: // Download 8192C firmware code. // // int FirmwareDownload92C( IN PADAPTER Adapter ) { int rtStatus = _SUCCESS; HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter); char R92CFwImageFileName_TSMC[] ={RTL8192C_FW_TSMC_IMG}; char R92CFwImageFileName_UMC[] ={RTL8192C_FW_UMC_IMG}; char R8723FwImageFileName_UMC[] ={RTL8723_FW_UMC_IMG}; char * FwImage; u32 FwImageLen; char* pFwImageFileName; //vivi, merge 92c and 92s into one driver, 20090817 //vivi modify this temply, consider it later!!!!!!!! //PRT_FIRMWARE pFirmware = GET_FIRMWARE_819X(Adapter); //PRT_FIRMWARE_92C pFirmware = GET_FIRMWARE_8192C(Adapter); PRT_FIRMWARE_92C pFirmware = NULL; PRT_8192C_FIRMWARE_HDR pFwHdr = NULL; u8 *pFirmwareBuf; u32 FirmwareLen; pFirmware = (PRT_FIRMWARE_92C)_rtw_malloc(sizeof(RT_FIRMWARE_92C)); if(!pFirmware) { rtStatus = _FAIL; goto Exit; } //RT_TRACE(COMP_INIT, DBG_LOUD, (" ===> FirmwareDownload91C() fw:%s\n", pFwImageFileName)); #ifdef CONFIG_EMBEDDED_FWIMG pFirmware->eFWSource = FW_SOURCE_HEADER_FILE; #else pFirmware->eFWSource = FW_SOURCE_IMG_FILE; #endif if(IS_NORMAL_CHIP(pHalData->VersionID)) { if(IS_VENDOR_UMC_A_CUT(pHalData->VersionID) && !IS_92C_SERIAL(pHalData->VersionID))// UMC , 8188 { pFwImageFileName = R92CFwImageFileName_UMC; FwImage = Rtl819XFwUMCImageArray; FwImageLen = UMCImgArrayLength; DBG_871X(" ===> FirmwareDownload91C() fw:Rtl819XFwImageArray_UMC\n"); } else { pFwImageFileName = R92CFwImageFileName_TSMC; FwImage = Rtl819XFwTSMCImageArray; FwImageLen = TSMCImgArrayLength; DBG_871X(" ===> FirmwareDownload91C() fw:Rtl819XFwImageArray_TSMC\n"); } } else { #if 0 pFwImageFileName = TestChipFwFile; FwImage = Rtl8192CTestFwImg; FwImageLen = Rtl8192CTestFwImgLen; RT_TRACE(COMP_INIT, DBG_LOUD, (" ===> FirmwareDownload91C() fw:Rtl8192CTestFwImg\n")); #endif } switch(pFirmware->eFWSource) { case FW_SOURCE_IMG_FILE: //TODO:load fw bin file break; case FW_SOURCE_HEADER_FILE: if(TSMCImgArrayLength > FW_8192C_SIZE){ rtStatus = _FAIL; //RT_TRACE(COMP_INIT, DBG_SERIOUS, ("Firmware size exceed 0x%X. Check it.\n", FW_8192C_SIZE) ); DBG_871X("Firmware size exceed 0x%X. Check it.\n", FW_8192C_SIZE); goto Exit; } _rtw_memcpy(pFirmware->szFwBuffer, FwImage, FwImageLen); pFirmware->ulFwLength = FwImageLen; break; } pFirmwareBuf = pFirmware->szFwBuffer; FirmwareLen = pFirmware->ulFwLength; // To Check Fw header. pFwHdr = (PRT_8192C_FIRMWARE_HDR)pFirmware->szFwBuffer; pHalData->FirmwareVersion = le16_to_cpu(pFwHdr->Version); pHalData->FirmwareSubVersion = le16_to_cpu(pFwHdr->Subversion); //RT_TRACE(COMP_INIT, DBG_LOUD, (" FirmwareVersion(%#x), Signature(%#x)\n", // Adapter->MgntInfo.FirmwareVersion, pFwHdr->Signature)); DBG_8192C("fw_ver=v%d, fw_subver=%d, sig=0x%x\n", pHalData->FirmwareVersion, pHalData->FirmwareSubVersion, le16_to_cpu(pFwHdr->Signature)&0xFFF0); if(IS_FW_HEADER_EXIST(pFwHdr)) { //RT_TRACE(COMP_INIT, DBG_LOUD,("Shift 32 bytes for FW header!!\n")); pFirmwareBuf = pFirmwareBuf + 32; FirmwareLen = FirmwareLen -32; } // Suggested by Filen. If 8051 is running in RAM code, driver should inform Fw to reset by itself, // or it will cause download Fw fail. 2010.02.01. by tynli. if(rtw_read8(Adapter, REG_MCUFWDL)&BIT7) //8051 RAM code { DBG_8192C("8051 in Ram......prepare to reset by itself\n"); _FirmwareSelfReset(Adapter); rtw_write8(Adapter, REG_MCUFWDL, 0x00); } _FWDownloadEnable(Adapter, _TRUE); _WriteFW(Adapter, pFirmwareBuf, FirmwareLen); _FWDownloadEnable(Adapter, _FALSE); rtStatus = _FWFreeToGo(Adapter); if(_SUCCESS != rtStatus){ //RT_TRACE(COMP_INIT, DBG_SERIOUS, ("DL Firmware failed!\n") ); goto Exit; } //RT_TRACE(COMP_INIT, DBG_LOUD, (" Firmware is ready to run!\n")); Exit: if(pFirmware) _rtw_mfree((u8*)pFirmware, sizeof(RT_FIRMWARE_92C)); //RT_TRACE(COMP_INIT, DBG_LOUD, (" <=== FirmwareDownload91C()\n")); return rtStatus; }
static void usb_write_port_complete(struct urb *purb, struct pt_regs *regs) { _irqL irqL; int i; struct xmit_buf *pxmitbuf = (struct xmit_buf *)purb->context; //struct xmit_frame *pxmitframe = (struct xmit_frame *)pxmitbuf->priv_data; //_adapter *padapter = pxmitframe->padapter; _adapter *padapter = pxmitbuf->padapter; struct xmit_priv *pxmitpriv = &padapter->xmitpriv; //struct pkt_attrib *pattrib = &pxmitframe->attrib; _func_enter_; switch(pxmitbuf->flags) { case VO_QUEUE_INX: pxmitpriv->voq_cnt--; break; case VI_QUEUE_INX: pxmitpriv->viq_cnt--; break; case BE_QUEUE_INX: pxmitpriv->beq_cnt--; break; case BK_QUEUE_INX: pxmitpriv->bkq_cnt--; break; default: break; } /* _enter_critical(&pxmitpriv->lock, &irqL); pxmitpriv->txirp_cnt--; switch(pattrib->priority) { case 1: case 2: pxmitpriv->bkq_cnt--; //DBG_8192C("pxmitpriv->bkq_cnt=%d\n", pxmitpriv->bkq_cnt); break; case 4: case 5: pxmitpriv->viq_cnt--; //DBG_8192C("pxmitpriv->viq_cnt=%d\n", pxmitpriv->viq_cnt); break; case 6: case 7: pxmitpriv->voq_cnt--; //DBG_8192C("pxmitpriv->voq_cnt=%d\n", pxmitpriv->voq_cnt); break; case 0: case 3: default: pxmitpriv->beq_cnt--; //DBG_8192C("pxmitpriv->beq_cnt=%d\n", pxmitpriv->beq_cnt); break; } _exit_critical(&pxmitpriv->lock, &irqL); if(pxmitpriv->txirp_cnt==0) { RT_TRACE(_module_hci_ops_os_c_,_drv_err_,("usb_write_port_complete: txirp_cnt== 0, set allrxreturnevt!\n")); _rtw_up_sema(&(pxmitpriv->tx_retevt)); } */ //rtw_free_xmitframe(pxmitpriv, pxmitframe); if (RTW_CANNOT_TX(padapter)) { RT_TRACE(_module_hci_ops_os_c_,_drv_err_,("usb_write_port_complete:bDriverStopped(%d) OR bSurpriseRemoved(%d)", padapter->bDriverStopped, padapter->bSurpriseRemoved)); DBG_8192C("%s(): TX Warning! bDriverStopped(%d) OR bSurpriseRemoved(%d) pxmitbuf->buf_tag(%x) \n", __FUNCTION__,padapter->bDriverStopped, padapter->bSurpriseRemoved,pxmitbuf->buf_tag); goto check_completion; } if (purb->status==0) { } else { RT_TRACE(_module_hci_ops_os_c_,_drv_err_,("usb_write_port_complete : purb->status(%d) != 0 \n", purb->status)); DBG_871X("###=> urb_write_port_complete status(%d)\n",purb->status); if((purb->status==-EPIPE)||(purb->status==-EPROTO)) { //usb_clear_halt(pusbdev, purb->pipe); //msleep(10); sreset_set_wifi_error_status(padapter, USB_WRITE_PORT_FAIL); } else if (purb->status == -EINPROGRESS) { RT_TRACE(_module_hci_ops_os_c_,_drv_err_,("usb_write_port_complete: EINPROGESS\n")); goto check_completion; } else if (purb->status == -ENOENT) { DBG_871X("%s: -ENOENT\n", __func__); goto check_completion; } else if (purb->status == -ECONNRESET) { DBG_871X("%s: -ECONNRESET\n", __func__); goto check_completion; } else if (purb->status == -ESHUTDOWN) { RT_TRACE(_module_hci_ops_os_c_,_drv_err_,("usb_write_port_complete: ESHUTDOWN\n")); padapter->bDriverStopped=_TRUE; RT_TRACE(_module_hci_ops_os_c_,_drv_err_,("usb_write_port_complete:bDriverStopped=TRUE\n")); goto check_completion; } else { padapter->bSurpriseRemoved=_TRUE; DBG_8192C("bSurpriseRemoved=TRUE\n"); //rtl8192cu_trigger_gpio_0(padapter); RT_TRACE(_module_hci_ops_os_c_,_drv_err_,("usb_write_port_complete:bSurpriseRemoved=TRUE\n")); goto check_completion; } } #ifdef DBG_CONFIG_ERROR_DETECT { HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter); pHalData->srestpriv.last_tx_complete_time = jiffies; } #endif check_completion: _enter_critical(&pxmitpriv->lock_sctx, &irqL); rtw_sctx_done_err(&pxmitbuf->sctx, purb->status ? RTW_SCTX_DONE_WRITE_PORT_ERR : RTW_SCTX_DONE_SUCCESS); _exit_critical(&pxmitpriv->lock_sctx, &irqL); rtw_free_xmitbuf(pxmitpriv, pxmitbuf); //if(rtw_txframes_pending(padapter)) { tasklet_hi_schedule(&pxmitpriv->xmit_tasklet); } _func_exit_; }
int rtl8192eu_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 #ifdef PLATFORM_LINUX tasklet_init(&precvpriv->recv_tasklet, (void(*)(unsigned long))rtl8192eu_recv_tasklet, (unsigned long)padapter); #endif #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 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; } _rtw_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); 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; #ifdef PLATFORM_LINUX 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 #endif exit: return res; }