.. | .. |
---|
70 | 70 | } |
---|
71 | 71 | |
---|
72 | 72 | /* return current EMWA throughput */ |
---|
73 | | -int minstrel_get_tp_avg(struct minstrel_rate *mr, int prob_ewma) |
---|
| 73 | +int minstrel_get_tp_avg(struct minstrel_rate *mr, int prob_avg) |
---|
74 | 74 | { |
---|
75 | 75 | int usecs; |
---|
76 | 76 | |
---|
.. | .. |
---|
79 | 79 | usecs = 1000000; |
---|
80 | 80 | |
---|
81 | 81 | /* reset thr. below 10% success */ |
---|
82 | | - if (mr->stats.prob_ewma < MINSTREL_FRAC(10, 100)) |
---|
| 82 | + if (mr->stats.prob_avg < MINSTREL_FRAC(10, 100)) |
---|
83 | 83 | return 0; |
---|
84 | 84 | |
---|
85 | | - if (prob_ewma > MINSTREL_FRAC(90, 100)) |
---|
| 85 | + if (prob_avg > MINSTREL_FRAC(90, 100)) |
---|
86 | 86 | return MINSTREL_TRUNC(100000 * (MINSTREL_FRAC(90, 100) / usecs)); |
---|
87 | 87 | else |
---|
88 | | - return MINSTREL_TRUNC(100000 * (prob_ewma / usecs)); |
---|
| 88 | + return MINSTREL_TRUNC(100000 * (prob_avg / usecs)); |
---|
89 | 89 | } |
---|
90 | 90 | |
---|
91 | 91 | /* find & sort topmost throughput rates */ |
---|
.. | .. |
---|
98 | 98 | |
---|
99 | 99 | for (j = MAX_THR_RATES; j > 0; --j) { |
---|
100 | 100 | tmp_mrs = &mi->r[tp_list[j - 1]].stats; |
---|
101 | | - if (minstrel_get_tp_avg(&mi->r[i], cur_mrs->prob_ewma) <= |
---|
102 | | - minstrel_get_tp_avg(&mi->r[tp_list[j - 1]], tmp_mrs->prob_ewma)) |
---|
| 101 | + if (minstrel_get_tp_avg(&mi->r[i], cur_mrs->prob_avg) <= |
---|
| 102 | + minstrel_get_tp_avg(&mi->r[tp_list[j - 1]], tmp_mrs->prob_avg)) |
---|
103 | 103 | break; |
---|
104 | 104 | } |
---|
105 | 105 | |
---|
.. | .. |
---|
157 | 157 | * Recalculate statistics and counters of a given rate |
---|
158 | 158 | */ |
---|
159 | 159 | void |
---|
160 | | -minstrel_calc_rate_stats(struct minstrel_rate_stats *mrs) |
---|
| 160 | +minstrel_calc_rate_stats(struct minstrel_priv *mp, |
---|
| 161 | + struct minstrel_rate_stats *mrs) |
---|
161 | 162 | { |
---|
162 | 163 | unsigned int cur_prob; |
---|
163 | 164 | |
---|
164 | 165 | if (unlikely(mrs->attempts > 0)) { |
---|
165 | 166 | mrs->sample_skipped = 0; |
---|
166 | 167 | cur_prob = MINSTREL_FRAC(mrs->success, mrs->attempts); |
---|
167 | | - if (unlikely(!mrs->att_hist)) { |
---|
168 | | - mrs->prob_ewma = cur_prob; |
---|
| 168 | + if (mp->new_avg) { |
---|
| 169 | + minstrel_filter_avg_add(&mrs->prob_avg, |
---|
| 170 | + &mrs->prob_avg_1, cur_prob); |
---|
| 171 | + } else if (unlikely(!mrs->att_hist)) { |
---|
| 172 | + mrs->prob_avg = cur_prob; |
---|
169 | 173 | } else { |
---|
170 | | - /* update exponential weighted moving variance */ |
---|
171 | | - mrs->prob_ewmv = minstrel_ewmv(mrs->prob_ewmv, |
---|
172 | | - cur_prob, |
---|
173 | | - mrs->prob_ewma, |
---|
174 | | - EWMA_LEVEL); |
---|
175 | | - |
---|
176 | 174 | /*update exponential weighted moving avarage */ |
---|
177 | | - mrs->prob_ewma = minstrel_ewma(mrs->prob_ewma, |
---|
178 | | - cur_prob, |
---|
179 | | - EWMA_LEVEL); |
---|
| 175 | + mrs->prob_avg = minstrel_ewma(mrs->prob_avg, |
---|
| 176 | + cur_prob, |
---|
| 177 | + EWMA_LEVEL); |
---|
180 | 178 | } |
---|
181 | 179 | mrs->att_hist += mrs->attempts; |
---|
182 | 180 | mrs->succ_hist += mrs->success; |
---|
.. | .. |
---|
206 | 204 | struct minstrel_rate_stats *tmp_mrs = &mi->r[tmp_prob_rate].stats; |
---|
207 | 205 | |
---|
208 | 206 | /* Update statistics of success probability per rate */ |
---|
209 | | - minstrel_calc_rate_stats(mrs); |
---|
| 207 | + minstrel_calc_rate_stats(mp, mrs); |
---|
210 | 208 | |
---|
211 | 209 | /* Sample less often below the 10% chance of success. |
---|
212 | 210 | * Sample less often above the 95% chance of success. */ |
---|
213 | | - if (mrs->prob_ewma > MINSTREL_FRAC(95, 100) || |
---|
214 | | - mrs->prob_ewma < MINSTREL_FRAC(10, 100)) { |
---|
| 211 | + if (mrs->prob_avg > MINSTREL_FRAC(95, 100) || |
---|
| 212 | + mrs->prob_avg < MINSTREL_FRAC(10, 100)) { |
---|
215 | 213 | mr->adjusted_retry_count = mrs->retry_count >> 1; |
---|
216 | 214 | if (mr->adjusted_retry_count > 2) |
---|
217 | 215 | mr->adjusted_retry_count = 2; |
---|
.. | .. |
---|
231 | 229 | * choose the maximum throughput rate as max_prob_rate |
---|
232 | 230 | * (2) if all success probabilities < 95%, the rate with |
---|
233 | 231 | * highest success probability is chosen as max_prob_rate */ |
---|
234 | | - if (mrs->prob_ewma >= MINSTREL_FRAC(95, 100)) { |
---|
235 | | - tmp_cur_tp = minstrel_get_tp_avg(mr, mrs->prob_ewma); |
---|
| 232 | + if (mrs->prob_avg >= MINSTREL_FRAC(95, 100)) { |
---|
| 233 | + tmp_cur_tp = minstrel_get_tp_avg(mr, mrs->prob_avg); |
---|
236 | 234 | tmp_prob_tp = minstrel_get_tp_avg(&mi->r[tmp_prob_rate], |
---|
237 | | - tmp_mrs->prob_ewma); |
---|
| 235 | + tmp_mrs->prob_avg); |
---|
238 | 236 | if (tmp_cur_tp >= tmp_prob_tp) |
---|
239 | 237 | tmp_prob_rate = i; |
---|
240 | 238 | } else { |
---|
241 | | - if (mrs->prob_ewma >= tmp_mrs->prob_ewma) |
---|
| 239 | + if (mrs->prob_avg >= tmp_mrs->prob_avg) |
---|
242 | 240 | tmp_prob_rate = i; |
---|
243 | 241 | } |
---|
244 | 242 | } |
---|
.. | .. |
---|
290 | 288 | } |
---|
291 | 289 | |
---|
292 | 290 | if (time_after(jiffies, mi->last_stats_update + |
---|
293 | | - (mp->update_interval * HZ) / 1000)) |
---|
| 291 | + mp->update_interval / (mp->new_avg ? 2 : 1))) |
---|
294 | 292 | minstrel_update_stats(mp, mi); |
---|
295 | 293 | } |
---|
296 | 294 | |
---|
.. | .. |
---|
339 | 337 | bool prev_sample; |
---|
340 | 338 | int delta; |
---|
341 | 339 | int sampling_ratio; |
---|
342 | | - |
---|
343 | | - /* management/no-ack frames do not use rate control */ |
---|
344 | | - if (rate_control_send_low(sta, priv_sta, txrc)) |
---|
345 | | - return; |
---|
346 | 340 | |
---|
347 | 341 | /* check multi-rate-retry capabilities & adjust lookaround_rate */ |
---|
348 | 342 | mrr_capable = mp->has_mrr && |
---|
.. | .. |
---|
414 | 408 | * has a probability of >95%, we shouldn't be attempting |
---|
415 | 409 | * to use it, as this only wastes precious airtime */ |
---|
416 | 410 | if (!mrr_capable && |
---|
417 | | - (mi->r[ndx].stats.prob_ewma > MINSTREL_FRAC(95, 100))) |
---|
| 411 | + (mi->r[ndx].stats.prob_avg > MINSTREL_FRAC(95, 100))) |
---|
418 | 412 | return; |
---|
419 | 413 | |
---|
420 | 414 | mi->prev_sample = true; |
---|
.. | .. |
---|
555 | 549 | minstrel_update_rates(mp, mi); |
---|
556 | 550 | } |
---|
557 | 551 | |
---|
558 | | -static void * |
---|
559 | | -minstrel_alloc_sta(void *priv, struct ieee80211_sta *sta, gfp_t gfp) |
---|
560 | | -{ |
---|
561 | | - struct ieee80211_supported_band *sband; |
---|
562 | | - struct minstrel_sta_info *mi; |
---|
563 | | - struct minstrel_priv *mp = priv; |
---|
564 | | - struct ieee80211_hw *hw = mp->hw; |
---|
565 | | - int max_rates = 0; |
---|
566 | | - int i; |
---|
567 | | - |
---|
568 | | - mi = kzalloc(sizeof(struct minstrel_sta_info), gfp); |
---|
569 | | - if (!mi) |
---|
570 | | - return NULL; |
---|
571 | | - |
---|
572 | | - for (i = 0; i < NUM_NL80211_BANDS; i++) { |
---|
573 | | - sband = hw->wiphy->bands[i]; |
---|
574 | | - if (sband && sband->n_bitrates > max_rates) |
---|
575 | | - max_rates = sband->n_bitrates; |
---|
576 | | - } |
---|
577 | | - |
---|
578 | | - mi->r = kcalloc(max_rates, sizeof(struct minstrel_rate), gfp); |
---|
579 | | - if (!mi->r) |
---|
580 | | - goto error; |
---|
581 | | - |
---|
582 | | - mi->sample_table = kmalloc_array(max_rates, SAMPLE_COLUMNS, gfp); |
---|
583 | | - if (!mi->sample_table) |
---|
584 | | - goto error1; |
---|
585 | | - |
---|
586 | | - mi->last_stats_update = jiffies; |
---|
587 | | - return mi; |
---|
588 | | - |
---|
589 | | -error1: |
---|
590 | | - kfree(mi->r); |
---|
591 | | -error: |
---|
592 | | - kfree(mi); |
---|
593 | | - return NULL; |
---|
594 | | -} |
---|
595 | | - |
---|
596 | | -static void |
---|
597 | | -minstrel_free_sta(void *priv, struct ieee80211_sta *sta, void *priv_sta) |
---|
598 | | -{ |
---|
599 | | - struct minstrel_sta_info *mi = priv_sta; |
---|
600 | | - |
---|
601 | | - kfree(mi->sample_table); |
---|
602 | | - kfree(mi->r); |
---|
603 | | - kfree(mi); |
---|
604 | | -} |
---|
605 | | - |
---|
606 | | -static void |
---|
607 | | -minstrel_init_cck_rates(struct minstrel_priv *mp) |
---|
608 | | -{ |
---|
609 | | - static const int bitrates[4] = { 10, 20, 55, 110 }; |
---|
610 | | - struct ieee80211_supported_band *sband; |
---|
611 | | - u32 rate_flags = ieee80211_chandef_rate_flags(&mp->hw->conf.chandef); |
---|
612 | | - int i, j; |
---|
613 | | - |
---|
614 | | - sband = mp->hw->wiphy->bands[NL80211_BAND_2GHZ]; |
---|
615 | | - if (!sband) |
---|
616 | | - return; |
---|
617 | | - |
---|
618 | | - for (i = 0, j = 0; i < sband->n_bitrates; i++) { |
---|
619 | | - struct ieee80211_rate *rate = &sband->bitrates[i]; |
---|
620 | | - |
---|
621 | | - if (rate->flags & IEEE80211_RATE_ERP_G) |
---|
622 | | - continue; |
---|
623 | | - |
---|
624 | | - if ((rate_flags & sband->bitrates[i].flags) != rate_flags) |
---|
625 | | - continue; |
---|
626 | | - |
---|
627 | | - for (j = 0; j < ARRAY_SIZE(bitrates); j++) { |
---|
628 | | - if (rate->bitrate != bitrates[j]) |
---|
629 | | - continue; |
---|
630 | | - |
---|
631 | | - mp->cck_rates[j] = i; |
---|
632 | | - break; |
---|
633 | | - } |
---|
634 | | - } |
---|
635 | | -} |
---|
636 | | - |
---|
637 | | -static void * |
---|
638 | | -minstrel_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir) |
---|
639 | | -{ |
---|
640 | | - struct minstrel_priv *mp; |
---|
641 | | - |
---|
642 | | - mp = kzalloc(sizeof(struct minstrel_priv), GFP_ATOMIC); |
---|
643 | | - if (!mp) |
---|
644 | | - return NULL; |
---|
645 | | - |
---|
646 | | - /* contention window settings |
---|
647 | | - * Just an approximation. Using the per-queue values would complicate |
---|
648 | | - * the calculations and is probably unnecessary */ |
---|
649 | | - mp->cw_min = 15; |
---|
650 | | - mp->cw_max = 1023; |
---|
651 | | - |
---|
652 | | - /* number of packets (in %) to use for sampling other rates |
---|
653 | | - * sample less often for non-mrr packets, because the overhead |
---|
654 | | - * is much higher than with mrr */ |
---|
655 | | - mp->lookaround_rate = 5; |
---|
656 | | - mp->lookaround_rate_mrr = 10; |
---|
657 | | - |
---|
658 | | - /* maximum time that the hw is allowed to stay in one MRR segment */ |
---|
659 | | - mp->segment_size = 6000; |
---|
660 | | - |
---|
661 | | - if (hw->max_rate_tries > 0) |
---|
662 | | - mp->max_retry = hw->max_rate_tries; |
---|
663 | | - else |
---|
664 | | - /* safe default, does not necessarily have to match hw properties */ |
---|
665 | | - mp->max_retry = 7; |
---|
666 | | - |
---|
667 | | - if (hw->max_rates >= 4) |
---|
668 | | - mp->has_mrr = true; |
---|
669 | | - |
---|
670 | | - mp->hw = hw; |
---|
671 | | - mp->update_interval = 100; |
---|
672 | | - |
---|
673 | | -#ifdef CONFIG_MAC80211_DEBUGFS |
---|
674 | | - mp->fixed_rate_idx = (u32) -1; |
---|
675 | | - mp->dbg_fixed_rate = debugfs_create_u32("fixed_rate_idx", |
---|
676 | | - 0666, debugfsdir, &mp->fixed_rate_idx); |
---|
677 | | -#endif |
---|
678 | | - |
---|
679 | | - minstrel_init_cck_rates(mp); |
---|
680 | | - |
---|
681 | | - return mp; |
---|
682 | | -} |
---|
683 | | - |
---|
684 | | -static void |
---|
685 | | -minstrel_free(void *priv) |
---|
686 | | -{ |
---|
687 | | -#ifdef CONFIG_MAC80211_DEBUGFS |
---|
688 | | - debugfs_remove(((struct minstrel_priv *)priv)->dbg_fixed_rate); |
---|
689 | | -#endif |
---|
690 | | - kfree(priv); |
---|
691 | | -} |
---|
692 | | - |
---|
693 | 552 | static u32 minstrel_get_expected_throughput(void *priv_sta) |
---|
694 | 553 | { |
---|
695 | 554 | struct minstrel_sta_info *mi = priv_sta; |
---|
.. | .. |
---|
701 | 560 | * computing cur_tp |
---|
702 | 561 | */ |
---|
703 | 562 | tmp_mrs = &mi->r[idx].stats; |
---|
704 | | - tmp_cur_tp = minstrel_get_tp_avg(&mi->r[idx], tmp_mrs->prob_ewma) * 10; |
---|
| 563 | + tmp_cur_tp = minstrel_get_tp_avg(&mi->r[idx], tmp_mrs->prob_avg) * 10; |
---|
705 | 564 | tmp_cur_tp = tmp_cur_tp * 1200 * 8 / 1024; |
---|
706 | 565 | |
---|
707 | 566 | return tmp_cur_tp; |
---|
708 | 567 | } |
---|
709 | 568 | |
---|
710 | 569 | const struct rate_control_ops mac80211_minstrel = { |
---|
711 | | - .name = "minstrel", |
---|
712 | 570 | .tx_status_ext = minstrel_tx_status, |
---|
713 | 571 | .get_rate = minstrel_get_rate, |
---|
714 | 572 | .rate_init = minstrel_rate_init, |
---|
715 | | - .alloc = minstrel_alloc, |
---|
716 | | - .free = minstrel_free, |
---|
717 | | - .alloc_sta = minstrel_alloc_sta, |
---|
718 | | - .free_sta = minstrel_free_sta, |
---|
719 | | -#ifdef CONFIG_MAC80211_DEBUGFS |
---|
720 | | - .add_sta_debugfs = minstrel_add_sta_debugfs, |
---|
721 | | - .remove_sta_debugfs = minstrel_remove_sta_debugfs, |
---|
722 | | -#endif |
---|
723 | 573 | .get_expected_throughput = minstrel_get_expected_throughput, |
---|
724 | 574 | }; |
---|
725 | | - |
---|
726 | | -int __init |
---|
727 | | -rc80211_minstrel_init(void) |
---|
728 | | -{ |
---|
729 | | - return ieee80211_rate_control_register(&mac80211_minstrel); |
---|
730 | | -} |
---|
731 | | - |
---|
732 | | -void |
---|
733 | | -rc80211_minstrel_exit(void) |
---|
734 | | -{ |
---|
735 | | - ieee80211_rate_control_unregister(&mac80211_minstrel); |
---|
736 | | -} |
---|