iwlwifi: mvm: always init rs with 20mhz bandwidth rates

In AP mode, when a new station associates, rs is initialized immediately
upon association completion, before the phy context is updated with the
association parameters, so the sta bandwidth might be wider than the phy
context allows.
To avoid this issue, always initialize rs with 20mhz bandwidth rate, and
after authorization, when the phy context is already up-to-date, re-init
rs with the correct bw.

Signed-off-by: Naftali Goldstein <naftali.goldstein@intel.com>
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
This commit is contained in:
Naftali Goldstein 2017-12-28 15:53:04 +02:00 committed by Luca Coelho
parent 4b7f7ee2a5
commit 6b7a5aea71
2 changed files with 24 additions and 8 deletions

View file

@ -2682,6 +2682,10 @@ static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw,
/* enable beacon filtering */
WARN_ON(iwl_mvm_enable_beacon_filter(mvm, vif, 0));
iwl_mvm_rs_rate_init(mvm, sta, mvmvif->phy_ctxt->channel->band,
false);
ret = 0;
} else if (old_state == IEEE80211_STA_AUTHORIZED &&
new_state == IEEE80211_STA_ASSOC) {

View file

@ -2684,7 +2684,8 @@ static void rs_get_initial_rate(struct iwl_mvm *mvm,
struct ieee80211_sta *sta,
struct iwl_lq_sta *lq_sta,
enum nl80211_band band,
struct rs_rate *rate)
struct rs_rate *rate,
bool init)
{
int i, nentries;
unsigned long active_rate;
@ -2738,14 +2739,25 @@ static void rs_get_initial_rate(struct iwl_mvm *mvm,
*/
if (sta->vht_cap.vht_supported &&
best_rssi > IWL_RS_LOW_RSSI_THRESHOLD) {
switch (sta->bandwidth) {
case IEEE80211_STA_RX_BW_160:
case IEEE80211_STA_RX_BW_80:
case IEEE80211_STA_RX_BW_40:
/*
* In AP mode, when a new station associates, rs is initialized
* immediately upon association completion, before the phy
* context is updated with the association parameters, so the
* sta bandwidth might be wider than the phy context allows.
* To avoid this issue, always initialize rs with 20mhz
* bandwidth rate, and after authorization, when the phy context
* is already up-to-date, re-init rs with the correct bw.
*/
u32 bw = init ? RATE_MCS_CHAN_WIDTH_20 : rs_bw_from_sta_bw(sta);
switch (bw) {
case RATE_MCS_CHAN_WIDTH_40:
case RATE_MCS_CHAN_WIDTH_80:
case RATE_MCS_CHAN_WIDTH_160:
initial_rates = rs_optimal_rates_vht;
nentries = ARRAY_SIZE(rs_optimal_rates_vht);
break;
case IEEE80211_STA_RX_BW_20:
case RATE_MCS_CHAN_WIDTH_20:
initial_rates = rs_optimal_rates_vht_20mhz;
nentries = ARRAY_SIZE(rs_optimal_rates_vht_20mhz);
break;
@ -2756,7 +2768,7 @@ static void rs_get_initial_rate(struct iwl_mvm *mvm,
active_rate = lq_sta->active_siso_rate;
rate->type = LQ_VHT_SISO;
rate->bw = rs_bw_from_sta_bw(sta);
rate->bw = bw;
} else if (sta->ht_cap.ht_supported &&
best_rssi > IWL_RS_LOW_RSSI_THRESHOLD) {
initial_rates = rs_optimal_rates_ht;
@ -2839,7 +2851,7 @@ static void rs_initialize_lq(struct iwl_mvm *mvm,
tbl = &(lq_sta->lq_info[active_tbl]);
rate = &tbl->rate;
rs_get_initial_rate(mvm, sta, lq_sta, band, rate);
rs_get_initial_rate(mvm, sta, lq_sta, band, rate, init);
rs_init_optimal_rate(mvm, sta, lq_sta);
WARN_ONCE(rate->ant != ANT_A && rate->ant != ANT_B,