diff --git a/package/kernel/mac80211/patches/subsys/342-wifi-mac80211-Support-EHT-1024-aggregation-size-in-T.patch b/package/kernel/mac80211/patches/subsys/342-wifi-mac80211-Support-EHT-1024-aggregation-size-in-T.patch new file mode 100644 index 0000000000..2771f5eac7 --- /dev/null +++ b/package/kernel/mac80211/patches/subsys/342-wifi-mac80211-Support-EHT-1024-aggregation-size-in-T.patch @@ -0,0 +1,321 @@ +From 406c5548c661df0bff6bb6ee79bf9d49faf23e31 Mon Sep 17 00:00:00 2001 +From: MeiChia Chiu +Date: Tue, 12 Nov 2024 16:38:46 +0800 +Subject: [PATCH] wifi: mac80211: Support EHT 1024 aggregation size in TX + +Support EHT 1024 aggregation size in TX + +The 1024 agg size for RX is supported but not for TX. +This patch adds this support and refactors common parsing logics for +addbaext in both process_addba_resp and process_addba_req into a +function. + +Reviewed-by: Shayne Chen +Reviewed-by: Money Wang +Co-developed-by: Peter Chiu +Signed-off-by: Peter Chiu +Signed-off-by: MeiChia Chiu +Link: https://patch.msgid.link/20241112083846.32063-1-MeiChia.Chiu@mediatek.com +[pass elems/len instead of mgmt/len/is_req] +Signed-off-by: Johannes Berg +--- + include/linux/ieee80211.h | 2 + + net/mac80211/agg-rx.c | 94 +++++++++++++++++++++++--------------- + net/mac80211/agg-tx.c | 31 +++++++++---- + net/mac80211/ht.c | 2 +- + net/mac80211/ieee80211_i.h | 9 +++- + 5 files changed, 90 insertions(+), 48 deletions(-) + +diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h +index 456bca45ff05..05dedc45505c 100644 +--- a/include/linux/ieee80211.h ++++ b/include/linux/ieee80211.h +@@ -1445,6 +1445,8 @@ struct ieee80211_mgmt { + __le16 status; + __le16 capab; + __le16 timeout; ++ /* followed by BA Extension */ ++ u8 variable[]; + } __packed addba_resp; + struct{ + u8 action_code; +diff --git a/net/mac80211/agg-rx.c b/net/mac80211/agg-rx.c +index fe7eab4b681b..f3fbe5a4395e 100644 +--- a/net/mac80211/agg-rx.c ++++ b/net/mac80211/agg-rx.c +@@ -170,28 +170,63 @@ static void sta_rx_agg_reorder_timer_expired(struct timer_list *t) + rcu_read_unlock(); + } + +-static void ieee80211_add_addbaext(struct ieee80211_sub_if_data *sdata, +- struct sk_buff *skb, +- const struct ieee80211_addba_ext_ie *req, +- u16 buf_size) ++void ieee80211_add_addbaext(struct sk_buff *skb, ++ const u8 req_addba_ext_data, ++ u16 buf_size) + { +- struct ieee80211_addba_ext_ie *resp; ++ struct ieee80211_addba_ext_ie *addba_ext; + u8 *pos; + + pos = skb_put_zero(skb, 2 + sizeof(struct ieee80211_addba_ext_ie)); + *pos++ = WLAN_EID_ADDBA_EXT; + *pos++ = sizeof(struct ieee80211_addba_ext_ie); +- resp = (struct ieee80211_addba_ext_ie *)pos; +- resp->data = req->data & IEEE80211_ADDBA_EXT_NO_FRAG; ++ addba_ext = (struct ieee80211_addba_ext_ie *)pos; + +- resp->data |= u8_encode_bits(buf_size >> IEEE80211_ADDBA_EXT_BUF_SIZE_SHIFT, +- IEEE80211_ADDBA_EXT_BUF_SIZE_MASK); ++ addba_ext->data = IEEE80211_ADDBA_EXT_NO_FRAG; ++ if (req_addba_ext_data) ++ addba_ext->data &= req_addba_ext_data; ++ ++ addba_ext->data |= ++ u8_encode_bits(buf_size >> IEEE80211_ADDBA_EXT_BUF_SIZE_SHIFT, ++ IEEE80211_ADDBA_EXT_BUF_SIZE_MASK); ++} ++ ++u8 ieee80211_retrieve_addba_ext_data(struct sta_info *sta, ++ const void *elem_data, ssize_t elem_len, ++ u16 *buf_size) ++{ ++ struct ieee802_11_elems *elems; ++ u8 buf_size_1k, data = 0; ++ ++ if (!sta->sta.deflink.he_cap.has_he) ++ return 0; ++ ++ if (elem_len <= 0) ++ return 0; ++ ++ elems = ieee802_11_parse_elems(elem_data, elem_len, true, NULL); ++ ++ if (elems && !elems->parse_error && elems->addba_ext_ie) { ++ data = elems->addba_ext_ie->data; ++ ++ if (!sta->sta.deflink.eht_cap.has_eht || !buf_size) ++ goto free; ++ ++ buf_size_1k = u8_get_bits(elems->addba_ext_ie->data, ++ IEEE80211_ADDBA_EXT_BUF_SIZE_MASK); ++ *buf_size |= (u16)buf_size_1k << ++ IEEE80211_ADDBA_EXT_BUF_SIZE_SHIFT; ++ } ++free: ++ kfree(elems); ++ ++ return data; + } + + static void ieee80211_send_addba_resp(struct sta_info *sta, u8 *da, u16 tid, + u8 dialog_token, u16 status, u16 policy, + u16 buf_size, u16 timeout, +- const struct ieee80211_addba_ext_ie *addbaext) ++ const u8 req_addba_ext_data) + { + struct ieee80211_sub_if_data *sdata = sta->sdata; + struct ieee80211_local *local = sdata->local; +@@ -223,8 +258,8 @@ static void ieee80211_send_addba_resp(struct sta_info *sta, u8 *da, u16 tid, + mgmt->u.action.u.addba_resp.timeout = cpu_to_le16(timeout); + mgmt->u.action.u.addba_resp.status = cpu_to_le16(status); + +- if (sta->sta.deflink.he_cap.has_he && addbaext) +- ieee80211_add_addbaext(sdata, skb, addbaext, buf_size); ++ if (sta->sta.deflink.he_cap.has_he) ++ ieee80211_add_addbaext(skb, req_addba_ext_data, buf_size); + + ieee80211_tx_skb(sdata, skb); + } +@@ -233,7 +268,7 @@ void __ieee80211_start_rx_ba_session(struct sta_info *sta, + u8 dialog_token, u16 timeout, + u16 start_seq_num, u16 ba_policy, u16 tid, + u16 buf_size, bool tx, bool auto_seq, +- const struct ieee80211_addba_ext_ie *addbaext) ++ const u8 addba_ext_data) + { + struct ieee80211_local *local = sta->sdata->local; + struct tid_ampdu_rx *tid_agg_rx; +@@ -419,7 +454,7 @@ void __ieee80211_start_rx_ba_session(struct sta_info *sta, + if (tx) + ieee80211_send_addba_resp(sta, sta->sta.addr, tid, + dialog_token, status, 1, buf_size, +- timeout, addbaext); ++ timeout, addba_ext_data); + } + + void ieee80211_process_addba_request(struct ieee80211_local *local, +@@ -428,9 +463,7 @@ void ieee80211_process_addba_request(struct ieee80211_local *local, + size_t len) + { + u16 capab, tid, timeout, ba_policy, buf_size, start_seq_num; +- struct ieee802_11_elems *elems = NULL; +- u8 dialog_token; +- int ies_len; ++ u8 dialog_token, addba_ext_data; + + /* extract session parameters from addba request frame */ + dialog_token = mgmt->u.action.u.addba_req.dialog_token; +@@ -443,28 +476,17 @@ void ieee80211_process_addba_request(struct ieee80211_local *local, + tid = (capab & IEEE80211_ADDBA_PARAM_TID_MASK) >> 2; + buf_size = (capab & IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK) >> 6; + +- ies_len = len - offsetof(struct ieee80211_mgmt, +- u.action.u.addba_req.variable); +- if (ies_len) { +- elems = ieee802_11_parse_elems(mgmt->u.action.u.addba_req.variable, +- ies_len, true, NULL); +- if (!elems || elems->parse_error) +- goto free; +- } +- +- if (sta->sta.deflink.eht_cap.has_eht && elems && elems->addba_ext_ie) { +- u8 buf_size_1k = u8_get_bits(elems->addba_ext_ie->data, +- IEEE80211_ADDBA_EXT_BUF_SIZE_MASK); +- +- buf_size |= buf_size_1k << IEEE80211_ADDBA_EXT_BUF_SIZE_SHIFT; +- } ++ addba_ext_data = ++ ieee80211_retrieve_addba_ext_data(sta, ++ mgmt->u.action.u.addba_req.variable, ++ len - ++ offsetof(typeof(*mgmt), ++ u.action.u.addba_req.variable), ++ &buf_size); + + __ieee80211_start_rx_ba_session(sta, dialog_token, timeout, + start_seq_num, ba_policy, tid, +- buf_size, true, false, +- elems ? elems->addba_ext_ie : NULL); +-free: +- kfree(elems); ++ buf_size, true, false, addba_ext_data); + } + + void ieee80211_manage_rx_ba_offl(struct ieee80211_vif *vif, +diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c +index 04cb45cfb310..61f2cac37728 100644 +--- a/net/mac80211/agg-tx.c ++++ b/net/mac80211/agg-tx.c +@@ -58,23 +58,24 @@ + * complete. + */ + +-static void ieee80211_send_addba_request(struct ieee80211_sub_if_data *sdata, +- const u8 *da, u16 tid, ++static void ieee80211_send_addba_request(struct sta_info *sta, u16 tid, + u8 dialog_token, u16 start_seq_num, + u16 agg_size, u16 timeout) + { ++ struct ieee80211_sub_if_data *sdata = sta->sdata; + struct ieee80211_local *local = sdata->local; + struct sk_buff *skb; + struct ieee80211_mgmt *mgmt; + u16 capab; + +- skb = dev_alloc_skb(sizeof(*mgmt) + local->hw.extra_tx_headroom); +- ++ skb = dev_alloc_skb(sizeof(*mgmt) + ++ 2 + sizeof(struct ieee80211_addba_ext_ie) + ++ local->hw.extra_tx_headroom); + if (!skb) + return; + + skb_reserve(skb, local->hw.extra_tx_headroom); +- mgmt = ieee80211_mgmt_ba(skb, da, sdata); ++ mgmt = ieee80211_mgmt_ba(skb, sta->sta.addr, sdata); + + skb_put(skb, 1 + sizeof(mgmt->u.action.u.addba_req)); + +@@ -93,6 +94,9 @@ static void ieee80211_send_addba_request(struct ieee80211_sub_if_data *sdata, + mgmt->u.action.u.addba_req.start_seq_num = + cpu_to_le16(start_seq_num << 4); + ++ if (sta->sta.deflink.he_cap.has_he) ++ ieee80211_add_addbaext(skb, 0, agg_size); ++ + ieee80211_tx_skb_tid(sdata, skb, tid, -1); + } + +@@ -460,8 +464,11 @@ static void ieee80211_send_addba_with_timeout(struct sta_info *sta, + sta->ampdu_mlme.addba_req_num[tid]++; + spin_unlock_bh(&sta->lock); + +- if (sta->sta.deflink.he_cap.has_he) { ++ if (sta->sta.deflink.eht_cap.has_eht) { + buf_size = local->hw.max_tx_aggregation_subframes; ++ } else if (sta->sta.deflink.he_cap.has_he) { ++ buf_size = min_t(u16, local->hw.max_tx_aggregation_subframes, ++ IEEE80211_MAX_AMPDU_BUF_HE); + } else { + /* + * We really should use what the driver told us it will +@@ -473,9 +480,8 @@ static void ieee80211_send_addba_with_timeout(struct sta_info *sta, + } + + /* send AddBA request */ +- ieee80211_send_addba_request(sdata, sta->sta.addr, tid, +- tid_tx->dialog_token, tid_tx->ssn, +- buf_size, tid_tx->timeout); ++ ieee80211_send_addba_request(sta, tid, tid_tx->dialog_token, ++ tid_tx->ssn, buf_size, tid_tx->timeout); + + WARN_ON(test_and_set_bit(HT_AGG_STATE_SENT_ADDBA, &tid_tx->state)); + } +@@ -970,6 +976,13 @@ void ieee80211_process_addba_resp(struct ieee80211_local *local, + amsdu = capab & IEEE80211_ADDBA_PARAM_AMSDU_MASK; + tid = u16_get_bits(capab, IEEE80211_ADDBA_PARAM_TID_MASK); + buf_size = u16_get_bits(capab, IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK); ++ ++ ieee80211_retrieve_addba_ext_data(sta, ++ mgmt->u.action.u.addba_resp.variable, ++ len - offsetof(typeof(*mgmt), ++ u.action.u.addba_resp.variable), ++ &buf_size); ++ + buf_size = min(buf_size, local->hw.max_tx_aggregation_subframes); + + txq = sta->sta.txq[tid]; +diff --git a/net/mac80211/ht.c b/net/mac80211/ht.c +index 1c2b7dd8976a..32390d8a9d75 100644 +--- a/net/mac80211/ht.c ++++ b/net/mac80211/ht.c +@@ -379,7 +379,7 @@ void ieee80211_ba_session_work(struct wiphy *wiphy, struct wiphy_work *work) + sta->ampdu_mlme.tid_rx_manage_offl)) + __ieee80211_start_rx_ba_session(sta, 0, 0, 0, 1, tid, + IEEE80211_MAX_AMPDU_BUF_HT, +- false, true, NULL); ++ false, true, 0); + + if (test_and_clear_bit(tid + IEEE80211_NUM_TIDS, + sta->ampdu_mlme.tid_rx_manage_offl)) +diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h +index 7dcb46120abc..752297bcde76 100644 +--- a/net/mac80211/ieee80211_i.h ++++ b/net/mac80211/ieee80211_i.h +@@ -2111,14 +2111,19 @@ int ieee80211_send_smps_action(struct ieee80211_sub_if_data *sdata, + const u8 *bssid, int link_id); + bool ieee80211_smps_is_restrictive(enum ieee80211_smps_mode smps_mode_old, + enum ieee80211_smps_mode smps_mode_new); +- ++void ieee80211_add_addbaext(struct sk_buff *skb, ++ const u8 req_addba_ext_data, ++ u16 buf_size); ++u8 ieee80211_retrieve_addba_ext_data(struct sta_info *sta, ++ const void *elem_data, ssize_t elem_len, ++ u16 *buf_size); + void __ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, + u16 initiator, u16 reason, bool stop); + void __ieee80211_start_rx_ba_session(struct sta_info *sta, + u8 dialog_token, u16 timeout, + u16 start_seq_num, u16 ba_policy, u16 tid, + u16 buf_size, bool tx, bool auto_seq, +- const struct ieee80211_addba_ext_ie *addbaext); ++ const u8 addba_ext_data); + void ieee80211_sta_tear_down_BA_sessions(struct sta_info *sta, + enum ieee80211_agg_stop_reason reason); + void ieee80211_process_delba(struct ieee80211_sub_if_data *sdata, +-- +2.39.5 +