aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFelix Fietkau <nbd@openwrt.org>2013-04-22 10:14:42 -0400
committerJohannes Berg <johannes.berg@intel.com>2013-04-22 10:16:41 -0400
commita85666627b7f10c4229716b6ffaffcf196a128ca (patch)
treecc5b776384049e4b9eec911e53e1a2083d31a0c5
parent0d528d85c519b755b6f4e1bafa3a39984370e1c1 (diff)
mac80211/minstrel_ht: use the new rate control API
Pass the rate selection table to mac80211 from minstrel_ht_update_stats. Only rates for sample attempts are set in info->control.rates. Signed-off-by: Felix Fietkau <nbd@openwrt.org> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
-rw-r--r--net/mac80211/rc80211_minstrel_ht.c150
-rw-r--r--net/mac80211/rc80211_minstrel_ht.h2
2 files changed, 84 insertions, 68 deletions
diff --git a/net/mac80211/rc80211_minstrel_ht.c b/net/mac80211/rc80211_minstrel_ht.c
index a8e979e8f6b5..5b2d3012b983 100644
--- a/net/mac80211/rc80211_minstrel_ht.c
+++ b/net/mac80211/rc80211_minstrel_ht.c
@@ -126,6 +126,9 @@ const struct mcs_group minstrel_mcs_groups[] = {
126 126
127static u8 sample_table[SAMPLE_COLUMNS][MCS_GROUP_RATES]; 127static u8 sample_table[SAMPLE_COLUMNS][MCS_GROUP_RATES];
128 128
129static void
130minstrel_ht_update_rates(struct minstrel_priv *mp, struct minstrel_ht_sta *mi);
131
129/* 132/*
130 * Look up an MCS group index based on mac80211 rate information 133 * Look up an MCS group index based on mac80211 rate information
131 */ 134 */
@@ -465,7 +468,7 @@ minstrel_ht_tx_status(void *priv, struct ieee80211_supported_band *sband,
465 struct ieee80211_tx_rate *ar = info->status.rates; 468 struct ieee80211_tx_rate *ar = info->status.rates;
466 struct minstrel_rate_stats *rate, *rate2; 469 struct minstrel_rate_stats *rate, *rate2;
467 struct minstrel_priv *mp = priv; 470 struct minstrel_priv *mp = priv;
468 bool last; 471 bool last, update = false;
469 int i; 472 int i;
470 473
471 if (!msp->is_ht) 474 if (!msp->is_ht)
@@ -514,21 +517,29 @@ minstrel_ht_tx_status(void *priv, struct ieee80211_supported_band *sband,
514 rate = minstrel_get_ratestats(mi, mi->max_tp_rate); 517 rate = minstrel_get_ratestats(mi, mi->max_tp_rate);
515 if (rate->attempts > 30 && 518 if (rate->attempts > 30 &&
516 MINSTREL_FRAC(rate->success, rate->attempts) < 519 MINSTREL_FRAC(rate->success, rate->attempts) <
517 MINSTREL_FRAC(20, 100)) 520 MINSTREL_FRAC(20, 100)) {
518 minstrel_downgrade_rate(mi, &mi->max_tp_rate, true); 521 minstrel_downgrade_rate(mi, &mi->max_tp_rate, true);
522 update = true;
523 }
519 524
520 rate2 = minstrel_get_ratestats(mi, mi->max_tp_rate2); 525 rate2 = minstrel_get_ratestats(mi, mi->max_tp_rate2);
521 if (rate2->attempts > 30 && 526 if (rate2->attempts > 30 &&
522 MINSTREL_FRAC(rate2->success, rate2->attempts) < 527 MINSTREL_FRAC(rate2->success, rate2->attempts) <
523 MINSTREL_FRAC(20, 100)) 528 MINSTREL_FRAC(20, 100)) {
524 minstrel_downgrade_rate(mi, &mi->max_tp_rate2, false); 529 minstrel_downgrade_rate(mi, &mi->max_tp_rate2, false);
530 update = true;
531 }
525 532
526 if (time_after(jiffies, mi->stats_update + (mp->update_interval / 2 * HZ) / 1000)) { 533 if (time_after(jiffies, mi->stats_update + (mp->update_interval / 2 * HZ) / 1000)) {
534 update = true;
527 minstrel_ht_update_stats(mp, mi); 535 minstrel_ht_update_stats(mp, mi);
528 if (!(info->flags & IEEE80211_TX_CTL_AMPDU) && 536 if (!(info->flags & IEEE80211_TX_CTL_AMPDU) &&
529 mi->max_prob_rate / MCS_GROUP_RATES != MINSTREL_CCK_GROUP) 537 mi->max_prob_rate / MCS_GROUP_RATES != MINSTREL_CCK_GROUP)
530 minstrel_aggr_check(sta, skb); 538 minstrel_aggr_check(sta, skb);
531 } 539 }
540
541 if (update)
542 minstrel_ht_update_rates(mp, mi);
532} 543}
533 544
534static void 545static void
@@ -592,36 +603,71 @@ minstrel_calc_retransmit(struct minstrel_priv *mp, struct minstrel_ht_sta *mi,
592 603
593static void 604static void
594minstrel_ht_set_rate(struct minstrel_priv *mp, struct minstrel_ht_sta *mi, 605minstrel_ht_set_rate(struct minstrel_priv *mp, struct minstrel_ht_sta *mi,
595 struct ieee80211_tx_rate *rate, int index, 606 struct ieee80211_sta_rates *ratetbl, int offset, int index)
596 bool sample, bool rtscts)
597{ 607{
598 const struct mcs_group *group = &minstrel_mcs_groups[index / MCS_GROUP_RATES]; 608 const struct mcs_group *group = &minstrel_mcs_groups[index / MCS_GROUP_RATES];
599 struct minstrel_rate_stats *mr; 609 struct minstrel_rate_stats *mr;
610 u8 idx;
611 u16 flags;
600 612
601 mr = minstrel_get_ratestats(mi, index); 613 mr = minstrel_get_ratestats(mi, index);
602 if (!mr->retry_updated) 614 if (!mr->retry_updated)
603 minstrel_calc_retransmit(mp, mi, index); 615 minstrel_calc_retransmit(mp, mi, index);
604 616
605 if (sample) 617 if (mr->probability < MINSTREL_FRAC(20, 100) || !mr->retry_count) {
606 rate->count = 1; 618 ratetbl->rate[offset].count = 2;
607 else if (mr->probability < MINSTREL_FRAC(20, 100)) 619 ratetbl->rate[offset].count_rts = 2;
608 rate->count = 2; 620 ratetbl->rate[offset].count_cts = 2;
609 else if (rtscts) 621 } else {
610 rate->count = mr->retry_count_rtscts; 622 ratetbl->rate[offset].count = mr->retry_count;
611 else 623 ratetbl->rate[offset].count_cts = mr->retry_count;
612 rate->count = mr->retry_count; 624 ratetbl->rate[offset].count_rts = mr->retry_count_rtscts;
613 625 }
614 rate->flags = 0;
615 if (rtscts)
616 rate->flags |= IEEE80211_TX_RC_USE_RTS_CTS;
617 626
618 if (index / MCS_GROUP_RATES == MINSTREL_CCK_GROUP) { 627 if (index / MCS_GROUP_RATES == MINSTREL_CCK_GROUP) {
619 rate->idx = mp->cck_rates[index % ARRAY_SIZE(mp->cck_rates)]; 628 idx = mp->cck_rates[index % ARRAY_SIZE(mp->cck_rates)];
629 flags = 0;
630 } else {
631 idx = index % MCS_GROUP_RATES +
632 (group->streams - 1) * MCS_GROUP_RATES;
633 flags = IEEE80211_TX_RC_MCS | group->flags;
634 }
635
636 if (offset > 0) {
637 ratetbl->rate[offset].count = ratetbl->rate[offset].count_rts;
638 flags |= IEEE80211_TX_RC_USE_RTS_CTS;
639 }
640
641 ratetbl->rate[offset].idx = idx;
642 ratetbl->rate[offset].flags = flags;
643}
644
645static void
646minstrel_ht_update_rates(struct minstrel_priv *mp, struct minstrel_ht_sta *mi)
647{
648 struct ieee80211_sta_rates *rates;
649 int i = 0;
650
651 rates = kzalloc(sizeof(*rates), GFP_ATOMIC);
652 if (!rates)
620 return; 653 return;
654
655 /* Start with max_tp_rate */
656 minstrel_ht_set_rate(mp, mi, rates, i++, mi->max_tp_rate);
657
658 if (mp->hw->max_rates >= 3) {
659 /* At least 3 tx rates supported, use max_tp_rate2 next */
660 minstrel_ht_set_rate(mp, mi, rates, i++, mi->max_tp_rate2);
661 }
662
663 if (mp->hw->max_rates >= 2) {
664 /*
665 * At least 2 tx rates supported, use max_prob_rate next */
666 minstrel_ht_set_rate(mp, mi, rates, i++, mi->max_prob_rate);
621 } 667 }
622 668
623 rate->flags |= IEEE80211_TX_RC_MCS | group->flags; 669 rates->rate[i].idx = -1;
624 rate->idx = index % MCS_GROUP_RATES + (group->streams - 1) * MCS_GROUP_RATES; 670 rate_control_set_rates(mp->hw, mi->sta, rates);
625} 671}
626 672
627static inline int 673static inline int
@@ -711,13 +757,13 @@ static void
711minstrel_ht_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta, 757minstrel_ht_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta,
712 struct ieee80211_tx_rate_control *txrc) 758 struct ieee80211_tx_rate_control *txrc)
713{ 759{
760 const struct mcs_group *sample_group;
714 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(txrc->skb); 761 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(txrc->skb);
715 struct ieee80211_tx_rate *ar = info->status.rates; 762 struct ieee80211_tx_rate *rate = &info->status.rates[0];
716 struct minstrel_ht_sta_priv *msp = priv_sta; 763 struct minstrel_ht_sta_priv *msp = priv_sta;
717 struct minstrel_ht_sta *mi = &msp->ht; 764 struct minstrel_ht_sta *mi = &msp->ht;
718 struct minstrel_priv *mp = priv; 765 struct minstrel_priv *mp = priv;
719 int sample_idx; 766 int sample_idx;
720 bool sample = false;
721 767
722 if (rate_control_send_low(sta, priv_sta, txrc)) 768 if (rate_control_send_low(sta, priv_sta, txrc))
723 return; 769 return;
@@ -745,51 +791,6 @@ minstrel_ht_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta,
745 } 791 }
746#endif 792#endif
747 793
748 if (sample_idx >= 0) {
749 sample = true;
750 minstrel_ht_set_rate(mp, mi, &ar[0], sample_idx,
751 true, false);
752 info->flags |= IEEE80211_TX_CTL_RATE_CTRL_PROBE;
753 } else {
754 minstrel_ht_set_rate(mp, mi, &ar[0], mi->max_tp_rate,
755 false, false);
756 }
757
758 if (mp->hw->max_rates >= 3) {
759 /*
760 * At least 3 tx rates supported, use
761 * sample_rate -> max_tp_rate -> max_prob_rate for sampling and
762 * max_tp_rate -> max_tp_rate2 -> max_prob_rate by default.
763 */
764 if (sample_idx >= 0)
765 minstrel_ht_set_rate(mp, mi, &ar[1], mi->max_tp_rate,
766 false, false);
767 else
768 minstrel_ht_set_rate(mp, mi, &ar[1], mi->max_tp_rate2,
769 false, true);
770
771 minstrel_ht_set_rate(mp, mi, &ar[2], mi->max_prob_rate,
772 false, !sample);
773
774 ar[3].count = 0;
775 ar[3].idx = -1;
776 } else if (mp->hw->max_rates == 2) {
777 /*
778 * Only 2 tx rates supported, use
779 * sample_rate -> max_prob_rate for sampling and
780 * max_tp_rate -> max_prob_rate by default.
781 */
782 minstrel_ht_set_rate(mp, mi, &ar[1], mi->max_prob_rate,
783 false, !sample);
784
785 ar[2].count = 0;
786 ar[2].idx = -1;
787 } else {
788 /* Not using MRR, only use the first rate */
789 ar[1].count = 0;
790 ar[1].idx = -1;
791 }
792
793 mi->total_packets++; 794 mi->total_packets++;
794 795
795 /* wraparound */ 796 /* wraparound */
@@ -797,6 +798,16 @@ minstrel_ht_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta,
797 mi->total_packets = 0; 798 mi->total_packets = 0;
798 mi->sample_packets = 0; 799 mi->sample_packets = 0;
799 } 800 }
801
802 if (sample_idx < 0)
803 return;
804
805 sample_group = &minstrel_mcs_groups[sample_idx / MCS_GROUP_RATES];
806 info->flags |= IEEE80211_TX_CTL_RATE_CTRL_PROBE;
807 rate->idx = sample_idx % MCS_GROUP_RATES +
808 (sample_group->streams - 1) * MCS_GROUP_RATES;
809 rate->flags = IEEE80211_TX_RC_MCS | sample_group->flags;
810 rate->count = 1;
800} 811}
801 812
802static void 813static void
@@ -846,6 +857,8 @@ minstrel_ht_update_caps(void *priv, struct ieee80211_supported_band *sband,
846 857
847 msp->is_ht = true; 858 msp->is_ht = true;
848 memset(mi, 0, sizeof(*mi)); 859 memset(mi, 0, sizeof(*mi));
860
861 mi->sta = sta;
849 mi->stats_update = jiffies; 862 mi->stats_update = jiffies;
850 863
851 ack_dur = ieee80211_frame_duration(sband->band, 10, 60, 1, 1); 864 ack_dur = ieee80211_frame_duration(sband->band, 10, 60, 1, 1);
@@ -907,8 +920,9 @@ minstrel_ht_update_caps(void *priv, struct ieee80211_supported_band *sband,
907 if (!n_supported) 920 if (!n_supported)
908 goto use_legacy; 921 goto use_legacy;
909 922
910 /* init {mi,mi->groups[*]}->{max_tp_rate,max_tp_rate2,max_prob_rate} */ 923 /* create an initial rate table with the lowest supported rates */
911 minstrel_ht_update_stats(mp, mi); 924 minstrel_ht_update_stats(mp, mi);
925 minstrel_ht_update_rates(mp, mi);
912 926
913 return; 927 return;
914 928
diff --git a/net/mac80211/rc80211_minstrel_ht.h b/net/mac80211/rc80211_minstrel_ht.h
index 9b16e9de9923..d655586773ac 100644
--- a/net/mac80211/rc80211_minstrel_ht.h
+++ b/net/mac80211/rc80211_minstrel_ht.h
@@ -65,6 +65,8 @@ struct minstrel_mcs_group_data {
65}; 65};
66 66
67struct minstrel_ht_sta { 67struct minstrel_ht_sta {
68 struct ieee80211_sta *sta;
69
68 /* ampdu length (average, per sampling interval) */ 70 /* ampdu length (average, per sampling interval) */
69 unsigned int ampdu_len; 71 unsigned int ampdu_len;
70 unsigned int ampdu_packets; 72 unsigned int ampdu_packets;