// free all stainfo which in sta_hash[all] void rtw_free_all_stainfo(_adapter *padapter) { _irqL irqL; _list *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); if(pstapriv->asoc_sta_count==1) return; SPIN_LOCK_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); } } SPIN_UNLOCK_BH(pstapriv->sta_hash_lock, &irqL); }
/* free all stainfo which in sta_hash[all] */ void rtw_free_all_stainfo(struct adapter *padapter) { 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); if (pstapriv->asoc_sta_count == 1) return; spin_lock_bh(&pstapriv->sta_hash_lock); for (index = 0; index < NUM_STA; index++) { phead = &pstapriv->sta_hash[index]; plist = phead->next; while (phead != plist) { psta = container_of(plist, struct sta_info, hash_list); plist = plist->next; if (pbcmc_stainfo != psta) rtw_free_stainfo(padapter, psta); } } spin_unlock_bh(&pstapriv->sta_hash_lock); }
// free all stainfo which in sta_hash[all] void rtw_free_all_stainfo(_adapter *padapter) { _irqL irqL; _list *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); u8 free_sta_num = 0; char free_sta_list[NUM_STA]; int stainfo_offset; _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_list_delete(&psta->hash_list); //rtw_free_stainfo(padapter , psta); stainfo_offset = rtw_stainfo_offset(pstapriv, psta); if (stainfo_offset_valid(stainfo_offset)) { free_sta_list[free_sta_num++] = stainfo_offset; } } } } _exit_critical_bh(&pstapriv->sta_hash_lock, &irqL); for (index = 0; index < free_sta_num; index++) { psta = rtw_get_stainfo_by_offset(pstapriv, free_sta_list[index]); rtw_free_stainfo(padapter , psta); } exit: _func_exit_; }
void stop_ap_mode(struct adapter *padapter) { struct list_head *phead, *plist; struct rtw_wlan_acl_node *paclnode; struct sta_info *psta = NULL; struct sta_priv *pstapriv = &padapter->stapriv; struct mlme_priv *pmlmepriv = &padapter->mlmepriv; struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; struct wlan_acl_pool *pacl_list = &pstapriv->acl_list; struct __queue *pacl_node_q = &pacl_list->acl_node_q; pmlmepriv->update_bcn = false; pmlmeext->bstart_bss = false; /* reset and init security priv , this can refine with * rtw_reset_securitypriv */ memset((unsigned char *)&padapter->securitypriv, 0, sizeof(struct security_priv)); padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeOpen; padapter->securitypriv.ndisencryptstatus = Ndis802_11WEPDisabled; /* for ACL */ spin_lock_bh(&pacl_node_q->lock); phead = get_list_head(pacl_node_q); plist = phead->next; while (phead != plist) { paclnode = container_of(plist, struct rtw_wlan_acl_node, list); plist = plist->next; if (paclnode->valid) { paclnode->valid = false; list_del_init(&paclnode->list); pacl_list->num--; } } spin_unlock_bh(&pacl_node_q->lock); DBG_88E("%s, free acl_node_queue, num =%d\n", __func__, pacl_list->num); rtw_sta_flush(padapter); /* free_assoc_sta_resources */ rtw_free_all_stainfo(padapter); psta = rtw_get_bcmc_stainfo(padapter); spin_lock_bh(&pstapriv->sta_hash_lock); rtw_free_stainfo(padapter, psta); spin_unlock_bh(&pstapriv->sta_hash_lock); rtw_init_bcmc_stainfo(padapter); rtw_free_mlme_priv_ie_data(pmlmepriv); }
/* 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_; }
// free all stainfo which in sta_hash[all] void rtw_free_all_stainfo(_adapter *padapter) { _list *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; spin_lock_bh(&pstapriv->sta_hash_lock); for(index=0; index< NUM_STA; index++) { phead = &(pstapriv->sta_hash[index]); plist = get_next(phead); while (phead != plist) { psta = LIST_CONTAINOR(plist, struct sta_info ,hash_list); plist = get_next(plist); if(pbcmc_stainfo!=psta) rtw_free_stainfo(padapter , psta); } } spin_unlock_bh(&pstapriv->sta_hash_lock); exit: _func_exit_; }
u8 ap_free_sta(struct adapter *padapter, struct sta_info *psta, bool active, u16 reason) { u8 beacon_updated = false; struct sta_priv *pstapriv = &padapter->stapriv; if (!psta) return beacon_updated; /* tear down Rx AMPDU */ send_delba(padapter, 0, psta->hwaddr);/* recipient */ /* tear down TX AMPDU */ send_delba(padapter, 1, psta->hwaddr);/* originator */ psta->htpriv.agg_enable_bitmap = 0x0;/* reset */ psta->htpriv.candidate_tid_bitmap = 0x0;/* reset */ if (active) issue_deauth(padapter, psta->hwaddr, reason); /* clear cam entry / key */ rtw_clearstakey_cmd(padapter, (u8 *)psta, (u8)(psta->mac_id + 3), true); spin_lock_bh(&psta->lock); psta->state &= ~_FW_LINKED; spin_unlock_bh(&psta->lock); rtw_indicate_sta_disassoc_event(padapter, psta); report_del_sta_event(padapter, psta->hwaddr, reason); beacon_updated = bss_cap_update_on_sta_leave(padapter, psta); spin_lock_bh(&pstapriv->sta_hash_lock); rtw_free_stainfo(padapter, psta); spin_unlock_bh(&pstapriv->sta_hash_lock); return beacon_updated; }
void free_mlme_ap_info(struct adapter *padapter) { struct sta_info *psta = NULL; struct sta_priv *pstapriv = &padapter->stapriv; struct mlme_priv *pmlmepriv = &padapter->mlmepriv; struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; pmlmepriv->update_bcn = false; pmlmeext->bstart_bss = false; rtw_sta_flush(padapter); pmlmeinfo->state = _HW_STATE_NOLINK_; /* free_assoc_sta_resources */ rtw_free_all_stainfo(padapter); /* free bc/mc sta_info */ psta = rtw_get_bcmc_stainfo(padapter); spin_lock_bh(&pstapriv->sta_hash_lock); rtw_free_stainfo(padapter, psta); spin_unlock_bh(&pstapriv->sta_hash_lock); }
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); }