Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
[firefly-linux-kernel-4.4.55.git] / net / mac80211 / rc80211_minstrel.c
index f8d99a54798f3a31cd2116e151bebc1feb21dd19..1c36c9b4fa4a8f72689bcbf057edfbfa656f1d70 100644 (file)
@@ -69,14 +69,31 @@ rix_to_ndx(struct minstrel_sta_info *mi, int rix)
        return i;
 }
 
+/* find & sort topmost throughput rates */
+static inline void
+minstrel_sort_best_tp_rates(struct minstrel_sta_info *mi, int i, u8 *tp_list)
+{
+       int j = MAX_THR_RATES;
+
+       while (j > 0 && mi->r[i].cur_tp > mi->r[tp_list[j - 1]].cur_tp)
+               j--;
+       if (j < MAX_THR_RATES - 1)
+               memmove(&tp_list[j + 1], &tp_list[j], MAX_THR_RATES - (j + 1));
+       if (j < MAX_THR_RATES)
+               tp_list[j] = i;
+}
+
 static void
 minstrel_update_stats(struct minstrel_priv *mp, struct minstrel_sta_info *mi)
 {
-       u32 max_tp = 0, index_max_tp = 0, index_max_tp2 = 0;
-       u32 max_prob = 0, index_max_prob = 0;
+       u8 tmp_tp_rate[MAX_THR_RATES];
+       u8 tmp_prob_rate = 0;
        u32 usecs;
        int i;
 
+       for (i=0; i < MAX_THR_RATES; i++)
+           tmp_tp_rate[i] = 0;
+
        for (i = 0; i < mi->n_rates; i++) {
                struct minstrel_rate *mr = &mi->r[i];
 
@@ -120,35 +137,27 @@ minstrel_update_stats(struct minstrel_priv *mp, struct minstrel_sta_info *mi)
                }
                if (!mr->adjusted_retry_count)
                        mr->adjusted_retry_count = 2;
-       }
 
-       for (i = 0; i < mi->n_rates; i++) {
-               struct minstrel_rate *mr = &mi->r[i];
-               if (max_tp < mr->cur_tp) {
-                       index_max_tp = i;
-                       max_tp = mr->cur_tp;
-               }
-               if (max_prob < mr->probability) {
-                       index_max_prob = i;
-                       max_prob = mr->probability;
+               minstrel_sort_best_tp_rates(mi, i, tmp_tp_rate);
+
+               /* To determine the most robust rate (max_prob_rate) used at
+                * 3rd mmr stage we distinct between two cases:
+                * (1) if any success probabilitiy >= 95%, out of those rates
+                * choose the maximum throughput rate as max_prob_rate
+                * (2) if all success probabilities < 95%, the rate with
+                * highest success probability is choosen as max_prob_rate */
+               if (mr->probability >= MINSTREL_FRAC(95,100)) {
+                       if (mr->cur_tp >= mi->r[tmp_prob_rate].cur_tp)
+                               tmp_prob_rate = i;
+               } else {
+                       if (mr->probability >= mi->r[tmp_prob_rate].probability)
+                               tmp_prob_rate = i;
                }
        }
 
-       max_tp = 0;
-       for (i = 0; i < mi->n_rates; i++) {
-               struct minstrel_rate *mr = &mi->r[i];
-
-               if (i == index_max_tp)
-                       continue;
-
-               if (max_tp < mr->cur_tp) {
-                       index_max_tp2 = i;
-                       max_tp = mr->cur_tp;
-               }
-       }
-       mi->max_tp_rate = index_max_tp;
-       mi->max_tp_rate2 = index_max_tp2;
-       mi->max_prob_rate = index_max_prob;
+       /* Assign the new rate set */
+       memcpy(mi->max_tp_rate, tmp_tp_rate, sizeof(mi->max_tp_rate));
+       mi->max_prob_rate = tmp_prob_rate;
 
        /* Reset update timer */
        mi->stats_update = jiffies;
@@ -254,7 +263,7 @@ minstrel_get_rate(void *priv, struct ieee80211_sta *sta,
                sampling_ratio = mp->lookaround_rate;
 
        /* init rateindex [ndx] with max throughput rate */
-       ndx = mi->max_tp_rate;
+       ndx = mi->max_tp_rate[0];
 
        /* increase sum packet counter */
        mi->packet_count++;
@@ -322,7 +331,7 @@ minstrel_get_rate(void *priv, struct ieee80211_sta *sta,
         * to use it, as this only wastes precious airtime */
        if (!mrr_capable && rate_sampling &&
           (mi->r[ndx].probability > MINSTREL_FRAC(95, 100)))
-               ndx = mi->max_tp_rate;
+               ndx = mi->max_tp_rate[0];
 
        /* mrr setup for 1st stage */
        ar[0].idx = mi->r[ndx].rix;
@@ -342,9 +351,9 @@ minstrel_get_rate(void *priv, struct ieee80211_sta *sta,
                if (indirect_rate_sampling)
                        mrr_ndx[0] = sample_ndx;
                else
-                       mrr_ndx[0] = mi->max_tp_rate;
+                       mrr_ndx[0] = mi->max_tp_rate[0];
        } else {
-               mrr_ndx[0] = mi->max_tp_rate2;
+               mrr_ndx[0] = mi->max_tp_rate[1];
        }
 
        /* mrr setup for 3rd & 4th stage */