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>
This commit is contained in:
MeiChia Chiu 2024-11-12 16:38:46 +08:00 committed by Johannes Berg
parent 8251e7621b
commit 406c5548c6
5 changed files with 90 additions and 48 deletions

View File

@ -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;

View File

@ -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,

View File

@ -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];

View File

@ -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))

View File

@ -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,