|
@@ -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 */
|