aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorThomas Huehn <thomas@net.t-labs.tu-berlin.de>2013-03-04 17:30:07 -0500
committerJohannes Berg <johannes.berg@intel.com>2013-03-06 10:36:10 -0500
commit2ff2b690c56588efc063288f71a9d1cea33772cb (patch)
treed4079a56194ea0abc45ecfaf713bb53aed61827b /net
parentdb8c5ee6924cda3823fac83ee8c4115d1a8248c8 (diff)
mac80211: improve minstrels rate sorting by means of throughput & probability
This patch improves the way minstrel sorts rates according to throughput and success probability. 3 FOR-loops across the entire rate set in function minstrel_update_stats() which where used to determine the fastest, second fastest and most robust rate are reduced to 1 FOR-loop. The sorted list of rates according throughput is extended to the best four rates as we need them in upcoming joint rate and power control. The sorting is done via the new function minstrel_sort_best_tp_rates(). The most robust rate selection is aligned with minstrel_ht's approach. Once any success probability is above 95% the one with the highest throughput is chosen as most robust rate. If success probabilities of all rates are below 95%, the rate with the highest succ. prob. is elected as most robust one Acked-by: Felix Fietkau <nbd@openwrt.org> Signed-off-by: Thomas Huehn <thomas@net.t-labs.tu-berlin.de> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net')
-rw-r--r--net/mac80211/rc80211_minstrel.c71
-rw-r--r--net/mac80211/rc80211_minstrel.h8
-rw-r--r--net/mac80211/rc80211_minstrel_debugfs.c6
3 files changed, 49 insertions, 36 deletions
diff --git a/net/mac80211/rc80211_minstrel.c b/net/mac80211/rc80211_minstrel.c
index f8d99a54798f..1c36c9b4fa4a 100644
--- a/net/mac80211/rc80211_minstrel.c
+++ b/net/mac80211/rc80211_minstrel.c
@@ -69,14 +69,31 @@ rix_to_ndx(struct minstrel_sta_info *mi, int rix)
69 return i; 69 return i;
70} 70}
71 71
72/* find & sort topmost throughput rates */
73static inline void
74minstrel_sort_best_tp_rates(struct minstrel_sta_info *mi, int i, u8 *tp_list)
75{
76 int j = MAX_THR_RATES;
77
78 while (j > 0 && mi->r[i].cur_tp > mi->r[tp_list[j - 1]].cur_tp)
79 j--;
80 if (j < MAX_THR_RATES - 1)
81 memmove(&tp_list[j + 1], &tp_list[j], MAX_THR_RATES - (j + 1));
82 if (j < MAX_THR_RATES)
83 tp_list[j] = i;
84}
85
72static void 86static void
73minstrel_update_stats(struct minstrel_priv *mp, struct minstrel_sta_info *mi) 87minstrel_update_stats(struct minstrel_priv *mp, struct minstrel_sta_info *mi)
74{ 88{
75 u32 max_tp = 0, index_max_tp = 0, index_max_tp2 = 0; 89 u8 tmp_tp_rate[MAX_THR_RATES];
76 u32 max_prob = 0, index_max_prob = 0; 90 u8 tmp_prob_rate = 0;
77 u32 usecs; 91 u32 usecs;
78 int i; 92 int i;
79 93
94 for (i=0; i < MAX_THR_RATES; i++)
95 tmp_tp_rate[i] = 0;
96
80 for (i = 0; i < mi->n_rates; i++) { 97 for (i = 0; i < mi->n_rates; i++) {
81 struct minstrel_rate *mr = &mi->r[i]; 98 struct minstrel_rate *mr = &mi->r[i];
82 99
@@ -120,35 +137,27 @@ minstrel_update_stats(struct minstrel_priv *mp, struct minstrel_sta_info *mi)
120 } 137 }
121 if (!mr->adjusted_retry_count) 138 if (!mr->adjusted_retry_count)
122 mr->adjusted_retry_count = 2; 139 mr->adjusted_retry_count = 2;
123 }
124 140
125 for (i = 0; i < mi->n_rates; i++) { 141 minstrel_sort_best_tp_rates(mi, i, tmp_tp_rate);
126 struct minstrel_rate *mr = &mi->r[i]; 142
127 if (max_tp < mr->cur_tp) { 143 /* To determine the most robust rate (max_prob_rate) used at
128 index_max_tp = i; 144 * 3rd mmr stage we distinct between two cases:
129 max_tp = mr->cur_tp; 145 * (1) if any success probabilitiy >= 95%, out of those rates
130 } 146 * choose the maximum throughput rate as max_prob_rate
131 if (max_prob < mr->probability) { 147 * (2) if all success probabilities < 95%, the rate with
132 index_max_prob = i; 148 * highest success probability is choosen as max_prob_rate */
133 max_prob = mr->probability; 149 if (mr->probability >= MINSTREL_FRAC(95,100)) {
150 if (mr->cur_tp >= mi->r[tmp_prob_rate].cur_tp)
151 tmp_prob_rate = i;
152 } else {
153 if (mr->probability >= mi->r[tmp_prob_rate].probability)
154 tmp_prob_rate = i;
134 } 155 }
135 } 156 }
136 157
137 max_tp = 0; 158 /* Assign the new rate set */
138 for (i = 0; i < mi->n_rates; i++) { 159 memcpy(mi->max_tp_rate, tmp_tp_rate, sizeof(mi->max_tp_rate));
139 struct minstrel_rate *mr = &mi->r[i]; 160 mi->max_prob_rate = tmp_prob_rate;
140
141 if (i == index_max_tp)
142 continue;
143
144 if (max_tp < mr->cur_tp) {
145 index_max_tp2 = i;
146 max_tp = mr->cur_tp;
147 }
148 }
149 mi->max_tp_rate = index_max_tp;
150 mi->max_tp_rate2 = index_max_tp2;
151 mi->max_prob_rate = index_max_prob;
152 161
153 /* Reset update timer */ 162 /* Reset update timer */
154 mi->stats_update = jiffies; 163 mi->stats_update = jiffies;
@@ -254,7 +263,7 @@ minstrel_get_rate(void *priv, struct ieee80211_sta *sta,
254 sampling_ratio = mp->lookaround_rate; 263 sampling_ratio = mp->lookaround_rate;
255 264
256 /* init rateindex [ndx] with max throughput rate */ 265 /* init rateindex [ndx] with max throughput rate */
257 ndx = mi->max_tp_rate; 266 ndx = mi->max_tp_rate[0];
258 267
259 /* increase sum packet counter */ 268 /* increase sum packet counter */
260 mi->packet_count++; 269 mi->packet_count++;
@@ -322,7 +331,7 @@ minstrel_get_rate(void *priv, struct ieee80211_sta *sta,
322 * to use it, as this only wastes precious airtime */ 331 * to use it, as this only wastes precious airtime */
323 if (!mrr_capable && rate_sampling && 332 if (!mrr_capable && rate_sampling &&
324 (mi->r[ndx].probability > MINSTREL_FRAC(95, 100))) 333 (mi->r[ndx].probability > MINSTREL_FRAC(95, 100)))
325 ndx = mi->max_tp_rate; 334 ndx = mi->max_tp_rate[0];
326 335
327 /* mrr setup for 1st stage */ 336 /* mrr setup for 1st stage */
328 ar[0].idx = mi->r[ndx].rix; 337 ar[0].idx = mi->r[ndx].rix;
@@ -342,9 +351,9 @@ minstrel_get_rate(void *priv, struct ieee80211_sta *sta,
342 if (indirect_rate_sampling) 351 if (indirect_rate_sampling)
343 mrr_ndx[0] = sample_ndx; 352 mrr_ndx[0] = sample_ndx;
344 else 353 else
345 mrr_ndx[0] = mi->max_tp_rate; 354 mrr_ndx[0] = mi->max_tp_rate[0];
346 } else { 355 } else {
347 mrr_ndx[0] = mi->max_tp_rate2; 356 mrr_ndx[0] = mi->max_tp_rate[1];
348 } 357 }
349 358
350 /* mrr setup for 3rd & 4th stage */ 359 /* mrr setup for 3rd & 4th stage */
diff --git a/net/mac80211/rc80211_minstrel.h b/net/mac80211/rc80211_minstrel.h
index a0ccc5779910..85ebf42cb46d 100644
--- a/net/mac80211/rc80211_minstrel.h
+++ b/net/mac80211/rc80211_minstrel.h
@@ -18,6 +18,9 @@
18#define MINSTREL_FRAC(val, div) (((val) << MINSTREL_SCALE) / div) 18#define MINSTREL_FRAC(val, div) (((val) << MINSTREL_SCALE) / div)
19#define MINSTREL_TRUNC(val) ((val) >> MINSTREL_SCALE) 19#define MINSTREL_TRUNC(val) ((val) >> MINSTREL_SCALE)
20 20
21/* number of highest throughput rates to consider*/
22#define MAX_THR_RATES 4
23
21/* 24/*
22 * Perform EWMA (Exponentially Weighted Moving Average) calculation 25 * Perform EWMA (Exponentially Weighted Moving Average) calculation
23 */ 26 */
@@ -65,9 +68,8 @@ struct minstrel_sta_info {
65 68
66 unsigned int lowest_rix; 69 unsigned int lowest_rix;
67 70
68 unsigned int max_tp_rate; 71 u8 max_tp_rate[MAX_THR_RATES];
69 unsigned int max_tp_rate2; 72 u8 max_prob_rate;
70 unsigned int max_prob_rate;
71 unsigned int packet_count; 73 unsigned int packet_count;
72 unsigned int sample_count; 74 unsigned int sample_count;
73 int sample_deferred; 75 int sample_deferred;
diff --git a/net/mac80211/rc80211_minstrel_debugfs.c b/net/mac80211/rc80211_minstrel_debugfs.c
index c0ebfaca6ba0..d1048348d399 100644
--- a/net/mac80211/rc80211_minstrel_debugfs.c
+++ b/net/mac80211/rc80211_minstrel_debugfs.c
@@ -73,8 +73,10 @@ minstrel_stats_open(struct inode *inode, struct file *file)
73 for (i = 0; i < mi->n_rates; i++) { 73 for (i = 0; i < mi->n_rates; i++) {
74 struct minstrel_rate *mr = &mi->r[i]; 74 struct minstrel_rate *mr = &mi->r[i];
75 75
76 *(p++) = (i == mi->max_tp_rate) ? 'T' : ' '; 76 *(p++) = (i == mi->max_tp_rate[0]) ? 'A' : ' ';
77 *(p++) = (i == mi->max_tp_rate2) ? 't' : ' '; 77 *(p++) = (i == mi->max_tp_rate[1]) ? 'B' : ' ';
78 *(p++) = (i == mi->max_tp_rate[2]) ? 'C' : ' ';
79 *(p++) = (i == mi->max_tp_rate[3]) ? 'D' : ' ';
78 *(p++) = (i == mi->max_prob_rate) ? 'P' : ' '; 80 *(p++) = (i == mi->max_prob_rate) ? 'P' : ' ';
79 p += sprintf(p, "%3u%s", mr->bitrate / 2, 81 p += sprintf(p, "%3u%s", mr->bitrate / 2,
80 (mr->bitrate & 1 ? ".5" : " ")); 82 (mr->bitrate & 1 ? ".5" : " "));