static u8 _rtw_mi_beacon_update(_adapter *padapter, void *data) { struct mlme_ext_priv *mlmeext = &padapter->mlmeextpriv; if (mlmeext_msr(mlmeext) == WIFI_FW_AP_STATE && check_fwstate(&padapter->mlmepriv, _FW_LINKED) == _TRUE) { RTW_INFO(ADPT_FMT"-WIFI_FW_AP_STATE - update_beacon\n", ADPT_ARG(padapter)); update_beacon(padapter, 0, NULL, _TRUE); } return _TRUE; }
static void rtw_chk_hi_queue_hdl(struct adapter *padapter) { int cnt = 0; struct sta_info *psta_bmc; struct sta_priv *pstapriv = &padapter->stapriv; psta_bmc = rtw_get_bcmc_stainfo(padapter); if (!psta_bmc) return; if (psta_bmc->sleepq_len == 0) { u8 val = 0; /* while ((rtw_read32(padapter, 0x414)&0x00ffff00)!= 0) */ /* while ((rtw_read32(padapter, 0x414)&0x0000ff00)!= 0) */ rtw_hal_get_hwreg(padapter, HW_VAR_CHK_HI_QUEUE_EMPTY, &val); while (!val) { msleep(100); cnt++; if (cnt > 10) break; rtw_hal_get_hwreg(padapter, HW_VAR_CHK_HI_QUEUE_EMPTY, &val); } if (cnt <= 10) { pstapriv->tim_bitmap &= ~BIT(0); pstapriv->sta_dz_bitmap &= ~BIT(0); update_beacon(padapter, _TIM_IE_, NULL, false); } else { /* re check again */ rtw_chk_hi_queue_cmd(padapter); } } }
static void start_bss_network(struct adapter *padapter, u8 *pbuf) { u8 *p; u8 val8, cur_channel, cur_bwmode, cur_ch_offset; u16 bcn_interval; u32 acparm; uint ie_len; struct registry_priv *pregpriv = &padapter->registrypriv; struct mlme_priv *pmlmepriv = &padapter->mlmepriv; struct security_priv *psecuritypriv = &padapter->securitypriv; struct wlan_bssid_ex *pnetwork = (struct wlan_bssid_ex *)&pmlmepriv->cur_network.network; struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; struct wlan_bssid_ex *pnetwork_mlmeext = &pmlmeinfo->network; struct HT_info_element *pht_info = NULL; bcn_interval = (u16)pnetwork->Configuration.BeaconPeriod; cur_channel = pnetwork->Configuration.DSConfig; cur_bwmode = HT_CHANNEL_WIDTH_20; cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE; /* check if there is wps ie, * if there is wpsie in beacon, the hostapd will update * beacon twice when stating hostapd, and at first time the * security ie (RSN/WPA IE) will not include in beacon. */ if (!rtw_get_wps_ie(pnetwork->ies + _FIXED_IE_LENGTH_, pnetwork->ie_length - _FIXED_IE_LENGTH_, NULL, NULL)) pmlmeext->bstart_bss = true; /* todo: update wmm, ht cap */ if (pmlmepriv->qospriv.qos_option) pmlmeinfo->WMM_enable = true; if (pmlmepriv->htpriv.ht_option) { pmlmeinfo->WMM_enable = true; pmlmeinfo->HT_enable = true; update_hw_ht_param(padapter); } /* setting only at first time */ if (pmlmepriv->cur_network.join_res != true) { /* WEP Key will be set before this function, do not * clear CAM. */ if ((psecuritypriv->dot11PrivacyAlgrthm != _WEP40_) && (psecuritypriv->dot11PrivacyAlgrthm != _WEP104_)) flush_all_cam_entry(padapter); /* clear CAM */ } /* set MSR to AP_Mode */ Set_MSR(padapter, _HW_STATE_AP_); /* Set BSSID REG */ rtw_hal_set_hwreg(padapter, HW_VAR_BSSID, pnetwork->MacAddress); /* Set EDCA param reg */ acparm = 0x002F3217; /* VO */ rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_VO, (u8 *)(&acparm)); acparm = 0x005E4317; /* VI */ rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_VI, (u8 *)(&acparm)); acparm = 0x005ea42b; rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_BE, (u8 *)(&acparm)); acparm = 0x0000A444; /* BK */ rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_BK, (u8 *)(&acparm)); /* Set Security */ val8 = (psecuritypriv->dot11AuthAlgrthm == dot11AuthAlgrthm_8021X) ? 0xcc : 0xcf; rtw_hal_set_hwreg(padapter, HW_VAR_SEC_CFG, (u8 *)(&val8)); /* Beacon Control related register */ rtw_hal_set_hwreg(padapter, HW_VAR_BEACON_INTERVAL, (u8 *)(&bcn_interval)); UpdateBrateTbl(padapter, pnetwork->SupportedRates); rtw_hal_set_hwreg(padapter, HW_VAR_BASIC_RATE, pnetwork->SupportedRates); if (!pmlmepriv->cur_network.join_res) { /* setting only at first time */ /* turn on all dynamic functions */ Switch_DM_Func(padapter, DYNAMIC_ALL_FUNC_ENABLE, true); } /* set channel, bwmode */ p = rtw_get_ie((pnetwork->ies + sizeof(struct ndis_802_11_fixed_ie)), _HT_ADD_INFO_IE_, &ie_len, (pnetwork->ie_length - sizeof(struct ndis_802_11_fixed_ie))); if (p && ie_len) { pht_info = (struct HT_info_element *)(p + 2); if ((pregpriv->cbw40_enable) && (pht_info->infos[0] & BIT(2))) { /* switch to the 40M Hz mode */ cur_bwmode = HT_CHANNEL_WIDTH_40; switch (pht_info->infos[0] & 0x3) { case 1: cur_ch_offset = HAL_PRIME_CHNL_OFFSET_LOWER; break; case 3: cur_ch_offset = HAL_PRIME_CHNL_OFFSET_UPPER; break; default: cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE; break; } } } /* TODO: need to judge the phy parameters on concurrent * mode for single phy */ set_channel_bwmode(padapter, cur_channel, cur_ch_offset, cur_bwmode); DBG_88E("CH =%d, BW =%d, offset =%d\n", cur_channel, cur_bwmode, cur_ch_offset); /* */ pmlmeext->cur_channel = cur_channel; pmlmeext->cur_bwmode = cur_bwmode; pmlmeext->cur_ch_offset = cur_ch_offset; pmlmeext->cur_wireless_mode = pmlmepriv->cur_network.network_type; /* update cur_wireless_mode */ update_wireless_mode(padapter); /* update capability after cur_wireless_mode updated */ update_capinfo(padapter, rtw_get_capability((struct wlan_bssid_ex *)pnetwork)); /* let pnetwork_mlmeext == pnetwork_mlme. */ memcpy(pnetwork_mlmeext, pnetwork, pnetwork->Length); if (pmlmeext->bstart_bss) { update_beacon(padapter, _TIM_IE_, NULL, false); /* issue beacon frame */ if (send_beacon(padapter) == _FAIL) DBG_88E("send_beacon, fail!\n"); } /* update bc/mc sta_info */ update_bmc_sta(padapter); }
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); }
u8 bss_cap_update_on_sta_leave(struct adapter *padapter, struct sta_info *psta) { u8 beacon_updated = false; struct mlme_priv *pmlmepriv = &padapter->mlmepriv; struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; if (!psta) return beacon_updated; if (psta->no_short_preamble_set) { psta->no_short_preamble_set = 0; pmlmepriv->num_sta_no_short_preamble--; if (pmlmeext->cur_wireless_mode > WIRELESS_11B && pmlmepriv->num_sta_no_short_preamble == 0) { beacon_updated = true; update_beacon(padapter, 0xFF, NULL, true); } } if (psta->nonerp_set) { psta->nonerp_set = 0; pmlmepriv->num_sta_non_erp--; if (pmlmepriv->num_sta_non_erp == 0) { beacon_updated = true; update_beacon(padapter, _ERPINFO_IE_, NULL, true); } } if (psta->no_short_slot_time_set) { psta->no_short_slot_time_set = 0; pmlmepriv->num_sta_no_short_slot_time--; if (pmlmeext->cur_wireless_mode > WIRELESS_11B && pmlmepriv->num_sta_no_short_slot_time == 0) { beacon_updated = true; update_beacon(padapter, 0xFF, NULL, true); } } if (psta->no_ht_gf_set) { psta->no_ht_gf_set = 0; pmlmepriv->num_sta_ht_no_gf--; } if (psta->no_ht_set) { psta->no_ht_set = 0; pmlmepriv->num_sta_no_ht--; } if (psta->ht_20mhz_set) { psta->ht_20mhz_set = 0; pmlmepriv->num_sta_ht_20mhz--; } if (rtw_ht_operation_update(padapter) > 0) { update_beacon(padapter, _HT_CAPABILITY_IE_, NULL, false); update_beacon(padapter, _HT_ADD_INFO_IE_, NULL, true); } /* update associated stations cap. */ DBG_88E("%s, updated =%d\n", __func__, beacon_updated); return beacon_updated; }
/* called > TSR LEVEL for USB or SDIO Interface*/ void bss_cap_update_on_sta_join(struct adapter *padapter, struct sta_info *psta) { u8 beacon_updated = false; struct mlme_priv *pmlmepriv = &padapter->mlmepriv; struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; if (!(psta->flags & WLAN_STA_SHORT_PREAMBLE)) { if (!psta->no_short_preamble_set) { psta->no_short_preamble_set = 1; pmlmepriv->num_sta_no_short_preamble++; if ((pmlmeext->cur_wireless_mode > WIRELESS_11B) && (pmlmepriv->num_sta_no_short_preamble == 1)) { beacon_updated = true; update_beacon(padapter, 0xFF, NULL, true); } } } else { if (psta->no_short_preamble_set) { psta->no_short_preamble_set = 0; pmlmepriv->num_sta_no_short_preamble--; if ((pmlmeext->cur_wireless_mode > WIRELESS_11B) && (pmlmepriv->num_sta_no_short_preamble == 0)) { beacon_updated = true; update_beacon(padapter, 0xFF, NULL, true); } } } if (psta->flags & WLAN_STA_NONERP) { if (!psta->nonerp_set) { psta->nonerp_set = 1; pmlmepriv->num_sta_non_erp++; if (pmlmepriv->num_sta_non_erp == 1) { beacon_updated = true; update_beacon(padapter, _ERPINFO_IE_, NULL, true); } } } else { if (psta->nonerp_set) { psta->nonerp_set = 0; pmlmepriv->num_sta_non_erp--; if (pmlmepriv->num_sta_non_erp == 0) { beacon_updated = true; update_beacon(padapter, _ERPINFO_IE_, NULL, true); } } } if (!(psta->capability & WLAN_CAPABILITY_SHORT_SLOT_TIME)) { if (!psta->no_short_slot_time_set) { psta->no_short_slot_time_set = 1; pmlmepriv->num_sta_no_short_slot_time++; if ((pmlmeext->cur_wireless_mode > WIRELESS_11B) && (pmlmepriv->num_sta_no_short_slot_time == 1)) { beacon_updated = true; update_beacon(padapter, 0xFF, NULL, true); } } } else { if (psta->no_short_slot_time_set) { psta->no_short_slot_time_set = 0; pmlmepriv->num_sta_no_short_slot_time--; if ((pmlmeext->cur_wireless_mode > WIRELESS_11B) && (pmlmepriv->num_sta_no_short_slot_time == 0)) { beacon_updated = true; update_beacon(padapter, 0xFF, NULL, true); } } } if (psta->flags & WLAN_STA_HT) { u16 ht_capab = le16_to_cpu(psta->htpriv.ht_cap.cap_info); DBG_88E("HT: STA %pM HT Capabilities Info: 0x%04x\n", (psta->hwaddr), ht_capab); if (psta->no_ht_set) { psta->no_ht_set = 0; pmlmepriv->num_sta_no_ht--; } if ((ht_capab & IEEE80211_HT_CAP_GRN_FLD) == 0) { if (!psta->no_ht_gf_set) { psta->no_ht_gf_set = 1; pmlmepriv->num_sta_ht_no_gf++; } DBG_88E("%s STA %pM - no greenfield, num of non-gf stations %d\n", __func__, (psta->hwaddr), pmlmepriv->num_sta_ht_no_gf); } if ((ht_capab & IEEE80211_HT_CAP_SUP_WIDTH) == 0) { if (!psta->ht_20mhz_set) { psta->ht_20mhz_set = 1; pmlmepriv->num_sta_ht_20mhz++; } DBG_88E("%s STA %pM - 20 MHz HT, num of 20MHz HT STAs %d\n", __func__, (psta->hwaddr), pmlmepriv->num_sta_ht_20mhz); } } else { if (!psta->no_ht_set) { psta->no_ht_set = 1; pmlmepriv->num_sta_no_ht++; } if (pmlmepriv->htpriv.ht_option) { DBG_88E("%s STA %pM - no HT, num of non-HT stations %d\n", __func__, (psta->hwaddr), pmlmepriv->num_sta_no_ht); } } if (rtw_ht_operation_update(padapter) > 0) { update_beacon(padapter, _HT_CAPABILITY_IE_, NULL, false); update_beacon(padapter, _HT_ADD_INFO_IE_, NULL, true); } /* update associated stations cap. */ associated_clients_update(padapter, beacon_updated); DBG_88E("%s, updated =%d\n", __func__, beacon_updated); }