From: Felix Fietkau Date: Sun, 6 Jun 2021 18:57:39 +0000 (+0200) Subject: mac80211: improve rate control performance X-Git-Url: http://git.lede-project.org./?a=commitdiff_plain;h=a078037ace500a9c0f7cf4ec4f1c3095115dc70b;p=openwrt%2Fstaging%2Fxback.git mac80211: improve rate control performance Call rate control handler after intermediate queueuing Includes follow-up fixes Signed-off-by: Felix Fietkau cherry-picked from commits: - 7dd8829ef915f1c5fc728be8f8360c61ddaadf1b - a603e82dd342680d584c4eb5f1b222e056379890 - 8bb4437c01ca35a5ac67e391630a1b24cb52dbb7 --- diff --git a/package/kernel/mac80211/patches/subsys/374-mac80211-move-A-MPDU-session-check-from-minstrel_ht-.patch b/package/kernel/mac80211/patches/subsys/374-mac80211-move-A-MPDU-session-check-from-minstrel_ht-.patch new file mode 100644 index 0000000000..4e3242e6a9 --- /dev/null +++ b/package/kernel/mac80211/patches/subsys/374-mac80211-move-A-MPDU-session-check-from-minstrel_ht-.patch @@ -0,0 +1,126 @@ +From: Felix Fietkau +Date: Thu, 17 Jun 2021 17:56:54 +0200 +Subject: [PATCH] mac80211: move A-MPDU session check from minstrel_ht to + mac80211 + +This avoids calling back into tx handlers from within the rate control module. +Preparation for deferring rate control until tx dequeue + +Signed-off-by: Felix Fietkau +--- + +--- a/include/net/mac80211.h ++++ b/include/net/mac80211.h +@@ -6160,6 +6160,11 @@ enum rate_control_capabilities { + * otherwise the NSS difference doesn't bother us. + */ + RATE_CTRL_CAPA_VHT_EXT_NSS_BW = BIT(0), ++ /** ++ * @RATE_CTRL_CAPA_AMPDU_TRIGGER: ++ * mac80211 should start A-MPDU sessions on tx ++ */ ++ RATE_CTRL_CAPA_AMPDU_TRIGGER = BIT(1), + }; + + struct rate_control_ops { +--- a/net/mac80211/rc80211_minstrel_ht.c ++++ b/net/mac80211/rc80211_minstrel_ht.c +@@ -1153,29 +1153,6 @@ minstrel_downgrade_prob_rate(struct mins + } + + static void +-minstrel_aggr_check(struct ieee80211_sta *pubsta, struct sk_buff *skb) +-{ +- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; +- struct sta_info *sta = container_of(pubsta, struct sta_info, sta); +- u16 tid; +- +- if (skb_get_queue_mapping(skb) == IEEE80211_AC_VO) +- return; +- +- if (unlikely(!ieee80211_is_data_qos(hdr->frame_control))) +- return; +- +- if (unlikely(skb->protocol == cpu_to_be16(ETH_P_PAE))) +- return; +- +- tid = ieee80211_get_tid(hdr); +- if (likely(sta->ampdu_mlme.tid_tx[tid])) +- return; +- +- ieee80211_start_tx_ba_session(pubsta, tid, 0); +-} +- +-static void + minstrel_ht_tx_status(void *priv, struct ieee80211_supported_band *sband, + void *priv_sta, struct ieee80211_tx_status *st) + { +@@ -1477,10 +1454,6 @@ minstrel_ht_get_rate(void *priv, struct + struct minstrel_priv *mp = priv; + u16 sample_idx; + +- if (!(info->flags & IEEE80211_TX_CTL_AMPDU) && +- !minstrel_ht_is_legacy_group(MI_RATE_GROUP(mi->max_prob_rate))) +- minstrel_aggr_check(sta, txrc->skb); +- + info->flags |= mi->tx_flags; + + #ifdef CPTCFG_MAC80211_DEBUGFS +@@ -1894,6 +1867,7 @@ static u32 minstrel_ht_get_expected_thro + + static const struct rate_control_ops mac80211_minstrel_ht = { + .name = "minstrel_ht", ++ .capa = RATE_CTRL_CAPA_AMPDU_TRIGGER, + .tx_status_ext = minstrel_ht_tx_status, + .get_rate = minstrel_ht_get_rate, + .rate_init = minstrel_ht_rate_init, +--- a/net/mac80211/tx.c ++++ b/net/mac80211/tx.c +@@ -3933,6 +3933,29 @@ void ieee80211_txq_schedule_start(struct + } + EXPORT_SYMBOL(ieee80211_txq_schedule_start); + ++static void ++ieee80211_aggr_check(struct ieee80211_sub_if_data *sdata, ++ struct sta_info *sta, ++ struct sk_buff *skb) ++{ ++ struct rate_control_ref *ref = sdata->local->rate_ctrl; ++ u16 tid; ++ ++ if (!ref || !(ref->ops->capa & RATE_CTRL_CAPA_AMPDU_TRIGGER)) ++ return; ++ ++ if (!sta || !sta->sta.ht_cap.ht_supported || ++ !sta->sta.wme || skb_get_queue_mapping(skb) == IEEE80211_AC_VO || ++ skb->protocol == sdata->control_port_protocol) ++ return; ++ ++ tid = skb->priority & IEEE80211_QOS_CTL_TID_MASK; ++ if (likely(sta->ampdu_mlme.tid_tx[tid])) ++ return; ++ ++ ieee80211_start_tx_ba_session(&sta->sta, tid, 0); ++} ++ + void __ieee80211_subif_start_xmit(struct sk_buff *skb, + struct net_device *dev, + u32 info_flags, +@@ -3963,6 +3986,8 @@ void __ieee80211_subif_start_xmit(struct + skb_get_hash(skb); + } + ++ ieee80211_aggr_check(sdata, sta, skb); ++ + if (sta) { + struct ieee80211_fast_tx *fast_tx; + +@@ -4226,6 +4251,8 @@ static void ieee80211_8023_xmit(struct i + + memset(info, 0, sizeof(*info)); + ++ ieee80211_aggr_check(sdata, sta, skb); ++ + tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK; + tid_tx = rcu_dereference(sta->ampdu_mlme.tid_tx[tid]); + if (tid_tx) { diff --git a/package/kernel/mac80211/patches/subsys/375-mac80211-call-ieee80211_tx_h_rate_ctrl-when-dequeue.patch b/package/kernel/mac80211/patches/subsys/375-mac80211-call-ieee80211_tx_h_rate_ctrl-when-dequeue.patch new file mode 100644 index 0000000000..49b1212213 --- /dev/null +++ b/package/kernel/mac80211/patches/subsys/375-mac80211-call-ieee80211_tx_h_rate_ctrl-when-dequeue.patch @@ -0,0 +1,114 @@ +From: Ryder Lee +Date: Fri, 28 May 2021 14:05:41 +0800 +Subject: [PATCH] mac80211: call ieee80211_tx_h_rate_ctrl() when dequeue + +Make ieee80211_tx_h_rate_ctrl() get called on dequeue to improve +performance since it reduces the turnaround time for rate control. + +Signed-off-by: Ryder Lee +--- + +--- a/net/mac80211/tx.c ++++ b/net/mac80211/tx.c +@@ -1780,8 +1780,6 @@ static int invoke_tx_handlers_early(stru + CALL_TXH(ieee80211_tx_h_ps_buf); + CALL_TXH(ieee80211_tx_h_check_control_port_protocol); + CALL_TXH(ieee80211_tx_h_select_key); +- if (!ieee80211_hw_check(&tx->local->hw, HAS_RATE_CONTROL)) +- CALL_TXH(ieee80211_tx_h_rate_ctrl); + + txh_done: + if (unlikely(res == TX_DROP)) { +@@ -1814,6 +1812,9 @@ static int invoke_tx_handlers_late(struc + goto txh_done; + } + ++ if (!ieee80211_hw_check(&tx->local->hw, HAS_RATE_CONTROL)) ++ CALL_TXH(ieee80211_tx_h_rate_ctrl); ++ + CALL_TXH(ieee80211_tx_h_michael_mic_add); + CALL_TXH(ieee80211_tx_h_sequence); + CALL_TXH(ieee80211_tx_h_fragment); +@@ -3384,15 +3385,21 @@ out: + * Can be called while the sta lock is held. Anything that can cause packets to + * be generated will cause deadlock! + */ +-static void ieee80211_xmit_fast_finish(struct ieee80211_sub_if_data *sdata, +- struct sta_info *sta, u8 pn_offs, +- struct ieee80211_key *key, +- struct sk_buff *skb) ++static ieee80211_tx_result ++ieee80211_xmit_fast_finish(struct ieee80211_sub_if_data *sdata, ++ struct sta_info *sta, u8 pn_offs, ++ struct ieee80211_key *key, ++ struct ieee80211_tx_data *tx) + { ++ struct sk_buff *skb = tx->skb; + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + struct ieee80211_hdr *hdr = (void *)skb->data; + u8 tid = IEEE80211_NUM_TIDS; + ++ if (!ieee80211_hw_check(&tx->local->hw, HAS_RATE_CONTROL) && ++ ieee80211_tx_h_rate_ctrl(tx) != TX_CONTINUE) ++ return TX_DROP; ++ + if (key) + info->control.hw_key = &key->conf; + +@@ -3441,6 +3448,8 @@ static void ieee80211_xmit_fast_finish(s + break; + } + } ++ ++ return TX_CONTINUE; + } + + static bool ieee80211_xmit_fast(struct ieee80211_sub_if_data *sdata, +@@ -3544,24 +3553,17 @@ static bool ieee80211_xmit_fast(struct i + tx.sta = sta; + tx.key = fast_tx->key; + +- if (!ieee80211_hw_check(&local->hw, HAS_RATE_CONTROL)) { +- tx.skb = skb; +- r = ieee80211_tx_h_rate_ctrl(&tx); +- skb = tx.skb; +- tx.skb = NULL; +- +- if (r != TX_CONTINUE) { +- if (r != TX_QUEUED) +- kfree_skb(skb); +- return true; +- } +- } +- + if (ieee80211_queue_skb(local, sdata, sta, skb)) + return true; + +- ieee80211_xmit_fast_finish(sdata, sta, fast_tx->pn_offs, +- fast_tx->key, skb); ++ tx.skb = skb; ++ r = ieee80211_xmit_fast_finish(sdata, sta, fast_tx->pn_offs, ++ fast_tx->key, &tx); ++ tx.skb = NULL; ++ if (r == TX_DROP) { ++ kfree_skb(skb); ++ return true; ++ } + + if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) + sdata = container_of(sdata->bss, +@@ -3672,8 +3674,12 @@ begin: + (tx.key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV)) + pn_offs = ieee80211_hdrlen(hdr->frame_control); + +- ieee80211_xmit_fast_finish(sta->sdata, sta, pn_offs, +- tx.key, skb); ++ r = ieee80211_xmit_fast_finish(sta->sdata, sta, pn_offs, ++ tx.key, &tx); ++ if (r != TX_CONTINUE) { ++ ieee80211_free_txskb(&local->hw, skb); ++ goto begin; ++ } + } else { + if (invoke_tx_handlers_late(&tx)) + goto begin; diff --git a/package/kernel/mac80211/patches/subsys/377-mac80211-minstrel_ht-fix-sample-time-check.patch b/package/kernel/mac80211/patches/subsys/377-mac80211-minstrel_ht-fix-sample-time-check.patch index 787254b4df..d4b327c69c 100644 --- a/package/kernel/mac80211/patches/subsys/377-mac80211-minstrel_ht-fix-sample-time-check.patch +++ b/package/kernel/mac80211/patches/subsys/377-mac80211-minstrel_ht-fix-sample-time-check.patch @@ -12,7 +12,7 @@ Signed-off-by: Felix Fietkau --- a/net/mac80211/rc80211_minstrel_ht.c +++ b/net/mac80211/rc80211_minstrel_ht.c -@@ -1498,7 +1498,7 @@ minstrel_ht_get_rate(void *priv, struct +@@ -1466,7 +1466,7 @@ minstrel_ht_get_rate(void *priv, struct (info->control.flags & IEEE80211_TX_CTRL_PORT_CTRL_PROTO)) return; diff --git a/package/kernel/mac80211/patches/subsys/379-mac80211-fix-starting-aggregation-sessions-on-mesh-i.patch b/package/kernel/mac80211/patches/subsys/379-mac80211-fix-starting-aggregation-sessions-on-mesh-i.patch new file mode 100644 index 0000000000..56eafaf847 --- /dev/null +++ b/package/kernel/mac80211/patches/subsys/379-mac80211-fix-starting-aggregation-sessions-on-mesh-i.patch @@ -0,0 +1,112 @@ +From: Felix Fietkau +Date: Tue, 29 Jun 2021 13:25:09 +0200 +Subject: [PATCH] mac80211: fix starting aggregation sessions on mesh + interfaces + +The logic for starting aggregation sessions was recently moved from minstrel_ht +to mac80211, into the subif tx handler just after the sta lookup. +Unfortunately this didn't work for mesh interfaces, since the sta lookup is +deferred until a much later point in time on those. +Fix this by also calling the aggregation check right after the deferred sta +lookup. + +Fixes: 08a46c642001 ("mac80211: move A-MPDU session check from minstrel_ht to mac80211") +Signed-off-by: Felix Fietkau +--- + +--- a/net/mac80211/tx.c ++++ b/net/mac80211/tx.c +@@ -1159,6 +1159,29 @@ static bool ieee80211_tx_prep_agg(struct + return queued; + } + ++static void ++ieee80211_aggr_check(struct ieee80211_sub_if_data *sdata, ++ struct sta_info *sta, ++ struct sk_buff *skb) ++{ ++ struct rate_control_ref *ref = sdata->local->rate_ctrl; ++ u16 tid; ++ ++ if (!ref || !(ref->ops->capa & RATE_CTRL_CAPA_AMPDU_TRIGGER)) ++ return; ++ ++ if (!sta || !sta->sta.ht_cap.ht_supported || ++ !sta->sta.wme || skb_get_queue_mapping(skb) == IEEE80211_AC_VO || ++ skb->protocol == sdata->control_port_protocol) ++ return; ++ ++ tid = skb->priority & IEEE80211_QOS_CTL_TID_MASK; ++ if (likely(sta->ampdu_mlme.tid_tx[tid])) ++ return; ++ ++ ieee80211_start_tx_ba_session(&sta->sta, tid, 0); ++} ++ + /* + * initialises @tx + * pass %NULL for the station if unknown, a valid pointer if known +@@ -1172,6 +1195,7 @@ ieee80211_tx_prepare(struct ieee80211_su + struct ieee80211_local *local = sdata->local; + struct ieee80211_hdr *hdr; + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); ++ bool aggr_check = false; + int tid; + + memset(tx, 0, sizeof(*tx)); +@@ -1202,8 +1226,10 @@ ieee80211_tx_prepare(struct ieee80211_su + tx->sdata->control_port_protocol == tx->skb->protocol) { + tx->sta = sta_info_get_bss(sdata, hdr->addr1); + } +- if (!tx->sta && !is_multicast_ether_addr(hdr->addr1)) ++ if (!tx->sta && !is_multicast_ether_addr(hdr->addr1)) { + tx->sta = sta_info_get(sdata, hdr->addr1); ++ aggr_check = true; ++ } + } + + if (tx->sta && ieee80211_is_data_qos(hdr->frame_control) && +@@ -1213,8 +1239,12 @@ ieee80211_tx_prepare(struct ieee80211_su + struct tid_ampdu_tx *tid_tx; + + tid = ieee80211_get_tid(hdr); +- + tid_tx = rcu_dereference(tx->sta->ampdu_mlme.tid_tx[tid]); ++ if (!tid_tx && aggr_check) { ++ ieee80211_aggr_check(sdata, tx->sta, skb); ++ tid_tx = rcu_dereference(tx->sta->ampdu_mlme.tid_tx[tid]); ++ } ++ + if (tid_tx) { + bool queued; + +@@ -3949,29 +3979,6 @@ void ieee80211_txq_schedule_start(struct + } + EXPORT_SYMBOL(ieee80211_txq_schedule_start); + +-static void +-ieee80211_aggr_check(struct ieee80211_sub_if_data *sdata, +- struct sta_info *sta, +- struct sk_buff *skb) +-{ +- struct rate_control_ref *ref = sdata->local->rate_ctrl; +- u16 tid; +- +- if (!ref || !(ref->ops->capa & RATE_CTRL_CAPA_AMPDU_TRIGGER)) +- return; +- +- if (!sta || !sta->sta.ht_cap.ht_supported || +- !sta->sta.wme || skb_get_queue_mapping(skb) == IEEE80211_AC_VO || +- skb->protocol == sdata->control_port_protocol) +- return; +- +- tid = skb->priority & IEEE80211_QOS_CTL_TID_MASK; +- if (likely(sta->ampdu_mlme.tid_tx[tid])) +- return; +- +- ieee80211_start_tx_ba_session(&sta->sta, tid, 0); +-} +- + void __ieee80211_subif_start_xmit(struct sk_buff *skb, + struct net_device *dev, + u32 info_flags,