iwlwifi: mvm: always init rs with 20mhz bandwidth rates
authorNaftali Goldstein <naftali.goldstein@intel.com>
Thu, 28 Dec 2017 13:53:04 +0000 (15:53 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 30 May 2018 05:51:57 +0000 (07:51 +0200)
[ Upstream commit 6b7a5aea71b342ec0593d23b08383e1f33da4c9a ]

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>
Signed-off-by: Sasha Levin <alexander.levin@microsoft.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
drivers/net/wireless/intel/iwlwifi/mvm/rs.c

index a9ac872226fdf79d87d6bc8b9643d9d6d86cd793..8ba427a68bd0a68d654839fe7fed976040e75618 100644 (file)
@@ -2703,6 +2703,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) {
index d22cef7381baa496a7ee8df68efa9dac2c402d81..386fdee23eb0ef35f9523ff37b3b7297ce415175 100644 (file)
@@ -2690,7 +2690,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;
@@ -2744,14 +2745,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;
@@ -2762,7 +2774,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;
@@ -2844,7 +2856,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,