Example #1
0
static u8 _rtw_mi_issue_nulldata(_adapter *padapter, void *data)
{
    struct nulldata_param *pnulldata_param = (struct nulldata_param *)data;

    if (is_client_associated_to_ap(padapter) == _TRUE) {
        /* TODO: TDLS peers */
        issue_nulldata(padapter, pnulldata_param->da, pnulldata_param->power_mode, pnulldata_param->try_cnt, pnulldata_param->wait_ms);
        return _TRUE;
    }
    return _FALSE;
}
Example #2
0
//Set channel back to base channel
void base_channel_workitem_callback(struct work_struct *work)
{
	struct sta_info *ptdls_sta = container_of(work, struct sta_info, base_ch_workitem);
	_adapter *padapter = ptdls_sta->padapter;
	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
	
	SelectChannel(ptdls_sta->padapter, pmlmeext->cur_channel);
	issue_nulldata(ptdls_sta->padapter, 0);

	DBG_8192C("change channel to base ch:%02x\n", pmlmeext->cur_channel);

	ptdls_sta->state &= ~(TDLS_PEER_AT_OFF_STATE| TDLS_AT_OFF_CH_STATE);

	_set_timer(&ptdls_sta->off_ch_timer, 500);	

}
Example #3
0
//Set channel back to off channel
void off_channel_workitem_callback(struct work_struct *work)
{
	struct sta_info *ptdls_sta = container_of(work, struct sta_info, off_ch_workitem);
	_adapter *padapter = ptdls_sta->padapter;
	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
	
	issue_nulldata(ptdls_sta->padapter, 1);

	SelectChannel(ptdls_sta->padapter, ptdls_sta->off_ch);

	DBG_8192C("change channel to off ch:%02x\n", ptdls_sta->off_ch);
	ptdls_sta->state |= TDLS_AT_OFF_CH_STATE;

	if((ptdls_sta->state & TDLS_PEER_AT_OFF_STATE) != TDLS_PEER_AT_OFF_STATE){
		issue_nulldata_to_TDLS_peer_STA(ptdls_sta->padapter, ptdls_sta, 0);
	}

	_set_timer(&ptdls_sta->base_ch_timer, 500);	
}
Example #4
0
void	expire_timeout_chk(struct adapter *padapter)
{
	struct list_head *phead, *plist;
	u8 updated = 0;
	struct sta_info *psta = NULL;
	struct sta_priv *pstapriv = &padapter->stapriv;
	u8 chk_alive_num = 0;
	char chk_alive_list[NUM_STA];
	int i;

	spin_lock_bh(&pstapriv->auth_list_lock);

	phead = &pstapriv->auth_list;
	plist = phead->next;

	/* check auth_queue */
	while (phead != plist) {
		psta = container_of(plist, struct sta_info, auth_list);
		plist = plist->next;

		if (psta->expire_to > 0) {
			psta->expire_to--;
			if (psta->expire_to == 0) {
				list_del_init(&psta->auth_list);
				pstapriv->auth_list_cnt--;

				DBG_88E("auth expire %6ph\n",
					psta->hwaddr);

				spin_unlock_bh(&pstapriv->auth_list_lock);

				spin_lock_bh(&pstapriv->sta_hash_lock);
				rtw_free_stainfo(padapter, psta);
				spin_unlock_bh(&pstapriv->sta_hash_lock);

				spin_lock_bh(&pstapriv->auth_list_lock);
			}
		}
	}
	spin_unlock_bh(&pstapriv->auth_list_lock);

	psta = NULL;

	spin_lock_bh(&pstapriv->asoc_list_lock);

	phead = &pstapriv->asoc_list;
	plist = phead->next;

	/* check asoc_queue */
	while (phead != plist) {
		psta = container_of(plist, struct sta_info, asoc_list);
		plist = plist->next;

		if (chk_sta_is_alive(psta) || !psta->expire_to) {
			psta->expire_to = pstapriv->expire_to;
			psta->keep_alive_trycnt = 0;
			psta->under_exist_checking = 0;
		} else {
			psta->expire_to--;
		}

		if (psta->expire_to <= 0) {
			struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;

			if (padapter->registrypriv.wifi_spec == 1) {
				psta->expire_to = pstapriv->expire_to;
				continue;
			}

			if (psta->state & WIFI_SLEEP_STATE) {
				if (!(psta->state & WIFI_STA_ALIVE_CHK_STATE)) {
					/* to check if alive by another methods
					 * if station is at ps mode.
					 */
					psta->expire_to = pstapriv->expire_to;
					psta->state |= WIFI_STA_ALIVE_CHK_STATE;

					/* to update bcn with tim_bitmap
					 * for this station
					 */
					pstapriv->tim_bitmap |= BIT(psta->aid);
					update_beacon(padapter, _TIM_IE_, NULL,
						      false);

					if (!pmlmeext->active_keep_alive_check)
						continue;
				}
			}
			if (pmlmeext->active_keep_alive_check) {
				int stainfo_offset;

				stainfo_offset =
					rtw_stainfo_offset(pstapriv, psta);
				if (stainfo_offset_valid(stainfo_offset))
					chk_alive_list[chk_alive_num++] =
						stainfo_offset;
				continue;
			}

			list_del_init(&psta->asoc_list);
			pstapriv->asoc_list_cnt--;

			DBG_88E("asoc expire %pM, state = 0x%x\n", (psta->hwaddr), psta->state);
			updated = ap_free_sta(padapter, psta, true, WLAN_REASON_DEAUTH_LEAVING);
		} else {
			/* TODO: Aging mechanism to digest frames in sleep_q to avoid running out of xmitframe */
			if (psta->sleepq_len > (NR_XMITFRAME / pstapriv->asoc_list_cnt) &&
			    padapter->xmitpriv.free_xmitframe_cnt < (NR_XMITFRAME / pstapriv->asoc_list_cnt / 2)) {
				DBG_88E("%s sta:%pM, sleepq_len:%u, free_xmitframe_cnt:%u, asoc_list_cnt:%u, clear sleep_q\n", __func__,
					(psta->hwaddr), psta->sleepq_len,
					padapter->xmitpriv.free_xmitframe_cnt,
					pstapriv->asoc_list_cnt);
				wakeup_sta_to_xmit(padapter, psta);
			}
		}
	}

	spin_unlock_bh(&pstapriv->asoc_list_lock);

	if (chk_alive_num) {
		u8 backup_oper_channel = 0;
		struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
		/* switch to correct channel of current network  before issue keep-alive frames */
		if (rtw_get_oper_ch(padapter) != pmlmeext->cur_channel) {
			backup_oper_channel = rtw_get_oper_ch(padapter);
			SelectChannel(padapter, pmlmeext->cur_channel);
		}

		/* issue null data to check sta alive*/
		for (i = 0; i < chk_alive_num; i++) {
			int ret = _FAIL;

			psta = rtw_get_stainfo_by_offset(pstapriv, chk_alive_list[i]);

			if (psta->state & WIFI_SLEEP_STATE)
				ret = issue_nulldata(padapter, psta->hwaddr, 0, 1, 50);
			else
				ret = issue_nulldata(padapter, psta->hwaddr, 0, 3, 50);

			psta->keep_alive_trycnt++;
			if (ret == _SUCCESS) {
				DBG_88E("asoc check, sta(%pM) is alive\n", (psta->hwaddr));
				psta->expire_to = pstapriv->expire_to;
				psta->keep_alive_trycnt = 0;
				continue;
			} else if (psta->keep_alive_trycnt <= 3) {
				DBG_88E("ack check for asoc expire, keep_alive_trycnt =%d\n", psta->keep_alive_trycnt);
				psta->expire_to = 1;
				continue;
			}

			psta->keep_alive_trycnt = 0;

			DBG_88E("asoc expire %pM, state = 0x%x\n", (psta->hwaddr), psta->state);
			spin_lock_bh(&pstapriv->asoc_list_lock);
			list_del_init(&psta->asoc_list);
			pstapriv->asoc_list_cnt--;
			updated = ap_free_sta(padapter, psta, true, WLAN_REASON_DEAUTH_LEAVING);
			spin_unlock_bh(&pstapriv->asoc_list_lock);
		}

		if (backup_oper_channel > 0) /* back to the original operation channel */
			SelectChannel(padapter, backup_oper_channel);
	}

	associated_clients_update(padapter, updated);
}
Example #5
0
// 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;			
	}
	
}