u32 _rtw_free_sta_priv(struct sta_priv *pstapriv) { _irqL irqL; _list *phead, *plist; struct sta_info *psta = NULL; struct recv_reorder_ctrl *preorder_ctrl; int index; _func_enter_; if(pstapriv){ /* delete all reordering_ctrl_timer */ _enter_critical_bh(&pstapriv->sta_hash_lock, &irqL); for(index = 0; index < NUM_STA; index++) { phead = &(pstapriv->sta_hash[index]); plist = get_next(phead); while ((rtw_end_of_queue_search(phead, plist)) == _FALSE) { int i; psta = LIST_CONTAINOR(plist, struct sta_info ,hash_list); plist = get_next(plist); for(i=0; i < 16 ; i++) { preorder_ctrl = &psta->recvreorder_ctrl[i]; _cancel_timer_ex(&preorder_ctrl->reordering_ctrl_timer); } } } _exit_critical_bh(&pstapriv->sta_hash_lock, &irqL); /*===============================*/ rtw_mfree_sta_priv_lock(pstapriv); if(pstapriv->pallocated_stainfo_buf) { rtw_vmfree(pstapriv->pallocated_stainfo_buf, sizeof(struct sta_info)*NUM_STA+4); } } _func_exit_; return _SUCCESS; }
/* 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; _func_enter_; if(hwaddr==NULL) return NULL; index = wifi_mac_hash(hwaddr); _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,hwaddr, 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 rtl8723bs_free_xmit_priv(PADAPTER padapter) { PHAL_DATA_TYPE phal; struct xmit_priv *pxmitpriv; struct xmit_buf *pxmitbuf; _queue *pqueue; _list *plist, *phead; _list tmplist; _irqL irql; phal = GET_HAL_DATA(padapter); pxmitpriv = &padapter->xmitpriv; pqueue = &pxmitpriv->pending_xmitbuf_queue; phead = get_list_head(pqueue); _rtw_init_listhead(&tmplist); _enter_critical_bh(&pqueue->lock, &irql); if (_rtw_queue_empty(pqueue) == _FALSE) { // Insert tmplist to end of queue, and delete phead // then tmplist become head of queue. rtw_list_insert_tail(&tmplist, phead); rtw_list_delete(phead); } _exit_critical_bh(&pqueue->lock, &irql); phead = &tmplist; while (rtw_is_list_empty(phead) == _FALSE) { plist = get_next(phead); rtw_list_delete(plist); pxmitbuf = LIST_CONTAINOR(plist, struct xmit_buf, list); rtw_free_xmitframe(pxmitpriv, (struct xmit_frame*)pxmitbuf->priv_data); pxmitbuf->priv_data = NULL; rtw_free_xmitbuf(pxmitpriv, pxmitbuf); } _rtw_spinlock_free(&phal->SdioTxFIFOFreePageLock); }
void rtw_mi_buddy_indicate_scan_done(_adapter *padapter, bool bscan_aborted) { #if defined(CONFIG_IOCTL_CFG80211) int i; u8 ret = 0; _adapter *iface = NULL; _irqL irqL; struct dvobj_priv *dvobj = adapter_to_dvobj(padapter); struct mlme_priv *mlmepriv; struct rtw_wdev_priv *wdev_priv; bool indicate_buddy_scan = _FALSE; for (i = 0; i < dvobj->iface_nums; i++) { iface = dvobj->padapters[i]; if ((iface) && rtw_is_adapter_up(iface)) { if (iface == padapter) continue; mlmepriv = &(iface->mlmepriv); wdev_priv = adapter_wdev_data(iface); _enter_critical_bh(&wdev_priv->scan_req_lock, &irqL); if (wdev_priv->scan_request && mlmepriv->scanning_via_buddy_intf == _TRUE) { mlmepriv->scanning_via_buddy_intf = _FALSE; clr_fwstate(mlmepriv, _FW_UNDER_SURVEY); indicate_buddy_scan = _TRUE; } _exit_critical_bh(&wdev_priv->scan_req_lock, &irqL); if (indicate_buddy_scan == _TRUE) { rtw_cfg80211_surveydone_event_callback(iface); rtw_indicate_scan_done(iface, bscan_aborted); } } } #endif }
/* * Description: * Handle xmitframe(packet) come from rtw_xmit() * * Return: * _TRUE dump packet directly ok * _FALSE enqueue, temporary can't transmit packets to hardware */ s32 rtl8723as_hal_xmit(PADAPTER padapter, struct xmit_frame *pxmitframe) { struct xmit_priv *pxmitpriv; PHAL_DATA_TYPE phal; _irqL irql; s32 err; pxmitframe->attrib.qsel = pxmitframe->attrib.priority; pxmitpriv = &padapter->xmitpriv; phal = GET_HAL_DATA(padapter); #ifdef CONFIG_80211N_HT if ((pxmitframe->frame_tag == DATA_FRAMETAG) && (pxmitframe->attrib.ether_type != 0x0806) && (pxmitframe->attrib.ether_type != 0x888e) && (pxmitframe->attrib.dhcp_pkt != 1)) { if (padapter->mlmepriv.LinkDetectInfo.bBusyTraffic == _TRUE) rtw_issue_addbareq_cmd(padapter, pxmitframe); } #endif _enter_critical_bh(&pxmitpriv->lock, &irql); err = rtw_xmitframe_enqueue(padapter, pxmitframe); _exit_critical_bh(&pxmitpriv->lock, &irql); if (err != _SUCCESS) { RT_TRACE(_module_hal_xmit_c_, _drv_err_, ("rtl8723as_hal_xmit: enqueue xmitframe fail\n")); rtw_free_xmitframe(pxmitpriv, pxmitframe); // Trick, make the statistics correct pxmitpriv->tx_pkts--; pxmitpriv->tx_drop++; return _TRUE; } _rtw_up_sema(&phal->SdioXmitSema); return _FALSE; }
/* free all stainfo which in sta_hash[all] */ void rtw_free_all_stainfo(_adapter *padapter) { unsigned long irqL; struct list_head *plist, *phead; s32 index; struct sta_info *psta = NULL; struct sta_priv *pstapriv = &padapter->stapriv; struct sta_info* pbcmc_stainfo =rtw_get_bcmc_stainfo( padapter); _func_enter_; if (pstapriv->asoc_sta_count==1) goto exit; _enter_critical_bh(&pstapriv->sta_hash_lock, &irqL); for (index=0; index< NUM_STA; index++) { 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); plist = get_next(plist); if (pbcmc_stainfo!=psta) rtw_free_stainfo(padapter , psta); } } _exit_critical_bh(&pstapriv->sta_hash_lock, &irqL); exit: _func_exit_; }
void rtw_os_xmit_schedule(_adapter *padapter) { #if defined(CONFIG_SDIO_HCI) || defined(CONFIG_GSPI_HCI) _adapter *pri_adapter = GET_PRIMARY_ADAPTER(padapter); if (!padapter) return; if (_rtw_queue_empty(&padapter->xmitpriv.pending_xmitbuf_queue) == _FALSE) _rtw_up_sema(&pri_adapter->xmitpriv.xmit_sema); #else _irqL irqL; struct xmit_priv *pxmitpriv; if (!padapter) return; pxmitpriv = &padapter->xmitpriv; _enter_critical_bh(&pxmitpriv->lock, &irqL); if (rtw_txframes_pending(padapter)) tasklet_hi_schedule(&pxmitpriv->xmit_tasklet); _exit_critical_bh(&pxmitpriv->lock, &irqL); #if defined(CONFIG_PCI_HCI) && defined(CONFIG_XMIT_THREAD_MODE) if (_rtw_queue_empty(&padapter->xmitpriv.pending_xmitbuf_queue) == _FALSE) _rtw_up_sema(&padapter->xmitpriv.xmit_sema); #endif #endif }
void nat25_db_cleanup(_adapter *priv) { int i; _irqL irqL; _enter_critical_bh(&priv->br_ext_lock, &irqL); for(i=0; i<NAT25_HASH_SIZE; i++) { struct nat25_network_db_entry *f, *g; for (f = priv->nethash[i]; f != NULL; f = g) { g = f->next_hash; if (priv->scdb_entry == f) { set_zero_mac_addr(priv->scdb_mac); RTW_WN32(priv->scdb_ip, 0); priv->scdb_entry = NULL; } __network_hash_unlink(f); rtw_mfree((u8 *) f, sizeof(struct nat25_network_db_entry)); } } _exit_critical_bh(&priv->br_ext_lock, &irqL); }
void rtw_os_xmit_schedule(_adapter *padapter) { _adapter *pri_adapter = padapter; #if defined(CONFIG_SDIO_HCI) || defined(CONFIG_GSPI_HCI) if(!padapter) return; #ifdef CONFIG_CONCURRENT_MODE if(padapter->adapter_type > PRIMARY_ADAPTER) pri_adapter = padapter->pbuddy_adapter; #endif if (_rtw_queue_empty(&padapter->xmitpriv.pending_xmitbuf_queue) == _FALSE) _rtw_up_sema(&pri_adapter->xmitpriv.xmit_sema); #else _irqL irqL; struct xmit_priv *pxmitpriv; if(!padapter) return; pxmitpriv = &padapter->xmitpriv; _enter_critical_bh(&pxmitpriv->lock, &irqL); if(rtw_txframes_pending(padapter)) { tasklet_hi_schedule(&pxmitpriv->xmit_tasklet); } _exit_critical_bh(&pxmitpriv->lock, &irqL); #endif }
u8 rtw_set_802_11_disassociate(_adapter *padapter) { _irqL irqL; struct mlme_priv * pmlmepriv = &padapter->mlmepriv; _func_enter_; _enter_critical_bh(&pmlmepriv->lock, &irqL); if (check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE) { RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_info_,("MgntActrtw_set_802_11_disassociate: rtw_indicate_disconnect\n")); rtw_disassoc_cmd(padapter); rtw_indicate_disconnect(padapter); rtw_free_assoc_resources(padapter, 1); } _exit_critical_bh(&pmlmepriv->lock, &irqL); _func_exit_; return _TRUE; }
/* * 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=0; struct hw_xmit *hwxmits, *phwxmit; u8 no_res, idx, hwentry; _irqL irql; 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; u8 txdesc_size = TXDESC_SIZE; int inx[4]; err = 0; no_res = _FALSE; hwxmits = pxmitpriv->hwxmits; hwentry = pxmitpriv->hwxmit_entry; ptxservq = NULL; pxmitframe = NULL; pframe_queue = NULL; pxmitbuf = NULL; if (padapter->registrypriv.wifi_spec == 1) { for(idx=0; idx<4; idx++) inx[idx] = pxmitpriv->wmm_para_seq[idx]; } else { inx[0] = 0; inx[1] = 1; inx[2] = 2; inx[3] = 3; } // 0(VO), 1(VI), 2(BE), 3(BK) for (idx = 0; idx < hwentry; idx++) { phwxmit = hwxmits + inx[idx]; if((check_pending_xmitbuf(pxmitpriv) == _TRUE) && (padapter->mlmepriv.LinkDetectInfo.bHigherBusyTxTraffic == _TRUE)) { if ((phwxmit->accnt > 0) && (phwxmit->accnt < 5)) { err = -2; break; } } _enter_critical_bh(&pxmitpriv->lock, &irql); sta_phead = get_list_head(phwxmit->sta_queue); sta_plist = get_next(sta_phead); //because stop_sta_xmit may delete sta_plist at any time //so we should add lock here, or while loop can not exit 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); #ifdef DBG_XMIT_BUF DBG_871X("%s idx:%d hwxmit_pkt_num:%d ptxservq_pkt_num:%d\n", __func__, idx, phwxmit->accnt, ptxservq->qcnt); DBG_871X("%s free_xmit_extbuf_cnt=%d free_xmitbuf_cnt=%d free_xmitframe_cnt=%d \n", __func__, pxmitpriv->free_xmit_extbuf_cnt, pxmitpriv->free_xmitbuf_cnt, pxmitpriv->free_xmitframe_cnt); #endif pframe_queue = &ptxservq->sta_pending; 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) { //pxmitbuf->priv_data will be NULL, and will crash here if (pxmitbuf->len > 0 && pxmitbuf->priv_data) { struct xmit_frame *pframe; pframe = (struct xmit_frame*)pxmitbuf->priv_data; pframe->agg_num = k; pxmitbuf->agg_num = k; rtl8723b_update_txdesc(pframe, pframe->buf_addr); rtw_free_xmitframe(pxmitpriv, pframe); pxmitbuf->priv_data = NULL; enqueue_pending_xmitbuf(pxmitpriv, pxmitbuf); //can not yield under lock //rtw_yield_os(); } else { rtw_free_xmitbuf(pxmitpriv, pxmitbuf); } } pxmitbuf = rtw_alloc_xmitbuf(pxmitpriv); if (pxmitbuf == NULL) { #ifdef DBG_XMIT_BUF DBG_871X_LEVEL(_drv_err_, "%s: xmit_buf is not enough!\n", __FUNCTION__); #endif err = -2; break; } k = 0; } // ok to send, remove frame from queue #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)) { DBG_871X("%s: one not triggered pkt in queue when this STA sleep," " break and goto next sta\n", __func__); break; } } #endif rtw_list_delete(&pxmitframe->list); ptxservq->qcnt--; phwxmit->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) { DBG_871X_LEVEL(_drv_err_, "%s: coalesce FAIL!", __FUNCTION__); // Todo: error handler } else { k++; if (k != 1) rtl8723b_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; } if (_rtw_queue_empty(pframe_queue) == _TRUE) rtw_list_delete(&ptxservq->tx_pending); if (err) break; } _exit_critical_bh(&pxmitpriv->lock, &irql); // dump xmit_buf to hw tx fifo if (pxmitbuf) { RT_TRACE(_module_hal_xmit_c_, _drv_info_, ("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; rtl8723b_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; }
int proc_get_all_sta_info(struct seq_file *m, void *v) { struct net_device *dev = m->private; _irqL irqL; struct sta_info *psta; _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); struct sta_priv *pstapriv = &padapter->stapriv; int i, j; _list *plist, *phead; struct recv_reorder_ctrl *preorder_ctrl; DBG_871X_SEL_NL(m, "sta_dz_bitmap=0x%x, tim_bitmap=0x%x\n", pstapriv->sta_dz_bitmap, pstapriv->tim_bitmap); _enter_critical_bh(&pstapriv->sta_hash_lock, &irqL); for(i=0; i< NUM_STA; i++) { phead = &(pstapriv->sta_hash[i]); plist = get_next(phead); while ((rtw_end_of_queue_search(phead, plist)) == _FALSE) { psta = LIST_CONTAINOR(plist, struct sta_info, hash_list); plist = get_next(plist); //if(extra_arg == psta->aid) { DBG_871X_SEL_NL(m, "==============================\n"); DBG_871X_SEL_NL(m, "sta's macaddr:" MAC_FMT "\n", MAC_ARG(psta->hwaddr)); DBG_871X_SEL_NL(m, "rtsen=%d, cts2slef=%d\n", psta->rtsen, psta->cts2self); DBG_871X_SEL_NL(m, "state=0x%x, aid=%d, macid=%d, raid=%d\n", psta->state, psta->aid, psta->mac_id, psta->raid); #ifdef CONFIG_80211N_HT DBG_871X_SEL_NL(m, "qos_en=%d, ht_en=%d, init_rate=%d\n", psta->qos_option, psta->htpriv.ht_option, psta->init_rate); DBG_871X_SEL_NL(m, "bwmode=%d, ch_offset=%d, sgi_20m=%d,sgi_40m=%d\n", psta->bw_mode, psta->htpriv.ch_offset, psta->htpriv.sgi_20m, psta->htpriv.sgi_40m); DBG_871X_SEL_NL(m, "ampdu_enable = %d\n", psta->htpriv.ampdu_enable); DBG_871X_SEL_NL(m, "agg_enable_bitmap=%x, candidate_tid_bitmap=%x\n", psta->htpriv.agg_enable_bitmap, psta->htpriv.candidate_tid_bitmap); #endif //CONFIG_80211N_HT DBG_871X_SEL_NL(m, "sleepq_len=%d\n", psta->sleepq_len); DBG_871X_SEL_NL(m, "sta_xmitpriv.vo_q_qcnt=%d\n", psta->sta_xmitpriv.vo_q.qcnt); DBG_871X_SEL_NL(m, "sta_xmitpriv.vi_q_qcnt=%d\n", psta->sta_xmitpriv.vi_q.qcnt); DBG_871X_SEL_NL(m, "sta_xmitpriv.be_q_qcnt=%d\n", psta->sta_xmitpriv.be_q.qcnt); DBG_871X_SEL_NL(m, "sta_xmitpriv.bk_q_qcnt=%d\n", psta->sta_xmitpriv.bk_q.qcnt); DBG_871X_SEL_NL(m, "capability=0x%x\n", psta->capability); DBG_871X_SEL_NL(m, "flags=0x%x\n", psta->flags); DBG_871X_SEL_NL(m, "wpa_psk=0x%x\n", psta->wpa_psk); DBG_871X_SEL_NL(m, "wpa2_group_cipher=0x%x\n", psta->wpa2_group_cipher); DBG_871X_SEL_NL(m, "wpa2_pairwise_cipher=0x%x\n", psta->wpa2_pairwise_cipher); DBG_871X_SEL_NL(m, "qos_info=0x%x\n", psta->qos_info); DBG_871X_SEL_NL(m, "dot118021XPrivacy=0x%x\n", psta->dot118021XPrivacy); for(j=0;j<16;j++) { preorder_ctrl = &psta->recvreorder_ctrl[j]; if(preorder_ctrl->enable) { DBG_871X_SEL_NL(m, "tid=%d, indicate_seq=%d\n", j, preorder_ctrl->indicate_seq); } } #ifdef CONFIG_TDLS DBG_871X_SEL_NL(m, "tdls_sta_state=0x%08x\n", psta->tdls_sta_state); DBG_871X_SEL_NL(m, "PeerKey_Lifetime=%d\n", psta->TDLS_PeerKey_Lifetime); DBG_871X_SEL_NL(m, "rx_data_pkts=%llu\n", psta->sta_stats.rx_data_pkts); DBG_871X_SEL_NL(m, "rx_bytes=%llu\n", psta->sta_stats.rx_bytes); DBG_871X_SEL_NL(m, "tx_data_pkts=%llu\n", psta->sta_stats.tx_pkts); DBG_871X_SEL_NL(m, "tx_bytes=%llu\n", psta->sta_stats.tx_bytes); #endif //CONFIG_TDLS DBG_871X_SEL_NL(m, "==============================\n"); } } } _exit_critical_bh(&pstapriv->sta_hash_lock, &irqL); return 0; }
void nat25_db_expire(_adapter *priv) { int i; _irqL irqL; _enter_critical_bh(&priv->br_ext_lock, &irqL); /* if (!priv->ethBrExtInfo.nat25_disable) */ { for (i=0; i<NAT25_HASH_SIZE; i++) { struct nat25_network_db_entry *f; f = priv->nethash[i]; while (f != NULL) { struct nat25_network_db_entry *g; g = f->next_hash; if (__nat25_has_expired(priv, f)) { if (atomic_dec_and_test(&f->use_count)) { #ifdef BR_EXT_DEBUG panic_printk("NAT25 Expire H(%02d) M:%02x%02x%02x%02x%02x%02x N:%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x" "%02x%02x%02x%02x%02x%02x\n", i, f->macAddr[0], f->macAddr[1], f->macAddr[2], f->macAddr[3], f->macAddr[4], f->macAddr[5], f->networkAddr[0], f->networkAddr[1], f->networkAddr[2], f->networkAddr[3], f->networkAddr[4], f->networkAddr[5], f->networkAddr[6], f->networkAddr[7], f->networkAddr[8], f->networkAddr[9], f->networkAddr[10], f->networkAddr[11], f->networkAddr[12], f->networkAddr[13], f->networkAddr[14], f->networkAddr[15], f->networkAddr[16]); #endif if (priv->scdb_entry == f) { memset(priv->scdb_mac, 0, ETH_ALEN); memset(priv->scdb_ip, 0, 4); priv->scdb_entry = NULL; } __network_hash_unlink(f); rtw_mfree((u8 *) f, sizeof(struct nat25_network_db_entry)); } } f = g; } } } _exit_critical_bh(&priv->br_ext_lock, &irqL); }
struct sta_info *rtw_alloc_stainfo(struct sta_priv *pstapriv, u8 *hwaddr) { unsigned long irqL, irqL2; s32 index; struct list_head *phash_list; struct sta_info *psta; struct __queue *pfree_sta_queue; struct recv_reorder_ctrl *preorder_ctrl; int i = 0; u16 wRxSeqInitialValue = 0xffff; _func_enter_; pfree_sta_queue = &pstapriv->free_sta_queue; _enter_critical_bh(&(pfree_sta_queue->lock), &irqL); if (_rtw_queue_empty(pfree_sta_queue) == true) { _exit_critical_bh(&(pfree_sta_queue->lock), &irqL); psta = NULL; } else { psta = LIST_CONTAINOR(get_next(&pfree_sta_queue->queue), struct sta_info, list); rtw_list_delete(&(psta->list)); _exit_critical_bh(&(pfree_sta_queue->lock), &irqL); _rtw_init_stainfo(psta); _rtw_memcpy(psta->hwaddr, hwaddr, ETH_ALEN); index = wifi_mac_hash(hwaddr); RT_TRACE(_module_rtl871x_sta_mgt_c_,_drv_info_,("rtw_alloc_stainfo: index = %x", index)); if (index >= NUM_STA) { RT_TRACE(_module_rtl871x_sta_mgt_c_,_drv_err_,("ERROR=> rtw_alloc_stainfo: index >= NUM_STA")); psta= NULL; goto exit; } phash_list = &(pstapriv->sta_hash[index]); _enter_critical_bh(&(pstapriv->sta_hash_lock), &irqL2); rtw_list_insert_tail(&psta->hash_list, phash_list); pstapriv->asoc_sta_count ++ ; _exit_critical_bh(&(pstapriv->sta_hash_lock), &irqL2); /* Commented by Albert 2009/08/13 */ /* For the SMC router, the sequence number of first packet of WPS handshake will be 0. */ /* In this case, this packet will be dropped by recv_decache function if we use the 0x00 as the default value for tid_rxseq variable. */ /* So, we initialize the tid_rxseq variable as the 0xffff. */ for ( i = 0; i < 16; i++ ) { _rtw_memcpy( &psta->sta_recvpriv.rxcache.tid_rxseq[ i ], &wRxSeqInitialValue, 2 ); } RT_TRACE(_module_rtl871x_sta_mgt_c_,_drv_info_,("alloc number_%d stainfo with hwaddr = %x %x %x %x %x %x\n", pstapriv->asoc_sta_count , hwaddr[0], hwaddr[1], hwaddr[2],hwaddr[3],hwaddr[4],hwaddr[5])); init_addba_retry_timer(pstapriv->padapter, psta); /* for A-MPDU Rx reordering buffer control */ for (i=0; i < 16 ; i++) { preorder_ctrl = &psta->recvreorder_ctrl[i]; preorder_ctrl->padapter = pstapriv->padapter; preorder_ctrl->enable = false; preorder_ctrl->indicate_seq = 0xffff; preorder_ctrl->wend_b= 0xffff; preorder_ctrl->wsize_b = 64;/* 64; */ _rtw_init_queue(&preorder_ctrl->pending_recvframe_queue); rtw_init_recv_timer(preorder_ctrl); } /* init for DM */ psta->rssi_stat.UndecoratedSmoothedPWDB = (-1); psta->rssi_stat.UndecoratedSmoothedCCK = (-1); /* init for the sequence number of received management frame */ psta->RxMgmtFrameSeqNum = 0xffff; } exit: _func_exit_; return psta; }
void rtw_set_ps_mode(PADAPTER padapter, u8 ps_mode, u8 smart_ps, u8 bcn_ant_mode) { struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv; #ifdef CONFIG_P2P struct wifidirect_info *pwdinfo = &( padapter->wdinfo ); #endif //CONFIG_P2P #ifdef CONFIG_TDLS struct sta_priv *pstapriv = &padapter->stapriv; _irqL irqL; int i, j; _list *plist, *phead; struct sta_info *ptdls_sta; #endif //CONFIG_TDLS _func_enter_; RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_notice_, ("%s: PowerMode=%d Smart_PS=%d\n", __FUNCTION__, 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) { if (PS_MODE_ACTIVE == ps_mode) return; if ((pwrpriv->smart_ps == smart_ps) && (pwrpriv->bcn_ant_mode == bcn_ant_mode)) { return; } } #ifdef CONFIG_LPS_LCLK _enter_pwrlock(&pwrpriv->lock); #endif //if(pwrpriv->pwr_mode == PS_MODE_ACTIVE) if(ps_mode == PS_MODE_ACTIVE) { #ifdef CONFIG_P2P_PS if(pwdinfo->opp_ps == 0) #endif //CONFIG_P2P_PS { DBG_871X("rtw_set_ps_mode: Leave 802.11 power save\n"); #ifdef CONFIG_TDLS _enter_critical_bh(&pstapriv->sta_hash_lock, &irqL); for(i=0; i< NUM_STA; i++) { phead = &(pstapriv->sta_hash[i]); plist = get_next(phead); while ((rtw_end_of_queue_search(phead, plist)) == _FALSE) { ptdls_sta = LIST_CONTAINOR(plist, struct sta_info, hash_list); if( ptdls_sta->tdls_sta_state & TDLS_LINKED_STATE ) issue_nulldata_to_TDLS_peer_STA(padapter, ptdls_sta, 0); plist = get_next(plist); } } _exit_critical_bh(&pstapriv->sta_hash_lock, &irqL); #endif //CONFIG_TDLS pwrpriv->pwr_mode = ps_mode; rtw_set_rpwm(padapter, PS_STATE_S4); #ifdef CONFIG_WOWLAN if (padapter->pwrctrlpriv.wowlan_mode == _TRUE) { u32 start_time, delay_ms; u8 val8; delay_ms = 20; start_time = rtw_get_current_time(); do { val8 = rtw_read8(padapter, 0x90); if (!(val8 & BIT(0))) break; if (rtw_get_passing_time_ms(start_time) > delay_ms) { DBG_871X("%s: Wait for FW 32K leave more than %u ms!!!\n", __FUNCTION__, delay_ms); break; } rtw_usleep_os(100); } while (1); pwrpriv->cpwm = PS_STATE_S4; } #endif rtw_hal_set_hwreg(padapter, HW_VAR_H2C_FW_PWRMODE, (u8 *)(&ps_mode)); pwrpriv->bFwCurrentInPSMode = _FALSE; } }
/* * 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); _enter_critical_bh(&pxmitpriv->lock, &irql); 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 DBG_871X("%s: coalesce FAIL!", __FUNCTION__); } 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); _exit_critical_bh(&pxmitpriv->lock, &irql); // 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; }
// using pstapriv->sta_hash_lock to protect u32 rtw_free_stainfo(_adapter *padapter , struct sta_info *psta) { int i; _irqL irqL0; _queue *pfree_sta_queue; struct recv_reorder_ctrl *preorder_ctrl; struct sta_xmit_priv *pstaxmitpriv; struct xmit_priv *pxmitpriv= &padapter->xmitpriv; struct sta_priv *pstapriv = &padapter->stapriv; struct hw_xmit *phwxmit; _func_enter_; if (psta == NULL) goto exit; _enter_critical_bh(&psta->lock, &irqL0); psta->state &= ~_FW_LINKED; _exit_critical_bh(&psta->lock, &irqL0); pfree_sta_queue = &pstapriv->free_sta_queue; pstaxmitpriv = &psta->sta_xmitpriv; //rtw_list_delete(&psta->sleep_list); //rtw_list_delete(&psta->wakeup_list); _enter_critical_bh(&pxmitpriv->lock, &irqL0); rtw_free_xmitframe_queue(pxmitpriv, &psta->sleep_q); psta->sleepq_len = 0; //vo //_enter_critical_bh(&(pxmitpriv->vo_pending.lock), &irqL0); rtw_free_xmitframe_queue( pxmitpriv, &pstaxmitpriv->vo_q.sta_pending); rtw_list_delete(&(pstaxmitpriv->vo_q.tx_pending)); phwxmit = pxmitpriv->hwxmits; phwxmit->accnt -= pstaxmitpriv->vo_q.qcnt; pstaxmitpriv->vo_q.qcnt = 0; //_exit_critical_bh(&(pxmitpriv->vo_pending.lock), &irqL0); //vi //_enter_critical_bh(&(pxmitpriv->vi_pending.lock), &irqL0); rtw_free_xmitframe_queue( pxmitpriv, &pstaxmitpriv->vi_q.sta_pending); rtw_list_delete(&(pstaxmitpriv->vi_q.tx_pending)); phwxmit = pxmitpriv->hwxmits+1; phwxmit->accnt -= pstaxmitpriv->vi_q.qcnt; pstaxmitpriv->vi_q.qcnt = 0; //_exit_critical_bh(&(pxmitpriv->vi_pending.lock), &irqL0); //be //_enter_critical_bh(&(pxmitpriv->be_pending.lock), &irqL0); rtw_free_xmitframe_queue( pxmitpriv, &pstaxmitpriv->be_q.sta_pending); rtw_list_delete(&(pstaxmitpriv->be_q.tx_pending)); phwxmit = pxmitpriv->hwxmits+2; phwxmit->accnt -= pstaxmitpriv->be_q.qcnt; pstaxmitpriv->be_q.qcnt = 0; //_exit_critical_bh(&(pxmitpriv->be_pending.lock), &irqL0); //bk //_enter_critical_bh(&(pxmitpriv->bk_pending.lock), &irqL0); rtw_free_xmitframe_queue( pxmitpriv, &pstaxmitpriv->bk_q.sta_pending); rtw_list_delete(&(pstaxmitpriv->bk_q.tx_pending)); phwxmit = pxmitpriv->hwxmits+3; phwxmit->accnt -= pstaxmitpriv->bk_q.qcnt; pstaxmitpriv->bk_q.qcnt = 0; //_exit_critical_bh(&(pxmitpriv->bk_pending.lock), &irqL0); _exit_critical_bh(&pxmitpriv->lock, &irqL0); rtw_list_delete(&psta->hash_list); RT_TRACE(_module_rtl871x_sta_mgt_c_,_drv_err_,("\n free number_%d stainfo with hwaddr = 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x \n",pstapriv->asoc_sta_count , psta->hwaddr[0], psta->hwaddr[1], psta->hwaddr[2],psta->hwaddr[3],psta->hwaddr[4],psta->hwaddr[5])); pstapriv->asoc_sta_count --; // re-init sta_info; 20061114 // will be init in alloc_stainfo //_rtw_init_sta_xmit_priv(&psta->sta_xmitpriv); //_rtw_init_sta_recv_priv(&psta->sta_recvpriv); _cancel_timer_ex(&psta->addba_retry_timer); #ifdef CONFIG_TDLS _cancel_timer_ex(&psta->TPK_timer); _cancel_timer_ex(&psta->option_timer); _cancel_timer_ex(&psta->base_ch_timer); _cancel_timer_ex(&psta->off_ch_timer); _cancel_timer_ex(&psta->alive_timer1); _cancel_timer_ex(&psta->alive_timer2); #endif //CONFIG_TDLS //for A-MPDU Rx reordering buffer control, cancel reordering_ctrl_timer for(i=0; i < 16 ; i++) { _irqL irqL; _list *phead, *plist; union recv_frame *prframe; _queue *ppending_recvframe_queue; _queue *pfree_recv_queue = &padapter->recvpriv.free_recv_queue; preorder_ctrl = &psta->recvreorder_ctrl[i]; _cancel_timer_ex(&preorder_ctrl->reordering_ctrl_timer); ppending_recvframe_queue = &preorder_ctrl->pending_recvframe_queue; _enter_critical_bh(&ppending_recvframe_queue->lock, &irqL); phead = get_list_head(ppending_recvframe_queue); plist = get_next(phead); while(!rtw_is_list_empty(phead)) { prframe = LIST_CONTAINOR(plist, union recv_frame, u); plist = get_next(plist); rtw_list_delete(&(prframe->u.hdr.list)); rtw_free_recvframe(prframe, pfree_recv_queue); } _exit_critical_bh(&ppending_recvframe_queue->lock, &irqL); } if (!(psta->state & WIFI_AP_STATE)) rtw_hal_set_odm_var(padapter, HAL_ODM_STA_INFO, psta, _FALSE); //release mac id for non-bc/mc station, rtw_release_macid(pstapriv->padapter, psta); #ifdef CONFIG_AP_MODE /* _enter_critical_bh(&pstapriv->asoc_list_lock, &irqL0); rtw_list_delete(&psta->asoc_list); _exit_critical_bh(&pstapriv->asoc_list_lock, &irqL0); */ _enter_critical_bh(&pstapriv->auth_list_lock, &irqL0); if (!rtw_is_list_empty(&psta->auth_list)) { rtw_list_delete(&psta->auth_list); pstapriv->auth_list_cnt--; } _exit_critical_bh(&pstapriv->auth_list_lock, &irqL0); psta->expire_to = 0; psta->sleepq_ac_len = 0; psta->qos_info = 0; psta->max_sp_len = 0; psta->uapsd_bk = 0; psta->uapsd_be = 0; psta->uapsd_vi = 0; psta->uapsd_vo = 0; psta->has_legacy_ac = 0; #ifdef CONFIG_NATIVEAP_MLME pstapriv->sta_dz_bitmap &=~BIT(psta->aid); pstapriv->tim_bitmap &=~BIT(psta->aid); //rtw_indicate_sta_disassoc_event(padapter, psta); if ((psta->aid >0)&&(pstapriv->sta_aid[psta->aid - 1] == psta)) { pstapriv->sta_aid[psta->aid - 1] = NULL; psta->aid = 0; } #endif // CONFIG_NATIVEAP_MLME #ifdef CONFIG_TX_MCAST2UNI psta->under_exist_checking = 0; #endif // CONFIG_TX_MCAST2UNI #endif // CONFIG_AP_MODE _rtw_spinlock_free(&psta->lock); //_enter_critical_bh(&(pfree_sta_queue->lock), &irqL0); rtw_list_insert_tail(&psta->list, get_list_head(pfree_sta_queue)); //_exit_critical_bh(&(pfree_sta_queue->lock), &irqL0); exit: _func_exit_; return _SUCCESS; }
u8 rtw_set_802_11_infrastructure_mode(_adapter* padapter, NDIS_802_11_NETWORK_INFRASTRUCTURE networktype) { _irqL irqL; struct mlme_priv *pmlmepriv = &padapter->mlmepriv; struct wlan_network *cur_network = &pmlmepriv->cur_network; NDIS_802_11_NETWORK_INFRASTRUCTURE* pold_state = &(cur_network->network.InfrastructureMode); _func_enter_; RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_notice_, ("+rtw_set_802_11_infrastructure_mode: old=%d new=%d fw_state=0x%08x\n", *pold_state, networktype, get_fwstate(pmlmepriv))); if(*pold_state != networktype) { _enter_critical_bh(&pmlmepriv->lock, &irqL); RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_info_,(" change mode!")); //DBG_871X("change mode, old_mode=%d, new_mode=%d, fw_state=0x%x\n", *pold_state, networktype, get_fwstate(pmlmepriv)); if(*pold_state==Ndis802_11APMode) { //change to other mode from Ndis802_11APMode cur_network->join_res = -1; #ifdef CONFIG_NATIVEAP_MLME stop_ap_mode(padapter); #endif } if((check_fwstate(pmlmepriv, _FW_LINKED)== _TRUE) ||(*pold_state==Ndis802_11IBSS)) rtw_disassoc_cmd(padapter); if((check_fwstate(pmlmepriv, _FW_LINKED)== _TRUE) || (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)== _TRUE) ) rtw_free_assoc_resources(padapter, 1); if((check_fwstate(pmlmepriv, _FW_LINKED)== _TRUE) || (*pold_state==Ndis802_11Infrastructure) ||(*pold_state==Ndis802_11IBSS)) { rtw_indicate_disconnect(padapter); //will clr Linked_state; before this function, we must have chked whether issue dis-assoc_cmd or not } *pold_state = networktype; _clr_fwstate_(pmlmepriv, ~WIFI_NULL_STATE); switch(networktype) { case Ndis802_11IBSS: set_fwstate(pmlmepriv, WIFI_ADHOC_STATE); break; case Ndis802_11Infrastructure: set_fwstate(pmlmepriv, WIFI_STATION_STATE); break; case Ndis802_11APMode: set_fwstate(pmlmepriv, WIFI_AP_STATE); #ifdef CONFIG_NATIVEAP_MLME start_ap_mode(padapter); //rtw_indicate_connect(padapter); #endif break; case Ndis802_11AutoUnknown: case Ndis802_11InfrastructureMax: break; } //SecClearAllKeys(adapter); //RT_TRACE(COMP_OID_SET, DBG_LOUD, ("set_infrastructure: fw_state:%x after changing mode\n", // get_fwstate(pmlmepriv) )); _exit_critical_bh(&pmlmepriv->lock, &irqL); } _func_exit_; return _TRUE; }
/* * Return * _TRUE dump packet directly * _FALSE enqueue packet */ static s32 pre_xmitframe(_adapter *padapter, struct xmit_frame *pxmitframe) { _irqL irqL; s32 res; struct xmit_buf *pxmitbuf = NULL; struct xmit_priv *pxmitpriv = &padapter->xmitpriv; struct pkt_attrib *pattrib = &pxmitframe->attrib; struct mlme_priv *pmlmepriv = &padapter->mlmepriv; #ifdef CONFIG_CONCURRENT_MODE PADAPTER pbuddy_adapter = padapter->pbuddy_adapter; struct mlme_priv *pbuddy_mlmepriv = &(pbuddy_adapter->mlmepriv); #endif // CONFIG_CONCURRENT_MODE _enter_critical_bh(&pxmitpriv->lock, &irqL); if ( (rtw_txframes_sta_ac_pending(padapter, pattrib) > 0) || (check_nic_enough_desc(padapter, pattrib) == _FALSE)) goto enqueue; if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY) == _TRUE) goto enqueue; #ifdef CONFIG_CONCURRENT_MODE if (check_fwstate(pbuddy_mlmepriv, _FW_UNDER_SURVEY|_FW_UNDER_LINKING) == _TRUE) goto enqueue; #endif // CONFIG_CONCURRENT_MODE pxmitbuf = rtw_alloc_xmitbuf(pxmitpriv); if (pxmitbuf == NULL) goto enqueue; _exit_critical_bh(&pxmitpriv->lock, &irqL); pxmitframe->pxmitbuf = pxmitbuf; pxmitframe->buf_addr = pxmitbuf->pbuf; pxmitbuf->priv_data = pxmitframe; if (xmitframe_direct(padapter, pxmitframe) != _SUCCESS) { rtw_free_xmitbuf(pxmitpriv, pxmitbuf); rtw_free_xmitframe_ex(pxmitpriv, pxmitframe); } return _TRUE; enqueue: res = rtw_xmitframe_enqueue(padapter, pxmitframe); _exit_critical_bh(&pxmitpriv->lock, &irqL); if (res != _SUCCESS) { RT_TRACE(_module_xmit_osdep_c_, _drv_err_, ("pre_xmitframe: enqueue xmitframe fail\n")); rtw_free_xmitframe_ex(pxmitpriv, pxmitframe); // Trick, make the statistics correct pxmitpriv->tx_pkts--; pxmitpriv->tx_drop++; return _TRUE; } return _FALSE; }
//struct sta_info *rtw_alloc_stainfo(_queue *pfree_sta_queue, unsigned char *hwaddr) struct sta_info *rtw_alloc_stainfo(struct sta_priv *pstapriv, u8 *hwaddr) { _irqL irqL, irqL2; uint tmp_aid; s32 index; _list *phash_list; struct sta_info *psta; _queue *pfree_sta_queue; struct recv_reorder_ctrl *preorder_ctrl; int i = 0; u16 wRxSeqInitialValue = 0xffff; _func_enter_; pfree_sta_queue = &pstapriv->free_sta_queue; _enter_critical_bh(&(pfree_sta_queue->lock), &irqL); if (_rtw_queue_empty(pfree_sta_queue) == _TRUE) { psta = NULL; } else { psta = LIST_CONTAINOR(get_next(&pfree_sta_queue->queue), struct sta_info, list); rtw_list_delete(&(psta->list)); tmp_aid = psta->aid; _rtw_init_stainfo(psta); _rtw_memcpy(psta->hwaddr, hwaddr, ETH_ALEN); index = wifi_mac_hash(hwaddr); RT_TRACE(_module_rtl871x_sta_mgt_c_,_drv_info_,("rtw_alloc_stainfo: index = %x", index)); if(index >= NUM_STA) { RT_TRACE(_module_rtl871x_sta_mgt_c_,_drv_err_,("ERROR=> rtw_alloc_stainfo: index >= NUM_STA")); psta= NULL; goto exit; } phash_list = &(pstapriv->sta_hash[index]); _enter_critical_bh(&(pstapriv->sta_hash_lock), &irqL2); rtw_list_insert_tail(&psta->hash_list, phash_list); pstapriv->asoc_sta_count ++ ; _exit_critical_bh(&(pstapriv->sta_hash_lock), &irqL2); // Commented by Albert 2009/08/13 // For the SMC router, the sequence number of first packet of WPS handshake will be 0. // In this case, this packet will be dropped by recv_decache function if we use the 0x00 as the default value for tid_rxseq variable. // So, we initialize the tid_rxseq variable as the 0xffff. for( i = 0; i < 16; i++ ) { _rtw_memcpy( &psta->sta_recvpriv.rxcache.tid_rxseq[ i ], &wRxSeqInitialValue, 2 ); } RT_TRACE(_module_rtl871x_sta_mgt_c_,_drv_info_,("alloc number_%d stainfo with hwaddr = %x %x %x %x %x %x \n", pstapriv->asoc_sta_count , hwaddr[0], hwaddr[1], hwaddr[2],hwaddr[3],hwaddr[4],hwaddr[5])); init_addba_retry_timer(pstapriv->padapter, psta); #ifdef CONFIG_TDLS psta->padapter = pstapriv->padapter; init_TPK_timer(pstapriv->padapter, psta); _init_workitem(&psta->option_workitem, TDLS_option_workitem_callback, psta); init_ch_switch_timer(pstapriv->padapter, psta); init_base_ch_timer(pstapriv->padapter, psta); _init_workitem(&psta->base_ch_workitem, base_channel_workitem_callback, psta); init_off_ch_timer(pstapriv->padapter, psta); _init_workitem(&psta->off_ch_workitem, off_channel_workitem_callback, psta); #endif //for A-MPDU Rx reordering buffer control for(i=0; i < 16 ; i++) { preorder_ctrl = &psta->recvreorder_ctrl[i]; preorder_ctrl->padapter = pstapriv->padapter; preorder_ctrl->enable = _FALSE; preorder_ctrl->indicate_seq = 0xffff; #ifdef DBG_RX_SEQ DBG_871X("DBG_RX_SEQ %s:%d IndicateSeq: %d\n", __FUNCTION__, __LINE__, preorder_ctrl->indicate_seq); #endif preorder_ctrl->wend_b= 0xffff; //preorder_ctrl->wsize_b = (NR_RECVBUFF-2); preorder_ctrl->wsize_b = 64;//64; _rtw_init_queue(&preorder_ctrl->pending_recvframe_queue); rtw_init_recv_timer(preorder_ctrl); } } exit: _exit_critical_bh(&(pfree_sta_queue->lock), &irqL); _func_exit_; return psta; }
/* using pstapriv->sta_hash_lock to protect */ u32 rtw_free_stainfo(_adapter *padapter , struct sta_info *psta) { int i; unsigned long irqL0; struct __queue *pfree_sta_queue; struct recv_reorder_ctrl *preorder_ctrl; struct sta_xmit_priv *pstaxmitpriv; struct xmit_priv *pxmitpriv= &padapter->xmitpriv; struct sta_priv *pstapriv = &padapter->stapriv; _func_enter_; if (psta == NULL) goto exit; pfree_sta_queue = &pstapriv->free_sta_queue; pstaxmitpriv = &psta->sta_xmitpriv; _enter_critical_bh(&pxmitpriv->lock, &irqL0); rtw_free_xmitframe_queue(pxmitpriv, &psta->sleep_q); psta->sleepq_len = 0; rtw_free_xmitframe_queue( pxmitpriv, &pstaxmitpriv->vo_q.sta_pending); rtw_list_delete(&(pstaxmitpriv->vo_q.tx_pending)); rtw_free_xmitframe_queue( pxmitpriv, &pstaxmitpriv->vi_q.sta_pending); rtw_list_delete(&(pstaxmitpriv->vi_q.tx_pending)); rtw_free_xmitframe_queue( pxmitpriv, &pstaxmitpriv->bk_q.sta_pending); rtw_list_delete(&(pstaxmitpriv->bk_q.tx_pending)); rtw_free_xmitframe_queue( pxmitpriv, &pstaxmitpriv->be_q.sta_pending); rtw_list_delete(&(pstaxmitpriv->be_q.tx_pending)); _exit_critical_bh(&pxmitpriv->lock, &irqL0); rtw_list_delete(&psta->hash_list); RT_TRACE(_module_rtl871x_sta_mgt_c_,_drv_err_,("\n free number_%d stainfo with hwaddr = 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x\n",pstapriv->asoc_sta_count , psta->hwaddr[0], psta->hwaddr[1], psta->hwaddr[2],psta->hwaddr[3],psta->hwaddr[4],psta->hwaddr[5])); pstapriv->asoc_sta_count --; /* re-init sta_info; 20061114 */ _rtw_init_sta_xmit_priv(&psta->sta_xmitpriv); _rtw_init_sta_recv_priv(&psta->sta_recvpriv); _cancel_timer_ex(&psta->addba_retry_timer); /* for A-MPDU Rx reordering buffer control, cancel reordering_ctrl_timer */ for (i=0; i < 16 ; i++) { unsigned long irqL; struct list_head *phead, *plist; union recv_frame *prframe; struct __queue *ppending_recvframe_queue; struct __queue *pfree_recv_queue = &padapter->recvpriv.free_recv_queue; preorder_ctrl = &psta->recvreorder_ctrl[i]; _cancel_timer_ex(&preorder_ctrl->reordering_ctrl_timer); ppending_recvframe_queue = &preorder_ctrl->pending_recvframe_queue; _enter_critical_bh(&ppending_recvframe_queue->lock, &irqL); phead = get_list_head(ppending_recvframe_queue); plist = get_next(phead); while (!rtw_is_list_empty(phead)) { prframe = LIST_CONTAINOR(plist, union recv_frame, u); plist = get_next(plist); rtw_list_delete(&(prframe->u.hdr.list)); rtw_free_recvframe(prframe, pfree_recv_queue); } _exit_critical_bh(&ppending_recvframe_queue->lock, &irqL); } if (!(psta->state & WIFI_AP_STATE)) rtw_hal_set_odm_var(padapter, HAL_ODM_STA_INFO, psta, false); #ifdef CONFIG_AP_MODE _enter_critical_bh(&pstapriv->auth_list_lock, &irqL0); if (!rtw_is_list_empty(&psta->auth_list)) { rtw_list_delete(&psta->auth_list); pstapriv->auth_list_cnt--; } _exit_critical_bh(&pstapriv->auth_list_lock, &irqL0); psta->expire_to = 0; psta->sleepq_ac_len = 0; psta->qos_info = 0; psta->max_sp_len = 0; psta->uapsd_bk = 0; psta->uapsd_be = 0; psta->uapsd_vi = 0; psta->uapsd_vo = 0; psta->has_legacy_ac = 0; pstapriv->sta_dz_bitmap &=~BIT(psta->aid); pstapriv->tim_bitmap &=~BIT(psta->aid); if ((psta->aid >0)&&(pstapriv->sta_aid[psta->aid - 1] == psta)) { pstapriv->sta_aid[psta->aid - 1] = NULL; psta->aid = 0; } psta->under_exist_checking = 0; #endif /* CONFIG_AP_MODE */ _enter_critical_bh(&(pfree_sta_queue->lock), &irqL0); rtw_list_insert_tail(&psta->list, get_list_head(pfree_sta_queue)); _exit_critical_bh(&(pfree_sta_queue->lock), &irqL0); exit: _func_exit_; return _SUCCESS; }
// using pstapriv->sta_hash_lock to protect u32 rtw_free_stainfo(_adapter *padapter , struct sta_info *psta) { int i; _irqL irqL0; _queue *pfree_sta_queue; struct recv_reorder_ctrl *preorder_ctrl; struct sta_xmit_priv *pstaxmitpriv; struct xmit_priv *pxmitpriv= &padapter->xmitpriv; struct sta_priv *pstapriv = &padapter->stapriv; _func_enter_; if (psta == NULL) goto exit; pfree_sta_queue = &pstapriv->free_sta_queue; pstaxmitpriv = &psta->sta_xmitpriv; //rtw_list_delete(&psta->sleep_list); //rtw_list_delete(&psta->wakeup_list); rtw_free_xmitframe_queue(pxmitpriv, &psta->sleep_q); psta->sleepq_len = 0; _enter_critical_bh(&(pxmitpriv->vo_pending.lock), &irqL0); rtw_free_xmitframe_queue( pxmitpriv, &pstaxmitpriv->vo_q.sta_pending); rtw_list_delete(&(pstaxmitpriv->vo_q.tx_pending)); _exit_critical_bh(&(pxmitpriv->vo_pending.lock), &irqL0); _enter_critical_bh(&(pxmitpriv->vi_pending.lock), &irqL0); rtw_free_xmitframe_queue( pxmitpriv, &pstaxmitpriv->vi_q.sta_pending); rtw_list_delete(&(pstaxmitpriv->vi_q.tx_pending)); _exit_critical_bh(&(pxmitpriv->vi_pending.lock), &irqL0); _enter_critical_bh(&(pxmitpriv->bk_pending.lock), &irqL0); rtw_free_xmitframe_queue( pxmitpriv, &pstaxmitpriv->bk_q.sta_pending); rtw_list_delete(&(pstaxmitpriv->bk_q.tx_pending)); _exit_critical_bh(&(pxmitpriv->bk_pending.lock), &irqL0); _enter_critical_bh(&(pxmitpriv->be_pending.lock), &irqL0); rtw_free_xmitframe_queue( pxmitpriv, &pstaxmitpriv->be_q.sta_pending); rtw_list_delete(&(pstaxmitpriv->be_q.tx_pending)); _exit_critical_bh(&(pxmitpriv->be_pending.lock), &irqL0); rtw_list_delete(&psta->hash_list); RT_TRACE(_module_rtl871x_sta_mgt_c_,_drv_err_,("\n free number_%d stainfo with hwaddr = 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x \n",pstapriv->asoc_sta_count , psta->hwaddr[0], psta->hwaddr[1], psta->hwaddr[2],psta->hwaddr[3],psta->hwaddr[4],psta->hwaddr[5])); pstapriv->asoc_sta_count --; // re-init sta_info; 20061114 _rtw_init_sta_xmit_priv(&psta->sta_xmitpriv); _rtw_init_sta_recv_priv(&psta->sta_recvpriv); _cancel_timer_ex(&psta->addba_retry_timer); #ifdef CONFIG_TDLS _cancel_timer_ex(&psta->TPK_timer); _cancel_timer_ex(&psta->option_timer); _cancel_timer_ex(&psta->base_ch_timer); _cancel_timer_ex(&psta->off_ch_timer); #endif //for A-MPDU Rx reordering buffer control, cancel reordering_ctrl_timer for(i=0; i < 16 ; i++) { preorder_ctrl = &psta->recvreorder_ctrl[i]; _cancel_timer_ex(&preorder_ctrl->reordering_ctrl_timer); } #ifdef CONFIG_AP_MODE rtw_list_delete(&psta->asoc_list); rtw_list_delete(&psta->auth_list); psta->expire_to = 0; psta->sleepq_ac_len = 0; psta->qos_info = 0; psta->max_sp_len = 0; psta->uapsd_bk = 0; psta->uapsd_be = 0; psta->uapsd_vi = 0; psta->uapsd_vo = 0; psta->has_legacy_ac = 0; #ifdef CONFIG_NATIVEAP_MLME pstapriv->sta_dz_bitmap &=~BIT(psta->aid); pstapriv->tim_bitmap &=~BIT(psta->aid); rtw_indicate_sta_disassoc_event(padapter, psta); if (pstapriv->sta_aid[psta->aid - 1] == psta) { pstapriv->sta_aid[psta->aid - 1] = NULL; psta->aid = 0; } #endif #endif _enter_critical_bh(&(pfree_sta_queue->lock), &irqL0); rtw_list_insert_tail(&psta->list, get_list_head(pfree_sta_queue)); _exit_critical_bh(&(pfree_sta_queue->lock), &irqL0); exit: _func_exit_; return _SUCCESS; }
int nat25_handle_frame(_adapter *priv, struct sk_buff *skb) { #ifdef BR_EXT_DEBUG if ((!priv->ethBrExtInfo.nat25_disable) && (!(skb->data[0] & 1))) { panic_printk("NAT25: Input Frame: DA=%02x%02x%02x%02x%02x%02x SA=%02x%02x%02x%02x%02x%02x\n", skb->data[0], skb->data[1], skb->data[2], skb->data[3], skb->data[4], skb->data[5], skb->data[6], skb->data[7], skb->data[8], skb->data[9], skb->data[10], skb->data[11]); } #endif if (!(skb->data[0] & 1)) { int is_vlan_tag=0, i, retval=0; unsigned short vlan_hdr=0; unsigned short protocol; protocol = be16_to_cpu(*((__be16 *)(skb->data + 2 * ETH_ALEN))); if (protocol == ETH_P_8021Q) { is_vlan_tag = 1; vlan_hdr = *((unsigned short *)(skb->data+ETH_ALEN*2+2)); for (i=0; i<6; i++) *((unsigned short *)(skb->data+ETH_ALEN*2+2-i*2)) = *((unsigned short *)(skb->data+ETH_ALEN*2-2-i*2)); skb_pull(skb, 4); } if (!priv->ethBrExtInfo.nat25_disable) { _irqL irqL; _enter_critical_bh(&priv->br_ext_lock, &irqL); /* * This function look up the destination network address from * the NAT2.5 database. Return value = -1 means that the * corresponding network protocol is NOT support. */ if (!priv->ethBrExtInfo.nat25sc_disable && (be16_to_cpu(*((__be16 *)(skb->data+ETH_ALEN*2))) == ETH_P_IP) && !memcmp(priv->scdb_ip, skb->data+ETH_HLEN+16, 4)) { memcpy(skb->data, priv->scdb_mac, ETH_ALEN); _exit_critical_bh(&priv->br_ext_lock, &irqL); } else { _exit_critical_bh(&priv->br_ext_lock, &irqL); retval = nat25_db_handle(priv, skb, NAT25_LOOKUP); } } else { if (((be16_to_cpu(*((__be16 *)(skb->data+ETH_ALEN*2))) == ETH_P_IP) && !memcmp(priv->br_ip, skb->data+ETH_HLEN+16, 4)) || ((be16_to_cpu(*((__be16 *)(skb->data+ETH_ALEN*2))) == ETH_P_ARP) && !memcmp(priv->br_ip, skb->data+ETH_HLEN+24, 4))) { /* for traffic to upper TCP/IP */ retval = nat25_db_handle(priv, skb, NAT25_LOOKUP); } } if (is_vlan_tag) { skb_push(skb, 4); for (i=0; i<6; i++) *((unsigned short *)(skb->data+i*2)) = *((unsigned short *)(skb->data+4+i*2)); *((__be16 *)(skb->data+ETH_ALEN*2)) = __constant_htons(ETH_P_8021Q); *((unsigned short *)(skb->data+ETH_ALEN*2+2)) = vlan_hdr; } if (retval == -1) { /* DEBUG_ERR("NAT25: Lookup fail!\n"); */ return -1; } } return 0; }
u8 rtw_set_802_11_bssid(_adapter* padapter, u8 *bssid) { _irqL irqL; u8 status=_SUCCESS; u32 cur_time = 0; struct mlme_priv *pmlmepriv = &padapter->mlmepriv; _func_enter_; RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_notice_, ("+rtw_set_802_11_bssid: bssid="MAC_FMT"\n", MAC_ARG(bssid) )); if ((bssid[0]==0x00 && bssid[1]==0x00 && bssid[2]==0x00 && bssid[3]==0x00 && bssid[4]==0x00 &&bssid[5]==0x00) || (bssid[0]==0xFF && bssid[1]==0xFF && bssid[2]==0xFF && bssid[3]==0xFF && bssid[4]==0xFF &&bssid[5]==0xFF)) { status = _FAIL; goto exit; } _enter_critical_bh(&pmlmepriv->lock, &irqL); DBG_871X("Set BSSID under fw_state=0x%08x\n", get_fwstate(pmlmepriv)); if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY) == _TRUE) { goto handle_tkip_countermeasure; } else if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING) == _TRUE) { goto release_mlme_lock; } if (check_fwstate(pmlmepriv, _FW_LINKED|WIFI_ADHOC_MASTER_STATE) == _TRUE) { RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_, ("set_bssid: _FW_LINKED||WIFI_ADHOC_MASTER_STATE\n")); if (_rtw_memcmp(&pmlmepriv->cur_network.network.MacAddress, bssid, ETH_ALEN) == _TRUE) { if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) == _FALSE) goto release_mlme_lock;//it means driver is in WIFI_ADHOC_MASTER_STATE, we needn't create bss again. } else { RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_info_,("Set BSSID not the same bssid\n")); RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_info_,("set_bssid="MAC_FMT"\n", MAC_ARG(bssid) )); RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_info_,("cur_bssid="MAC_FMT"\n", MAC_ARG(pmlmepriv->cur_network.network.MacAddress) )); rtw_disassoc_cmd(padapter, 0, _TRUE); if (check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE) rtw_indicate_disconnect(padapter); rtw_free_assoc_resources(padapter, 1); if ((check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == _TRUE)) { _clr_fwstate_(pmlmepriv, WIFI_ADHOC_MASTER_STATE); set_fwstate(pmlmepriv, WIFI_ADHOC_STATE); } } } handle_tkip_countermeasure: if (rtw_handle_tkip_countermeasure(padapter, __func__) == _FAIL) { status = _FAIL; goto release_mlme_lock; } _rtw_memcpy(&pmlmepriv->assoc_bssid, bssid, ETH_ALEN); pmlmepriv->assoc_by_bssid=_TRUE; if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY) == _TRUE) { pmlmepriv->to_join = _TRUE; } else { status = rtw_do_join(padapter); } release_mlme_lock: _exit_critical_bh(&pmlmepriv->lock, &irqL); exit: RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, ("rtw_set_802_11_bssid: status=%d\n", status)); _func_exit_; return status; }
s32 rtl8812au_xmitframe_complete(_adapter *padapter, struct xmit_priv *pxmitpriv, struct xmit_buf *pxmitbuf) { HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter); struct xmit_frame *pxmitframe = NULL; struct xmit_frame *pfirstframe = NULL; // aggregate variable struct hw_xmit *phwxmit; struct sta_info *psta = NULL; struct tx_servq *ptxservq = NULL; _irqL irqL; _list *xmitframe_plist = NULL, *xmitframe_phead = NULL; u32 pbuf; // next pkt address u32 pbuf_tail; // last pkt tail u32 len; // packet length, except TXDESC_SIZE and PKT_OFFSET u32 bulkSize = pHalData->UsbBulkOutSize; u8 descCount; u32 bulkPtr; // dump frame variable u32 ff_hwaddr; #ifndef IDEA_CONDITION int res = _SUCCESS; #endif RT_TRACE(_module_rtl8192c_xmit_c_, _drv_info_, ("+xmitframe_complete\n")); // check xmitbuffer is ok if (pxmitbuf == NULL) { pxmitbuf = rtw_alloc_xmitbuf(pxmitpriv); if (pxmitbuf == NULL){ //DBG_871X("%s #1, connot alloc xmitbuf!!!! \n",__FUNCTION__); return _FALSE; } } //DBG_8192C("%s ===================================== \n",__FUNCTION__); //3 1. pick up first frame do { rtw_free_xmitframe(pxmitpriv, pxmitframe); pxmitframe = rtw_dequeue_xframe(pxmitpriv, pxmitpriv->hwxmits, pxmitpriv->hwxmit_entry); if (pxmitframe == NULL) { // no more xmit frame, release xmit buffer //DBG_8192C("no more xmit frame ,return\n"); rtw_free_xmitbuf(pxmitpriv, pxmitbuf); return _FALSE; } #ifndef IDEA_CONDITION if (pxmitframe->frame_tag != DATA_FRAMETAG) { RT_TRACE(_module_rtl8192c_xmit_c_, _drv_err_, ("xmitframe_complete: frame tag(%d) is not DATA_FRAMETAG(%d)!\n", pxmitframe->frame_tag, DATA_FRAMETAG)); // rtw_free_xmitframe(pxmitpriv, pxmitframe); continue; } // TID 0~15 if ((pxmitframe->attrib.priority < 0) || (pxmitframe->attrib.priority > 15)) { RT_TRACE(_module_rtl8192c_xmit_c_, _drv_err_, ("xmitframe_complete: TID(%d) should be 0~15!\n", pxmitframe->attrib.priority)); // rtw_free_xmitframe(pxmitpriv, pxmitframe); continue; } #endif //DBG_8192C("==> pxmitframe->attrib.priority:%d\n",pxmitframe->attrib.priority); pxmitframe->pxmitbuf = pxmitbuf; pxmitframe->buf_addr = pxmitbuf->pbuf; pxmitbuf->priv_data = pxmitframe; pxmitframe->agg_num = 1; // alloc xmitframe should assign to 1. #ifdef CONFIG_TX_EARLY_MODE pxmitframe->pkt_offset = (PACKET_OFFSET_SZ/8)+1; // 2; // first frame of aggregation, reserve one offset for EM info ,another for usb bulk-out block check #else pxmitframe->pkt_offset = (PACKET_OFFSET_SZ/8); // 1; // first frame of aggregation, reserve offset #endif if (rtw_xmitframe_coalesce(padapter, pxmitframe->pkt, pxmitframe) == _FALSE) { DBG_871X("%s coalesce 1st xmitframe failed \n",__FUNCTION__); continue; } // always return ndis_packet after rtw_xmitframe_coalesce rtw_os_xmit_complete(padapter, pxmitframe); break; } while (1); //3 2. aggregate same priority and same DA(AP or STA) frames pfirstframe = pxmitframe; len = xmitframe_need_length(pfirstframe) + TXDESC_SIZE+(pfirstframe->pkt_offset*PACKET_OFFSET_SZ); pbuf_tail = len; pbuf = _RND8(pbuf_tail); // check pkt amount in one bulk descCount = 0; bulkPtr = bulkSize; if (pbuf < bulkPtr) descCount++; if (descCount == pHalData->UsbTxAggDescNum) goto agg_end; else { descCount = 0; bulkPtr = ((pbuf / bulkSize) + 1) * bulkSize; // round to next bulkSize } // dequeue same priority packet from station tx queue psta = pfirstframe->attrib.psta; switch (pfirstframe->attrib.priority) { case 1: case 2: ptxservq = &(psta->sta_xmitpriv.bk_q); phwxmit = pxmitpriv->hwxmits + 3; break; case 4: case 5: ptxservq = &(psta->sta_xmitpriv.vi_q); phwxmit = pxmitpriv->hwxmits + 1; break; case 6: case 7: ptxservq = &(psta->sta_xmitpriv.vo_q); phwxmit = pxmitpriv->hwxmits; break; case 0: case 3: default: ptxservq = &(psta->sta_xmitpriv.be_q); phwxmit = pxmitpriv->hwxmits + 2; break; } //DBG_8192C("==> pkt_no=%d,pkt_len=%d,len=%d,RND8_LEN=%d,pkt_offset=0x%02x\n", //pxmitframe->agg_num,pxmitframe->attrib.last_txcmdsz,len,pbuf,pxmitframe->pkt_offset ); _enter_critical_bh(&pxmitpriv->lock, &irqL); xmitframe_phead = get_list_head(&ptxservq->sta_pending); xmitframe_plist = get_next(xmitframe_phead); while (rtw_end_of_queue_search(xmitframe_phead, xmitframe_plist) == _FALSE) { pxmitframe = LIST_CONTAINOR(xmitframe_plist, struct xmit_frame, list); xmitframe_plist = get_next(xmitframe_plist); if(_FAIL == rtw_hal_busagg_qsel_check(padapter,pfirstframe->attrib.qsel,pxmitframe->attrib.qsel)) break; pxmitframe->agg_num = 0; // not first frame of aggregation #ifdef CONFIG_TX_EARLY_MODE pxmitframe->pkt_offset = 1;// not first frame of aggregation,reserve offset for EM Info #else pxmitframe->pkt_offset = 0; // not first frame of aggregation, no need to reserve offset #endif len = xmitframe_need_length(pxmitframe) + TXDESC_SIZE +(pxmitframe->pkt_offset*PACKET_OFFSET_SZ); if (_RND8(pbuf + len) > MAX_XMITBUF_SZ) //if (_RND8(pbuf + len) > (MAX_XMITBUF_SZ/2))//to do : for TX TP finial tune , Georgia 2012-0323 { //DBG_8192C("%s....len> MAX_XMITBUF_SZ\n",__FUNCTION__); pxmitframe->agg_num = 1; pxmitframe->pkt_offset = 1; break; } rtw_list_delete(&pxmitframe->list); ptxservq->qcnt--; phwxmit->accnt--; #ifndef IDEA_CONDITION // suppose only data frames would be in queue if (pxmitframe->frame_tag != DATA_FRAMETAG) { RT_TRACE(_module_rtl8192c_xmit_c_, _drv_err_, ("xmitframe_complete: frame tag(%d) is not DATA_FRAMETAG(%d)!\n", pxmitframe->frame_tag, DATA_FRAMETAG)); rtw_free_xmitframe(pxmitpriv, pxmitframe); continue; } // TID 0~15 if ((pxmitframe->attrib.priority < 0) || (pxmitframe->attrib.priority > 15)) { RT_TRACE(_module_rtl8192c_xmit_c_, _drv_err_, ("xmitframe_complete: TID(%d) should be 0~15!\n", pxmitframe->attrib.priority)); rtw_free_xmitframe(pxmitpriv, pxmitframe); continue; } #endif // pxmitframe->pxmitbuf = pxmitbuf; pxmitframe->buf_addr = pxmitbuf->pbuf + pbuf; if (rtw_xmitframe_coalesce(padapter, pxmitframe->pkt, pxmitframe) == _FALSE) { DBG_871X("%s coalesce failed \n",__FUNCTION__); rtw_free_xmitframe(pxmitpriv, pxmitframe); continue; } //DBG_8192C("==> pxmitframe->attrib.priority:%d\n",pxmitframe->attrib.priority); // always return ndis_packet after rtw_xmitframe_coalesce rtw_os_xmit_complete(padapter, pxmitframe); // (len - TXDESC_SIZE) == pxmitframe->attrib.last_txcmdsz update_txdesc(pxmitframe, pxmitframe->buf_addr, pxmitframe->attrib.last_txcmdsz,_TRUE); // don't need xmitframe any more rtw_free_xmitframe(pxmitpriv, pxmitframe); // handle pointer and stop condition pbuf_tail = pbuf + len; pbuf = _RND8(pbuf_tail); pfirstframe->agg_num++; #ifdef CONFIG_TX_EARLY_MODE pxmitpriv->agg_pkt[pfirstframe->agg_num-1].offset = _RND8(len); pxmitpriv->agg_pkt[pfirstframe->agg_num-1].pkt_len = pxmitframe->attrib.last_txcmdsz; #endif if (MAX_TX_AGG_PACKET_NUMBER == pfirstframe->agg_num) break; if (pbuf < bulkPtr) { descCount++; if (descCount == pHalData->UsbTxAggDescNum) break; } else { descCount = 0; bulkPtr = ((pbuf / bulkSize) + 1) * bulkSize; } }//end while( aggregate same priority and same DA(AP or STA) frames) if (_rtw_queue_empty(&ptxservq->sta_pending) == _TRUE) rtw_list_delete(&ptxservq->tx_pending); _exit_critical_bh(&pxmitpriv->lock, &irqL); agg_end: #ifdef CONFIG_80211N_HT if ((pfirstframe->attrib.ether_type != 0x0806) && (pfirstframe->attrib.ether_type != 0x888e) && (pfirstframe->attrib.ether_type != 0x88b4) && (pfirstframe->attrib.dhcp_pkt != 1)) { rtw_issue_addbareq_cmd(padapter, pfirstframe); } #endif //CONFIG_80211N_HT #ifndef CONFIG_USE_USB_BUFFER_ALLOC_TX //3 3. update first frame txdesc if ((PACKET_OFFSET_SZ != 0) && ((pbuf_tail % bulkSize) == 0)) { // remove pkt_offset pbuf_tail -= PACKET_OFFSET_SZ; pfirstframe->buf_addr += PACKET_OFFSET_SZ; pfirstframe->pkt_offset--; //DBG_8192C("$$$$$ buf size equal to USB block size $$$$$$\n"); } #endif // CONFIG_USE_USB_BUFFER_ALLOC_TX update_txdesc(pfirstframe, pfirstframe->buf_addr, pfirstframe->attrib.last_txcmdsz,_TRUE); #ifdef CONFIG_TX_EARLY_MODE //prepare EM info for first frame, agg_num value start from 1 pxmitpriv->agg_pkt[0].offset = _RND8(pfirstframe->attrib.last_txcmdsz +TXDESC_SIZE +(pfirstframe->pkt_offset*PACKET_OFFSET_SZ)); pxmitpriv->agg_pkt[0].pkt_len = pfirstframe->attrib.last_txcmdsz;//get from rtw_xmitframe_coalesce UpdateEarlyModeInfo8812(pxmitpriv,pxmitbuf ); #endif //3 4. write xmit buffer to USB FIFO ff_hwaddr = rtw_get_ff_hwaddr(pfirstframe); //DBG_8192C("%s ===================================== write port,buf_size(%d) \n",__FUNCTION__,pbuf_tail); // xmit address == ((xmit_frame*)pxmitbuf->priv_data)->buf_addr rtw_write_port(padapter, ff_hwaddr, pbuf_tail, (u8*)pxmitbuf); //3 5. update statisitc pbuf_tail -= (pfirstframe->agg_num * TXDESC_SIZE); pbuf_tail -= (pfirstframe->pkt_offset * PACKET_OFFSET_SZ); rtw_count_tx_stats(padapter, pfirstframe, pbuf_tail); rtw_free_xmitframe(pxmitpriv, pfirstframe); return _TRUE; }
u8 rtw_set_802_11_ssid(_adapter* padapter, NDIS_802_11_SSID *ssid) { _irqL irqL; u8 status = _SUCCESS; u32 cur_time = 0; struct mlme_priv *pmlmepriv = &padapter->mlmepriv; struct wlan_network *pnetwork = &pmlmepriv->cur_network; _func_enter_; RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_notice_, ("+rtw_set_802_11_ssid: ssid=[%s] fw_state=0x%08x\n", ssid->Ssid, get_fwstate(pmlmepriv))); if(padapter->hw_init_completed==_FALSE){ RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, ("set_ssid: hw_init_completed==_FALSE=>exit!!!\n")); status = _FAIL; goto exit; } _enter_critical_bh(&pmlmepriv->lock, &irqL); DBG_871X("Set SSID under fw_state=0x%08x\n", get_fwstate(pmlmepriv)); if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY) == _TRUE) { goto handle_tkip_countermeasure; } else if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING) == _TRUE) { goto release_mlme_lock; } if (check_fwstate(pmlmepriv, _FW_LINKED|WIFI_ADHOC_MASTER_STATE) == _TRUE) { RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_, ("set_ssid: _FW_LINKED||WIFI_ADHOC_MASTER_STATE\n")); if ((pmlmepriv->assoc_ssid.SsidLength == ssid->SsidLength) && (_rtw_memcmp(&pmlmepriv->assoc_ssid.Ssid, ssid->Ssid, ssid->SsidLength) == _TRUE)) { if((check_fwstate(pmlmepriv, WIFI_STATION_STATE) == _FALSE)) { RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, ("Set SSID is the same ssid, fw_state=0x%08x\n", get_fwstate(pmlmepriv))); if(rtw_is_same_ibss(padapter, pnetwork) == _FALSE) { //if in WIFI_ADHOC_MASTER_STATE | WIFI_ADHOC_STATE, create bss or rejoin again rtw_disassoc_cmd(padapter, 0, _TRUE); if (check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE) rtw_indicate_disconnect(padapter); rtw_free_assoc_resources(padapter, 1); if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == _TRUE) { _clr_fwstate_(pmlmepriv, WIFI_ADHOC_MASTER_STATE); set_fwstate(pmlmepriv, WIFI_ADHOC_STATE); } } else { goto release_mlme_lock;//it means driver is in WIFI_ADHOC_MASTER_STATE, we needn't create bss again. } } #ifdef CONFIG_LPS else { rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_JOINBSS, 1); } #endif } else { RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_info_,("Set SSID not the same ssid\n")); RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_info_,("set_ssid=[%s] len=0x%x\n", ssid->Ssid, (unsigned int)ssid->SsidLength)); RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_info_,("assoc_ssid=[%s] len=0x%x\n", pmlmepriv->assoc_ssid.Ssid, (unsigned int)pmlmepriv->assoc_ssid.SsidLength)); rtw_disassoc_cmd(padapter, 0, _TRUE); if (check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE) rtw_indicate_disconnect(padapter); rtw_free_assoc_resources(padapter, 1); if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == _TRUE) { _clr_fwstate_(pmlmepriv, WIFI_ADHOC_MASTER_STATE); set_fwstate(pmlmepriv, WIFI_ADHOC_STATE); } } } handle_tkip_countermeasure: if (rtw_handle_tkip_countermeasure(padapter, __func__) == _FAIL) { status = _FAIL; goto release_mlme_lock; } if (rtw_validate_ssid(ssid) == _FALSE) { status = _FAIL; goto release_mlme_lock; } _rtw_memcpy(&pmlmepriv->assoc_ssid, ssid, sizeof(NDIS_802_11_SSID)); pmlmepriv->assoc_by_bssid=_FALSE; if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY) == _TRUE) { pmlmepriv->to_join = _TRUE; } else { status = rtw_do_join(padapter); } release_mlme_lock: _exit_critical_bh(&pmlmepriv->lock, &irqL); exit: RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, ("-rtw_set_802_11_ssid: status=%d\n", status)); _func_exit_; return status; }
int proc_get_all_sta_info(char *page, char **start, off_t offset, int count, int *eof, void *data) { _irqL irqL; struct sta_info *psta; struct net_device *dev = data; _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); struct sta_priv *pstapriv = &padapter->stapriv; int i, j; _list *plist, *phead; struct recv_reorder_ctrl *preorder_ctrl; int len = 0; len += snprintf(page + len, count - len, "sta_dz_bitmap=0x%x, tim_bitmap=0x%x\n", pstapriv->sta_dz_bitmap, pstapriv->tim_bitmap); _enter_critical_bh(&pstapriv->sta_hash_lock, &irqL); for(i=0; i< NUM_STA; i++) { phead = &(pstapriv->sta_hash[i]); plist = get_next(phead); while ((rtw_end_of_queue_search(phead, plist)) == _FALSE) { psta = LIST_CONTAINOR(plist, struct sta_info, hash_list); plist = get_next(plist); //if(extra_arg == psta->aid) { len += snprintf(page + len, count - len, "sta's macaddr:" MAC_FMT "\n", MAC_ARG(psta->hwaddr)); len += snprintf(page + len, count - len, "rtsen=%d, cts2slef=%d\n", psta->rtsen, psta->cts2self); len += snprintf(page + len, count - len, "state=0x%x, aid=%d, macid=%d, raid=%d\n", psta->state, psta->aid, psta->mac_id, psta->raid); #ifdef CONFIG_80211N_HT len += snprintf(page + len, count - len, "qos_en=%d, ht_en=%d, init_rate=%d\n", psta->qos_option, psta->htpriv.ht_option, psta->init_rate); len += snprintf(page + len, count - len, "bwmode=%d, ch_offset=%d, sgi=%d\n", psta->htpriv.bwmode, psta->htpriv.ch_offset, psta->htpriv.sgi); len += snprintf(page + len, count - len, "ampdu_enable = %d\n", psta->htpriv.ampdu_enable); len += snprintf(page + len, count - len, "agg_enable_bitmap=%x, candidate_tid_bitmap=%x\n", psta->htpriv.agg_enable_bitmap, psta->htpriv.candidate_tid_bitmap); #endif //CONFIG_80211N_HT len += snprintf(page + len, count - len, "sleepq_len=%d\n", psta->sleepq_len); len += snprintf(page + len, count - len, "capability=0x%x\n", psta->capability); len += snprintf(page + len, count - len, "flags=0x%x\n", psta->flags); len += snprintf(page + len, count - len, "wpa_psk=0x%x\n", psta->wpa_psk); len += snprintf(page + len, count - len, "wpa2_group_cipher=0x%x\n", psta->wpa2_group_cipher); len += snprintf(page + len, count - len, "wpa2_pairwise_cipher=0x%x\n", psta->wpa2_pairwise_cipher); len += snprintf(page + len, count - len, "qos_info=0x%x\n", psta->qos_info); len += snprintf(page + len, count - len, "dot118021XPrivacy=0x%x\n", psta->dot118021XPrivacy); for(j=0;j<16;j++) { preorder_ctrl = &psta->recvreorder_ctrl[j]; if(preorder_ctrl->enable) { len += snprintf(page + len, count - len, "tid=%d, indicate_seq=%d\n", j, preorder_ctrl->indicate_seq); } } } } } _exit_critical_bh(&pstapriv->sta_hash_lock, &irqL); *eof = 1; return len; }
u8 rtw_set_802_11_connect(_adapter* padapter, const u8 *bssid, NDIS_802_11_SSID *ssid) { _irqL irqL; u8 status = _SUCCESS; u32 cur_time = 0; bool bssid_valid = _TRUE; bool ssid_valid = _TRUE; struct mlme_priv *pmlmepriv = &padapter->mlmepriv; _func_enter_; if (!ssid || rtw_validate_ssid(ssid) == _FALSE) ssid_valid = _FALSE; if (!bssid || rtw_validate_bssid(bssid) == _FALSE) bssid_valid = _FALSE; if (ssid_valid == _FALSE && bssid_valid == _FALSE) { DBG_871X(FUNC_ADPT_FMT" ssid:%p, ssid_valid:%d, bssid:%p, bssid_valid:%d\n", FUNC_ADPT_ARG(padapter), ssid, ssid_valid, bssid, bssid_valid); status = _FAIL; goto exit; } if(padapter->hw_init_completed==_FALSE){ RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, ("set_ssid: hw_init_completed==_FALSE=>exit!!!\n")); status = _FAIL; goto exit; } _enter_critical_bh(&pmlmepriv->lock, &irqL); LOG_LEVEL(_drv_info_, FUNC_ADPT_FMT" fw_state=0x%08x\n", FUNC_ADPT_ARG(padapter), get_fwstate(pmlmepriv)); if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY) == _TRUE) { goto handle_tkip_countermeasure; } else if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING) == _TRUE) { goto release_mlme_lock; } handle_tkip_countermeasure: if (rtw_handle_tkip_countermeasure(padapter, __func__) == _FAIL) { status = _FAIL; goto release_mlme_lock; } if (ssid && ssid_valid) _rtw_memcpy(&pmlmepriv->assoc_ssid, ssid, sizeof(NDIS_802_11_SSID)); if (bssid && bssid_valid) { _rtw_memcpy(&pmlmepriv->assoc_bssid, bssid, ETH_ALEN); pmlmepriv->assoc_by_bssid = _TRUE; } if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY) == _TRUE) { pmlmepriv->to_join = _TRUE; } else { status = rtw_do_join(padapter); } release_mlme_lock: _exit_critical_bh(&pmlmepriv->lock, &irqL); exit: _func_exit_; return status; }
int rtw_mlcst2unicst(_adapter *padapter, struct sk_buff *skb) { struct sta_priv *pstapriv = &padapter->stapriv; struct xmit_priv *pxmitpriv = &padapter->xmitpriv; _irqL irqL; _list *phead, *plist; struct sk_buff *newskb; struct sta_info *psta = NULL; u8 chk_alive_num = 0; char chk_alive_list[NUM_STA]; u8 bc_addr[6]={0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; u8 null_addr[6]={0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; int i; s32 res; DBG_COUNTER(padapter->tx_logs.os_tx_m2u); _enter_critical_bh(&pstapriv->asoc_list_lock, &irqL); phead = &pstapriv->asoc_list; plist = get_next(phead); //free sta asoc_queue while ((rtw_end_of_queue_search(phead, plist)) == _FALSE) { int stainfo_offset; psta = LIST_CONTAINOR(plist, struct sta_info, asoc_list); plist = get_next(plist); stainfo_offset = rtw_stainfo_offset(pstapriv, psta); if (stainfo_offset_valid(stainfo_offset)) { chk_alive_list[chk_alive_num++] = stainfo_offset; } } _exit_critical_bh(&pstapriv->asoc_list_lock, &irqL); for (i = 0; i < chk_alive_num; i++) { psta = rtw_get_stainfo_by_offset(pstapriv, chk_alive_list[i]); if(!(psta->state &_FW_LINKED)) { DBG_COUNTER(padapter->tx_logs.os_tx_m2u_ignore_fw_linked); continue; } /* avoid come from STA1 and send back STA1 */ if (_rtw_memcmp(psta->hwaddr, &skb->data[6], 6) == _TRUE || _rtw_memcmp(psta->hwaddr, null_addr, 6) == _TRUE || _rtw_memcmp(psta->hwaddr, bc_addr, 6) == _TRUE ) { DBG_COUNTER(padapter->tx_logs.os_tx_m2u_ignore_self); continue; } DBG_COUNTER(padapter->tx_logs.os_tx_m2u_entry); newskb = rtw_skb_copy(skb); if (newskb) { _rtw_memcpy(newskb->data, psta->hwaddr, 6); res = rtw_xmit(padapter, &newskb); if (res < 0) { DBG_COUNTER(padapter->tx_logs.os_tx_m2u_entry_err_xmit); DBG_871X("%s()-%d: rtw_xmit() return error! res=%d\n", __FUNCTION__, __LINE__, res); pxmitpriv->tx_drop++; rtw_skb_free(newskb); } } else { DBG_COUNTER(padapter->tx_logs.os_tx_m2u_entry_err_skb); DBG_871X("%s-%d: rtw_skb_copy() failed!\n", __FUNCTION__, __LINE__); pxmitpriv->tx_drop++; //rtw_skb_free(skb); return _FALSE; // Caller shall tx this multicast frame via normal way. } } rtw_skb_free(skb); return _TRUE; }
u8 rtw_do_join(_adapter * padapter) { _irqL irqL; _list *plist, *phead; u8* pibss = NULL; struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); _queue *queue = &(pmlmepriv->scanned_queue); u8 ret=_SUCCESS; _func_enter_; _enter_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL); phead = get_list_head(queue); plist = get_next(phead); RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_info_,("\n rtw_do_join: phead = %p; plist = %p \n\n\n", phead, plist)); pmlmepriv->cur_network.join_res = -2; set_fwstate(pmlmepriv, _FW_UNDER_LINKING); pmlmepriv->pscanned = plist; pmlmepriv->to_join = _TRUE; if(_rtw_queue_empty(queue)== _TRUE) { _exit_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL); _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING); //when set_ssid/set_bssid for rtw_do_join(), but scanning queue is empty //we try to issue sitesurvey firstly if (pmlmepriv->LinkDetectInfo.bBusyTraffic ==_FALSE || rtw_to_roaming(padapter) > 0 ) { RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_info_,("rtw_do_join(): site survey if scanned_queue is empty\n.")); // submit site_survey_cmd if(_SUCCESS!=(ret=rtw_sitesurvey_cmd(padapter, &pmlmepriv->assoc_ssid, 1, NULL, 0)) ) { RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_err_,("rtw_do_join(): site survey return error\n.")); } } goto exit; } else { int select_ret; _exit_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL); if((select_ret=rtw_select_and_join_from_scanned_queue(pmlmepriv))==_SUCCESS) { pmlmepriv->to_join = _FALSE; _set_timer(&pmlmepriv->assoc_timer, MAX_JOIN_TIMEOUT); } else if(ret == 2)//there is no need to wait for join { ret = _SUCCESS; _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING); rtw_indicate_connect(padapter); } else { if(check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)==_TRUE) { // submit createbss_cmd to change to a ADHOC_MASTER //pmlmepriv->lock has been acquired by caller... WLAN_BSSID_EX *pdev_network = &(padapter->registrypriv.dev_network); pmlmepriv->fw_state = WIFI_ADHOC_MASTER_STATE; pibss = padapter->registrypriv.dev_network.MacAddress; _rtw_memset(&pdev_network->Ssid, 0, sizeof(NDIS_802_11_SSID)); _rtw_memcpy(&pdev_network->Ssid, &pmlmepriv->assoc_ssid, sizeof(NDIS_802_11_SSID)); rtw_update_registrypriv_dev_network(padapter); rtw_generate_random_ibss(pibss); if(rtw_createbss_cmd(padapter)!=_SUCCESS) { RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_err_,("***Error=>do_goin: rtw_createbss_cmd status FAIL*** \n ")); ret = _FALSE; goto exit; } pmlmepriv->to_join = _FALSE; RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_info_,("***Error=> rtw_select_and_join_from_scanned_queue FAIL under STA_Mode*** \n ")); } else { // can't associate ; reset under-linking _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING); #if 0 if((check_fwstate(pmlmepriv, WIFI_STATION_STATE) == _TRUE)) { if(_rtw_memcmp(pmlmepriv->cur_network.network.Ssid.Ssid, pmlmepriv->assoc_ssid.Ssid, pmlmepriv->assoc_ssid.SsidLength)) { // for funk to do roaming // funk will reconnect, but funk will not sitesurvey before reconnect RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_info_,("for funk to do roaming")); if(pmlmepriv->sitesurveyctrl.traffic_busy==_FALSE) rtw_sitesurvey_cmd(padapter, &pmlmepriv->assoc_ssid, 1, NULL, 0); } } #endif //when set_ssid/set_bssid for rtw_do_join(), but there are no desired bss in scanning queue //we try to issue sitesurvey firstly if(pmlmepriv->LinkDetectInfo.bBusyTraffic==_FALSE || rtw_to_roaming(padapter) > 0 ) { //DBG_871X("rtw_do_join() when no desired bss in scanning queue \n"); if( _SUCCESS!=(ret=rtw_sitesurvey_cmd(padapter, &pmlmepriv->assoc_ssid, 1, NULL, 0)) ){ RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_err_,("do_join(): site survey return error\n.")); } } } } } exit: _func_exit_; return ret; }