aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFelix Fietkau <nbd@openwrt.org>2016-03-03 16:59:01 -0500
committerJohannes Berg <johannes.berg@intel.com>2016-04-06 07:18:20 -0400
commit918fe04b288b3784f4ca90d3dff12fc23dc2751f (patch)
treeb99a0d6af4edf88ed9825a2ce2bfc90bbe35f69e
parent6e0456b5454561c4e9fa9e8a4acea405e6d56c80 (diff)
mac80211: minstrel_ht: set A-MSDU tx limits based on selected max_prob_rate
Prevents excessive A-MSDU aggregation at low data rates or bad conditions. 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.c54
1 files changed, 54 insertions, 0 deletions
diff --git a/net/mac80211/rc80211_minstrel_ht.c b/net/mac80211/rc80211_minstrel_ht.c
index 46ce08ed70b5..d77a9a842338 100644
--- a/net/mac80211/rc80211_minstrel_ht.c
+++ b/net/mac80211/rc80211_minstrel_ht.c
@@ -883,6 +883,59 @@ minstrel_ht_set_rate(struct minstrel_priv *mp, struct minstrel_ht_sta *mi,
883 ratetbl->rate[offset].flags = flags; 883 ratetbl->rate[offset].flags = flags;
884} 884}
885 885
886static inline int
887minstrel_ht_get_prob_ewma(struct minstrel_ht_sta *mi, int rate)
888{
889 int group = rate / MCS_GROUP_RATES;
890 rate %= MCS_GROUP_RATES;
891 return mi->groups[group].rates[rate].prob_ewma;
892}
893
894static int
895minstrel_ht_get_max_amsdu_len(struct minstrel_ht_sta *mi)
896{
897 int group = mi->max_prob_rate / MCS_GROUP_RATES;
898 const struct mcs_group *g = &minstrel_mcs_groups[group];
899 int rate = mi->max_prob_rate % MCS_GROUP_RATES;
900
901 /* Disable A-MSDU if max_prob_rate is bad */
902 if (mi->groups[group].rates[rate].prob_ewma < MINSTREL_FRAC(50, 100))
903 return 1;
904
905 /* If the rate is slower than single-stream MCS1, make A-MSDU limit small */
906 if (g->duration[rate] > MCS_DURATION(1, 0, 52))
907 return 500;
908
909 /*
910 * If the rate is slower than single-stream MCS4, limit A-MSDU to usual
911 * data packet size
912 */
913 if (g->duration[rate] > MCS_DURATION(1, 0, 104))
914 return 1600;
915
916 /*
917 * If the rate is slower than single-stream MCS7, or if the max throughput
918 * rate success probability is less than 75%, limit A-MSDU to twice the usual
919 * data packet size
920 */
921 if (g->duration[rate] > MCS_DURATION(1, 0, 260) ||
922 (minstrel_ht_get_prob_ewma(mi, mi->max_tp_rate[0]) <
923 MINSTREL_FRAC(75, 100)))
924 return 3200;
925
926 /*
927 * HT A-MPDU limits maximum MPDU size under BA agreement to 4095 bytes.
928 * Since aggregation sessions are started/stopped without txq flush, use
929 * the limit here to avoid the complexity of having to de-aggregate
930 * packets in the queue.
931 */
932 if (!mi->sta->vht_cap.vht_supported)
933 return IEEE80211_MAX_MPDU_LEN_HT_BA;
934
935 /* unlimited */
936 return 0;
937}
938
886static void 939static void
887minstrel_ht_update_rates(struct minstrel_priv *mp, struct minstrel_ht_sta *mi) 940minstrel_ht_update_rates(struct minstrel_priv *mp, struct minstrel_ht_sta *mi)
888{ 941{
@@ -907,6 +960,7 @@ minstrel_ht_update_rates(struct minstrel_priv *mp, struct minstrel_ht_sta *mi)
907 minstrel_ht_set_rate(mp, mi, rates, i++, mi->max_prob_rate); 960 minstrel_ht_set_rate(mp, mi, rates, i++, mi->max_prob_rate);
908 } 961 }
909 962
963 mi->sta->max_rc_amsdu_len = minstrel_ht_get_max_amsdu_len(mi);
910 rates->rate[i].idx = -1; 964 rates->rate[i].idx = -1;
911 rate_control_set_rates(mp->hw, mi->sta, rates); 965 rate_control_set_rates(mp->hw, mi->sta, rates);
912} 966}