aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Huehn <thomas@net.t-labs.tu-berlin.de>2015-03-24 16:09:40 -0400
committerJohannes Berg <johannes.berg@intel.com>2015-04-01 14:44:32 -0400
commit6a27b2c40b4829e625bc1dfdd0705c5ece720ab4 (patch)
tree78581e6b867299e807b9d31febe9655ba5579d7e
parent9134073bc693633b5e1f1a7252c93b3fb262aae4 (diff)
mac80211: restructure per-rate throughput calculation into function
This patch moves Minstrels and Minstrel-HTs per-rate throughput calculation (EWMA(thr)) into a dedicated function to be called. Therefore the variable "unsigned int cur_tp" within struct "minstrel_rate_stats" becomes obsolete. and is removed to free up its space. Signed-off-by: Thomas Huehn <thomas@net.t-labs.tu-berlin.de> Acked-by: Felix Fietkau <nbd@openwrt.org> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
-rw-r--r--net/mac80211/rc80211_minstrel.c43
-rw-r--r--net/mac80211/rc80211_minstrel.h4
-rw-r--r--net/mac80211/rc80211_minstrel_debugfs.c12
-rw-r--r--net/mac80211/rc80211_minstrel_ht.c77
-rw-r--r--net/mac80211/rc80211_minstrel_ht.h1
-rw-r--r--net/mac80211/rc80211_minstrel_ht_debugfs.c12
6 files changed, 88 insertions, 61 deletions
diff --git a/net/mac80211/rc80211_minstrel.c b/net/mac80211/rc80211_minstrel.c
index c86e42b67908..61a857bca971 100644
--- a/net/mac80211/rc80211_minstrel.c
+++ b/net/mac80211/rc80211_minstrel.c
@@ -69,14 +69,32 @@ rix_to_ndx(struct minstrel_sta_info *mi, int rix)
69 return i; 69 return i;
70} 70}
71 71
72/* return current EMWA throughput */
73int minstrel_get_tp_avg(struct minstrel_rate *mr)
74{
75 int usecs;
76
77 usecs = mr->perfect_tx_time;
78 if (!usecs)
79 usecs = 1000000;
80
81 /* reset thr. below 10% success */
82 if (mr->stats.prob_ewma < MINSTREL_FRAC(10, 100))
83 return 0;
84 else
85 return MINSTREL_TRUNC(mr->stats.prob_ewma * (100000 / usecs));
86}
87
72/* find & sort topmost throughput rates */ 88/* find & sort topmost throughput rates */
73static inline void 89static inline void
74minstrel_sort_best_tp_rates(struct minstrel_sta_info *mi, int i, u8 *tp_list) 90minstrel_sort_best_tp_rates(struct minstrel_sta_info *mi, int i, u8 *tp_list)
75{ 91{
76 int j = MAX_THR_RATES; 92 int j = MAX_THR_RATES;
77 93
78 while (j > 0 && mi->r[i].stats.cur_tp > mi->r[tp_list[j - 1]].stats.cur_tp) 94 while (j > 0 && (minstrel_get_tp_avg(&mi->r[i]) >
95 minstrel_get_tp_avg(&mi->r[tp_list[j - 1]])))
79 j--; 96 j--;
97
80 if (j < MAX_THR_RATES - 1) 98 if (j < MAX_THR_RATES - 1)
81 memmove(&tp_list[j + 1], &tp_list[j], MAX_THR_RATES - (j + 1)); 99 memmove(&tp_list[j + 1], &tp_list[j], MAX_THR_RATES - (j + 1));
82 if (j < MAX_THR_RATES) 100 if (j < MAX_THR_RATES)
@@ -158,8 +176,7 @@ minstrel_update_stats(struct minstrel_priv *mp, struct minstrel_sta_info *mi)
158{ 176{
159 u8 tmp_tp_rate[MAX_THR_RATES]; 177 u8 tmp_tp_rate[MAX_THR_RATES];
160 u8 tmp_prob_rate = 0; 178 u8 tmp_prob_rate = 0;
161 u32 usecs; 179 int i, tmp_cur_tp, tmp_prob_tp;
162 int i;
163 180
164 for (i = 0; i < MAX_THR_RATES; i++) 181 for (i = 0; i < MAX_THR_RATES; i++)
165 tmp_tp_rate[i] = 0; 182 tmp_tp_rate[i] = 0;
@@ -168,19 +185,9 @@ minstrel_update_stats(struct minstrel_priv *mp, struct minstrel_sta_info *mi)
168 struct minstrel_rate *mr = &mi->r[i]; 185 struct minstrel_rate *mr = &mi->r[i];
169 struct minstrel_rate_stats *mrs = &mi->r[i].stats; 186 struct minstrel_rate_stats *mrs = &mi->r[i].stats;
170 187
171 usecs = mr->perfect_tx_time;
172 if (!usecs)
173 usecs = 1000000;
174
175 /* Update success probabilities per rate */ 188 /* Update success probabilities per rate */
176 minstrel_calc_rate_stats(mrs); 189 minstrel_calc_rate_stats(mrs);
177 190
178 /* Update throughput per rate, reset thr. below 10% success */
179 if (mrs->prob_ewma < MINSTREL_FRAC(10, 100))
180 mrs->cur_tp = 0;
181 else
182 mrs->cur_tp = mrs->prob_ewma * (1000000 / usecs);
183
184 /* Sample less often below the 10% chance of success. 191 /* Sample less often below the 10% chance of success.
185 * Sample less often above the 95% chance of success. */ 192 * Sample less often above the 95% chance of success. */
186 if (mrs->prob_ewma > MINSTREL_FRAC(95, 100) || 193 if (mrs->prob_ewma > MINSTREL_FRAC(95, 100) ||
@@ -205,7 +212,9 @@ minstrel_update_stats(struct minstrel_priv *mp, struct minstrel_sta_info *mi)
205 * (2) if all success probabilities < 95%, the rate with 212 * (2) if all success probabilities < 95%, the rate with
206 * highest success probability is chosen as max_prob_rate */ 213 * highest success probability is chosen as max_prob_rate */
207 if (mrs->prob_ewma >= MINSTREL_FRAC(95, 100)) { 214 if (mrs->prob_ewma >= MINSTREL_FRAC(95, 100)) {
208 if (mrs->cur_tp >= mi->r[tmp_prob_rate].stats.cur_tp) 215 tmp_cur_tp = minstrel_get_tp_avg(mr);
216 tmp_prob_tp = minstrel_get_tp_avg(&mi->r[tmp_prob_rate]);
217 if (tmp_cur_tp >= tmp_prob_tp)
209 tmp_prob_rate = i; 218 tmp_prob_rate = i;
210 } else { 219 } else {
211 if (mrs->prob_ewma >= mi->r[tmp_prob_rate].stats.prob_ewma) 220 if (mrs->prob_ewma >= mi->r[tmp_prob_rate].stats.prob_ewma)
@@ -676,11 +685,15 @@ static u32 minstrel_get_expected_throughput(void *priv_sta)
676{ 685{
677 struct minstrel_sta_info *mi = priv_sta; 686 struct minstrel_sta_info *mi = priv_sta;
678 int idx = mi->max_tp_rate[0]; 687 int idx = mi->max_tp_rate[0];
688 int tmp_cur_tp;
679 689
680 /* convert pkt per sec in kbps (1200 is the average pkt size used for 690 /* convert pkt per sec in kbps (1200 is the average pkt size used for
681 * computing cur_tp 691 * computing cur_tp
682 */ 692 */
683 return MINSTREL_TRUNC(mi->r[idx].stats.cur_tp) * 1200 * 8 / 1024; 693 tmp_cur_tp = minstrel_get_tp_avg(&mi->r[idx]);
694 tmp_cur_tp = tmp_cur_tp * 1200 * 8 / 1024;
695
696 return tmp_cur_tp;
684} 697}
685 698
686const struct rate_control_ops mac80211_minstrel = { 699const struct rate_control_ops mac80211_minstrel = {
diff --git a/net/mac80211/rc80211_minstrel.h b/net/mac80211/rc80211_minstrel.h
index 58f287028437..490df3b1f3ec 100644
--- a/net/mac80211/rc80211_minstrel.h
+++ b/net/mac80211/rc80211_minstrel.h
@@ -38,9 +38,6 @@ struct minstrel_rate_stats {
38 /* total attempts/success counters */ 38 /* total attempts/success counters */
39 u64 att_hist, succ_hist; 39 u64 att_hist, succ_hist;
40 40
41 /* current EWMA of rate throughput */
42 unsigned int cur_tp;
43
44 /* statistis of packet delivery probability 41 /* statistis of packet delivery probability
45 * cur_prob - current prob within last update intervall 42 * cur_prob - current prob within last update intervall
46 * prob_ewma - exponential weighted moving average of prob */ 43 * prob_ewma - exponential weighted moving average of prob */
@@ -137,6 +134,7 @@ void minstrel_remove_sta_debugfs(void *priv, void *priv_sta);
137 134
138/* Recalculate success probabilities and counters for a given rate using EWMA */ 135/* Recalculate success probabilities and counters for a given rate using EWMA */
139void minstrel_calc_rate_stats(struct minstrel_rate_stats *mrs); 136void minstrel_calc_rate_stats(struct minstrel_rate_stats *mrs);
137int minstrel_get_tp_avg(struct minstrel_rate *mr);
140 138
141/* debugfs */ 139/* debugfs */
142int minstrel_stats_open(struct inode *inode, struct file *file); 140int minstrel_stats_open(struct inode *inode, struct file *file);
diff --git a/net/mac80211/rc80211_minstrel_debugfs.c b/net/mac80211/rc80211_minstrel_debugfs.c
index 8a0b73eda99a..188e9858713f 100644
--- a/net/mac80211/rc80211_minstrel_debugfs.c
+++ b/net/mac80211/rc80211_minstrel_debugfs.c
@@ -75,7 +75,7 @@ minstrel_stats_open(struct inode *inode, struct file *file)
75{ 75{
76 struct minstrel_sta_info *mi = inode->i_private; 76 struct minstrel_sta_info *mi = inode->i_private;
77 struct minstrel_debugfs_info *ms; 77 struct minstrel_debugfs_info *ms;
78 unsigned int i, tp, prob, eprob; 78 unsigned int i, tp_avg, prob, eprob;
79 char *p; 79 char *p;
80 80
81 ms = kmalloc(2048, GFP_KERNEL); 81 ms = kmalloc(2048, GFP_KERNEL);
@@ -105,13 +105,13 @@ minstrel_stats_open(struct inode *inode, struct file *file)
105 p += sprintf(p, "%3u ", i); 105 p += sprintf(p, "%3u ", i);
106 p += sprintf(p, "%6u ", mr->perfect_tx_time); 106 p += sprintf(p, "%6u ", mr->perfect_tx_time);
107 107
108 tp = MINSTREL_TRUNC(mrs->cur_tp / 10); 108 tp_avg = minstrel_get_tp_avg(mr);
109 prob = MINSTREL_TRUNC(mrs->cur_prob * 1000); 109 prob = MINSTREL_TRUNC(mrs->cur_prob * 1000);
110 eprob = MINSTREL_TRUNC(mrs->prob_ewma * 1000); 110 eprob = MINSTREL_TRUNC(mrs->prob_ewma * 1000);
111 111
112 p += sprintf(p, " %4u.%1u %3u.%1u %3u.%1u %3u" 112 p += sprintf(p, " %4u.%1u %3u.%1u %3u.%1u %3u"
113 " %3u %-3u %9llu %-9llu\n", 113 " %3u %-3u %9llu %-9llu\n",
114 tp / 10, tp % 10, 114 tp_avg / 10, tp_avg % 10,
115 eprob / 10, eprob % 10, 115 eprob / 10, eprob % 10,
116 prob / 10, prob % 10, 116 prob / 10, prob % 10,
117 mrs->retry_count, 117 mrs->retry_count,
@@ -144,7 +144,7 @@ minstrel_stats_csv_open(struct inode *inode, struct file *file)
144{ 144{
145 struct minstrel_sta_info *mi = inode->i_private; 145 struct minstrel_sta_info *mi = inode->i_private;
146 struct minstrel_debugfs_info *ms; 146 struct minstrel_debugfs_info *ms;
147 unsigned int i, tp, prob, eprob; 147 unsigned int i, tp_avg, prob, eprob;
148 char *p; 148 char *p;
149 149
150 ms = kmalloc(2048, GFP_KERNEL); 150 ms = kmalloc(2048, GFP_KERNEL);
@@ -169,13 +169,13 @@ minstrel_stats_csv_open(struct inode *inode, struct file *file)
169 p += sprintf(p, "%u,", i); 169 p += sprintf(p, "%u,", i);
170 p += sprintf(p, "%u,",mr->perfect_tx_time); 170 p += sprintf(p, "%u,",mr->perfect_tx_time);
171 171
172 tp = MINSTREL_TRUNC(mrs->cur_tp / 10); 172 tp_avg = minstrel_get_tp_avg(mr);
173 prob = MINSTREL_TRUNC(mrs->cur_prob * 1000); 173 prob = MINSTREL_TRUNC(mrs->cur_prob * 1000);
174 eprob = MINSTREL_TRUNC(mrs->prob_ewma * 1000); 174 eprob = MINSTREL_TRUNC(mrs->prob_ewma * 1000);
175 175
176 p += sprintf(p, "%u.%u,%u.%u,%u.%u,%u,%u,%u," 176 p += sprintf(p, "%u.%u,%u.%u,%u.%u,%u,%u,%u,"
177 "%llu,%llu,%d,%d\n", 177 "%llu,%llu,%d,%d\n",
178 tp / 10, tp % 10, 178 tp_avg / 10, tp_avg % 10,
179 eprob / 10, eprob % 10, 179 eprob / 10, eprob % 10,
180 prob / 10, prob % 10, 180 prob / 10, prob % 10,
181 mrs->retry_count, 181 mrs->retry_count,
diff --git a/net/mac80211/rc80211_minstrel_ht.c b/net/mac80211/rc80211_minstrel_ht.c
index aca8b642661c..7202e34ec04c 100644
--- a/net/mac80211/rc80211_minstrel_ht.c
+++ b/net/mac80211/rc80211_minstrel_ht.c
@@ -314,11 +314,11 @@ minstrel_get_ratestats(struct minstrel_ht_sta *mi, int index)
314} 314}
315 315
316/* 316/*
317 * Calculate throughput based on the average A-MPDU length, taking into account 317 * Return current throughput based on the average A-MPDU length, taking into
318 * the expected number of retransmissions and their expected length 318 * account the expected number of retransmissions and their expected length
319 */ 319 */
320static void 320int
321minstrel_ht_calc_tp(struct minstrel_ht_sta *mi, int group, int rate) 321minstrel_ht_get_tp_avg(struct minstrel_ht_sta *mi, int group, int rate)
322{ 322{
323 struct minstrel_rate_stats *mrs; 323 struct minstrel_rate_stats *mrs;
324 unsigned int nsecs = 0; 324 unsigned int nsecs = 0;
@@ -328,10 +328,8 @@ minstrel_ht_calc_tp(struct minstrel_ht_sta *mi, int group, int rate)
328 tmp_prob_ewma = mrs->prob_ewma; 328 tmp_prob_ewma = mrs->prob_ewma;
329 329
330 /* do not account throughput if sucess prob is below 10% */ 330 /* do not account throughput if sucess prob is below 10% */
331 if (mrs->prob_ewma < MINSTREL_FRAC(10, 100)) { 331 if (mrs->prob_ewma < MINSTREL_FRAC(10, 100))
332 mrs->cur_tp = 0; 332 return 0;
333 return;
334 }
335 333
336 /* 334 /*
337 * For the throughput calculation, limit the probability value to 90% to 335 * For the throughput calculation, limit the probability value to 90% to
@@ -346,7 +344,7 @@ minstrel_ht_calc_tp(struct minstrel_ht_sta *mi, int group, int rate)
346 nsecs += minstrel_mcs_groups[group].duration[rate]; 344 nsecs += minstrel_mcs_groups[group].duration[rate];
347 345
348 /* prob is scaled - see MINSTREL_FRAC above */ 346 /* prob is scaled - see MINSTREL_FRAC above */
349 mrs->cur_tp = MINSTREL_TRUNC(1000000 * ((tmp_prob_ewma * 1000) / nsecs)); 347 return MINSTREL_TRUNC(100000 * ((tmp_prob_ewma * 1000) / nsecs));
350} 348}
351 349
352/* 350/*
@@ -360,22 +358,22 @@ static void
360minstrel_ht_sort_best_tp_rates(struct minstrel_ht_sta *mi, u16 index, 358minstrel_ht_sort_best_tp_rates(struct minstrel_ht_sta *mi, u16 index,
361 u16 *tp_list) 359 u16 *tp_list)
362{ 360{
363 int cur_group, cur_idx, cur_thr, cur_prob; 361 int cur_group, cur_idx, cur_tp_avg, cur_prob;
364 int tmp_group, tmp_idx, tmp_thr, tmp_prob; 362 int tmp_group, tmp_idx, tmp_tp_avg, tmp_prob;
365 int j = MAX_THR_RATES; 363 int j = MAX_THR_RATES;
366 364
367 cur_group = index / MCS_GROUP_RATES; 365 cur_group = index / MCS_GROUP_RATES;
368 cur_idx = index % MCS_GROUP_RATES; 366 cur_idx = index % MCS_GROUP_RATES;
369 cur_thr = mi->groups[cur_group].rates[cur_idx].cur_tp; 367 cur_tp_avg = minstrel_ht_get_tp_avg(mi, cur_group, cur_idx);
370 cur_prob = mi->groups[cur_group].rates[cur_idx].prob_ewma; 368 cur_prob = mi->groups[cur_group].rates[cur_idx].prob_ewma;
371 369
372 do { 370 do {
373 tmp_group = tp_list[j - 1] / MCS_GROUP_RATES; 371 tmp_group = tp_list[j - 1] / MCS_GROUP_RATES;
374 tmp_idx = tp_list[j - 1] % MCS_GROUP_RATES; 372 tmp_idx = tp_list[j - 1] % MCS_GROUP_RATES;
375 tmp_thr = mi->groups[tmp_group].rates[tmp_idx].cur_tp; 373 tmp_tp_avg = minstrel_ht_get_tp_avg(mi, tmp_group, tmp_idx);
376 tmp_prob = mi->groups[tmp_group].rates[tmp_idx].prob_ewma; 374 tmp_prob = mi->groups[tmp_group].rates[tmp_idx].prob_ewma;
377 if (cur_thr < tmp_thr || 375 if (cur_tp_avg < tmp_tp_avg ||
378 (cur_thr == tmp_thr && cur_prob <= tmp_prob)) 376 (cur_tp_avg == tmp_tp_avg && cur_prob <= tmp_prob))
379 break; 377 break;
380 j--; 378 j--;
381 } while (j > 0); 379 } while (j > 0);
@@ -396,14 +394,19 @@ minstrel_ht_set_best_prob_rate(struct minstrel_ht_sta *mi, u16 index)
396{ 394{
397 struct minstrel_mcs_group_data *mg; 395 struct minstrel_mcs_group_data *mg;
398 struct minstrel_rate_stats *mrs; 396 struct minstrel_rate_stats *mrs;
399 int tmp_group, tmp_idx, tmp_tp, tmp_prob, max_tp_group; 397 int tmp_group, tmp_idx, tmp_tp_avg, tmp_prob;
398 int max_tp_group, cur_tp_avg, cur_group, cur_idx;
399 int max_group_prob_rate_group, max_group_prob_rate_idx;
400 int max_group_prob_rate_tp_avg;
400 401
402 cur_group = index / MCS_GROUP_RATES;
403 cur_idx = index % MCS_GROUP_RATES;
401 mg = &mi->groups[index / MCS_GROUP_RATES]; 404 mg = &mi->groups[index / MCS_GROUP_RATES];
402 mrs = &mg->rates[index % MCS_GROUP_RATES]; 405 mrs = &mg->rates[index % MCS_GROUP_RATES];
403 406
404 tmp_group = mi->max_prob_rate / MCS_GROUP_RATES; 407 tmp_group = mi->max_prob_rate / MCS_GROUP_RATES;
405 tmp_idx = mi->max_prob_rate % MCS_GROUP_RATES; 408 tmp_idx = mi->max_prob_rate % MCS_GROUP_RATES;
406 tmp_tp = mi->groups[tmp_group].rates[tmp_idx].cur_tp; 409 tmp_tp_avg = minstrel_ht_get_tp_avg(mi, tmp_group, tmp_idx);
407 tmp_prob = mi->groups[tmp_group].rates[tmp_idx].prob_ewma; 410 tmp_prob = mi->groups[tmp_group].rates[tmp_idx].prob_ewma;
408 411
409 /* if max_tp_rate[0] is from MCS_GROUP max_prob_rate get selected from 412 /* if max_tp_rate[0] is from MCS_GROUP max_prob_rate get selected from
@@ -414,9 +417,18 @@ minstrel_ht_set_best_prob_rate(struct minstrel_ht_sta *mi, u16 index)
414 return; 417 return;
415 418
416 if (mrs->prob_ewma > MINSTREL_FRAC(75, 100)) { 419 if (mrs->prob_ewma > MINSTREL_FRAC(75, 100)) {
417 if (mrs->cur_tp > tmp_tp) 420 cur_tp_avg = minstrel_ht_get_tp_avg(mi, cur_group, cur_idx);
421 if (cur_tp_avg > tmp_tp_avg)
418 mi->max_prob_rate = index; 422 mi->max_prob_rate = index;
419 if (mrs->cur_tp > mg->rates[mg->max_group_prob_rate].cur_tp) 423
424 max_group_prob_rate_group = mg->max_group_prob_rate /
425 MCS_GROUP_RATES;
426 max_group_prob_rate_idx = mg->max_group_prob_rate %
427 MCS_GROUP_RATES;
428 max_group_prob_rate_tp_avg = minstrel_ht_get_tp_avg(mi,
429 max_group_prob_rate_group,
430 max_group_prob_rate_idx);
431 if (cur_tp_avg > max_group_prob_rate_tp_avg)
420 mg->max_group_prob_rate = index; 432 mg->max_group_prob_rate = index;
421 } else { 433 } else {
422 if (mrs->prob_ewma > tmp_prob) 434 if (mrs->prob_ewma > tmp_prob)
@@ -443,11 +455,11 @@ minstrel_ht_assign_best_tp_rates(struct minstrel_ht_sta *mi,
443 455
444 tmp_group = tmp_cck_tp_rate[0] / MCS_GROUP_RATES; 456 tmp_group = tmp_cck_tp_rate[0] / MCS_GROUP_RATES;
445 tmp_idx = tmp_cck_tp_rate[0] % MCS_GROUP_RATES; 457 tmp_idx = tmp_cck_tp_rate[0] % MCS_GROUP_RATES;
446 tmp_cck_tp = mi->groups[tmp_group].rates[tmp_idx].cur_tp; 458 tmp_cck_tp = minstrel_ht_get_tp_avg(mi, tmp_group, tmp_idx);
447 459
448 tmp_group = tmp_mcs_tp_rate[0] / MCS_GROUP_RATES; 460 tmp_group = tmp_mcs_tp_rate[0] / MCS_GROUP_RATES;
449 tmp_idx = tmp_mcs_tp_rate[0] % MCS_GROUP_RATES; 461 tmp_idx = tmp_mcs_tp_rate[0] % MCS_GROUP_RATES;
450 tmp_mcs_tp = mi->groups[tmp_group].rates[tmp_idx].cur_tp; 462 tmp_mcs_tp = minstrel_ht_get_tp_avg(mi, tmp_group, tmp_idx);
451 463
452 if (tmp_cck_tp > tmp_mcs_tp) { 464 if (tmp_cck_tp > tmp_mcs_tp) {
453 for(i = 0; i < MAX_THR_RATES; i++) { 465 for(i = 0; i < MAX_THR_RATES; i++) {
@@ -466,8 +478,7 @@ static inline void
466minstrel_ht_prob_rate_reduce_streams(struct minstrel_ht_sta *mi) 478minstrel_ht_prob_rate_reduce_streams(struct minstrel_ht_sta *mi)
467{ 479{
468 struct minstrel_mcs_group_data *mg; 480 struct minstrel_mcs_group_data *mg;
469 struct minstrel_rate_stats *mrs; 481 int tmp_max_streams, group, tmp_idx;
470 int tmp_max_streams, group;
471 int tmp_tp = 0; 482 int tmp_tp = 0;
472 483
473 tmp_max_streams = minstrel_mcs_groups[mi->max_tp_rate[0] / 484 tmp_max_streams = minstrel_mcs_groups[mi->max_tp_rate[0] /
@@ -476,11 +487,14 @@ minstrel_ht_prob_rate_reduce_streams(struct minstrel_ht_sta *mi)
476 mg = &mi->groups[group]; 487 mg = &mi->groups[group];
477 if (!mg->supported || group == MINSTREL_CCK_GROUP) 488 if (!mg->supported || group == MINSTREL_CCK_GROUP)
478 continue; 489 continue;
479 mrs = minstrel_get_ratestats(mi, mg->max_group_prob_rate); 490
480 if (tmp_tp < mrs->cur_tp && 491 tmp_idx = mg->max_group_prob_rate % MCS_GROUP_RATES;
492
493 if (tmp_tp < minstrel_ht_get_tp_avg(mi, group, tmp_idx) &&
481 (minstrel_mcs_groups[group].streams < tmp_max_streams)) { 494 (minstrel_mcs_groups[group].streams < tmp_max_streams)) {
482 mi->max_prob_rate = mg->max_group_prob_rate; 495 mi->max_prob_rate = mg->max_group_prob_rate;
483 tmp_tp = mrs->cur_tp; 496 tmp_tp = minstrel_ht_get_tp_avg(mi, group,
497 tmp_idx);
484 } 498 }
485 } 499 }
486} 500}
@@ -541,9 +555,8 @@ minstrel_ht_update_stats(struct minstrel_priv *mp, struct minstrel_ht_sta *mi)
541 mrs = &mg->rates[i]; 555 mrs = &mg->rates[i];
542 mrs->retry_updated = false; 556 mrs->retry_updated = false;
543 minstrel_calc_rate_stats(mrs); 557 minstrel_calc_rate_stats(mrs);
544 minstrel_ht_calc_tp(mi, group, i);
545 558
546 if (!mrs->cur_tp) 559 if (minstrel_ht_get_tp_avg(mi, group, i) == 0)
547 continue; 560 continue;
548 561
549 /* Find max throughput rate set */ 562 /* Find max throughput rate set */
@@ -1302,7 +1315,7 @@ static u32 minstrel_ht_get_expected_throughput(void *priv_sta)
1302{ 1315{
1303 struct minstrel_ht_sta_priv *msp = priv_sta; 1316 struct minstrel_ht_sta_priv *msp = priv_sta;
1304 struct minstrel_ht_sta *mi = &msp->ht; 1317 struct minstrel_ht_sta *mi = &msp->ht;
1305 int i, j; 1318 int i, j, tp_avg;
1306 1319
1307 if (!msp->is_ht) 1320 if (!msp->is_ht)
1308 return mac80211_minstrel.get_expected_throughput(priv_sta); 1321 return mac80211_minstrel.get_expected_throughput(priv_sta);
@@ -1310,8 +1323,10 @@ static u32 minstrel_ht_get_expected_throughput(void *priv_sta)
1310 i = mi->max_tp_rate[0] / MCS_GROUP_RATES; 1323 i = mi->max_tp_rate[0] / MCS_GROUP_RATES;
1311 j = mi->max_tp_rate[0] % MCS_GROUP_RATES; 1324 j = mi->max_tp_rate[0] % MCS_GROUP_RATES;
1312 1325
1313 /* convert cur_tp from pkt per second in kbps */ 1326 /* convert tp_avg from pkt per second in kbps */
1314 return mi->groups[i].rates[j].cur_tp * AVG_PKT_SIZE * 8 / 1024; 1327 tp_avg = minstrel_ht_get_tp_avg(mi, i, j) * AVG_PKT_SIZE * 8 / 1024;
1328
1329 return tp_avg;
1315} 1330}
1316 1331
1317static const struct rate_control_ops mac80211_minstrel_ht = { 1332static const struct rate_control_ops mac80211_minstrel_ht = {
diff --git a/net/mac80211/rc80211_minstrel_ht.h b/net/mac80211/rc80211_minstrel_ht.h
index fa21a82b72c4..68dce4f8641c 100644
--- a/net/mac80211/rc80211_minstrel_ht.h
+++ b/net/mac80211/rc80211_minstrel_ht.h
@@ -121,5 +121,6 @@ struct minstrel_ht_sta_priv {
121 121
122void minstrel_ht_add_sta_debugfs(void *priv, void *priv_sta, struct dentry *dir); 122void minstrel_ht_add_sta_debugfs(void *priv, void *priv_sta, struct dentry *dir);
123void minstrel_ht_remove_sta_debugfs(void *priv, void *priv_sta); 123void minstrel_ht_remove_sta_debugfs(void *priv, void *priv_sta);
124int minstrel_ht_get_tp_avg(struct minstrel_ht_sta *mi, int group, int rate);
124 125
125#endif 126#endif
diff --git a/net/mac80211/rc80211_minstrel_ht_debugfs.c b/net/mac80211/rc80211_minstrel_ht_debugfs.c
index 84183dee9ef2..721cf74ea9a6 100644
--- a/net/mac80211/rc80211_minstrel_ht_debugfs.c
+++ b/net/mac80211/rc80211_minstrel_ht_debugfs.c
@@ -19,7 +19,7 @@ static char *
19minstrel_ht_stats_dump(struct minstrel_ht_sta *mi, int i, char *p) 19minstrel_ht_stats_dump(struct minstrel_ht_sta *mi, int i, char *p)
20{ 20{
21 const struct mcs_group *mg; 21 const struct mcs_group *mg;
22 unsigned int j, tp, prob, eprob, tx_time; 22 unsigned int j, tp_avg, prob, eprob, tx_time;
23 char htmode = '2'; 23 char htmode = '2';
24 char gimode = 'L'; 24 char gimode = 'L';
25 u32 gflags; 25 u32 gflags;
@@ -81,13 +81,13 @@ minstrel_ht_stats_dump(struct minstrel_ht_sta *mi, int i, char *p)
81 tx_time = DIV_ROUND_CLOSEST(mg->duration[j], 1000); 81 tx_time = DIV_ROUND_CLOSEST(mg->duration[j], 1000);
82 p += sprintf(p, "%6u ", tx_time); 82 p += sprintf(p, "%6u ", tx_time);
83 83
84 tp = mrs->cur_tp / 10; 84 tp_avg = minstrel_ht_get_tp_avg(mi, i, j);
85 prob = MINSTREL_TRUNC(mrs->cur_prob * 1000); 85 prob = MINSTREL_TRUNC(mrs->cur_prob * 1000);
86 eprob = MINSTREL_TRUNC(mrs->prob_ewma * 1000); 86 eprob = MINSTREL_TRUNC(mrs->prob_ewma * 1000);
87 87
88 p += sprintf(p, "%4u.%1u %3u.%1u %3u.%1u " 88 p += sprintf(p, "%4u.%1u %3u.%1u %3u.%1u "
89 "%3u %3u %-3u %9llu %-9llu\n", 89 "%3u %3u %-3u %9llu %-9llu\n",
90 tp / 10, tp % 10, 90 tp_avg / 10, tp_avg % 10,
91 eprob / 10, eprob % 10, 91 eprob / 10, eprob % 10,
92 prob / 10, prob % 10, 92 prob / 10, prob % 10,
93 mrs->retry_count, 93 mrs->retry_count,
@@ -163,7 +163,7 @@ static char *
163minstrel_ht_stats_csv_dump(struct minstrel_ht_sta *mi, int i, char *p) 163minstrel_ht_stats_csv_dump(struct minstrel_ht_sta *mi, int i, char *p)
164{ 164{
165 const struct mcs_group *mg; 165 const struct mcs_group *mg;
166 unsigned int j, tp, prob, eprob, tx_time; 166 unsigned int j, tp_avg, prob, eprob, tx_time;
167 char htmode = '2'; 167 char htmode = '2';
168 char gimode = 'L'; 168 char gimode = 'L';
169 u32 gflags; 169 u32 gflags;
@@ -222,12 +222,12 @@ minstrel_ht_stats_csv_dump(struct minstrel_ht_sta *mi, int i, char *p)
222 tx_time = DIV_ROUND_CLOSEST(mg->duration[j], 1000); 222 tx_time = DIV_ROUND_CLOSEST(mg->duration[j], 1000);
223 p += sprintf(p, "%u,", tx_time); 223 p += sprintf(p, "%u,", tx_time);
224 224
225 tp = mrs->cur_tp / 10; 225 tp_avg = minstrel_ht_get_tp_avg(mi, i, j);
226 prob = MINSTREL_TRUNC(mrs->cur_prob * 1000); 226 prob = MINSTREL_TRUNC(mrs->cur_prob * 1000);
227 eprob = MINSTREL_TRUNC(mrs->prob_ewma * 1000); 227 eprob = MINSTREL_TRUNC(mrs->prob_ewma * 1000);
228 228
229 p += sprintf(p, "%u.%u,%u.%u,%u.%u,%u,%u,%u,%llu,%llu,", 229 p += sprintf(p, "%u.%u,%u.%u,%u.%u,%u,%u,%u,%llu,%llu,",
230 tp / 10, tp % 10, 230 tp_avg / 10, tp_avg % 10,
231 eprob / 10, eprob % 10, 231 eprob / 10, eprob % 10,
232 prob / 10, prob % 10, 232 prob / 10, prob % 10,
233 mrs->retry_count, 233 mrs->retry_count,