From: Felix Fietkau Date: Thu, 17 Jun 2021 16:10:36 +0000 (+0200) Subject: mac80211: system hang caused by deferring calls into minstrel to dequeue X-Git-Tag: mikrotik~1853 X-Git-Url: http://git.lede-project.org./?a=commitdiff_plain;h=a603e82dd342680d584c4eb5f1b222e056379890;p=openwrt%2Fstaging%2Fchunkeey.git mac80211: system hang caused by deferring calls into minstrel to dequeue Move the aggregation check to mac80211 Signed-off-by: Felix Fietkau --- diff --git a/package/kernel/mac80211/patches/subsys/374-mac80211-call-ieee80211_tx_h_rate_ctrl-when-dequeue.patch b/package/kernel/mac80211/patches/subsys/374-mac80211-call-ieee80211_tx_h_rate_ctrl-when-dequeue.patch deleted file mode 100644 index 49b1212213..0000000000 --- a/package/kernel/mac80211/patches/subsys/374-mac80211-call-ieee80211_tx_h_rate_ctrl-when-dequeue.patch +++ /dev/null @@ -1,114 +0,0 @@ -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/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/375-mac80211-minstrel_ht-fix-minstrel_aggr_check-for-enc.patch b/package/kernel/mac80211/patches/subsys/375-mac80211-minstrel_ht-fix-minstrel_aggr_check-for-enc.patch deleted file mode 100644 index 2fe19dfd94..0000000000 --- a/package/kernel/mac80211/patches/subsys/375-mac80211-minstrel_ht-fix-minstrel_aggr_check-for-enc.patch +++ /dev/null @@ -1,39 +0,0 @@ -From: Ryder Lee -Date: Fri, 28 May 2021 14:05:42 +0800 -Subject: [PATCH] mac80211: minstrel_ht: fix minstrel_aggr_check for encap - offload - -Avoid checking ieee80211_hdr to support encap offload. - -Signed-off-by: Ryder Lee ---- - ---- a/net/mac80211/rc80211_minstrel_ht.c -+++ b/net/mac80211/rc80211_minstrel_ht.c -@@ -1156,19 +1156,24 @@ static void - minstrel_aggr_check(struct ieee80211_sta *pubsta, struct sk_buff *skb) - { - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; -+ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - 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))) -+ if (unlikely(!pubsta->wme)) -+ return; -+ -+ if (!(info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP) && -+ 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); -+ tid = skb->priority & IEEE80211_QOS_CTL_TID_MASK; - if (likely(sta->ampdu_mlme.tid_tx[tid])) - return; - 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;