]> git.kernelconcepts.de Git - karo-tx-linux.git/blobdiff - drivers/net/wireless/iwlwifi/mvm/rs.c
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/ide
[karo-tx-linux.git] / drivers / net / wireless / iwlwifi / mvm / rs.c
index 5ae9c8aa868fa445063e956a26ac1444caf5d8dd..d1ad10391b473fb0ff288f0311d9b7bd6f14921d 100644 (file)
@@ -177,9 +177,6 @@ static bool rs_mimo_allow(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
 
        mvmsta = iwl_mvm_sta_from_mac80211(sta);
        mvmvif = iwl_mvm_vif_from_mac80211(mvmsta->vif);
-       if (IWL_MVM_RS_DISABLE_P2P_MIMO &&
-           iwl_mvm_vif_low_latency(mvmvif) && mvmsta->vif->p2p)
-               return false;
 
        if (mvm->nvm_data->sku_cap_mimo_disabled)
                return false;
@@ -524,14 +521,56 @@ static const char *rs_pretty_lq_type(enum iwl_table_type type)
        return lq_types[type];
 }
 
+static char *rs_pretty_rate(const struct rs_rate *rate)
+{
+       static char buf[40];
+       static const char * const legacy_rates[] = {
+               [IWL_RATE_1M_INDEX] = "1M",
+               [IWL_RATE_2M_INDEX] = "2M",
+               [IWL_RATE_5M_INDEX] = "5.5M",
+               [IWL_RATE_11M_INDEX] = "11M",
+               [IWL_RATE_6M_INDEX] = "6M",
+               [IWL_RATE_9M_INDEX] = "9M",
+               [IWL_RATE_12M_INDEX] = "12M",
+               [IWL_RATE_18M_INDEX] = "18M",
+               [IWL_RATE_24M_INDEX] = "24M",
+               [IWL_RATE_36M_INDEX] = "36M",
+               [IWL_RATE_48M_INDEX] = "48M",
+               [IWL_RATE_54M_INDEX] = "54M",
+       };
+       static const char *const ht_vht_rates[] = {
+               [IWL_RATE_MCS_0_INDEX] = "MCS0",
+               [IWL_RATE_MCS_1_INDEX] = "MCS1",
+               [IWL_RATE_MCS_2_INDEX] = "MCS2",
+               [IWL_RATE_MCS_3_INDEX] = "MCS3",
+               [IWL_RATE_MCS_4_INDEX] = "MCS4",
+               [IWL_RATE_MCS_5_INDEX] = "MCS5",
+               [IWL_RATE_MCS_6_INDEX] = "MCS6",
+               [IWL_RATE_MCS_7_INDEX] = "MCS7",
+               [IWL_RATE_MCS_8_INDEX] = "MCS8",
+               [IWL_RATE_MCS_9_INDEX] = "MCS9",
+       };
+       const char *rate_str;
+
+       if (is_type_legacy(rate->type))
+               rate_str = legacy_rates[rate->index];
+       else if (is_type_ht(rate->type) || is_type_vht(rate->type))
+               rate_str = ht_vht_rates[rate->index];
+       else
+               rate_str = "BAD_RATE";
+
+       sprintf(buf, "(%s|%s|%s)", rs_pretty_lq_type(rate->type),
+               rs_pretty_ant(rate->ant), rate_str);
+       return buf;
+}
+
 static inline void rs_dump_rate(struct iwl_mvm *mvm, const struct rs_rate *rate,
                                const char *prefix)
 {
        IWL_DEBUG_RATE(mvm,
-                      "%s: (%s: %d) ANT: %s BW: %d SGI: %d LDPC: %d STBC: %d\n",
-                      prefix, rs_pretty_lq_type(rate->type),
-                      rate->index, rs_pretty_ant(rate->ant),
-                      rate->bw, rate->sgi, rate->ldpc, rate->stbc);
+                      "%s: %s BW: %d SGI: %d LDPC: %d STBC: %d\n",
+                      prefix, rs_pretty_rate(rate), rate->bw,
+                      rate->sgi, rate->ldpc, rate->stbc);
 }
 
 static void rs_rate_scale_clear_window(struct iwl_rate_scale_data *window)
@@ -562,8 +601,8 @@ static inline u8 rs_is_valid_ant(u8 valid_antenna, u8 ant_type)
 }
 
 static int rs_tl_turn_on_agg_for_tid(struct iwl_mvm *mvm,
-                                     struct iwl_lq_sta *lq_data, u8 tid,
-                                     struct ieee80211_sta *sta)
+                                    struct iwl_lq_sta *lq_data, u8 tid,
+                                    struct ieee80211_sta *sta)
 {
        int ret = -EAGAIN;
 
@@ -1485,7 +1524,7 @@ static s32 rs_get_best_rate(struct iwl_mvm *mvm,
        u32 target_tpt;
        int rate_idx;
 
-       if (success_ratio > IWL_MVM_RS_SR_NO_DECREASE) {
+       if (success_ratio >= RS_PERCENT(IWL_MVM_RS_SR_NO_DECREASE)) {
                target_tpt = 100 * expected_current_tpt;
                IWL_DEBUG_RATE(mvm,
                               "SR %d high. Find rate exceeding EXPECTED_CURRENT %d\n",
@@ -1493,7 +1532,7 @@ static s32 rs_get_best_rate(struct iwl_mvm *mvm,
        } else {
                target_tpt = lq_sta->last_tpt;
                IWL_DEBUG_RATE(mvm,
-                              "SR %d not thag good. Find rate exceeding ACTUAL_TPT %d\n",
+                              "SR %d not that good. Find rate exceeding ACTUAL_TPT %d\n",
                               success_ratio, target_tpt);
        }
 
@@ -1622,6 +1661,51 @@ static void rs_update_rate_tbl(struct iwl_mvm *mvm,
        iwl_mvm_send_lq_cmd(mvm, &lq_sta->lq, false);
 }
 
+static bool rs_tweak_rate_tbl(struct iwl_mvm *mvm,
+                             struct ieee80211_sta *sta,
+                             struct iwl_lq_sta *lq_sta,
+                             struct iwl_scale_tbl_info *tbl,
+                             enum rs_action scale_action)
+{
+       if (sta->bandwidth != IEEE80211_STA_RX_BW_80)
+               return false;
+
+       if (!is_vht_siso(&tbl->rate))
+               return false;
+
+       if ((tbl->rate.bw == RATE_MCS_CHAN_WIDTH_80) &&
+           (tbl->rate.index == IWL_RATE_MCS_0_INDEX) &&
+           (scale_action == RS_ACTION_DOWNSCALE)) {
+               tbl->rate.bw = RATE_MCS_CHAN_WIDTH_20;
+               tbl->rate.index = IWL_RATE_MCS_4_INDEX;
+               IWL_DEBUG_RATE(mvm, "Switch 80Mhz SISO MCS0 -> 20Mhz MCS4\n");
+               goto tweaked;
+       }
+
+       /* Go back to 80Mhz MCS1 only if we've established that 20Mhz MCS5 is
+        * sustainable, i.e. we're past the test window. We can't go back
+        * if MCS5 is just tested as this will happen always after switching
+        * to 20Mhz MCS4 because the rate stats are cleared.
+        */
+       if ((tbl->rate.bw == RATE_MCS_CHAN_WIDTH_20) &&
+           (((tbl->rate.index == IWL_RATE_MCS_5_INDEX) &&
+            (scale_action == RS_ACTION_STAY)) ||
+            ((tbl->rate.index > IWL_RATE_MCS_5_INDEX) &&
+             (scale_action == RS_ACTION_UPSCALE)))) {
+               tbl->rate.bw = RATE_MCS_CHAN_WIDTH_80;
+               tbl->rate.index = IWL_RATE_MCS_1_INDEX;
+               IWL_DEBUG_RATE(mvm, "Switch 20Mhz SISO MCS5 -> 80Mhz MCS1\n");
+               goto tweaked;
+       }
+
+       return false;
+
+tweaked:
+       rs_set_expected_tpt_table(lq_sta, tbl);
+       rs_rate_scale_clear_tbl_windows(mvm, tbl);
+       return true;
+}
+
 static enum rs_column rs_get_next_column(struct iwl_mvm *mvm,
                                         struct iwl_lq_sta *lq_sta,
                                         struct ieee80211_sta *sta,
@@ -2174,9 +2258,9 @@ static void rs_rate_scale_perform(struct iwl_mvm *mvm,
        if ((fail_count < IWL_MVM_RS_RATE_MIN_FAILURE_TH) &&
            (window->success_counter < IWL_MVM_RS_RATE_MIN_SUCCESS_TH)) {
                IWL_DEBUG_RATE(mvm,
-                              "(%s: %d): Test Window: succ %d total %d\n",
-                              rs_pretty_lq_type(rate->type),
-                              index, window->success_counter, window->counter);
+                              "%s: Test Window: succ %d total %d\n",
+                              rs_pretty_rate(rate),
+                              window->success_counter, window->counter);
 
                /* Can't calculate this yet; not enough history */
                window->average_tpt = IWL_INVALID_VALUE;
@@ -2253,8 +2337,8 @@ static void rs_rate_scale_perform(struct iwl_mvm *mvm,
                high_tpt = tbl->win[high].average_tpt;
 
        IWL_DEBUG_RATE(mvm,
-                      "(%s: %d): cur_tpt %d SR %d low %d high %d low_tpt %d high_tpt %d\n",
-                      rs_pretty_lq_type(rate->type), index, current_tpt, sr,
+                      "%s: cur_tpt %d SR %d low %d high %d low_tpt %d high_tpt %d\n",
+                      rs_pretty_rate(rate), current_tpt, sr,
                       low, high, low_tpt, high_tpt);
 
        scale_action = rs_get_rate_action(mvm, tbl, sr, low, high,
@@ -2305,6 +2389,8 @@ lq_update:
        /* Replace uCode's rate table for the destination station. */
        if (update_lq) {
                tbl->rate.index = index;
+               if (IWL_MVM_RS_80_20_FAR_RANGE_TWEAK)
+                       rs_tweak_rate_tbl(mvm, sta, lq_sta, tbl, scale_action);
                rs_update_rate_tbl(mvm, sta, lq_sta, tbl);
        }
 
@@ -2542,7 +2628,6 @@ static struct rs_rate *rs_get_optimal_rate(struct iwl_mvm *mvm,
                }
        }
 
-       rs_dump_rate(mvm, rate, "OPTIMAL RATE");
        return rate;
 }
 
@@ -2983,9 +3068,6 @@ void iwl_mvm_rs_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
        else
                rs_vht_init(mvm, sta, lq_sta, vht_cap);
 
-       if (IWL_MVM_RS_DISABLE_P2P_MIMO && sta_priv->vif->p2p)
-               lq_sta->active_mimo2_rate = 0;
-
        lq_sta->max_legacy_rate_idx =
                rs_get_max_rate_from_mask(lq_sta->active_legacy_rate);
        lq_sta->max_siso_rate_idx =