cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

agg-rx.c (17549B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * HT handling
      4 *
      5 * Copyright 2003, Jouni Malinen <jkmaline@cc.hut.fi>
      6 * Copyright 2002-2005, Instant802 Networks, Inc.
      7 * Copyright 2005-2006, Devicescape Software, Inc.
      8 * Copyright 2006-2007	Jiri Benc <jbenc@suse.cz>
      9 * Copyright 2007, Michael Wu <flamingice@sourmilk.net>
     10 * Copyright 2007-2010, Intel Corporation
     11 * Copyright(c) 2015-2017 Intel Deutschland GmbH
     12 * Copyright (C) 2018-2021 Intel Corporation
     13 */
     14
     15/**
     16 * DOC: RX A-MPDU aggregation
     17 *
     18 * Aggregation on the RX side requires only implementing the
     19 * @ampdu_action callback that is invoked to start/stop any
     20 * block-ack sessions for RX aggregation.
     21 *
     22 * When RX aggregation is started by the peer, the driver is
     23 * notified via @ampdu_action function, with the
     24 * %IEEE80211_AMPDU_RX_START action, and may reject the request
     25 * in which case a negative response is sent to the peer, if it
     26 * accepts it a positive response is sent.
     27 *
     28 * While the session is active, the device/driver are required
     29 * to de-aggregate frames and pass them up one by one to mac80211,
     30 * which will handle the reorder buffer.
     31 *
     32 * When the aggregation session is stopped again by the peer or
     33 * ourselves, the driver's @ampdu_action function will be called
     34 * with the action %IEEE80211_AMPDU_RX_STOP. In this case, the
     35 * call must not fail.
     36 */
     37
     38#include <linux/ieee80211.h>
     39#include <linux/slab.h>
     40#include <linux/export.h>
     41#include <net/mac80211.h>
     42#include "ieee80211_i.h"
     43#include "driver-ops.h"
     44
     45static void ieee80211_free_tid_rx(struct rcu_head *h)
     46{
     47	struct tid_ampdu_rx *tid_rx =
     48		container_of(h, struct tid_ampdu_rx, rcu_head);
     49	int i;
     50
     51	for (i = 0; i < tid_rx->buf_size; i++)
     52		__skb_queue_purge(&tid_rx->reorder_buf[i]);
     53	kfree(tid_rx->reorder_buf);
     54	kfree(tid_rx->reorder_time);
     55	kfree(tid_rx);
     56}
     57
     58void ___ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid,
     59				     u16 initiator, u16 reason, bool tx)
     60{
     61	struct ieee80211_local *local = sta->local;
     62	struct tid_ampdu_rx *tid_rx;
     63	struct ieee80211_ampdu_params params = {
     64		.sta = &sta->sta,
     65		.action = IEEE80211_AMPDU_RX_STOP,
     66		.tid = tid,
     67		.amsdu = false,
     68		.timeout = 0,
     69		.ssn = 0,
     70	};
     71
     72	lockdep_assert_held(&sta->ampdu_mlme.mtx);
     73
     74	tid_rx = rcu_dereference_protected(sta->ampdu_mlme.tid_rx[tid],
     75					lockdep_is_held(&sta->ampdu_mlme.mtx));
     76
     77	if (!test_bit(tid, sta->ampdu_mlme.agg_session_valid))
     78		return;
     79
     80	RCU_INIT_POINTER(sta->ampdu_mlme.tid_rx[tid], NULL);
     81	__clear_bit(tid, sta->ampdu_mlme.agg_session_valid);
     82
     83	ht_dbg(sta->sdata,
     84	       "Rx BA session stop requested for %pM tid %u %s reason: %d\n",
     85	       sta->sta.addr, tid,
     86	       initiator == WLAN_BACK_RECIPIENT ? "recipient" : "initiator",
     87	       (int)reason);
     88
     89	if (drv_ampdu_action(local, sta->sdata, &params))
     90		sdata_info(sta->sdata,
     91			   "HW problem - can not stop rx aggregation for %pM tid %d\n",
     92			   sta->sta.addr, tid);
     93
     94	/* check if this is a self generated aggregation halt */
     95	if (initiator == WLAN_BACK_RECIPIENT && tx)
     96		ieee80211_send_delba(sta->sdata, sta->sta.addr,
     97				     tid, WLAN_BACK_RECIPIENT, reason);
     98
     99	/*
    100	 * return here in case tid_rx is not assigned - which will happen if
    101	 * IEEE80211_HW_SUPPORTS_REORDERING_BUFFER is set.
    102	 */
    103	if (!tid_rx)
    104		return;
    105
    106	del_timer_sync(&tid_rx->session_timer);
    107
    108	/* make sure ieee80211_sta_reorder_release() doesn't re-arm the timer */
    109	spin_lock_bh(&tid_rx->reorder_lock);
    110	tid_rx->removed = true;
    111	spin_unlock_bh(&tid_rx->reorder_lock);
    112	del_timer_sync(&tid_rx->reorder_timer);
    113
    114	call_rcu(&tid_rx->rcu_head, ieee80211_free_tid_rx);
    115}
    116
    117void __ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid,
    118				    u16 initiator, u16 reason, bool tx)
    119{
    120	mutex_lock(&sta->ampdu_mlme.mtx);
    121	___ieee80211_stop_rx_ba_session(sta, tid, initiator, reason, tx);
    122	mutex_unlock(&sta->ampdu_mlme.mtx);
    123}
    124
    125void ieee80211_stop_rx_ba_session(struct ieee80211_vif *vif, u16 ba_rx_bitmap,
    126				  const u8 *addr)
    127{
    128	struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
    129	struct sta_info *sta;
    130	int i;
    131
    132	rcu_read_lock();
    133	sta = sta_info_get_bss(sdata, addr);
    134	if (!sta) {
    135		rcu_read_unlock();
    136		return;
    137	}
    138
    139	for (i = 0; i < IEEE80211_NUM_TIDS; i++)
    140		if (ba_rx_bitmap & BIT(i))
    141			set_bit(i, sta->ampdu_mlme.tid_rx_stop_requested);
    142
    143	ieee80211_queue_work(&sta->local->hw, &sta->ampdu_mlme.work);
    144	rcu_read_unlock();
    145}
    146EXPORT_SYMBOL(ieee80211_stop_rx_ba_session);
    147
    148/*
    149 * After accepting the AddBA Request we activated a timer,
    150 * resetting it after each frame that arrives from the originator.
    151 */
    152static void sta_rx_agg_session_timer_expired(struct timer_list *t)
    153{
    154	struct tid_ampdu_rx *tid_rx = from_timer(tid_rx, t, session_timer);
    155	struct sta_info *sta = tid_rx->sta;
    156	u8 tid = tid_rx->tid;
    157	unsigned long timeout;
    158
    159	timeout = tid_rx->last_rx + TU_TO_JIFFIES(tid_rx->timeout);
    160	if (time_is_after_jiffies(timeout)) {
    161		mod_timer(&tid_rx->session_timer, timeout);
    162		return;
    163	}
    164
    165	ht_dbg(sta->sdata, "RX session timer expired on %pM tid %d\n",
    166	       sta->sta.addr, tid);
    167
    168	set_bit(tid, sta->ampdu_mlme.tid_rx_timer_expired);
    169	ieee80211_queue_work(&sta->local->hw, &sta->ampdu_mlme.work);
    170}
    171
    172static void sta_rx_agg_reorder_timer_expired(struct timer_list *t)
    173{
    174	struct tid_ampdu_rx *tid_rx = from_timer(tid_rx, t, reorder_timer);
    175
    176	rcu_read_lock();
    177	ieee80211_release_reorder_timeout(tid_rx->sta, tid_rx->tid);
    178	rcu_read_unlock();
    179}
    180
    181static void ieee80211_add_addbaext(struct ieee80211_sub_if_data *sdata,
    182				   struct sk_buff *skb,
    183				   const struct ieee80211_addba_ext_ie *req,
    184				   u16 buf_size)
    185{
    186	struct ieee80211_supported_band *sband;
    187	struct ieee80211_addba_ext_ie *resp;
    188	const struct ieee80211_sta_he_cap *he_cap;
    189	u8 frag_level, cap_frag_level;
    190	u8 *pos;
    191
    192	sband = ieee80211_get_sband(sdata);
    193	if (!sband)
    194		return;
    195	he_cap = ieee80211_get_he_iftype_cap(sband,
    196					     ieee80211_vif_type_p2p(&sdata->vif));
    197	if (!he_cap)
    198		return;
    199
    200	pos = skb_put_zero(skb, 2 + sizeof(struct ieee80211_addba_ext_ie));
    201	*pos++ = WLAN_EID_ADDBA_EXT;
    202	*pos++ = sizeof(struct ieee80211_addba_ext_ie);
    203	resp = (struct ieee80211_addba_ext_ie *)pos;
    204	resp->data = req->data & IEEE80211_ADDBA_EXT_NO_FRAG;
    205
    206	frag_level = u32_get_bits(req->data,
    207				  IEEE80211_ADDBA_EXT_FRAG_LEVEL_MASK);
    208	cap_frag_level = u32_get_bits(he_cap->he_cap_elem.mac_cap_info[0],
    209				      IEEE80211_HE_MAC_CAP0_DYNAMIC_FRAG_MASK);
    210	if (frag_level > cap_frag_level)
    211		frag_level = cap_frag_level;
    212	resp->data |= u8_encode_bits(frag_level,
    213				     IEEE80211_ADDBA_EXT_FRAG_LEVEL_MASK);
    214	resp->data |= u8_encode_bits(buf_size >> IEEE80211_ADDBA_EXT_BUF_SIZE_SHIFT,
    215				     IEEE80211_ADDBA_EXT_BUF_SIZE_MASK);
    216}
    217
    218static void ieee80211_send_addba_resp(struct sta_info *sta, u8 *da, u16 tid,
    219				      u8 dialog_token, u16 status, u16 policy,
    220				      u16 buf_size, u16 timeout,
    221				      const struct ieee80211_addba_ext_ie *addbaext)
    222{
    223	struct ieee80211_sub_if_data *sdata = sta->sdata;
    224	struct ieee80211_local *local = sdata->local;
    225	struct sk_buff *skb;
    226	struct ieee80211_mgmt *mgmt;
    227	bool amsdu = ieee80211_hw_check(&local->hw, SUPPORTS_AMSDU_IN_AMPDU);
    228	u16 capab;
    229
    230	skb = dev_alloc_skb(sizeof(*mgmt) +
    231		    2 + sizeof(struct ieee80211_addba_ext_ie) +
    232		    local->hw.extra_tx_headroom);
    233	if (!skb)
    234		return;
    235
    236	skb_reserve(skb, local->hw.extra_tx_headroom);
    237	mgmt = skb_put_zero(skb, 24);
    238	memcpy(mgmt->da, da, ETH_ALEN);
    239	memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN);
    240	if (sdata->vif.type == NL80211_IFTYPE_AP ||
    241	    sdata->vif.type == NL80211_IFTYPE_AP_VLAN ||
    242	    sdata->vif.type == NL80211_IFTYPE_MESH_POINT)
    243		memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN);
    244	else if (sdata->vif.type == NL80211_IFTYPE_STATION)
    245		memcpy(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN);
    246	else if (sdata->vif.type == NL80211_IFTYPE_ADHOC)
    247		memcpy(mgmt->bssid, sdata->u.ibss.bssid, ETH_ALEN);
    248
    249	mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
    250					  IEEE80211_STYPE_ACTION);
    251
    252	skb_put(skb, 1 + sizeof(mgmt->u.action.u.addba_resp));
    253	mgmt->u.action.category = WLAN_CATEGORY_BACK;
    254	mgmt->u.action.u.addba_resp.action_code = WLAN_ACTION_ADDBA_RESP;
    255	mgmt->u.action.u.addba_resp.dialog_token = dialog_token;
    256
    257	capab = u16_encode_bits(amsdu, IEEE80211_ADDBA_PARAM_AMSDU_MASK);
    258	capab |= u16_encode_bits(policy, IEEE80211_ADDBA_PARAM_POLICY_MASK);
    259	capab |= u16_encode_bits(tid, IEEE80211_ADDBA_PARAM_TID_MASK);
    260	capab |= u16_encode_bits(buf_size, IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK);
    261
    262	mgmt->u.action.u.addba_resp.capab = cpu_to_le16(capab);
    263	mgmt->u.action.u.addba_resp.timeout = cpu_to_le16(timeout);
    264	mgmt->u.action.u.addba_resp.status = cpu_to_le16(status);
    265
    266	if (sta->sta.deflink.he_cap.has_he && addbaext)
    267		ieee80211_add_addbaext(sdata, skb, addbaext, buf_size);
    268
    269	ieee80211_tx_skb(sdata, skb);
    270}
    271
    272void ___ieee80211_start_rx_ba_session(struct sta_info *sta,
    273				      u8 dialog_token, u16 timeout,
    274				      u16 start_seq_num, u16 ba_policy, u16 tid,
    275				      u16 buf_size, bool tx, bool auto_seq,
    276				      const struct ieee80211_addba_ext_ie *addbaext)
    277{
    278	struct ieee80211_local *local = sta->sdata->local;
    279	struct tid_ampdu_rx *tid_agg_rx;
    280	struct ieee80211_ampdu_params params = {
    281		.sta = &sta->sta,
    282		.action = IEEE80211_AMPDU_RX_START,
    283		.tid = tid,
    284		.amsdu = false,
    285		.timeout = timeout,
    286		.ssn = start_seq_num,
    287	};
    288	int i, ret = -EOPNOTSUPP;
    289	u16 status = WLAN_STATUS_REQUEST_DECLINED;
    290	u16 max_buf_size;
    291
    292	if (tid >= IEEE80211_FIRST_TSPEC_TSID) {
    293		ht_dbg(sta->sdata,
    294		       "STA %pM requests BA session on unsupported tid %d\n",
    295		       sta->sta.addr, tid);
    296		goto end;
    297	}
    298
    299	if (!sta->sta.deflink.ht_cap.ht_supported &&
    300	    sta->sdata->vif.bss_conf.chandef.chan->band != NL80211_BAND_6GHZ) {
    301		ht_dbg(sta->sdata,
    302		       "STA %pM erroneously requests BA session on tid %d w/o QoS\n",
    303		       sta->sta.addr, tid);
    304		/* send a response anyway, it's an error case if we get here */
    305		goto end;
    306	}
    307
    308	if (test_sta_flag(sta, WLAN_STA_BLOCK_BA)) {
    309		ht_dbg(sta->sdata,
    310		       "Suspend in progress - Denying ADDBA request (%pM tid %d)\n",
    311		       sta->sta.addr, tid);
    312		goto end;
    313	}
    314
    315	if (sta->sta.deflink.eht_cap.has_eht)
    316		max_buf_size = IEEE80211_MAX_AMPDU_BUF_EHT;
    317	else if (sta->sta.deflink.he_cap.has_he)
    318		max_buf_size = IEEE80211_MAX_AMPDU_BUF_HE;
    319	else
    320		max_buf_size = IEEE80211_MAX_AMPDU_BUF_HT;
    321
    322	/* sanity check for incoming parameters:
    323	 * check if configuration can support the BA policy
    324	 * and if buffer size does not exceeds max value */
    325	/* XXX: check own ht delayed BA capability?? */
    326	if (((ba_policy != 1) &&
    327	     (!(sta->sta.deflink.ht_cap.cap & IEEE80211_HT_CAP_DELAY_BA))) ||
    328	    (buf_size > max_buf_size)) {
    329		status = WLAN_STATUS_INVALID_QOS_PARAM;
    330		ht_dbg_ratelimited(sta->sdata,
    331				   "AddBA Req with bad params from %pM on tid %u. policy %d, buffer size %d\n",
    332				   sta->sta.addr, tid, ba_policy, buf_size);
    333		goto end;
    334	}
    335	/* determine default buffer size */
    336	if (buf_size == 0)
    337		buf_size = max_buf_size;
    338
    339	/* make sure the size doesn't exceed the maximum supported by the hw */
    340	if (buf_size > sta->sta.max_rx_aggregation_subframes)
    341		buf_size = sta->sta.max_rx_aggregation_subframes;
    342	params.buf_size = buf_size;
    343
    344	ht_dbg(sta->sdata, "AddBA Req buf_size=%d for %pM\n",
    345	       buf_size, sta->sta.addr);
    346
    347	/* examine state machine */
    348	lockdep_assert_held(&sta->ampdu_mlme.mtx);
    349
    350	if (test_bit(tid, sta->ampdu_mlme.agg_session_valid)) {
    351		if (sta->ampdu_mlme.tid_rx_token[tid] == dialog_token) {
    352			struct tid_ampdu_rx *tid_rx;
    353
    354			ht_dbg_ratelimited(sta->sdata,
    355					   "updated AddBA Req from %pM on tid %u\n",
    356					   sta->sta.addr, tid);
    357			/* We have no API to update the timeout value in the
    358			 * driver so reject the timeout update if the timeout
    359			 * changed. If it did not change, i.e., no real update,
    360			 * just reply with success.
    361			 */
    362			rcu_read_lock();
    363			tid_rx = rcu_dereference(sta->ampdu_mlme.tid_rx[tid]);
    364			if (tid_rx && tid_rx->timeout == timeout)
    365				status = WLAN_STATUS_SUCCESS;
    366			else
    367				status = WLAN_STATUS_REQUEST_DECLINED;
    368			rcu_read_unlock();
    369			goto end;
    370		}
    371
    372		ht_dbg_ratelimited(sta->sdata,
    373				   "unexpected AddBA Req from %pM on tid %u\n",
    374				   sta->sta.addr, tid);
    375
    376		/* delete existing Rx BA session on the same tid */
    377		___ieee80211_stop_rx_ba_session(sta, tid, WLAN_BACK_RECIPIENT,
    378						WLAN_STATUS_UNSPECIFIED_QOS,
    379						false);
    380	}
    381
    382	if (ieee80211_hw_check(&local->hw, SUPPORTS_REORDERING_BUFFER)) {
    383		ret = drv_ampdu_action(local, sta->sdata, &params);
    384		ht_dbg(sta->sdata,
    385		       "Rx A-MPDU request on %pM tid %d result %d\n",
    386		       sta->sta.addr, tid, ret);
    387		if (!ret)
    388			status = WLAN_STATUS_SUCCESS;
    389		goto end;
    390	}
    391
    392	/* prepare A-MPDU MLME for Rx aggregation */
    393	tid_agg_rx = kzalloc(sizeof(*tid_agg_rx), GFP_KERNEL);
    394	if (!tid_agg_rx)
    395		goto end;
    396
    397	spin_lock_init(&tid_agg_rx->reorder_lock);
    398
    399	/* rx timer */
    400	timer_setup(&tid_agg_rx->session_timer,
    401		    sta_rx_agg_session_timer_expired, TIMER_DEFERRABLE);
    402
    403	/* rx reorder timer */
    404	timer_setup(&tid_agg_rx->reorder_timer,
    405		    sta_rx_agg_reorder_timer_expired, 0);
    406
    407	/* prepare reordering buffer */
    408	tid_agg_rx->reorder_buf =
    409		kcalloc(buf_size, sizeof(struct sk_buff_head), GFP_KERNEL);
    410	tid_agg_rx->reorder_time =
    411		kcalloc(buf_size, sizeof(unsigned long), GFP_KERNEL);
    412	if (!tid_agg_rx->reorder_buf || !tid_agg_rx->reorder_time) {
    413		kfree(tid_agg_rx->reorder_buf);
    414		kfree(tid_agg_rx->reorder_time);
    415		kfree(tid_agg_rx);
    416		goto end;
    417	}
    418
    419	for (i = 0; i < buf_size; i++)
    420		__skb_queue_head_init(&tid_agg_rx->reorder_buf[i]);
    421
    422	ret = drv_ampdu_action(local, sta->sdata, &params);
    423	ht_dbg(sta->sdata, "Rx A-MPDU request on %pM tid %d result %d\n",
    424	       sta->sta.addr, tid, ret);
    425	if (ret) {
    426		kfree(tid_agg_rx->reorder_buf);
    427		kfree(tid_agg_rx->reorder_time);
    428		kfree(tid_agg_rx);
    429		goto end;
    430	}
    431
    432	/* update data */
    433	tid_agg_rx->ssn = start_seq_num;
    434	tid_agg_rx->head_seq_num = start_seq_num;
    435	tid_agg_rx->buf_size = buf_size;
    436	tid_agg_rx->timeout = timeout;
    437	tid_agg_rx->stored_mpdu_num = 0;
    438	tid_agg_rx->auto_seq = auto_seq;
    439	tid_agg_rx->started = false;
    440	tid_agg_rx->reorder_buf_filtered = 0;
    441	tid_agg_rx->tid = tid;
    442	tid_agg_rx->sta = sta;
    443	status = WLAN_STATUS_SUCCESS;
    444
    445	/* activate it for RX */
    446	rcu_assign_pointer(sta->ampdu_mlme.tid_rx[tid], tid_agg_rx);
    447
    448	if (timeout) {
    449		mod_timer(&tid_agg_rx->session_timer, TU_TO_EXP_TIME(timeout));
    450		tid_agg_rx->last_rx = jiffies;
    451	}
    452
    453end:
    454	if (status == WLAN_STATUS_SUCCESS) {
    455		__set_bit(tid, sta->ampdu_mlme.agg_session_valid);
    456		__clear_bit(tid, sta->ampdu_mlme.unexpected_agg);
    457		sta->ampdu_mlme.tid_rx_token[tid] = dialog_token;
    458	}
    459
    460	if (tx)
    461		ieee80211_send_addba_resp(sta, sta->sta.addr, tid,
    462					  dialog_token, status, 1, buf_size,
    463					  timeout, addbaext);
    464}
    465
    466static void __ieee80211_start_rx_ba_session(struct sta_info *sta,
    467					    u8 dialog_token, u16 timeout,
    468					    u16 start_seq_num, u16 ba_policy,
    469					    u16 tid, u16 buf_size, bool tx,
    470					    bool auto_seq,
    471					    const struct ieee80211_addba_ext_ie *addbaext)
    472{
    473	mutex_lock(&sta->ampdu_mlme.mtx);
    474	___ieee80211_start_rx_ba_session(sta, dialog_token, timeout,
    475					 start_seq_num, ba_policy, tid,
    476					 buf_size, tx, auto_seq, addbaext);
    477	mutex_unlock(&sta->ampdu_mlme.mtx);
    478}
    479
    480void ieee80211_process_addba_request(struct ieee80211_local *local,
    481				     struct sta_info *sta,
    482				     struct ieee80211_mgmt *mgmt,
    483				     size_t len)
    484{
    485	u16 capab, tid, timeout, ba_policy, buf_size, start_seq_num;
    486	struct ieee802_11_elems *elems = NULL;
    487	u8 dialog_token;
    488	int ies_len;
    489
    490	/* extract session parameters from addba request frame */
    491	dialog_token = mgmt->u.action.u.addba_req.dialog_token;
    492	timeout = le16_to_cpu(mgmt->u.action.u.addba_req.timeout);
    493	start_seq_num =
    494		le16_to_cpu(mgmt->u.action.u.addba_req.start_seq_num) >> 4;
    495
    496	capab = le16_to_cpu(mgmt->u.action.u.addba_req.capab);
    497	ba_policy = (capab & IEEE80211_ADDBA_PARAM_POLICY_MASK) >> 1;
    498	tid = (capab & IEEE80211_ADDBA_PARAM_TID_MASK) >> 2;
    499	buf_size = (capab & IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK) >> 6;
    500
    501	ies_len = len - offsetof(struct ieee80211_mgmt,
    502				 u.action.u.addba_req.variable);
    503	if (ies_len) {
    504		elems = ieee802_11_parse_elems(mgmt->u.action.u.addba_req.variable,
    505					       ies_len, true, mgmt->bssid, NULL);
    506		if (!elems || elems->parse_error)
    507			goto free;
    508	}
    509
    510	if (sta->sta.deflink.eht_cap.has_eht && elems && elems->addba_ext_ie) {
    511		u8 buf_size_1k = u8_get_bits(elems->addba_ext_ie->data,
    512					     IEEE80211_ADDBA_EXT_BUF_SIZE_MASK);
    513
    514		buf_size |= buf_size_1k << IEEE80211_ADDBA_EXT_BUF_SIZE_SHIFT;
    515	}
    516
    517	__ieee80211_start_rx_ba_session(sta, dialog_token, timeout,
    518					start_seq_num, ba_policy, tid,
    519					buf_size, true, false,
    520					elems ? elems->addba_ext_ie : NULL);
    521free:
    522	kfree(elems);
    523}
    524
    525void ieee80211_manage_rx_ba_offl(struct ieee80211_vif *vif,
    526				 const u8 *addr, unsigned int tid)
    527{
    528	struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
    529	struct ieee80211_local *local = sdata->local;
    530	struct sta_info *sta;
    531
    532	rcu_read_lock();
    533	sta = sta_info_get_bss(sdata, addr);
    534	if (!sta)
    535		goto unlock;
    536
    537	set_bit(tid, sta->ampdu_mlme.tid_rx_manage_offl);
    538	ieee80211_queue_work(&local->hw, &sta->ampdu_mlme.work);
    539 unlock:
    540	rcu_read_unlock();
    541}
    542EXPORT_SYMBOL(ieee80211_manage_rx_ba_offl);
    543
    544void ieee80211_rx_ba_timer_expired(struct ieee80211_vif *vif,
    545				   const u8 *addr, unsigned int tid)
    546{
    547	struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
    548	struct ieee80211_local *local = sdata->local;
    549	struct sta_info *sta;
    550
    551	rcu_read_lock();
    552	sta = sta_info_get_bss(sdata, addr);
    553	if (!sta)
    554		goto unlock;
    555
    556	set_bit(tid, sta->ampdu_mlme.tid_rx_timer_expired);
    557	ieee80211_queue_work(&local->hw, &sta->ampdu_mlme.work);
    558
    559 unlock:
    560	rcu_read_unlock();
    561}
    562EXPORT_SYMBOL(ieee80211_rx_ba_timer_expired);