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:50:27 +0000 (07:50 +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 f1231c0ea336616fecf6b7101039118fb09e6f9c..0bffade1ea5bfec94bcfa180195fb1ab4bba4cb6 100644 (file)
@@ -2585,6 +2585,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 0aea476ebf5099aa412fce4d06049ecd6b6c6d5e..f251c2afebfcbb29dfac03f2e9bef53e4e7745c7 100644 (file)
@@ -2709,7 +2709,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;
@@ -2763,14 +2764,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;
@@ -2781,7 +2793,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;
@@ -2863,7 +2875,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_ON_ONCE(rate->ant != ANT_A && rate->ant != ANT_B);