diff options
author | Felix Fietkau <nbd@openwrt.org> | 2013-04-22 10:14:42 -0400 |
---|---|---|
committer | Johannes Berg <johannes.berg@intel.com> | 2013-04-22 10:16:41 -0400 |
commit | a85666627b7f10c4229716b6ffaffcf196a128ca (patch) | |
tree | cc5b776384049e4b9eec911e53e1a2083d31a0c5 | |
parent | 0d528d85c519b755b6f4e1bafa3a39984370e1c1 (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.c | 150 | ||||
-rw-r--r-- | net/mac80211/rc80211_minstrel_ht.h | 2 |
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 | ||
127 | static u8 sample_table[SAMPLE_COLUMNS][MCS_GROUP_RATES]; | 127 | static u8 sample_table[SAMPLE_COLUMNS][MCS_GROUP_RATES]; |
128 | 128 | ||
129 | static void | ||
130 | minstrel_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 | ||
534 | static void | 545 | static void |
@@ -592,36 +603,71 @@ minstrel_calc_retransmit(struct minstrel_priv *mp, struct minstrel_ht_sta *mi, | |||
592 | 603 | ||
593 | static void | 604 | static void |
594 | minstrel_ht_set_rate(struct minstrel_priv *mp, struct minstrel_ht_sta *mi, | 605 | minstrel_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 | |||
645 | static void | ||
646 | minstrel_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 | ||
627 | static inline int | 673 | static inline int |
@@ -711,13 +757,13 @@ static void | |||
711 | minstrel_ht_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta, | 757 | minstrel_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 | ||
802 | static void | 813 | static 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 | ||
67 | struct minstrel_ht_sta { | 67 | struct 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; |