Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * HT handling
0004  *
0005  * Copyright 2003, Jouni Malinen <jkmaline@cc.hut.fi>
0006  * Copyright 2002-2005, Instant802 Networks, Inc.
0007  * Copyright 2005-2006, Devicescape Software, Inc.
0008  * Copyright 2006-2007  Jiri Benc <jbenc@suse.cz>
0009  * Copyright 2007, Michael Wu <flamingice@sourmilk.net>
0010  * Copyright 2007-2010, Intel Corporation
0011  * Copyright(c) 2015-2017 Intel Deutschland GmbH
0012  * Copyright (C) 2018-2022 Intel Corporation
0013  */
0014 
0015 /**
0016  * DOC: RX A-MPDU aggregation
0017  *
0018  * Aggregation on the RX side requires only implementing the
0019  * @ampdu_action callback that is invoked to start/stop any
0020  * block-ack sessions for RX aggregation.
0021  *
0022  * When RX aggregation is started by the peer, the driver is
0023  * notified via @ampdu_action function, with the
0024  * %IEEE80211_AMPDU_RX_START action, and may reject the request
0025  * in which case a negative response is sent to the peer, if it
0026  * accepts it a positive response is sent.
0027  *
0028  * While the session is active, the device/driver are required
0029  * to de-aggregate frames and pass them up one by one to mac80211,
0030  * which will handle the reorder buffer.
0031  *
0032  * When the aggregation session is stopped again by the peer or
0033  * ourselves, the driver's @ampdu_action function will be called
0034  * with the action %IEEE80211_AMPDU_RX_STOP. In this case, the
0035  * call must not fail.
0036  */
0037 
0038 #include <linux/ieee80211.h>
0039 #include <linux/slab.h>
0040 #include <linux/export.h>
0041 #include <net/mac80211.h>
0042 #include "ieee80211_i.h"
0043 #include "driver-ops.h"
0044 
0045 static void ieee80211_free_tid_rx(struct rcu_head *h)
0046 {
0047     struct tid_ampdu_rx *tid_rx =
0048         container_of(h, struct tid_ampdu_rx, rcu_head);
0049     int i;
0050 
0051     for (i = 0; i < tid_rx->buf_size; i++)
0052         __skb_queue_purge(&tid_rx->reorder_buf[i]);
0053     kfree(tid_rx->reorder_buf);
0054     kfree(tid_rx->reorder_time);
0055     kfree(tid_rx);
0056 }
0057 
0058 void ___ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid,
0059                      u16 initiator, u16 reason, bool tx)
0060 {
0061     struct ieee80211_local *local = sta->local;
0062     struct tid_ampdu_rx *tid_rx;
0063     struct ieee80211_ampdu_params params = {
0064         .sta = &sta->sta,
0065         .action = IEEE80211_AMPDU_RX_STOP,
0066         .tid = tid,
0067         .amsdu = false,
0068         .timeout = 0,
0069         .ssn = 0,
0070     };
0071 
0072     lockdep_assert_held(&sta->ampdu_mlme.mtx);
0073 
0074     tid_rx = rcu_dereference_protected(sta->ampdu_mlme.tid_rx[tid],
0075                     lockdep_is_held(&sta->ampdu_mlme.mtx));
0076 
0077     if (!test_bit(tid, sta->ampdu_mlme.agg_session_valid))
0078         return;
0079 
0080     RCU_INIT_POINTER(sta->ampdu_mlme.tid_rx[tid], NULL);
0081     __clear_bit(tid, sta->ampdu_mlme.agg_session_valid);
0082 
0083     ht_dbg(sta->sdata,
0084            "Rx BA session stop requested for %pM tid %u %s reason: %d\n",
0085            sta->sta.addr, tid,
0086            initiator == WLAN_BACK_RECIPIENT ? "recipient" : "initiator",
0087            (int)reason);
0088 
0089     if (drv_ampdu_action(local, sta->sdata, &params))
0090         sdata_info(sta->sdata,
0091                "HW problem - can not stop rx aggregation for %pM tid %d\n",
0092                sta->sta.addr, tid);
0093 
0094     /* check if this is a self generated aggregation halt */
0095     if (initiator == WLAN_BACK_RECIPIENT && tx)
0096         ieee80211_send_delba(sta->sdata, sta->sta.addr,
0097                      tid, WLAN_BACK_RECIPIENT, reason);
0098 
0099     /*
0100      * return here in case tid_rx is not assigned - which will happen if
0101      * IEEE80211_HW_SUPPORTS_REORDERING_BUFFER is set.
0102      */
0103     if (!tid_rx)
0104         return;
0105 
0106     del_timer_sync(&tid_rx->session_timer);
0107 
0108     /* make sure ieee80211_sta_reorder_release() doesn't re-arm the timer */
0109     spin_lock_bh(&tid_rx->reorder_lock);
0110     tid_rx->removed = true;
0111     spin_unlock_bh(&tid_rx->reorder_lock);
0112     del_timer_sync(&tid_rx->reorder_timer);
0113 
0114     call_rcu(&tid_rx->rcu_head, ieee80211_free_tid_rx);
0115 }
0116 
0117 void __ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid,
0118                     u16 initiator, u16 reason, bool tx)
0119 {
0120     mutex_lock(&sta->ampdu_mlme.mtx);
0121     ___ieee80211_stop_rx_ba_session(sta, tid, initiator, reason, tx);
0122     mutex_unlock(&sta->ampdu_mlme.mtx);
0123 }
0124 
0125 void ieee80211_stop_rx_ba_session(struct ieee80211_vif *vif, u16 ba_rx_bitmap,
0126                   const u8 *addr)
0127 {
0128     struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
0129     struct sta_info *sta;
0130     int i;
0131 
0132     rcu_read_lock();
0133     sta = sta_info_get_bss(sdata, addr);
0134     if (!sta) {
0135         rcu_read_unlock();
0136         return;
0137     }
0138 
0139     for (i = 0; i < IEEE80211_NUM_TIDS; i++)
0140         if (ba_rx_bitmap & BIT(i))
0141             set_bit(i, sta->ampdu_mlme.tid_rx_stop_requested);
0142 
0143     ieee80211_queue_work(&sta->local->hw, &sta->ampdu_mlme.work);
0144     rcu_read_unlock();
0145 }
0146 EXPORT_SYMBOL(ieee80211_stop_rx_ba_session);
0147 
0148 /*
0149  * After accepting the AddBA Request we activated a timer,
0150  * resetting it after each frame that arrives from the originator.
0151  */
0152 static void sta_rx_agg_session_timer_expired(struct timer_list *t)
0153 {
0154     struct tid_ampdu_rx *tid_rx = from_timer(tid_rx, t, session_timer);
0155     struct sta_info *sta = tid_rx->sta;
0156     u8 tid = tid_rx->tid;
0157     unsigned long timeout;
0158 
0159     timeout = tid_rx->last_rx + TU_TO_JIFFIES(tid_rx->timeout);
0160     if (time_is_after_jiffies(timeout)) {
0161         mod_timer(&tid_rx->session_timer, timeout);
0162         return;
0163     }
0164 
0165     ht_dbg(sta->sdata, "RX session timer expired on %pM tid %d\n",
0166            sta->sta.addr, tid);
0167 
0168     set_bit(tid, sta->ampdu_mlme.tid_rx_timer_expired);
0169     ieee80211_queue_work(&sta->local->hw, &sta->ampdu_mlme.work);
0170 }
0171 
0172 static void sta_rx_agg_reorder_timer_expired(struct timer_list *t)
0173 {
0174     struct tid_ampdu_rx *tid_rx = from_timer(tid_rx, t, reorder_timer);
0175 
0176     rcu_read_lock();
0177     ieee80211_release_reorder_timeout(tid_rx->sta, tid_rx->tid);
0178     rcu_read_unlock();
0179 }
0180 
0181 static void ieee80211_add_addbaext(struct ieee80211_sub_if_data *sdata,
0182                    struct sk_buff *skb,
0183                    const struct ieee80211_addba_ext_ie *req,
0184                    u16 buf_size)
0185 {
0186     struct ieee80211_supported_band *sband;
0187     struct ieee80211_addba_ext_ie *resp;
0188     const struct ieee80211_sta_he_cap *he_cap;
0189     u8 frag_level, cap_frag_level;
0190     u8 *pos;
0191 
0192     sband = ieee80211_get_sband(sdata);
0193     if (!sband)
0194         return;
0195     he_cap = ieee80211_get_he_iftype_cap(sband,
0196                          ieee80211_vif_type_p2p(&sdata->vif));
0197     if (!he_cap)
0198         return;
0199 
0200     pos = skb_put_zero(skb, 2 + sizeof(struct ieee80211_addba_ext_ie));
0201     *pos++ = WLAN_EID_ADDBA_EXT;
0202     *pos++ = sizeof(struct ieee80211_addba_ext_ie);
0203     resp = (struct ieee80211_addba_ext_ie *)pos;
0204     resp->data = req->data & IEEE80211_ADDBA_EXT_NO_FRAG;
0205 
0206     frag_level = u32_get_bits(req->data,
0207                   IEEE80211_ADDBA_EXT_FRAG_LEVEL_MASK);
0208     cap_frag_level = u32_get_bits(he_cap->he_cap_elem.mac_cap_info[0],
0209                       IEEE80211_HE_MAC_CAP0_DYNAMIC_FRAG_MASK);
0210     if (frag_level > cap_frag_level)
0211         frag_level = cap_frag_level;
0212     resp->data |= u8_encode_bits(frag_level,
0213                      IEEE80211_ADDBA_EXT_FRAG_LEVEL_MASK);
0214     resp->data |= u8_encode_bits(buf_size >> IEEE80211_ADDBA_EXT_BUF_SIZE_SHIFT,
0215                      IEEE80211_ADDBA_EXT_BUF_SIZE_MASK);
0216 }
0217 
0218 static void ieee80211_send_addba_resp(struct sta_info *sta, u8 *da, u16 tid,
0219                       u8 dialog_token, u16 status, u16 policy,
0220                       u16 buf_size, u16 timeout,
0221                       const struct ieee80211_addba_ext_ie *addbaext)
0222 {
0223     struct ieee80211_sub_if_data *sdata = sta->sdata;
0224     struct ieee80211_local *local = sdata->local;
0225     struct sk_buff *skb;
0226     struct ieee80211_mgmt *mgmt;
0227     bool amsdu = ieee80211_hw_check(&local->hw, SUPPORTS_AMSDU_IN_AMPDU);
0228     u16 capab;
0229 
0230     skb = dev_alloc_skb(sizeof(*mgmt) +
0231             2 + sizeof(struct ieee80211_addba_ext_ie) +
0232             local->hw.extra_tx_headroom);
0233     if (!skb)
0234         return;
0235 
0236     skb_reserve(skb, local->hw.extra_tx_headroom);
0237     mgmt = skb_put_zero(skb, 24);
0238     memcpy(mgmt->da, da, ETH_ALEN);
0239     memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN);
0240     if (sdata->vif.type == NL80211_IFTYPE_AP ||
0241         sdata->vif.type == NL80211_IFTYPE_AP_VLAN ||
0242         sdata->vif.type == NL80211_IFTYPE_MESH_POINT)
0243         memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN);
0244     else if (sdata->vif.type == NL80211_IFTYPE_STATION)
0245         memcpy(mgmt->bssid, sdata->deflink.u.mgd.bssid, ETH_ALEN);
0246     else if (sdata->vif.type == NL80211_IFTYPE_ADHOC)
0247         memcpy(mgmt->bssid, sdata->u.ibss.bssid, ETH_ALEN);
0248 
0249     mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
0250                       IEEE80211_STYPE_ACTION);
0251 
0252     skb_put(skb, 1 + sizeof(mgmt->u.action.u.addba_resp));
0253     mgmt->u.action.category = WLAN_CATEGORY_BACK;
0254     mgmt->u.action.u.addba_resp.action_code = WLAN_ACTION_ADDBA_RESP;
0255     mgmt->u.action.u.addba_resp.dialog_token = dialog_token;
0256 
0257     capab = u16_encode_bits(amsdu, IEEE80211_ADDBA_PARAM_AMSDU_MASK);
0258     capab |= u16_encode_bits(policy, IEEE80211_ADDBA_PARAM_POLICY_MASK);
0259     capab |= u16_encode_bits(tid, IEEE80211_ADDBA_PARAM_TID_MASK);
0260     capab |= u16_encode_bits(buf_size, IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK);
0261 
0262     mgmt->u.action.u.addba_resp.capab = cpu_to_le16(capab);
0263     mgmt->u.action.u.addba_resp.timeout = cpu_to_le16(timeout);
0264     mgmt->u.action.u.addba_resp.status = cpu_to_le16(status);
0265 
0266     if (sta->sta.deflink.he_cap.has_he && addbaext)
0267         ieee80211_add_addbaext(sdata, skb, addbaext, buf_size);
0268 
0269     ieee80211_tx_skb(sdata, skb);
0270 }
0271 
0272 void ___ieee80211_start_rx_ba_session(struct sta_info *sta,
0273                       u8 dialog_token, u16 timeout,
0274                       u16 start_seq_num, u16 ba_policy, u16 tid,
0275                       u16 buf_size, bool tx, bool auto_seq,
0276                       const struct ieee80211_addba_ext_ie *addbaext)
0277 {
0278     struct ieee80211_local *local = sta->sdata->local;
0279     struct tid_ampdu_rx *tid_agg_rx;
0280     struct ieee80211_ampdu_params params = {
0281         .sta = &sta->sta,
0282         .action = IEEE80211_AMPDU_RX_START,
0283         .tid = tid,
0284         .amsdu = false,
0285         .timeout = timeout,
0286         .ssn = start_seq_num,
0287     };
0288     int i, ret = -EOPNOTSUPP;
0289     u16 status = WLAN_STATUS_REQUEST_DECLINED;
0290     u16 max_buf_size;
0291 
0292     if (tid >= IEEE80211_FIRST_TSPEC_TSID) {
0293         ht_dbg(sta->sdata,
0294                "STA %pM requests BA session on unsupported tid %d\n",
0295                sta->sta.addr, tid);
0296         goto end;
0297     }
0298 
0299     if (!sta->sta.deflink.ht_cap.ht_supported &&
0300         sta->sdata->vif.bss_conf.chandef.chan->band != NL80211_BAND_6GHZ) {
0301         ht_dbg(sta->sdata,
0302                "STA %pM erroneously requests BA session on tid %d w/o QoS\n",
0303                sta->sta.addr, tid);
0304         /* send a response anyway, it's an error case if we get here */
0305         goto end;
0306     }
0307 
0308     if (test_sta_flag(sta, WLAN_STA_BLOCK_BA)) {
0309         ht_dbg(sta->sdata,
0310                "Suspend in progress - Denying ADDBA request (%pM tid %d)\n",
0311                sta->sta.addr, tid);
0312         goto end;
0313     }
0314 
0315     if (sta->sta.deflink.eht_cap.has_eht)
0316         max_buf_size = IEEE80211_MAX_AMPDU_BUF_EHT;
0317     else if (sta->sta.deflink.he_cap.has_he)
0318         max_buf_size = IEEE80211_MAX_AMPDU_BUF_HE;
0319     else
0320         max_buf_size = IEEE80211_MAX_AMPDU_BUF_HT;
0321 
0322     /* sanity check for incoming parameters:
0323      * check if configuration can support the BA policy
0324      * and if buffer size does not exceeds max value */
0325     /* XXX: check own ht delayed BA capability?? */
0326     if (((ba_policy != 1) &&
0327          (!(sta->sta.deflink.ht_cap.cap & IEEE80211_HT_CAP_DELAY_BA))) ||
0328         (buf_size > max_buf_size)) {
0329         status = WLAN_STATUS_INVALID_QOS_PARAM;
0330         ht_dbg_ratelimited(sta->sdata,
0331                    "AddBA Req with bad params from %pM on tid %u. policy %d, buffer size %d\n",
0332                    sta->sta.addr, tid, ba_policy, buf_size);
0333         goto end;
0334     }
0335     /* determine default buffer size */
0336     if (buf_size == 0)
0337         buf_size = max_buf_size;
0338 
0339     /* make sure the size doesn't exceed the maximum supported by the hw */
0340     if (buf_size > sta->sta.max_rx_aggregation_subframes)
0341         buf_size = sta->sta.max_rx_aggregation_subframes;
0342     params.buf_size = buf_size;
0343 
0344     ht_dbg(sta->sdata, "AddBA Req buf_size=%d for %pM\n",
0345            buf_size, sta->sta.addr);
0346 
0347     /* examine state machine */
0348     lockdep_assert_held(&sta->ampdu_mlme.mtx);
0349 
0350     if (test_bit(tid, sta->ampdu_mlme.agg_session_valid)) {
0351         if (sta->ampdu_mlme.tid_rx_token[tid] == dialog_token) {
0352             struct tid_ampdu_rx *tid_rx;
0353 
0354             ht_dbg_ratelimited(sta->sdata,
0355                        "updated AddBA Req from %pM on tid %u\n",
0356                        sta->sta.addr, tid);
0357             /* We have no API to update the timeout value in the
0358              * driver so reject the timeout update if the timeout
0359              * changed. If it did not change, i.e., no real update,
0360              * just reply with success.
0361              */
0362             rcu_read_lock();
0363             tid_rx = rcu_dereference(sta->ampdu_mlme.tid_rx[tid]);
0364             if (tid_rx && tid_rx->timeout == timeout)
0365                 status = WLAN_STATUS_SUCCESS;
0366             else
0367                 status = WLAN_STATUS_REQUEST_DECLINED;
0368             rcu_read_unlock();
0369             goto end;
0370         }
0371 
0372         ht_dbg_ratelimited(sta->sdata,
0373                    "unexpected AddBA Req from %pM on tid %u\n",
0374                    sta->sta.addr, tid);
0375 
0376         /* delete existing Rx BA session on the same tid */
0377         ___ieee80211_stop_rx_ba_session(sta, tid, WLAN_BACK_RECIPIENT,
0378                         WLAN_STATUS_UNSPECIFIED_QOS,
0379                         false);
0380     }
0381 
0382     if (ieee80211_hw_check(&local->hw, SUPPORTS_REORDERING_BUFFER)) {
0383         ret = drv_ampdu_action(local, sta->sdata, &params);
0384         ht_dbg(sta->sdata,
0385                "Rx A-MPDU request on %pM tid %d result %d\n",
0386                sta->sta.addr, tid, ret);
0387         if (!ret)
0388             status = WLAN_STATUS_SUCCESS;
0389         goto end;
0390     }
0391 
0392     /* prepare A-MPDU MLME for Rx aggregation */
0393     tid_agg_rx = kzalloc(sizeof(*tid_agg_rx), GFP_KERNEL);
0394     if (!tid_agg_rx)
0395         goto end;
0396 
0397     spin_lock_init(&tid_agg_rx->reorder_lock);
0398 
0399     /* rx timer */
0400     timer_setup(&tid_agg_rx->session_timer,
0401             sta_rx_agg_session_timer_expired, TIMER_DEFERRABLE);
0402 
0403     /* rx reorder timer */
0404     timer_setup(&tid_agg_rx->reorder_timer,
0405             sta_rx_agg_reorder_timer_expired, 0);
0406 
0407     /* prepare reordering buffer */
0408     tid_agg_rx->reorder_buf =
0409         kcalloc(buf_size, sizeof(struct sk_buff_head), GFP_KERNEL);
0410     tid_agg_rx->reorder_time =
0411         kcalloc(buf_size, sizeof(unsigned long), GFP_KERNEL);
0412     if (!tid_agg_rx->reorder_buf || !tid_agg_rx->reorder_time) {
0413         kfree(tid_agg_rx->reorder_buf);
0414         kfree(tid_agg_rx->reorder_time);
0415         kfree(tid_agg_rx);
0416         goto end;
0417     }
0418 
0419     for (i = 0; i < buf_size; i++)
0420         __skb_queue_head_init(&tid_agg_rx->reorder_buf[i]);
0421 
0422     ret = drv_ampdu_action(local, sta->sdata, &params);
0423     ht_dbg(sta->sdata, "Rx A-MPDU request on %pM tid %d result %d\n",
0424            sta->sta.addr, tid, ret);
0425     if (ret) {
0426         kfree(tid_agg_rx->reorder_buf);
0427         kfree(tid_agg_rx->reorder_time);
0428         kfree(tid_agg_rx);
0429         goto end;
0430     }
0431 
0432     /* update data */
0433     tid_agg_rx->ssn = start_seq_num;
0434     tid_agg_rx->head_seq_num = start_seq_num;
0435     tid_agg_rx->buf_size = buf_size;
0436     tid_agg_rx->timeout = timeout;
0437     tid_agg_rx->stored_mpdu_num = 0;
0438     tid_agg_rx->auto_seq = auto_seq;
0439     tid_agg_rx->started = false;
0440     tid_agg_rx->reorder_buf_filtered = 0;
0441     tid_agg_rx->tid = tid;
0442     tid_agg_rx->sta = sta;
0443     status = WLAN_STATUS_SUCCESS;
0444 
0445     /* activate it for RX */
0446     rcu_assign_pointer(sta->ampdu_mlme.tid_rx[tid], tid_agg_rx);
0447 
0448     if (timeout) {
0449         mod_timer(&tid_agg_rx->session_timer, TU_TO_EXP_TIME(timeout));
0450         tid_agg_rx->last_rx = jiffies;
0451     }
0452 
0453 end:
0454     if (status == WLAN_STATUS_SUCCESS) {
0455         __set_bit(tid, sta->ampdu_mlme.agg_session_valid);
0456         __clear_bit(tid, sta->ampdu_mlme.unexpected_agg);
0457         sta->ampdu_mlme.tid_rx_token[tid] = dialog_token;
0458     }
0459 
0460     if (tx)
0461         ieee80211_send_addba_resp(sta, sta->sta.addr, tid,
0462                       dialog_token, status, 1, buf_size,
0463                       timeout, addbaext);
0464 }
0465 
0466 static void __ieee80211_start_rx_ba_session(struct sta_info *sta,
0467                         u8 dialog_token, u16 timeout,
0468                         u16 start_seq_num, u16 ba_policy,
0469                         u16 tid, u16 buf_size, bool tx,
0470                         bool auto_seq,
0471                         const struct ieee80211_addba_ext_ie *addbaext)
0472 {
0473     mutex_lock(&sta->ampdu_mlme.mtx);
0474     ___ieee80211_start_rx_ba_session(sta, dialog_token, timeout,
0475                      start_seq_num, ba_policy, tid,
0476                      buf_size, tx, auto_seq, addbaext);
0477     mutex_unlock(&sta->ampdu_mlme.mtx);
0478 }
0479 
0480 void ieee80211_process_addba_request(struct ieee80211_local *local,
0481                      struct sta_info *sta,
0482                      struct ieee80211_mgmt *mgmt,
0483                      size_t len)
0484 {
0485     u16 capab, tid, timeout, ba_policy, buf_size, start_seq_num;
0486     struct ieee802_11_elems *elems = NULL;
0487     u8 dialog_token;
0488     int ies_len;
0489 
0490     /* extract session parameters from addba request frame */
0491     dialog_token = mgmt->u.action.u.addba_req.dialog_token;
0492     timeout = le16_to_cpu(mgmt->u.action.u.addba_req.timeout);
0493     start_seq_num =
0494         le16_to_cpu(mgmt->u.action.u.addba_req.start_seq_num) >> 4;
0495 
0496     capab = le16_to_cpu(mgmt->u.action.u.addba_req.capab);
0497     ba_policy = (capab & IEEE80211_ADDBA_PARAM_POLICY_MASK) >> 1;
0498     tid = (capab & IEEE80211_ADDBA_PARAM_TID_MASK) >> 2;
0499     buf_size = (capab & IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK) >> 6;
0500 
0501     ies_len = len - offsetof(struct ieee80211_mgmt,
0502                  u.action.u.addba_req.variable);
0503     if (ies_len) {
0504         elems = ieee802_11_parse_elems(mgmt->u.action.u.addba_req.variable,
0505                            ies_len, true, NULL);
0506         if (!elems || elems->parse_error)
0507             goto free;
0508     }
0509 
0510     if (sta->sta.deflink.eht_cap.has_eht && elems && elems->addba_ext_ie) {
0511         u8 buf_size_1k = u8_get_bits(elems->addba_ext_ie->data,
0512                          IEEE80211_ADDBA_EXT_BUF_SIZE_MASK);
0513 
0514         buf_size |= buf_size_1k << IEEE80211_ADDBA_EXT_BUF_SIZE_SHIFT;
0515     }
0516 
0517     __ieee80211_start_rx_ba_session(sta, dialog_token, timeout,
0518                     start_seq_num, ba_policy, tid,
0519                     buf_size, true, false,
0520                     elems ? elems->addba_ext_ie : NULL);
0521 free:
0522     kfree(elems);
0523 }
0524 
0525 void ieee80211_manage_rx_ba_offl(struct ieee80211_vif *vif,
0526                  const u8 *addr, unsigned int tid)
0527 {
0528     struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
0529     struct ieee80211_local *local = sdata->local;
0530     struct sta_info *sta;
0531 
0532     rcu_read_lock();
0533     sta = sta_info_get_bss(sdata, addr);
0534     if (!sta)
0535         goto unlock;
0536 
0537     set_bit(tid, sta->ampdu_mlme.tid_rx_manage_offl);
0538     ieee80211_queue_work(&local->hw, &sta->ampdu_mlme.work);
0539  unlock:
0540     rcu_read_unlock();
0541 }
0542 EXPORT_SYMBOL(ieee80211_manage_rx_ba_offl);
0543 
0544 void ieee80211_rx_ba_timer_expired(struct ieee80211_vif *vif,
0545                    const u8 *addr, unsigned int tid)
0546 {
0547     struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
0548     struct ieee80211_local *local = sdata->local;
0549     struct sta_info *sta;
0550 
0551     rcu_read_lock();
0552     sta = sta_info_get_bss(sdata, addr);
0553     if (!sta)
0554         goto unlock;
0555 
0556     set_bit(tid, sta->ampdu_mlme.tid_rx_timer_expired);
0557     ieee80211_queue_work(&local->hw, &sta->ampdu_mlme.work);
0558 
0559  unlock:
0560     rcu_read_unlock();
0561 }
0562 EXPORT_SYMBOL(ieee80211_rx_ba_timer_expired);