LCOV - code coverage report
Current view: top level - net/mac80211 - agg-tx.c (source / functions) Hit Total Coverage
Test: combined.info Lines: 0 428 0.0 %
Date: 2022-03-28 15:32:58 Functions: 0 23 0.0 %
Branches: 0 177 0.0 %

           Branch data     Line data    Source code
       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 - 2019 Intel Corporation
      13                 :            :  */
      14                 :            : 
      15                 :            : #include <linux/ieee80211.h>
      16                 :            : #include <linux/slab.h>
      17                 :            : #include <linux/export.h>
      18                 :            : #include <net/mac80211.h>
      19                 :            : #include "ieee80211_i.h"
      20                 :            : #include "driver-ops.h"
      21                 :            : #include "wme.h"
      22                 :            : 
      23                 :            : /**
      24                 :            :  * DOC: TX A-MPDU aggregation
      25                 :            :  *
      26                 :            :  * Aggregation on the TX side requires setting the hardware flag
      27                 :            :  * %IEEE80211_HW_AMPDU_AGGREGATION. The driver will then be handed
      28                 :            :  * packets with a flag indicating A-MPDU aggregation. The driver
      29                 :            :  * or device is responsible for actually aggregating the frames,
      30                 :            :  * as well as deciding how many and which to aggregate.
      31                 :            :  *
      32                 :            :  * When TX aggregation is started by some subsystem (usually the rate
      33                 :            :  * control algorithm would be appropriate) by calling the
      34                 :            :  * ieee80211_start_tx_ba_session() function, the driver will be
      35                 :            :  * notified via its @ampdu_action function, with the
      36                 :            :  * %IEEE80211_AMPDU_TX_START action.
      37                 :            :  *
      38                 :            :  * In response to that, the driver is later required to call the
      39                 :            :  * ieee80211_start_tx_ba_cb_irqsafe() function, which will really
      40                 :            :  * start the aggregation session after the peer has also responded.
      41                 :            :  * If the peer responds negatively, the session will be stopped
      42                 :            :  * again right away. Note that it is possible for the aggregation
      43                 :            :  * session to be stopped before the driver has indicated that it
      44                 :            :  * is done setting it up, in which case it must not indicate the
      45                 :            :  * setup completion.
      46                 :            :  *
      47                 :            :  * Also note that, since we also need to wait for a response from
      48                 :            :  * the peer, the driver is notified of the completion of the
      49                 :            :  * handshake by the %IEEE80211_AMPDU_TX_OPERATIONAL action to the
      50                 :            :  * @ampdu_action callback.
      51                 :            :  *
      52                 :            :  * Similarly, when the aggregation session is stopped by the peer
      53                 :            :  * or something calling ieee80211_stop_tx_ba_session(), the driver's
      54                 :            :  * @ampdu_action function will be called with the action
      55                 :            :  * %IEEE80211_AMPDU_TX_STOP. In this case, the call must not fail,
      56                 :            :  * and the driver must later call ieee80211_stop_tx_ba_cb_irqsafe().
      57                 :            :  * Note that the sta can get destroyed before the BA tear down is
      58                 :            :  * complete.
      59                 :            :  */
      60                 :            : 
      61                 :          0 : static void ieee80211_send_addba_request(struct ieee80211_sub_if_data *sdata,
      62                 :            :                                          const u8 *da, u16 tid,
      63                 :            :                                          u8 dialog_token, u16 start_seq_num,
      64                 :            :                                          u16 agg_size, u16 timeout)
      65                 :            : {
      66                 :          0 :         struct ieee80211_local *local = sdata->local;
      67                 :          0 :         struct sk_buff *skb;
      68                 :          0 :         struct ieee80211_mgmt *mgmt;
      69                 :          0 :         u16 capab;
      70                 :            : 
      71                 :          0 :         skb = dev_alloc_skb(sizeof(*mgmt) + local->hw.extra_tx_headroom);
      72                 :            : 
      73         [ #  # ]:          0 :         if (!skb)
      74                 :            :                 return;
      75                 :            : 
      76                 :          0 :         skb_reserve(skb, local->hw.extra_tx_headroom);
      77                 :          0 :         mgmt = skb_put_zero(skb, 24);
      78                 :          0 :         memcpy(mgmt->da, da, ETH_ALEN);
      79                 :          0 :         memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN);
      80                 :          0 :         if (sdata->vif.type == NL80211_IFTYPE_AP ||
      81         [ #  # ]:          0 :             sdata->vif.type == NL80211_IFTYPE_AP_VLAN ||
      82                 :            :             sdata->vif.type == NL80211_IFTYPE_MESH_POINT)
      83                 :          0 :                 memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN);
      84         [ #  # ]:          0 :         else if (sdata->vif.type == NL80211_IFTYPE_STATION)
      85                 :          0 :                 memcpy(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN);
      86         [ #  # ]:          0 :         else if (sdata->vif.type == NL80211_IFTYPE_ADHOC)
      87                 :          0 :                 memcpy(mgmt->bssid, sdata->u.ibss.bssid, ETH_ALEN);
      88                 :            : 
      89                 :          0 :         mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
      90                 :            :                                           IEEE80211_STYPE_ACTION);
      91                 :            : 
      92                 :          0 :         skb_put(skb, 1 + sizeof(mgmt->u.action.u.addba_req));
      93                 :            : 
      94                 :          0 :         mgmt->u.action.category = WLAN_CATEGORY_BACK;
      95                 :          0 :         mgmt->u.action.u.addba_req.action_code = WLAN_ACTION_ADDBA_REQ;
      96                 :            : 
      97                 :          0 :         mgmt->u.action.u.addba_req.dialog_token = dialog_token;
      98                 :          0 :         capab = (u16)(1 << 0);            /* bit 0 A-MSDU support */
      99                 :          0 :         capab |= (u16)(1 << 1);           /* bit 1 aggregation policy */
     100                 :          0 :         capab |= (u16)(tid << 2);         /* bit 5:2 TID number */
     101                 :          0 :         capab |= (u16)(agg_size << 6);    /* bit 15:6 max size of aggergation */
     102                 :            : 
     103                 :          0 :         mgmt->u.action.u.addba_req.capab = cpu_to_le16(capab);
     104                 :            : 
     105                 :          0 :         mgmt->u.action.u.addba_req.timeout = cpu_to_le16(timeout);
     106                 :          0 :         mgmt->u.action.u.addba_req.start_seq_num =
     107                 :          0 :                                         cpu_to_le16(start_seq_num << 4);
     108                 :            : 
     109                 :          0 :         ieee80211_tx_skb(sdata, skb);
     110                 :            : }
     111                 :            : 
     112                 :          0 : void ieee80211_send_bar(struct ieee80211_vif *vif, u8 *ra, u16 tid, u16 ssn)
     113                 :            : {
     114                 :          0 :         struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
     115                 :          0 :         struct ieee80211_local *local = sdata->local;
     116                 :          0 :         struct sk_buff *skb;
     117                 :          0 :         struct ieee80211_bar *bar;
     118                 :          0 :         u16 bar_control = 0;
     119                 :            : 
     120                 :          0 :         skb = dev_alloc_skb(sizeof(*bar) + local->hw.extra_tx_headroom);
     121         [ #  # ]:          0 :         if (!skb)
     122                 :            :                 return;
     123                 :            : 
     124                 :          0 :         skb_reserve(skb, local->hw.extra_tx_headroom);
     125                 :          0 :         bar = skb_put_zero(skb, sizeof(*bar));
     126                 :          0 :         bar->frame_control = cpu_to_le16(IEEE80211_FTYPE_CTL |
     127                 :            :                                          IEEE80211_STYPE_BACK_REQ);
     128                 :          0 :         memcpy(bar->ra, ra, ETH_ALEN);
     129                 :          0 :         memcpy(bar->ta, sdata->vif.addr, ETH_ALEN);
     130                 :          0 :         bar_control |= (u16)IEEE80211_BAR_CTRL_ACK_POLICY_NORMAL;
     131                 :          0 :         bar_control |= (u16)IEEE80211_BAR_CTRL_CBMTID_COMPRESSED_BA;
     132                 :          0 :         bar_control |= (u16)(tid << IEEE80211_BAR_CTRL_TID_INFO_SHIFT);
     133                 :          0 :         bar->control = cpu_to_le16(bar_control);
     134                 :          0 :         bar->start_seq_num = cpu_to_le16(ssn);
     135                 :            : 
     136                 :          0 :         IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT |
     137                 :            :                                         IEEE80211_TX_CTL_REQ_TX_STATUS;
     138                 :          0 :         ieee80211_tx_skb_tid(sdata, skb, tid);
     139                 :            : }
     140                 :            : EXPORT_SYMBOL(ieee80211_send_bar);
     141                 :            : 
     142                 :          0 : void ieee80211_assign_tid_tx(struct sta_info *sta, int tid,
     143                 :            :                              struct tid_ampdu_tx *tid_tx)
     144                 :            : {
     145                 :          0 :         lockdep_assert_held(&sta->ampdu_mlme.mtx);
     146                 :          0 :         lockdep_assert_held(&sta->lock);
     147                 :          0 :         rcu_assign_pointer(sta->ampdu_mlme.tid_tx[tid], tid_tx);
     148                 :          0 : }
     149                 :            : 
     150                 :            : /*
     151                 :            :  * When multiple aggregation sessions on multiple stations
     152                 :            :  * are being created/destroyed simultaneously, we need to
     153                 :            :  * refcount the global queue stop caused by that in order
     154                 :            :  * to not get into a situation where one of the aggregation
     155                 :            :  * setup or teardown re-enables queues before the other is
     156                 :            :  * ready to handle that.
     157                 :            :  *
     158                 :            :  * These two functions take care of this issue by keeping
     159                 :            :  * a global "agg_queue_stop" refcount.
     160                 :            :  */
     161                 :            : static void __acquires(agg_queue)
     162                 :          0 : ieee80211_stop_queue_agg(struct ieee80211_sub_if_data *sdata, int tid)
     163                 :            : {
     164                 :          0 :         int queue = sdata->vif.hw_queue[ieee80211_ac_from_tid(tid)];
     165                 :            : 
     166                 :            :         /* we do refcounting here, so don't use the queue reason refcounting */
     167                 :            : 
     168         [ #  # ]:          0 :         if (atomic_inc_return(&sdata->local->agg_queue_stop[queue]) == 1)
     169                 :          0 :                 ieee80211_stop_queue_by_reason(
     170                 :          0 :                         &sdata->local->hw, queue,
     171                 :            :                         IEEE80211_QUEUE_STOP_REASON_AGGREGATION,
     172                 :            :                         false);
     173                 :          0 :         __acquire(agg_queue);
     174                 :          0 : }
     175                 :            : 
     176                 :            : static void __releases(agg_queue)
     177                 :          0 : ieee80211_wake_queue_agg(struct ieee80211_sub_if_data *sdata, int tid)
     178                 :            : {
     179                 :          0 :         int queue = sdata->vif.hw_queue[ieee80211_ac_from_tid(tid)];
     180                 :            : 
     181         [ #  # ]:          0 :         if (atomic_dec_return(&sdata->local->agg_queue_stop[queue]) == 0)
     182                 :          0 :                 ieee80211_wake_queue_by_reason(
     183                 :          0 :                         &sdata->local->hw, queue,
     184                 :            :                         IEEE80211_QUEUE_STOP_REASON_AGGREGATION,
     185                 :            :                         false);
     186                 :          0 :         __release(agg_queue);
     187                 :          0 : }
     188                 :            : 
     189                 :            : static void
     190                 :          0 : ieee80211_agg_stop_txq(struct sta_info *sta, int tid)
     191                 :            : {
     192                 :          0 :         struct ieee80211_txq *txq = sta->sta.txq[tid];
     193                 :          0 :         struct ieee80211_sub_if_data *sdata;
     194                 :          0 :         struct fq *fq;
     195                 :          0 :         struct txq_info *txqi;
     196                 :            : 
     197         [ #  # ]:          0 :         if (!txq)
     198                 :            :                 return;
     199                 :            : 
     200                 :          0 :         txqi = to_txq_info(txq);
     201                 :          0 :         sdata = vif_to_sdata(txq->vif);
     202                 :          0 :         fq = &sdata->local->fq;
     203                 :            : 
     204                 :            :         /* Lock here to protect against further seqno updates on dequeue */
     205                 :          0 :         spin_lock_bh(&fq->lock);
     206                 :          0 :         set_bit(IEEE80211_TXQ_STOP, &txqi->flags);
     207                 :          0 :         spin_unlock_bh(&fq->lock);
     208                 :            : }
     209                 :            : 
     210                 :            : static void
     211                 :          0 : ieee80211_agg_start_txq(struct sta_info *sta, int tid, bool enable)
     212                 :            : {
     213                 :          0 :         struct ieee80211_txq *txq = sta->sta.txq[tid];
     214                 :          0 :         struct txq_info *txqi;
     215                 :            : 
     216         [ #  # ]:          0 :         if (!txq)
     217                 :            :                 return;
     218                 :            : 
     219         [ #  # ]:          0 :         txqi = to_txq_info(txq);
     220                 :            : 
     221         [ #  # ]:          0 :         if (enable)
     222                 :          0 :                 set_bit(IEEE80211_TXQ_AMPDU, &txqi->flags);
     223                 :            :         else
     224                 :          0 :                 clear_bit(IEEE80211_TXQ_AMPDU, &txqi->flags);
     225                 :            : 
     226                 :          0 :         clear_bit(IEEE80211_TXQ_STOP, &txqi->flags);
     227                 :          0 :         local_bh_disable();
     228                 :          0 :         rcu_read_lock();
     229                 :          0 :         schedule_and_wake_txq(sta->sdata->local, txqi);
     230                 :          0 :         rcu_read_unlock();
     231                 :          0 :         local_bh_enable();
     232                 :            : }
     233                 :            : 
     234                 :            : /*
     235                 :            :  * splice packets from the STA's pending to the local pending,
     236                 :            :  * requires a call to ieee80211_agg_splice_finish later
     237                 :            :  */
     238                 :            : static void __acquires(agg_queue)
     239                 :          0 : ieee80211_agg_splice_packets(struct ieee80211_sub_if_data *sdata,
     240                 :            :                              struct tid_ampdu_tx *tid_tx, u16 tid)
     241                 :            : {
     242                 :          0 :         struct ieee80211_local *local = sdata->local;
     243                 :          0 :         int queue = sdata->vif.hw_queue[ieee80211_ac_from_tid(tid)];
     244                 :          0 :         unsigned long flags;
     245                 :            : 
     246                 :          0 :         ieee80211_stop_queue_agg(sdata, tid);
     247                 :            : 
     248   [ #  #  #  # ]:          0 :         if (WARN(!tid_tx,
     249                 :            :                  "TID %d gone but expected when splicing aggregates from the pending queue\n",
     250                 :            :                  tid))
     251                 :            :                 return;
     252                 :            : 
     253         [ #  # ]:          0 :         if (!skb_queue_empty(&tid_tx->pending)) {
     254                 :          0 :                 spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
     255                 :            :                 /* copy over remaining packets */
     256         [ #  # ]:          0 :                 skb_queue_splice_tail_init(&tid_tx->pending,
     257                 :            :                                            &local->pending[queue]);
     258                 :          0 :                 spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
     259                 :            :         }
     260                 :            : }
     261                 :            : 
     262                 :            : static void __releases(agg_queue)
     263                 :          0 : ieee80211_agg_splice_finish(struct ieee80211_sub_if_data *sdata, u16 tid)
     264                 :            : {
     265                 :          0 :         ieee80211_wake_queue_agg(sdata, tid);
     266                 :            : }
     267                 :            : 
     268                 :          0 : static void ieee80211_remove_tid_tx(struct sta_info *sta, int tid)
     269                 :            : {
     270                 :          0 :         struct tid_ampdu_tx *tid_tx;
     271                 :            : 
     272                 :          0 :         lockdep_assert_held(&sta->ampdu_mlme.mtx);
     273                 :          0 :         lockdep_assert_held(&sta->lock);
     274                 :            : 
     275                 :          0 :         tid_tx = rcu_dereference_protected_tid_tx(sta, tid);
     276                 :            : 
     277                 :            :         /*
     278                 :            :          * When we get here, the TX path will not be lockless any more wrt.
     279                 :            :          * aggregation, since the OPERATIONAL bit has long been cleared.
     280                 :            :          * Thus it will block on getting the lock, if it occurs. So if we
     281                 :            :          * stop the queue now, we will not get any more packets, and any
     282                 :            :          * that might be being processed will wait for us here, thereby
     283                 :            :          * guaranteeing that no packets go to the tid_tx pending queue any
     284                 :            :          * more.
     285                 :            :          */
     286                 :            : 
     287                 :          0 :         ieee80211_agg_splice_packets(sta->sdata, tid_tx, tid);
     288                 :            : 
     289                 :            :         /* future packets must not find the tid_tx struct any more */
     290                 :          0 :         ieee80211_assign_tid_tx(sta, tid, NULL);
     291                 :            : 
     292                 :          0 :         ieee80211_agg_splice_finish(sta->sdata, tid);
     293                 :          0 :         ieee80211_agg_start_txq(sta, tid, false);
     294                 :            : 
     295         [ #  # ]:          0 :         kfree_rcu(tid_tx, rcu_head);
     296                 :          0 : }
     297                 :            : 
     298                 :          0 : int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid,
     299                 :            :                                     enum ieee80211_agg_stop_reason reason)
     300                 :            : {
     301                 :          0 :         struct ieee80211_local *local = sta->local;
     302                 :          0 :         struct tid_ampdu_tx *tid_tx;
     303                 :          0 :         struct ieee80211_ampdu_params params = {
     304                 :          0 :                 .sta = &sta->sta,
     305                 :            :                 .tid = tid,
     306                 :            :                 .buf_size = 0,
     307                 :            :                 .amsdu = false,
     308                 :            :                 .timeout = 0,
     309                 :            :                 .ssn = 0,
     310                 :            :         };
     311                 :          0 :         int ret;
     312                 :            : 
     313                 :          0 :         lockdep_assert_held(&sta->ampdu_mlme.mtx);
     314                 :            : 
     315      [ #  #  # ]:          0 :         switch (reason) {
     316                 :          0 :         case AGG_STOP_DECLINED:
     317                 :            :         case AGG_STOP_LOCAL_REQUEST:
     318                 :            :         case AGG_STOP_PEER_REQUEST:
     319                 :          0 :                 params.action = IEEE80211_AMPDU_TX_STOP_CONT;
     320                 :          0 :                 break;
     321                 :          0 :         case AGG_STOP_DESTROY_STA:
     322                 :          0 :                 params.action = IEEE80211_AMPDU_TX_STOP_FLUSH;
     323                 :          0 :                 break;
     324                 :            :         default:
     325                 :          0 :                 WARN_ON_ONCE(1);
     326                 :          0 :                 return -EINVAL;
     327                 :            :         }
     328                 :            : 
     329                 :          0 :         spin_lock_bh(&sta->lock);
     330                 :            : 
     331                 :            :         /* free struct pending for start, if present */
     332                 :          0 :         tid_tx = sta->ampdu_mlme.tid_start_tx[tid];
     333                 :          0 :         kfree(tid_tx);
     334                 :          0 :         sta->ampdu_mlme.tid_start_tx[tid] = NULL;
     335                 :            : 
     336         [ #  # ]:          0 :         tid_tx = rcu_dereference_protected_tid_tx(sta, tid);
     337         [ #  # ]:          0 :         if (!tid_tx) {
     338                 :          0 :                 spin_unlock_bh(&sta->lock);
     339                 :          0 :                 return -ENOENT;
     340                 :            :         }
     341                 :            : 
     342                 :            :         /*
     343                 :            :          * if we're already stopping ignore any new requests to stop
     344                 :            :          * unless we're destroying it in which case notify the driver
     345                 :            :          */
     346         [ #  # ]:          0 :         if (test_bit(HT_AGG_STATE_STOPPING, &tid_tx->state)) {
     347                 :          0 :                 spin_unlock_bh(&sta->lock);
     348         [ #  # ]:          0 :                 if (reason != AGG_STOP_DESTROY_STA)
     349                 :            :                         return -EALREADY;
     350                 :          0 :                 params.action = IEEE80211_AMPDU_TX_STOP_FLUSH_CONT;
     351                 :          0 :                 ret = drv_ampdu_action(local, sta->sdata, &params);
     352         [ #  # ]:          0 :                 WARN_ON_ONCE(ret);
     353                 :            :                 return 0;
     354                 :            :         }
     355                 :            : 
     356         [ #  # ]:          0 :         if (test_bit(HT_AGG_STATE_WANT_START, &tid_tx->state)) {
     357                 :            :                 /* not even started yet! */
     358                 :          0 :                 ieee80211_assign_tid_tx(sta, tid, NULL);
     359                 :          0 :                 spin_unlock_bh(&sta->lock);
     360                 :          0 :                 kfree_rcu(tid_tx, rcu_head);
     361                 :          0 :                 return 0;
     362                 :            :         }
     363                 :            : 
     364                 :          0 :         set_bit(HT_AGG_STATE_STOPPING, &tid_tx->state);
     365                 :            : 
     366                 :          0 :         ieee80211_agg_stop_txq(sta, tid);
     367                 :            : 
     368                 :          0 :         spin_unlock_bh(&sta->lock);
     369                 :            : 
     370                 :          0 :         ht_dbg(sta->sdata, "Tx BA session stop requested for %pM tid %u\n",
     371                 :            :                sta->sta.addr, tid);
     372                 :            : 
     373                 :          0 :         del_timer_sync(&tid_tx->addba_resp_timer);
     374                 :          0 :         del_timer_sync(&tid_tx->session_timer);
     375                 :            : 
     376                 :            :         /*
     377                 :            :          * After this packets are no longer handed right through
     378                 :            :          * to the driver but are put onto tid_tx->pending instead,
     379                 :            :          * with locking to ensure proper access.
     380                 :            :          */
     381                 :          0 :         clear_bit(HT_AGG_STATE_OPERATIONAL, &tid_tx->state);
     382                 :            : 
     383                 :            :         /*
     384                 :            :          * There might be a few packets being processed right now (on
     385                 :            :          * another CPU) that have already gotten past the aggregation
     386                 :            :          * check when it was still OPERATIONAL and consequently have
     387                 :            :          * IEEE80211_TX_CTL_AMPDU set. In that case, this code might
     388                 :            :          * call into the driver at the same time or even before the
     389                 :            :          * TX paths calls into it, which could confuse the driver.
     390                 :            :          *
     391                 :            :          * Wait for all currently running TX paths to finish before
     392                 :            :          * telling the driver. New packets will not go through since
     393                 :            :          * the aggregation session is no longer OPERATIONAL.
     394                 :            :          */
     395         [ #  # ]:          0 :         if (!local->in_reconfig)
     396                 :          0 :                 synchronize_net();
     397                 :            : 
     398                 :          0 :         tid_tx->stop_initiator = reason == AGG_STOP_PEER_REQUEST ?
     399                 :          0 :                                         WLAN_BACK_RECIPIENT :
     400                 :            :                                         WLAN_BACK_INITIATOR;
     401                 :          0 :         tid_tx->tx_stop = reason == AGG_STOP_LOCAL_REQUEST;
     402                 :            : 
     403                 :          0 :         ret = drv_ampdu_action(local, sta->sdata, &params);
     404                 :            : 
     405                 :            :         /* HW shall not deny going back to legacy */
     406         [ #  # ]:          0 :         if (WARN_ON(ret)) {
     407                 :            :                 /*
     408                 :            :                  * We may have pending packets get stuck in this case...
     409                 :            :                  * Not bothering with a workaround for now.
     410                 :            :                  */
     411                 :            :         }
     412                 :            : 
     413                 :            :         /*
     414                 :            :          * In the case of AGG_STOP_DESTROY_STA, the driver won't
     415                 :            :          * necessarily call ieee80211_stop_tx_ba_cb(), so this may
     416                 :            :          * seem like we can leave the tid_tx data pending forever.
     417                 :            :          * This is true, in a way, but "forever" is only until the
     418                 :            :          * station struct is actually destroyed. In the meantime,
     419                 :            :          * leaving it around ensures that we don't transmit packets
     420                 :            :          * to the driver on this TID which might confuse it.
     421                 :            :          */
     422                 :            : 
     423                 :            :         return 0;
     424                 :            : }
     425                 :            : 
     426                 :            : /*
     427                 :            :  * After sending add Block Ack request we activated a timer until
     428                 :            :  * add Block Ack response will arrive from the recipient.
     429                 :            :  * If this timer expires sta_addba_resp_timer_expired will be executed.
     430                 :            :  */
     431                 :          0 : static void sta_addba_resp_timer_expired(struct timer_list *t)
     432                 :            : {
     433                 :          0 :         struct tid_ampdu_tx *tid_tx = from_timer(tid_tx, t, addba_resp_timer);
     434                 :          0 :         struct sta_info *sta = tid_tx->sta;
     435                 :          0 :         u8 tid = tid_tx->tid;
     436                 :            : 
     437                 :            :         /* check if the TID waits for addBA response */
     438         [ #  # ]:          0 :         if (test_bit(HT_AGG_STATE_RESPONSE_RECEIVED, &tid_tx->state)) {
     439                 :            :                 ht_dbg(sta->sdata,
     440                 :            :                        "timer expired on %pM tid %d not expecting addBA response\n",
     441                 :            :                        sta->sta.addr, tid);
     442                 :            :                 return;
     443                 :            :         }
     444                 :            : 
     445                 :          0 :         ht_dbg(sta->sdata, "addBA response timer expired on %pM tid %d\n",
     446                 :            :                sta->sta.addr, tid);
     447                 :            : 
     448                 :          0 :         ieee80211_stop_tx_ba_session(&sta->sta, tid);
     449                 :            : }
     450                 :            : 
     451                 :          0 : void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid)
     452                 :            : {
     453                 :          0 :         struct tid_ampdu_tx *tid_tx;
     454                 :          0 :         struct ieee80211_local *local = sta->local;
     455                 :          0 :         struct ieee80211_sub_if_data *sdata = sta->sdata;
     456                 :          0 :         struct ieee80211_ampdu_params params = {
     457                 :          0 :                 .sta = &sta->sta,
     458                 :            :                 .action = IEEE80211_AMPDU_TX_START,
     459                 :            :                 .tid = tid,
     460                 :            :                 .buf_size = 0,
     461                 :            :                 .amsdu = false,
     462                 :            :                 .timeout = 0,
     463                 :            :         };
     464                 :          0 :         int ret;
     465                 :          0 :         u16 buf_size;
     466                 :            : 
     467                 :          0 :         tid_tx = rcu_dereference_protected_tid_tx(sta, tid);
     468                 :            : 
     469                 :            :         /*
     470                 :            :          * Start queuing up packets for this aggregation session.
     471                 :            :          * We're going to release them once the driver is OK with
     472                 :            :          * that.
     473                 :            :          */
     474                 :          0 :         clear_bit(HT_AGG_STATE_WANT_START, &tid_tx->state);
     475                 :            : 
     476                 :          0 :         ieee80211_agg_stop_txq(sta, tid);
     477                 :            : 
     478                 :            :         /*
     479                 :            :          * Make sure no packets are being processed. This ensures that
     480                 :            :          * we have a valid starting sequence number and that in-flight
     481                 :            :          * packets have been flushed out and no packets for this TID
     482                 :            :          * will go into the driver during the ampdu_action call.
     483                 :            :          */
     484                 :          0 :         synchronize_net();
     485                 :            : 
     486                 :          0 :         params.ssn = sta->tid_seq[tid] >> 4;
     487                 :          0 :         ret = drv_ampdu_action(local, sdata, &params);
     488         [ #  # ]:          0 :         if (ret == IEEE80211_AMPDU_TX_START_IMMEDIATE) {
     489                 :            :                 /*
     490                 :            :                  * We didn't send the request yet, so don't need to check
     491                 :            :                  * here if we already got a response, just mark as driver
     492                 :            :                  * ready immediately.
     493                 :            :                  */
     494                 :          0 :                 set_bit(HT_AGG_STATE_DRV_READY, &tid_tx->state);
     495         [ #  # ]:          0 :         } else if (ret) {
     496                 :          0 :                 ht_dbg(sdata,
     497                 :            :                        "BA request denied - HW unavailable for %pM tid %d\n",
     498                 :            :                        sta->sta.addr, tid);
     499                 :          0 :                 spin_lock_bh(&sta->lock);
     500                 :          0 :                 ieee80211_agg_splice_packets(sdata, tid_tx, tid);
     501                 :          0 :                 ieee80211_assign_tid_tx(sta, tid, NULL);
     502                 :          0 :                 ieee80211_agg_splice_finish(sdata, tid);
     503                 :          0 :                 spin_unlock_bh(&sta->lock);
     504                 :            : 
     505                 :          0 :                 ieee80211_agg_start_txq(sta, tid, false);
     506                 :            : 
     507         [ #  # ]:          0 :                 kfree_rcu(tid_tx, rcu_head);
     508                 :          0 :                 return;
     509                 :            :         }
     510                 :            : 
     511                 :            :         /* activate the timer for the recipient's addBA response */
     512                 :          0 :         mod_timer(&tid_tx->addba_resp_timer, jiffies + ADDBA_RESP_INTERVAL);
     513                 :          0 :         ht_dbg(sdata, "activated addBA response timer on %pM tid %d\n",
     514                 :            :                sta->sta.addr, tid);
     515                 :            : 
     516                 :          0 :         spin_lock_bh(&sta->lock);
     517                 :          0 :         sta->ampdu_mlme.last_addba_req_time[tid] = jiffies;
     518                 :          0 :         sta->ampdu_mlme.addba_req_num[tid]++;
     519                 :          0 :         spin_unlock_bh(&sta->lock);
     520                 :            : 
     521         [ #  # ]:          0 :         if (sta->sta.he_cap.has_he) {
     522                 :          0 :                 buf_size = local->hw.max_tx_aggregation_subframes;
     523                 :            :         } else {
     524                 :            :                 /*
     525                 :            :                  * We really should use what the driver told us it will
     526                 :            :                  * transmit as the maximum, but certain APs (e.g. the
     527                 :            :                  * LinkSys WRT120N with FW v1.0.07 build 002 Jun 18 2012)
     528                 :            :                  * will crash when we use a lower number.
     529                 :            :                  */
     530                 :            :                 buf_size = IEEE80211_MAX_AMPDU_BUF_HT;
     531                 :            :         }
     532                 :            : 
     533                 :            :         /* send AddBA request */
     534                 :          0 :         ieee80211_send_addba_request(sdata, sta->sta.addr, tid,
     535                 :          0 :                                      tid_tx->dialog_token, params.ssn,
     536                 :          0 :                                      buf_size, tid_tx->timeout);
     537                 :            : }
     538                 :            : 
     539                 :            : /*
     540                 :            :  * After accepting the AddBA Response we activated a timer,
     541                 :            :  * resetting it after each frame that we send.
     542                 :            :  */
     543                 :          0 : static void sta_tx_agg_session_timer_expired(struct timer_list *t)
     544                 :            : {
     545                 :          0 :         struct tid_ampdu_tx *tid_tx = from_timer(tid_tx, t, session_timer);
     546                 :          0 :         struct sta_info *sta = tid_tx->sta;
     547                 :          0 :         u8 tid = tid_tx->tid;
     548                 :          0 :         unsigned long timeout;
     549                 :            : 
     550         [ #  # ]:          0 :         if (test_bit(HT_AGG_STATE_STOPPING, &tid_tx->state)) {
     551                 :            :                 return;
     552                 :            :         }
     553                 :            : 
     554         [ #  # ]:          0 :         timeout = tid_tx->last_tx + TU_TO_JIFFIES(tid_tx->timeout);
     555         [ #  # ]:          0 :         if (time_is_after_jiffies(timeout)) {
     556                 :          0 :                 mod_timer(&tid_tx->session_timer, timeout);
     557                 :          0 :                 return;
     558                 :            :         }
     559                 :            : 
     560                 :          0 :         ht_dbg(sta->sdata, "tx session timer expired on %pM tid %d\n",
     561                 :            :                sta->sta.addr, tid);
     562                 :            : 
     563                 :          0 :         ieee80211_stop_tx_ba_session(&sta->sta, tid);
     564                 :            : }
     565                 :            : 
     566                 :          0 : int ieee80211_start_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid,
     567                 :            :                                   u16 timeout)
     568                 :            : {
     569                 :          0 :         struct sta_info *sta = container_of(pubsta, struct sta_info, sta);
     570                 :          0 :         struct ieee80211_sub_if_data *sdata = sta->sdata;
     571                 :          0 :         struct ieee80211_local *local = sdata->local;
     572                 :          0 :         struct tid_ampdu_tx *tid_tx;
     573                 :          0 :         int ret = 0;
     574                 :            : 
     575                 :          0 :         trace_api_start_tx_ba_session(pubsta, tid);
     576                 :            : 
     577   [ #  #  #  # ]:          0 :         if (WARN(sta->reserved_tid == tid,
     578                 :            :                  "Requested to start BA session on reserved tid=%d", tid))
     579                 :            :                 return -EINVAL;
     580                 :            : 
     581         [ #  # ]:          0 :         if (!pubsta->ht_cap.ht_supported)
     582                 :            :                 return -EINVAL;
     583                 :            : 
     584   [ #  #  #  # ]:          0 :         if (WARN_ON_ONCE(!local->ops->ampdu_action))
     585                 :            :                 return -EINVAL;
     586                 :            : 
     587   [ #  #  #  # ]:          0 :         if ((tid >= IEEE80211_NUM_TIDS) ||
     588         [ #  # ]:          0 :             !ieee80211_hw_check(&local->hw, AMPDU_AGGREGATION) ||
     589                 :            :             ieee80211_hw_check(&local->hw, TX_AMPDU_SETUP_IN_HW))
     590                 :          0 :                 return -EINVAL;
     591                 :            : 
     592   [ #  #  #  # ]:          0 :         if (WARN_ON(tid >= IEEE80211_FIRST_TSPEC_TSID))
     593                 :            :                 return -EINVAL;
     594                 :            : 
     595                 :          0 :         ht_dbg(sdata, "Open BA session requested for %pM tid %u\n",
     596                 :            :                pubsta->addr, tid);
     597                 :            : 
     598         [ #  # ]:          0 :         if (sdata->vif.type != NL80211_IFTYPE_STATION &&
     599         [ #  # ]:          0 :             sdata->vif.type != NL80211_IFTYPE_MESH_POINT &&
     600         [ #  # ]:          0 :             sdata->vif.type != NL80211_IFTYPE_AP_VLAN &&
     601         [ #  # ]:          0 :             sdata->vif.type != NL80211_IFTYPE_AP &&
     602                 :            :             sdata->vif.type != NL80211_IFTYPE_ADHOC)
     603                 :            :                 return -EINVAL;
     604                 :            : 
     605         [ #  # ]:          0 :         if (test_sta_flag(sta, WLAN_STA_BLOCK_BA)) {
     606                 :            :                 ht_dbg(sdata,
     607                 :            :                        "BA sessions blocked - Denying BA session request %pM tid %d\n",
     608                 :            :                        sta->sta.addr, tid);
     609                 :            :                 return -EINVAL;
     610                 :            :         }
     611                 :            : 
     612                 :            :         /*
     613                 :            :          * 802.11n-2009 11.5.1.1: If the initiating STA is an HT STA, is a
     614                 :            :          * member of an IBSS, and has no other existing Block Ack agreement
     615                 :            :          * with the recipient STA, then the initiating STA shall transmit a
     616                 :            :          * Probe Request frame to the recipient STA and shall not transmit an
     617                 :            :          * ADDBA Request frame unless it receives a Probe Response frame
     618                 :            :          * from the recipient within dot11ADDBAFailureTimeout.
     619                 :            :          *
     620                 :            :          * The probe request mechanism for ADDBA is currently not implemented,
     621                 :            :          * but we only build up Block Ack session with HT STAs. This information
     622                 :            :          * is set when we receive a bss info from a probe response or a beacon.
     623                 :            :          */
     624         [ #  # ]:          0 :         if (sta->sdata->vif.type == NL80211_IFTYPE_ADHOC &&
     625         [ #  # ]:          0 :             !sta->sta.ht_cap.ht_supported) {
     626                 :            :                 ht_dbg(sdata,
     627                 :            :                        "BA request denied - IBSS STA %pM does not advertise HT support\n",
     628                 :            :                        pubsta->addr);
     629                 :            :                 return -EINVAL;
     630                 :            :         }
     631                 :            : 
     632                 :          0 :         spin_lock_bh(&sta->lock);
     633                 :            : 
     634                 :            :         /* we have tried too many times, receiver does not want A-MPDU */
     635         [ #  # ]:          0 :         if (sta->ampdu_mlme.addba_req_num[tid] > HT_AGG_MAX_RETRIES) {
     636                 :          0 :                 ret = -EBUSY;
     637                 :          0 :                 goto err_unlock_sta;
     638                 :            :         }
     639                 :            : 
     640                 :            :         /*
     641                 :            :          * if we have tried more than HT_AGG_BURST_RETRIES times we
     642                 :            :          * will spread our requests in time to avoid stalling connection
     643                 :            :          * for too long
     644                 :            :          */
     645         [ #  # ]:          0 :         if (sta->ampdu_mlme.addba_req_num[tid] > HT_AGG_BURST_RETRIES &&
     646         [ #  # ]:          0 :             time_before(jiffies, sta->ampdu_mlme.last_addba_req_time[tid] +
     647                 :            :                         HT_AGG_RETRIES_PERIOD)) {
     648                 :          0 :                 ht_dbg(sdata,
     649                 :            :                        "BA request denied - %d failed requests on %pM tid %u\n",
     650                 :            :                        sta->ampdu_mlme.addba_req_num[tid], sta->sta.addr, tid);
     651                 :          0 :                 ret = -EBUSY;
     652                 :          0 :                 goto err_unlock_sta;
     653                 :            :         }
     654                 :            : 
     655         [ #  # ]:          0 :         tid_tx = rcu_dereference_protected_tid_tx(sta, tid);
     656                 :            :         /* check if the TID is not in aggregation flow already */
     657   [ #  #  #  # ]:          0 :         if (tid_tx || sta->ampdu_mlme.tid_start_tx[tid]) {
     658                 :          0 :                 ht_dbg(sdata,
     659                 :            :                        "BA request denied - session is not idle on %pM tid %u\n",
     660                 :            :                        sta->sta.addr, tid);
     661                 :          0 :                 ret = -EAGAIN;
     662                 :          0 :                 goto err_unlock_sta;
     663                 :            :         }
     664                 :            : 
     665                 :            :         /* prepare A-MPDU MLME for Tx aggregation */
     666                 :          0 :         tid_tx = kzalloc(sizeof(struct tid_ampdu_tx), GFP_ATOMIC);
     667         [ #  # ]:          0 :         if (!tid_tx) {
     668                 :          0 :                 ret = -ENOMEM;
     669                 :          0 :                 goto err_unlock_sta;
     670                 :            :         }
     671                 :            : 
     672                 :          0 :         skb_queue_head_init(&tid_tx->pending);
     673                 :          0 :         __set_bit(HT_AGG_STATE_WANT_START, &tid_tx->state);
     674                 :            : 
     675                 :          0 :         tid_tx->timeout = timeout;
     676                 :          0 :         tid_tx->sta = sta;
     677                 :          0 :         tid_tx->tid = tid;
     678                 :            : 
     679                 :            :         /* response timer */
     680                 :          0 :         timer_setup(&tid_tx->addba_resp_timer, sta_addba_resp_timer_expired, 0);
     681                 :            : 
     682                 :            :         /* tx timer */
     683                 :          0 :         timer_setup(&tid_tx->session_timer,
     684                 :            :                     sta_tx_agg_session_timer_expired, TIMER_DEFERRABLE);
     685                 :            : 
     686                 :            :         /* assign a dialog token */
     687                 :          0 :         sta->ampdu_mlme.dialog_token_allocator++;
     688                 :          0 :         tid_tx->dialog_token = sta->ampdu_mlme.dialog_token_allocator;
     689                 :            : 
     690                 :            :         /*
     691                 :            :          * Finally, assign it to the start array; the work item will
     692                 :            :          * collect it and move it to the normal array.
     693                 :            :          */
     694                 :          0 :         sta->ampdu_mlme.tid_start_tx[tid] = tid_tx;
     695                 :            : 
     696                 :          0 :         ieee80211_queue_work(&local->hw, &sta->ampdu_mlme.work);
     697                 :            : 
     698                 :            :         /* this flow continues off the work */
     699                 :          0 :  err_unlock_sta:
     700                 :          0 :         spin_unlock_bh(&sta->lock);
     701                 :          0 :         return ret;
     702                 :            : }
     703                 :            : EXPORT_SYMBOL(ieee80211_start_tx_ba_session);
     704                 :            : 
     705                 :          0 : static void ieee80211_agg_tx_operational(struct ieee80211_local *local,
     706                 :            :                                          struct sta_info *sta, u16 tid)
     707                 :            : {
     708                 :          0 :         struct tid_ampdu_tx *tid_tx;
     709                 :          0 :         struct ieee80211_ampdu_params params = {
     710                 :          0 :                 .sta = &sta->sta,
     711                 :            :                 .action = IEEE80211_AMPDU_TX_OPERATIONAL,
     712                 :            :                 .tid = tid,
     713                 :            :                 .timeout = 0,
     714                 :            :                 .ssn = 0,
     715                 :            :         };
     716                 :            : 
     717                 :          0 :         lockdep_assert_held(&sta->ampdu_mlme.mtx);
     718                 :            : 
     719                 :          0 :         tid_tx = rcu_dereference_protected_tid_tx(sta, tid);
     720                 :          0 :         params.buf_size = tid_tx->buf_size;
     721                 :          0 :         params.amsdu = tid_tx->amsdu;
     722                 :            : 
     723                 :          0 :         ht_dbg(sta->sdata, "Aggregation is on for %pM tid %d\n",
     724                 :            :                sta->sta.addr, tid);
     725                 :            : 
     726                 :          0 :         drv_ampdu_action(local, sta->sdata, &params);
     727                 :            : 
     728                 :            :         /*
     729                 :            :          * synchronize with TX path, while splicing the TX path
     730                 :            :          * should block so it won't put more packets onto pending.
     731                 :            :          */
     732                 :          0 :         spin_lock_bh(&sta->lock);
     733                 :            : 
     734                 :          0 :         ieee80211_agg_splice_packets(sta->sdata, tid_tx, tid);
     735                 :            :         /*
     736                 :            :          * Now mark as operational. This will be visible
     737                 :            :          * in the TX path, and lets it go lock-free in
     738                 :            :          * the common case.
     739                 :            :          */
     740                 :          0 :         set_bit(HT_AGG_STATE_OPERATIONAL, &tid_tx->state);
     741                 :          0 :         ieee80211_agg_splice_finish(sta->sdata, tid);
     742                 :            : 
     743                 :          0 :         spin_unlock_bh(&sta->lock);
     744                 :            : 
     745                 :          0 :         ieee80211_agg_start_txq(sta, tid, true);
     746                 :          0 : }
     747                 :            : 
     748                 :          0 : void ieee80211_start_tx_ba_cb(struct sta_info *sta, int tid,
     749                 :            :                               struct tid_ampdu_tx *tid_tx)
     750                 :            : {
     751                 :          0 :         struct ieee80211_sub_if_data *sdata = sta->sdata;
     752                 :          0 :         struct ieee80211_local *local = sdata->local;
     753                 :            : 
     754   [ #  #  #  # ]:          0 :         if (WARN_ON(test_and_set_bit(HT_AGG_STATE_DRV_READY, &tid_tx->state)))
     755                 :            :                 return;
     756                 :            : 
     757         [ #  # ]:          0 :         if (test_bit(HT_AGG_STATE_RESPONSE_RECEIVED, &tid_tx->state))
     758                 :          0 :                 ieee80211_agg_tx_operational(local, sta, tid);
     759                 :            : }
     760                 :            : 
     761                 :            : static struct tid_ampdu_tx *
     762                 :          0 : ieee80211_lookup_tid_tx(struct ieee80211_sub_if_data *sdata,
     763                 :            :                         const u8 *ra, u16 tid, struct sta_info **sta)
     764                 :            : {
     765                 :          0 :         struct tid_ampdu_tx *tid_tx;
     766                 :            : 
     767         [ #  # ]:          0 :         if (tid >= IEEE80211_NUM_TIDS) {
     768                 :            :                 ht_dbg(sdata, "Bad TID value: tid = %d (>= %d)\n",
     769                 :            :                        tid, IEEE80211_NUM_TIDS);
     770                 :            :                 return NULL;
     771                 :            :         }
     772                 :            : 
     773                 :          0 :         *sta = sta_info_get_bss(sdata, ra);
     774         [ #  # ]:          0 :         if (!*sta) {
     775                 :            :                 ht_dbg(sdata, "Could not find station: %pM\n", ra);
     776                 :            :                 return NULL;
     777                 :            :         }
     778                 :            : 
     779         [ #  # ]:          0 :         tid_tx = rcu_dereference((*sta)->ampdu_mlme.tid_tx[tid]);
     780                 :            : 
     781         [ #  # ]:          0 :         if (WARN_ON(!tid_tx))
     782                 :            :                 ht_dbg(sdata, "addBA was not requested!\n");
     783                 :            : 
     784                 :            :         return tid_tx;
     785                 :            : }
     786                 :            : 
     787                 :          0 : void ieee80211_start_tx_ba_cb_irqsafe(struct ieee80211_vif *vif,
     788                 :            :                                       const u8 *ra, u16 tid)
     789                 :            : {
     790                 :          0 :         struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
     791                 :          0 :         struct ieee80211_local *local = sdata->local;
     792                 :          0 :         struct sta_info *sta;
     793                 :          0 :         struct tid_ampdu_tx *tid_tx;
     794                 :            : 
     795                 :          0 :         trace_api_start_tx_ba_cb(sdata, ra, tid);
     796                 :            : 
     797                 :          0 :         rcu_read_lock();
     798                 :          0 :         tid_tx = ieee80211_lookup_tid_tx(sdata, ra, tid, &sta);
     799         [ #  # ]:          0 :         if (!tid_tx)
     800                 :          0 :                 goto out;
     801                 :            : 
     802                 :          0 :         set_bit(HT_AGG_STATE_START_CB, &tid_tx->state);
     803                 :          0 :         ieee80211_queue_work(&local->hw, &sta->ampdu_mlme.work);
     804                 :          0 :  out:
     805                 :          0 :         rcu_read_unlock();
     806                 :          0 : }
     807                 :            : EXPORT_SYMBOL(ieee80211_start_tx_ba_cb_irqsafe);
     808                 :            : 
     809                 :          0 : int __ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid,
     810                 :            :                                    enum ieee80211_agg_stop_reason reason)
     811                 :            : {
     812                 :          0 :         int ret;
     813                 :            : 
     814                 :          0 :         mutex_lock(&sta->ampdu_mlme.mtx);
     815                 :            : 
     816                 :          0 :         ret = ___ieee80211_stop_tx_ba_session(sta, tid, reason);
     817                 :            : 
     818                 :          0 :         mutex_unlock(&sta->ampdu_mlme.mtx);
     819                 :            : 
     820                 :          0 :         return ret;
     821                 :            : }
     822                 :            : 
     823                 :          0 : int ieee80211_stop_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid)
     824                 :            : {
     825                 :          0 :         struct sta_info *sta = container_of(pubsta, struct sta_info, sta);
     826                 :          0 :         struct ieee80211_sub_if_data *sdata = sta->sdata;
     827                 :          0 :         struct ieee80211_local *local = sdata->local;
     828                 :          0 :         struct tid_ampdu_tx *tid_tx;
     829                 :          0 :         int ret = 0;
     830                 :            : 
     831                 :          0 :         trace_api_stop_tx_ba_session(pubsta, tid);
     832                 :            : 
     833         [ #  # ]:          0 :         if (!local->ops->ampdu_action)
     834                 :            :                 return -EINVAL;
     835                 :            : 
     836         [ #  # ]:          0 :         if (tid >= IEEE80211_NUM_TIDS)
     837                 :            :                 return -EINVAL;
     838                 :            : 
     839                 :          0 :         spin_lock_bh(&sta->lock);
     840         [ #  # ]:          0 :         tid_tx = rcu_dereference_protected_tid_tx(sta, tid);
     841                 :            : 
     842         [ #  # ]:          0 :         if (!tid_tx) {
     843                 :          0 :                 ret = -ENOENT;
     844                 :          0 :                 goto unlock;
     845                 :            :         }
     846                 :            : 
     847         [ #  # ]:          0 :         WARN(sta->reserved_tid == tid,
     848                 :            :              "Requested to stop BA session on reserved tid=%d", tid);
     849                 :            : 
     850         [ #  # ]:          0 :         if (test_bit(HT_AGG_STATE_STOPPING, &tid_tx->state)) {
     851                 :            :                 /* already in progress stopping it */
     852                 :          0 :                 ret = 0;
     853                 :          0 :                 goto unlock;
     854                 :            :         }
     855                 :            : 
     856                 :          0 :         set_bit(HT_AGG_STATE_WANT_STOP, &tid_tx->state);
     857                 :          0 :         ieee80211_queue_work(&local->hw, &sta->ampdu_mlme.work);
     858                 :            : 
     859                 :          0 :  unlock:
     860                 :          0 :         spin_unlock_bh(&sta->lock);
     861                 :          0 :         return ret;
     862                 :            : }
     863                 :            : EXPORT_SYMBOL(ieee80211_stop_tx_ba_session);
     864                 :            : 
     865                 :          0 : void ieee80211_stop_tx_ba_cb(struct sta_info *sta, int tid,
     866                 :            :                              struct tid_ampdu_tx *tid_tx)
     867                 :            : {
     868                 :          0 :         struct ieee80211_sub_if_data *sdata = sta->sdata;
     869                 :          0 :         bool send_delba = false;
     870                 :            : 
     871                 :          0 :         ht_dbg(sdata, "Stopping Tx BA session for %pM tid %d\n",
     872                 :            :                sta->sta.addr, tid);
     873                 :            : 
     874                 :          0 :         spin_lock_bh(&sta->lock);
     875                 :            : 
     876         [ #  # ]:          0 :         if (!test_bit(HT_AGG_STATE_STOPPING, &tid_tx->state)) {
     877                 :          0 :                 ht_dbg(sdata,
     878                 :            :                        "unexpected callback to A-MPDU stop for %pM tid %d\n",
     879                 :            :                        sta->sta.addr, tid);
     880                 :          0 :                 goto unlock_sta;
     881                 :            :         }
     882                 :            : 
     883   [ #  #  #  # ]:          0 :         if (tid_tx->stop_initiator == WLAN_BACK_INITIATOR && tid_tx->tx_stop)
     884                 :          0 :                 send_delba = true;
     885                 :            : 
     886                 :          0 :         ieee80211_remove_tid_tx(sta, tid);
     887                 :            : 
     888                 :          0 :  unlock_sta:
     889                 :          0 :         spin_unlock_bh(&sta->lock);
     890                 :            : 
     891         [ #  # ]:          0 :         if (send_delba)
     892                 :          0 :                 ieee80211_send_delba(sdata, sta->sta.addr, tid,
     893                 :            :                         WLAN_BACK_INITIATOR, WLAN_REASON_QSTA_NOT_USE);
     894                 :          0 : }
     895                 :            : 
     896                 :          0 : void ieee80211_stop_tx_ba_cb_irqsafe(struct ieee80211_vif *vif,
     897                 :            :                                      const u8 *ra, u16 tid)
     898                 :            : {
     899                 :          0 :         struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
     900                 :          0 :         struct ieee80211_local *local = sdata->local;
     901                 :          0 :         struct sta_info *sta;
     902                 :          0 :         struct tid_ampdu_tx *tid_tx;
     903                 :            : 
     904                 :          0 :         trace_api_stop_tx_ba_cb(sdata, ra, tid);
     905                 :            : 
     906                 :          0 :         rcu_read_lock();
     907                 :          0 :         tid_tx = ieee80211_lookup_tid_tx(sdata, ra, tid, &sta);
     908         [ #  # ]:          0 :         if (!tid_tx)
     909                 :          0 :                 goto out;
     910                 :            : 
     911                 :          0 :         set_bit(HT_AGG_STATE_STOP_CB, &tid_tx->state);
     912                 :          0 :         ieee80211_queue_work(&local->hw, &sta->ampdu_mlme.work);
     913                 :          0 :  out:
     914                 :          0 :         rcu_read_unlock();
     915                 :          0 : }
     916                 :            : EXPORT_SYMBOL(ieee80211_stop_tx_ba_cb_irqsafe);
     917                 :            : 
     918                 :            : 
     919                 :          0 : void ieee80211_process_addba_resp(struct ieee80211_local *local,
     920                 :            :                                   struct sta_info *sta,
     921                 :            :                                   struct ieee80211_mgmt *mgmt,
     922                 :            :                                   size_t len)
     923                 :            : {
     924                 :          0 :         struct tid_ampdu_tx *tid_tx;
     925                 :          0 :         struct ieee80211_txq *txq;
     926                 :          0 :         u16 capab, tid, buf_size;
     927                 :          0 :         bool amsdu;
     928                 :            : 
     929                 :          0 :         capab = le16_to_cpu(mgmt->u.action.u.addba_resp.capab);
     930                 :          0 :         amsdu = capab & IEEE80211_ADDBA_PARAM_AMSDU_MASK;
     931                 :          0 :         tid = (capab & IEEE80211_ADDBA_PARAM_TID_MASK) >> 2;
     932                 :          0 :         buf_size = (capab & IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK) >> 6;
     933                 :          0 :         buf_size = min(buf_size, local->hw.max_tx_aggregation_subframes);
     934                 :            : 
     935                 :          0 :         txq = sta->sta.txq[tid];
     936         [ #  # ]:          0 :         if (!amsdu && txq)
     937                 :          0 :                 set_bit(IEEE80211_TXQ_NO_AMSDU, &to_txq_info(txq)->flags);
     938                 :            : 
     939                 :          0 :         mutex_lock(&sta->ampdu_mlme.mtx);
     940                 :            : 
     941         [ #  # ]:          0 :         tid_tx = rcu_dereference_protected_tid_tx(sta, tid);
     942         [ #  # ]:          0 :         if (!tid_tx)
     943                 :          0 :                 goto out;
     944                 :            : 
     945         [ #  # ]:          0 :         if (mgmt->u.action.u.addba_resp.dialog_token != tid_tx->dialog_token) {
     946                 :          0 :                 ht_dbg(sta->sdata, "wrong addBA response token, %pM tid %d\n",
     947                 :            :                        sta->sta.addr, tid);
     948                 :          0 :                 goto out;
     949                 :            :         }
     950                 :            : 
     951                 :          0 :         del_timer_sync(&tid_tx->addba_resp_timer);
     952                 :            : 
     953                 :          0 :         ht_dbg(sta->sdata, "switched off addBA timer for %pM tid %d\n",
     954                 :            :                sta->sta.addr, tid);
     955                 :            : 
     956                 :            :         /*
     957                 :            :          * addba_resp_timer may have fired before we got here, and
     958                 :            :          * caused WANT_STOP to be set. If the stop then was already
     959                 :            :          * processed further, STOPPING might be set.
     960                 :            :          */
     961   [ #  #  #  # ]:          0 :         if (test_bit(HT_AGG_STATE_WANT_STOP, &tid_tx->state) ||
     962                 :            :             test_bit(HT_AGG_STATE_STOPPING, &tid_tx->state)) {
     963                 :          0 :                 ht_dbg(sta->sdata,
     964                 :            :                        "got addBA resp for %pM tid %d but we already gave up\n",
     965                 :            :                        sta->sta.addr, tid);
     966                 :          0 :                 goto out;
     967                 :            :         }
     968                 :            : 
     969                 :            :         /*
     970                 :            :          * IEEE 802.11-2007 7.3.1.14:
     971                 :            :          * In an ADDBA Response frame, when the Status Code field
     972                 :            :          * is set to 0, the Buffer Size subfield is set to a value
     973                 :            :          * of at least 1.
     974                 :            :          */
     975         [ #  # ]:          0 :         if (le16_to_cpu(mgmt->u.action.u.addba_resp.status)
     976         [ #  # ]:          0 :                         == WLAN_STATUS_SUCCESS && buf_size) {
     977         [ #  # ]:          0 :                 if (test_and_set_bit(HT_AGG_STATE_RESPONSE_RECEIVED,
     978                 :            :                                      &tid_tx->state)) {
     979                 :            :                         /* ignore duplicate response */
     980                 :          0 :                         goto out;
     981                 :            :                 }
     982                 :            : 
     983                 :          0 :                 tid_tx->buf_size = buf_size;
     984                 :          0 :                 tid_tx->amsdu = amsdu;
     985                 :            : 
     986         [ #  # ]:          0 :                 if (test_bit(HT_AGG_STATE_DRV_READY, &tid_tx->state))
     987                 :          0 :                         ieee80211_agg_tx_operational(local, sta, tid);
     988                 :            : 
     989                 :          0 :                 sta->ampdu_mlme.addba_req_num[tid] = 0;
     990                 :            : 
     991                 :          0 :                 tid_tx->timeout =
     992                 :          0 :                         le16_to_cpu(mgmt->u.action.u.addba_resp.timeout);
     993                 :            : 
     994         [ #  # ]:          0 :                 if (tid_tx->timeout) {
     995                 :          0 :                         mod_timer(&tid_tx->session_timer,
     996         [ #  # ]:          0 :                                   TU_TO_EXP_TIME(tid_tx->timeout));
     997                 :          0 :                         tid_tx->last_tx = jiffies;
     998                 :            :                 }
     999                 :            : 
    1000                 :            :         } else {
    1001                 :          0 :                 ___ieee80211_stop_tx_ba_session(sta, tid, AGG_STOP_DECLINED);
    1002                 :            :         }
    1003                 :            : 
    1004                 :          0 :  out:
    1005                 :          0 :         mutex_unlock(&sta->ampdu_mlme.mtx);
    1006                 :          0 : }

Generated by: LCOV version 1.14