From 42fc062d473348221c30774013406219b8592b4c Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Thu, 18 Feb 2016 18:55:35 +0000 Subject: [PATCH] mac80211: update A-MSDU tx support to the latest version Signed-off-by: Felix Fietkau SVN-Revision: 48743 --- .../322-mac80211-add-A-MSDU-tx-support.patch | 37 ++++++++--- ...l_ht-set-A-MSDU-tx-limits-based-on-s.patch | 61 +++++++++++++++++++ 2 files changed, 91 insertions(+), 7 deletions(-) create mode 100644 package/kernel/mac80211/patches/335-mac80211-minstrel_ht-set-A-MSDU-tx-limits-based-on-s.patch diff --git a/package/kernel/mac80211/patches/322-mac80211-add-A-MSDU-tx-support.patch b/package/kernel/mac80211/patches/322-mac80211-add-A-MSDU-tx-support.patch index d55f772760..a88229a3a0 100644 --- a/package/kernel/mac80211/patches/322-mac80211-add-A-MSDU-tx-support.patch +++ b/package/kernel/mac80211/patches/322-mac80211-add-A-MSDU-tx-support.patch @@ -26,7 +26,23 @@ Signed-off-by: Felix Fietkau }; /* -@@ -1961,6 +1963,12 @@ struct ieee80211_txq { +@@ -1728,6 +1730,7 @@ struct ieee80211_sta_rates { + * size is min(max_amsdu_len, 7935) bytes. + * Both additional HT limits must be enforced by the low level driver. + * This is defined by the spec (IEEE 802.11-2012 section 8.3.2.2 NOTE 2). ++ * @max_rc_amsdu_len: Maximum A-MSDU size in bytes recommended by rate control. + * @txq: per-TID data TX queues (if driver uses the TXQ abstraction) + */ + struct ieee80211_sta { +@@ -1748,6 +1751,7 @@ struct ieee80211_sta { + bool mfp; + u8 max_amsdu_subframes; + u16 max_amsdu_len; ++ u16 max_rc_amsdu_len; + + struct ieee80211_txq *txq[IEEE80211_NUM_TIDS]; + +@@ -1961,6 +1965,12 @@ struct ieee80211_txq { * order and does not need to manage its own reorder buffer or BA session * timeout. * @@ -39,7 +55,7 @@ Signed-off-by: Felix Fietkau * @NUM_IEEE80211_HW_FLAGS: number of hardware flags, used for sizing arrays */ enum ieee80211_hw_flags { -@@ -1998,6 +2006,8 @@ enum ieee80211_hw_flags { +@@ -1998,6 +2008,8 @@ enum ieee80211_hw_flags { IEEE80211_HW_BEACON_TX_STATUS, IEEE80211_HW_NEEDS_UNIQUE_STA_ADDR, IEEE80211_HW_SUPPORTS_REORDERING_BUFFER, @@ -48,7 +64,7 @@ Signed-off-by: Felix Fietkau /* keep last, obviously */ NUM_IEEE80211_HW_FLAGS -@@ -2070,6 +2080,8 @@ enum ieee80211_hw_flags { +@@ -2070,6 +2082,8 @@ enum ieee80211_hw_flags { * size is smaller (an example is LinkSys WRT120N with FW v1.0.07 * build 002 Jun 18 2012). * @@ -57,7 +73,7 @@ Signed-off-by: Felix Fietkau * @offchannel_tx_hw_queue: HW queue ID to use for offchannel TX * (if %IEEE80211_HW_QUEUE_CONTROL is set) * -@@ -2124,6 +2136,7 @@ struct ieee80211_hw { +@@ -2124,6 +2138,7 @@ struct ieee80211_hw { u8 max_rate_tries; u8 max_rx_aggregation_subframes; u8 max_tx_aggregation_subframes; @@ -120,7 +136,7 @@ Signed-off-by: Felix Fietkau return skb; } EXPORT_SYMBOL(ieee80211_tx_dequeue); -@@ -2757,6 +2761,158 @@ void ieee80211_clear_fast_xmit(struct st +@@ -2757,6 +2761,165 @@ void ieee80211_clear_fast_xmit(struct st kfree_rcu(fast_tx, rcu_head); } @@ -148,6 +164,9 @@ Signed-off-by: Felix Fietkau + void *data; + u8 *qc; + ++ if (info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE) ++ return false; ++ + if (info->control.flags & IEEE80211_TX_CTRL_AMSDU) + return true; + @@ -193,7 +212,7 @@ Signed-off-by: Felix Fietkau + int subframe_len = skb->len - ETH_ALEN; + u8 max_subframes = sta->sta.max_amsdu_subframes; + int max_frags = local->hw.max_tx_fragments; -+ int max_amsdu_len; ++ int max_amsdu_len = sta->sta.max_amsdu_len; + __be16 len; + void *data; + bool ret = false; @@ -209,6 +228,10 @@ Signed-off-by: Felix Fietkau + if (test_bit(IEEE80211_TXQ_NO_AMSDU, &txqi->flags)) + return false; + ++ if (sta->sta.max_rc_amsdu_len) ++ max_amsdu_len = min_t(int, max_amsdu_len, ++ sta->sta.max_rc_amsdu_len); ++ + spin_lock_bh(&txqi->queue.lock); + + head = skb_peek_tail(&txqi->queue); @@ -279,7 +302,7 @@ Signed-off-by: Felix Fietkau static bool ieee80211_xmit_fast(struct ieee80211_sub_if_data *sdata, struct net_device *dev, struct sta_info *sta, struct ieee80211_fast_tx *fast_tx, -@@ -2811,6 +2967,10 @@ static bool ieee80211_xmit_fast(struct i +@@ -2811,6 +2974,10 @@ static bool ieee80211_xmit_fast(struct i ieee80211_tx_stats(dev, skb->len + extra_head); diff --git a/package/kernel/mac80211/patches/335-mac80211-minstrel_ht-set-A-MSDU-tx-limits-based-on-s.patch b/package/kernel/mac80211/patches/335-mac80211-minstrel_ht-set-A-MSDU-tx-limits-based-on-s.patch new file mode 100644 index 0000000000..acaacf7cac --- /dev/null +++ b/package/kernel/mac80211/patches/335-mac80211-minstrel_ht-set-A-MSDU-tx-limits-based-on-s.patch @@ -0,0 +1,61 @@ +From: Felix Fietkau +Date: Thu, 18 Feb 2016 19:30:05 +0100 +Subject: [PATCH] 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 +--- + +--- a/net/mac80211/rc80211_minstrel_ht.c ++++ b/net/mac80211/rc80211_minstrel_ht.c +@@ -883,6 +883,39 @@ minstrel_ht_set_rate(struct minstrel_pri + ratetbl->rate[offset].flags = flags; + } + ++static int ++minstrel_ht_get_max_amsdu_len(struct minstrel_ht_sta *mi) ++{ ++ int group = mi->max_prob_rate / MCS_GROUP_RATES; ++ const struct mcs_group *g = &minstrel_mcs_groups[group]; ++ int rate = mi->max_prob_rate % MCS_GROUP_RATES; ++ ++ /* Disable A-MSDU if max_prob_rate is bad */ ++ if (mi->groups[group].rates[rate].prob_ewma < MINSTREL_FRAC(50, 100)) ++ return 1; ++ ++ /* If the rate is slower than single-stream MCS1, make A-MSDU limit small */ ++ if (g->duration[rate] > MCS_DURATION(1, 0, 52)) ++ return 500; ++ ++ /* ++ * If the rate is slower than single-stream MCS4, limit A-MSDU to usual ++ * data packet size ++ */ ++ if (g->duration[rate] > MCS_DURATION(1, 0, 104)) ++ return 1500; ++ ++ /* ++ * If the rate is slower than single-stream MCS7, limit A-MSDU to twice ++ * the usual data packet size ++ */ ++ if (g->duration[rate] > MCS_DURATION(1, 0, 260)) ++ return 3000; ++ ++ /* unlimited */ ++ return 0; ++} ++ + static void + minstrel_ht_update_rates(struct minstrel_priv *mp, struct minstrel_ht_sta *mi) + { +@@ -907,6 +940,7 @@ minstrel_ht_update_rates(struct minstrel + minstrel_ht_set_rate(mp, mi, rates, i++, mi->max_prob_rate); + } + ++ mi->sta->max_rc_amsdu_len = minstrel_ht_get_max_amsdu_len(mi); + rates->rate[i].idx = -1; + rate_control_set_rates(mp->hw, mi->sta, rates); + }