Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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 <shayne.chen@mediatek.com>
Reviewed-by: Money Wang <money.wang@mediatek.com>
Co-developed-by: Peter Chiu <chui-hao.chiu@mediatek.com>
Signed-off-by: Peter Chiu <chui-hao.chiu@mediatek.com>
Signed-off-by: MeiChia Chiu <MeiChia.Chiu@mediatek.com>
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 <johannes.berg@intel.com>

authored by

MeiChia Chiu and committed by
Johannes Berg
406c5548 8251e762

+90 -48
+2
include/linux/ieee80211.h
··· 1445 1445 __le16 status; 1446 1446 __le16 capab; 1447 1447 __le16 timeout; 1448 + /* followed by BA Extension */ 1449 + u8 variable[]; 1448 1450 } __packed addba_resp; 1449 1451 struct{ 1450 1452 u8 action_code;
+58 -36
net/mac80211/agg-rx.c
··· 170 170 rcu_read_unlock(); 171 171 } 172 172 173 - static void ieee80211_add_addbaext(struct ieee80211_sub_if_data *sdata, 174 - struct sk_buff *skb, 175 - const struct ieee80211_addba_ext_ie *req, 176 - u16 buf_size) 173 + void ieee80211_add_addbaext(struct sk_buff *skb, 174 + const u8 req_addba_ext_data, 175 + u16 buf_size) 177 176 { 178 - struct ieee80211_addba_ext_ie *resp; 177 + struct ieee80211_addba_ext_ie *addba_ext; 179 178 u8 *pos; 180 179 181 180 pos = skb_put_zero(skb, 2 + sizeof(struct ieee80211_addba_ext_ie)); 182 181 *pos++ = WLAN_EID_ADDBA_EXT; 183 182 *pos++ = sizeof(struct ieee80211_addba_ext_ie); 184 - resp = (struct ieee80211_addba_ext_ie *)pos; 185 - resp->data = req->data & IEEE80211_ADDBA_EXT_NO_FRAG; 183 + addba_ext = (struct ieee80211_addba_ext_ie *)pos; 186 184 187 - resp->data |= u8_encode_bits(buf_size >> IEEE80211_ADDBA_EXT_BUF_SIZE_SHIFT, 188 - IEEE80211_ADDBA_EXT_BUF_SIZE_MASK); 185 + addba_ext->data = IEEE80211_ADDBA_EXT_NO_FRAG; 186 + if (req_addba_ext_data) 187 + addba_ext->data &= req_addba_ext_data; 188 + 189 + addba_ext->data |= 190 + u8_encode_bits(buf_size >> IEEE80211_ADDBA_EXT_BUF_SIZE_SHIFT, 191 + IEEE80211_ADDBA_EXT_BUF_SIZE_MASK); 192 + } 193 + 194 + u8 ieee80211_retrieve_addba_ext_data(struct sta_info *sta, 195 + const void *elem_data, ssize_t elem_len, 196 + u16 *buf_size) 197 + { 198 + struct ieee802_11_elems *elems; 199 + u8 buf_size_1k, data = 0; 200 + 201 + if (!sta->sta.deflink.he_cap.has_he) 202 + return 0; 203 + 204 + if (elem_len <= 0) 205 + return 0; 206 + 207 + elems = ieee802_11_parse_elems(elem_data, elem_len, true, NULL); 208 + 209 + if (elems && !elems->parse_error && elems->addba_ext_ie) { 210 + data = elems->addba_ext_ie->data; 211 + 212 + if (!sta->sta.deflink.eht_cap.has_eht || !buf_size) 213 + goto free; 214 + 215 + buf_size_1k = u8_get_bits(elems->addba_ext_ie->data, 216 + IEEE80211_ADDBA_EXT_BUF_SIZE_MASK); 217 + *buf_size |= (u16)buf_size_1k << 218 + IEEE80211_ADDBA_EXT_BUF_SIZE_SHIFT; 219 + } 220 + free: 221 + kfree(elems); 222 + 223 + return data; 189 224 } 190 225 191 226 static void ieee80211_send_addba_resp(struct sta_info *sta, u8 *da, u16 tid, 192 227 u8 dialog_token, u16 status, u16 policy, 193 228 u16 buf_size, u16 timeout, 194 - const struct ieee80211_addba_ext_ie *addbaext) 229 + const u8 req_addba_ext_data) 195 230 { 196 231 struct ieee80211_sub_if_data *sdata = sta->sdata; 197 232 struct ieee80211_local *local = sdata->local; ··· 258 223 mgmt->u.action.u.addba_resp.timeout = cpu_to_le16(timeout); 259 224 mgmt->u.action.u.addba_resp.status = cpu_to_le16(status); 260 225 261 - if (sta->sta.deflink.he_cap.has_he && addbaext) 262 - ieee80211_add_addbaext(sdata, skb, addbaext, buf_size); 226 + if (sta->sta.deflink.he_cap.has_he) 227 + ieee80211_add_addbaext(skb, req_addba_ext_data, buf_size); 263 228 264 229 ieee80211_tx_skb(sdata, skb); 265 230 } ··· 268 233 u8 dialog_token, u16 timeout, 269 234 u16 start_seq_num, u16 ba_policy, u16 tid, 270 235 u16 buf_size, bool tx, bool auto_seq, 271 - const struct ieee80211_addba_ext_ie *addbaext) 236 + const u8 addba_ext_data) 272 237 { 273 238 struct ieee80211_local *local = sta->sdata->local; 274 239 struct tid_ampdu_rx *tid_agg_rx; ··· 454 419 if (tx) 455 420 ieee80211_send_addba_resp(sta, sta->sta.addr, tid, 456 421 dialog_token, status, 1, buf_size, 457 - timeout, addbaext); 422 + timeout, addba_ext_data); 458 423 } 459 424 460 425 void ieee80211_process_addba_request(struct ieee80211_local *local, ··· 463 428 size_t len) 464 429 { 465 430 u16 capab, tid, timeout, ba_policy, buf_size, start_seq_num; 466 - struct ieee802_11_elems *elems = NULL; 467 - u8 dialog_token; 468 - int ies_len; 431 + u8 dialog_token, addba_ext_data; 469 432 470 433 /* extract session parameters from addba request frame */ 471 434 dialog_token = mgmt->u.action.u.addba_req.dialog_token; ··· 476 443 tid = (capab & IEEE80211_ADDBA_PARAM_TID_MASK) >> 2; 477 444 buf_size = (capab & IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK) >> 6; 478 445 479 - ies_len = len - offsetof(struct ieee80211_mgmt, 480 - u.action.u.addba_req.variable); 481 - if (ies_len) { 482 - elems = ieee802_11_parse_elems(mgmt->u.action.u.addba_req.variable, 483 - ies_len, true, NULL); 484 - if (!elems || elems->parse_error) 485 - goto free; 486 - } 487 - 488 - if (sta->sta.deflink.eht_cap.has_eht && elems && elems->addba_ext_ie) { 489 - u8 buf_size_1k = u8_get_bits(elems->addba_ext_ie->data, 490 - IEEE80211_ADDBA_EXT_BUF_SIZE_MASK); 491 - 492 - buf_size |= buf_size_1k << IEEE80211_ADDBA_EXT_BUF_SIZE_SHIFT; 493 - } 446 + addba_ext_data = 447 + ieee80211_retrieve_addba_ext_data(sta, 448 + mgmt->u.action.u.addba_req.variable, 449 + len - 450 + offsetof(typeof(*mgmt), 451 + u.action.u.addba_req.variable), 452 + &buf_size); 494 453 495 454 __ieee80211_start_rx_ba_session(sta, dialog_token, timeout, 496 455 start_seq_num, ba_policy, tid, 497 - buf_size, true, false, 498 - elems ? elems->addba_ext_ie : NULL); 499 - free: 500 - kfree(elems); 456 + buf_size, true, false, addba_ext_data); 501 457 } 502 458 503 459 void ieee80211_manage_rx_ba_offl(struct ieee80211_vif *vif,
+22 -9
net/mac80211/agg-tx.c
··· 58 58 * complete. 59 59 */ 60 60 61 - static void ieee80211_send_addba_request(struct ieee80211_sub_if_data *sdata, 62 - const u8 *da, u16 tid, 61 + static void ieee80211_send_addba_request(struct sta_info *sta, u16 tid, 63 62 u8 dialog_token, u16 start_seq_num, 64 63 u16 agg_size, u16 timeout) 65 64 { 65 + struct ieee80211_sub_if_data *sdata = sta->sdata; 66 66 struct ieee80211_local *local = sdata->local; 67 67 struct sk_buff *skb; 68 68 struct ieee80211_mgmt *mgmt; 69 69 u16 capab; 70 70 71 - skb = dev_alloc_skb(sizeof(*mgmt) + local->hw.extra_tx_headroom); 72 - 71 + skb = dev_alloc_skb(sizeof(*mgmt) + 72 + 2 + sizeof(struct ieee80211_addba_ext_ie) + 73 + local->hw.extra_tx_headroom); 73 74 if (!skb) 74 75 return; 75 76 76 77 skb_reserve(skb, local->hw.extra_tx_headroom); 77 - mgmt = ieee80211_mgmt_ba(skb, da, sdata); 78 + mgmt = ieee80211_mgmt_ba(skb, sta->sta.addr, sdata); 78 79 79 80 skb_put(skb, 1 + sizeof(mgmt->u.action.u.addba_req)); 80 81 ··· 93 92 mgmt->u.action.u.addba_req.timeout = cpu_to_le16(timeout); 94 93 mgmt->u.action.u.addba_req.start_seq_num = 95 94 cpu_to_le16(start_seq_num << 4); 95 + 96 + if (sta->sta.deflink.he_cap.has_he) 97 + ieee80211_add_addbaext(skb, 0, agg_size); 96 98 97 99 ieee80211_tx_skb_tid(sdata, skb, tid, -1); 98 100 } ··· 464 460 sta->ampdu_mlme.addba_req_num[tid]++; 465 461 spin_unlock_bh(&sta->lock); 466 462 467 - if (sta->sta.deflink.he_cap.has_he) { 463 + if (sta->sta.deflink.eht_cap.has_eht) { 468 464 buf_size = local->hw.max_tx_aggregation_subframes; 465 + } else if (sta->sta.deflink.he_cap.has_he) { 466 + buf_size = min_t(u16, local->hw.max_tx_aggregation_subframes, 467 + IEEE80211_MAX_AMPDU_BUF_HE); 469 468 } else { 470 469 /* 471 470 * We really should use what the driver told us it will ··· 480 473 } 481 474 482 475 /* send AddBA request */ 483 - ieee80211_send_addba_request(sdata, sta->sta.addr, tid, 484 - tid_tx->dialog_token, tid_tx->ssn, 485 - buf_size, tid_tx->timeout); 476 + ieee80211_send_addba_request(sta, tid, tid_tx->dialog_token, 477 + tid_tx->ssn, buf_size, tid_tx->timeout); 486 478 487 479 WARN_ON(test_and_set_bit(HT_AGG_STATE_SENT_ADDBA, &tid_tx->state)); 488 480 } ··· 976 970 amsdu = capab & IEEE80211_ADDBA_PARAM_AMSDU_MASK; 977 971 tid = u16_get_bits(capab, IEEE80211_ADDBA_PARAM_TID_MASK); 978 972 buf_size = u16_get_bits(capab, IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK); 973 + 974 + ieee80211_retrieve_addba_ext_data(sta, 975 + mgmt->u.action.u.addba_resp.variable, 976 + len - offsetof(typeof(*mgmt), 977 + u.action.u.addba_resp.variable), 978 + &buf_size); 979 + 979 980 buf_size = min(buf_size, local->hw.max_tx_aggregation_subframes); 980 981 981 982 txq = sta->sta.txq[tid];
+1 -1
net/mac80211/ht.c
··· 379 379 sta->ampdu_mlme.tid_rx_manage_offl)) 380 380 __ieee80211_start_rx_ba_session(sta, 0, 0, 0, 1, tid, 381 381 IEEE80211_MAX_AMPDU_BUF_HT, 382 - false, true, NULL); 382 + false, true, 0); 383 383 384 384 if (test_and_clear_bit(tid + IEEE80211_NUM_TIDS, 385 385 sta->ampdu_mlme.tid_rx_manage_offl))
+7 -2
net/mac80211/ieee80211_i.h
··· 2111 2111 const u8 *bssid, int link_id); 2112 2112 bool ieee80211_smps_is_restrictive(enum ieee80211_smps_mode smps_mode_old, 2113 2113 enum ieee80211_smps_mode smps_mode_new); 2114 - 2114 + void ieee80211_add_addbaext(struct sk_buff *skb, 2115 + const u8 req_addba_ext_data, 2116 + u16 buf_size); 2117 + u8 ieee80211_retrieve_addba_ext_data(struct sta_info *sta, 2118 + const void *elem_data, ssize_t elem_len, 2119 + u16 *buf_size); 2115 2120 void __ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, 2116 2121 u16 initiator, u16 reason, bool stop); 2117 2122 void __ieee80211_start_rx_ba_session(struct sta_info *sta, 2118 2123 u8 dialog_token, u16 timeout, 2119 2124 u16 start_seq_num, u16 ba_policy, u16 tid, 2120 2125 u16 buf_size, bool tx, bool auto_seq, 2121 - const struct ieee80211_addba_ext_ie *addbaext); 2126 + const u8 addba_ext_data); 2122 2127 void ieee80211_sta_tear_down_BA_sessions(struct sta_info *sta, 2123 2128 enum ieee80211_agg_stop_reason reason); 2124 2129 void ieee80211_process_delba(struct ieee80211_sub_if_data *sdata,