diff options
author | Thomas Huehn <thomas@net.t-labs.tu-berlin.de> | 2015-03-24 16:09:40 -0400 |
---|---|---|
committer | Johannes Berg <johannes.berg@intel.com> | 2015-04-01 14:44:32 -0400 |
commit | 6a27b2c40b4829e625bc1dfdd0705c5ece720ab4 (patch) | |
tree | 78581e6b867299e807b9d31febe9655ba5579d7e | |
parent | 9134073bc693633b5e1f1a7252c93b3fb262aae4 (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.c | 43 | ||||
-rw-r--r-- | net/mac80211/rc80211_minstrel.h | 4 | ||||
-rw-r--r-- | net/mac80211/rc80211_minstrel_debugfs.c | 12 | ||||
-rw-r--r-- | net/mac80211/rc80211_minstrel_ht.c | 77 | ||||
-rw-r--r-- | net/mac80211/rc80211_minstrel_ht.h | 1 | ||||
-rw-r--r-- | net/mac80211/rc80211_minstrel_ht_debugfs.c | 12 |
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 */ | ||
73 | int 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 */ |
73 | static inline void | 89 | static inline void |
74 | minstrel_sort_best_tp_rates(struct minstrel_sta_info *mi, int i, u8 *tp_list) | 90 | minstrel_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 | ||
686 | const struct rate_control_ops mac80211_minstrel = { | 699 | const 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 */ |
139 | void minstrel_calc_rate_stats(struct minstrel_rate_stats *mrs); | 136 | void minstrel_calc_rate_stats(struct minstrel_rate_stats *mrs); |
137 | int minstrel_get_tp_avg(struct minstrel_rate *mr); | ||
140 | 138 | ||
141 | /* debugfs */ | 139 | /* debugfs */ |
142 | int minstrel_stats_open(struct inode *inode, struct file *file); | 140 | int 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 | */ |
320 | static void | 320 | int |
321 | minstrel_ht_calc_tp(struct minstrel_ht_sta *mi, int group, int rate) | 321 | minstrel_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 | |||
360 | minstrel_ht_sort_best_tp_rates(struct minstrel_ht_sta *mi, u16 index, | 358 | minstrel_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 | |||
466 | minstrel_ht_prob_rate_reduce_streams(struct minstrel_ht_sta *mi) | 478 | minstrel_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 | ||
1317 | static const struct rate_control_ops mac80211_minstrel_ht = { | 1332 | static 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 | ||
122 | void minstrel_ht_add_sta_debugfs(void *priv, void *priv_sta, struct dentry *dir); | 122 | void minstrel_ht_add_sta_debugfs(void *priv, void *priv_sta, struct dentry *dir); |
123 | void minstrel_ht_remove_sta_debugfs(void *priv, void *priv_sta); | 123 | void minstrel_ht_remove_sta_debugfs(void *priv, void *priv_sta); |
124 | int 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 * | |||
19 | minstrel_ht_stats_dump(struct minstrel_ht_sta *mi, int i, char *p) | 19 | minstrel_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 * | |||
163 | minstrel_ht_stats_csv_dump(struct minstrel_ht_sta *mi, int i, char *p) | 163 | minstrel_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, |