b.liu | e958203 | 2025-04-17 19:18:16 +0800 | [diff] [blame] | 1 | From: Felix Fietkau <nbd@nbd.name> |
| 2 | Date: Tue, 29 Jun 2021 13:25:09 +0200 |
| 3 | Subject: [PATCH] mac80211: fix starting aggregation sessions on mesh |
| 4 | interfaces |
| 5 | |
| 6 | The logic for starting aggregation sessions was recently moved from minstrel_ht |
| 7 | to mac80211, into the subif tx handler just after the sta lookup. |
| 8 | Unfortunately this didn't work for mesh interfaces, since the sta lookup is |
| 9 | deferred until a much later point in time on those. |
| 10 | Fix this by also calling the aggregation check right after the deferred sta |
| 11 | lookup. |
| 12 | |
| 13 | Fixes: 08a46c642001 ("mac80211: move A-MPDU session check from minstrel_ht to mac80211") |
| 14 | Signed-off-by: Felix Fietkau <nbd@nbd.name> |
| 15 | --- |
| 16 | |
| 17 | --- a/net/mac80211/tx.c |
| 18 | +++ b/net/mac80211/tx.c |
| 19 | @@ -1159,6 +1159,29 @@ static bool ieee80211_tx_prep_agg(struct |
| 20 | return queued; |
| 21 | } |
| 22 | |
| 23 | +static void |
| 24 | +ieee80211_aggr_check(struct ieee80211_sub_if_data *sdata, |
| 25 | + struct sta_info *sta, |
| 26 | + struct sk_buff *skb) |
| 27 | +{ |
| 28 | + struct rate_control_ref *ref = sdata->local->rate_ctrl; |
| 29 | + u16 tid; |
| 30 | + |
| 31 | + if (!ref || !(ref->ops->capa & RATE_CTRL_CAPA_AMPDU_TRIGGER)) |
| 32 | + return; |
| 33 | + |
| 34 | + if (!sta || !sta->sta.ht_cap.ht_supported || |
| 35 | + !sta->sta.wme || skb_get_queue_mapping(skb) == IEEE80211_AC_VO || |
| 36 | + skb->protocol == sdata->control_port_protocol) |
| 37 | + return; |
| 38 | + |
| 39 | + tid = skb->priority & IEEE80211_QOS_CTL_TID_MASK; |
| 40 | + if (likely(sta->ampdu_mlme.tid_tx[tid])) |
| 41 | + return; |
| 42 | + |
| 43 | + ieee80211_start_tx_ba_session(&sta->sta, tid, 0); |
| 44 | +} |
| 45 | + |
| 46 | /* |
| 47 | * initialises @tx |
| 48 | * pass %NULL for the station if unknown, a valid pointer if known |
| 49 | @@ -1172,6 +1195,7 @@ ieee80211_tx_prepare(struct ieee80211_su |
| 50 | struct ieee80211_local *local = sdata->local; |
| 51 | struct ieee80211_hdr *hdr; |
| 52 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
| 53 | + bool aggr_check = false; |
| 54 | int tid; |
| 55 | |
| 56 | memset(tx, 0, sizeof(*tx)); |
| 57 | @@ -1200,8 +1224,10 @@ ieee80211_tx_prepare(struct ieee80211_su |
| 58 | } else if (tx->sdata->control_port_protocol == tx->skb->protocol) { |
| 59 | tx->sta = sta_info_get_bss(sdata, hdr->addr1); |
| 60 | } |
| 61 | - if (!tx->sta && !is_multicast_ether_addr(hdr->addr1)) |
| 62 | + if (!tx->sta && !is_multicast_ether_addr(hdr->addr1)) { |
| 63 | tx->sta = sta_info_get(sdata, hdr->addr1); |
| 64 | + aggr_check = true; |
| 65 | + } |
| 66 | } |
| 67 | |
| 68 | if (tx->sta && ieee80211_is_data_qos(hdr->frame_control) && |
| 69 | @@ -1211,8 +1237,12 @@ ieee80211_tx_prepare(struct ieee80211_su |
| 70 | struct tid_ampdu_tx *tid_tx; |
| 71 | |
| 72 | tid = ieee80211_get_tid(hdr); |
| 73 | - |
| 74 | tid_tx = rcu_dereference(tx->sta->ampdu_mlme.tid_tx[tid]); |
| 75 | + if (!tid_tx && aggr_check) { |
| 76 | + ieee80211_aggr_check(sdata, tx->sta, skb); |
| 77 | + tid_tx = rcu_dereference(tx->sta->ampdu_mlme.tid_tx[tid]); |
| 78 | + } |
| 79 | + |
| 80 | if (tid_tx) { |
| 81 | bool queued; |
| 82 | |
| 83 | @@ -3981,29 +4011,6 @@ void ieee80211_txq_schedule_start(struct |
| 84 | } |
| 85 | EXPORT_SYMBOL(ieee80211_txq_schedule_start); |
| 86 | |
| 87 | -static void |
| 88 | -ieee80211_aggr_check(struct ieee80211_sub_if_data *sdata, |
| 89 | - struct sta_info *sta, |
| 90 | - struct sk_buff *skb) |
| 91 | -{ |
| 92 | - struct rate_control_ref *ref = sdata->local->rate_ctrl; |
| 93 | - u16 tid; |
| 94 | - |
| 95 | - if (!ref || !(ref->ops->capa & RATE_CTRL_CAPA_AMPDU_TRIGGER)) |
| 96 | - return; |
| 97 | - |
| 98 | - if (!sta || !sta->sta.ht_cap.ht_supported || |
| 99 | - !sta->sta.wme || skb_get_queue_mapping(skb) == IEEE80211_AC_VO || |
| 100 | - skb->protocol == sdata->control_port_protocol) |
| 101 | - return; |
| 102 | - |
| 103 | - tid = skb->priority & IEEE80211_QOS_CTL_TID_MASK; |
| 104 | - if (likely(sta->ampdu_mlme.tid_tx[tid])) |
| 105 | - return; |
| 106 | - |
| 107 | - ieee80211_start_tx_ba_session(&sta->sta, tid, 0); |
| 108 | -} |
| 109 | - |
| 110 | void __ieee80211_subif_start_xmit(struct sk_buff *skb, |
| 111 | struct net_device *dev, |
| 112 | u32 info_flags, |