00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #include <linux/ieee80211.h>
00017 #include <linux/slab.h>
00018 #include <linux/export.h>
00019 #include <net/mac80211.h>
00020 #include "ieee80211_i.h"
00021 #include "driver-ops.h"
00022 #include "wme.h"
00023
00060 static void ieee80211_send_addba_request(struct ieee80211_sub_if_data *sdata,
00061 const u8 *da, u16 tid,
00062 u8 dialog_token, u16 start_seq_num,
00063 u16 agg_size, u16 timeout)
00064 {
00065 struct ieee80211_local *local = sdata->local;
00066 struct sk_buff *skb;
00067 struct ieee80211_mgmt *mgmt;
00068 u16 capab;
00069
00070 skb = dev_alloc_skb(sizeof(*mgmt) + local->hw.extra_tx_headroom);
00071
00072 if (!skb)
00073 return;
00074
00075 skb_reserve(skb, local->hw.extra_tx_headroom);
00076 mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24);
00077 memset(mgmt, 0, 24);
00078 memcpy(mgmt->da, da, ETH_ALEN);
00079 memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN);
00080 if (sdata->vif.type == NL80211_IFTYPE_AP ||
00081 sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
00082 memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN);
00083 else if (sdata->vif.type == NL80211_IFTYPE_STATION)
00084 memcpy(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN);
00085
00086 mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
00087 IEEE80211_STYPE_ACTION);
00088
00089 skb_put(skb, 1 + sizeof(mgmt->u.action.u.addba_req));
00090
00091 mgmt->u.action.category = WLAN_CATEGORY_BACK;
00092 mgmt->u.action.u.addba_req.action_code = WLAN_ACTION_ADDBA_REQ;
00093
00094 mgmt->u.action.u.addba_req.dialog_token = dialog_token;
00095 capab = (u16)(1 << 1);
00096 capab |= (u16)(tid << 2);
00097 capab |= (u16)(agg_size << 6);
00098
00099 mgmt->u.action.u.addba_req.capab = cpu_to_le16(capab);
00100
00101 mgmt->u.action.u.addba_req.timeout = cpu_to_le16(timeout);
00102 mgmt->u.action.u.addba_req.start_seq_num =
00103 cpu_to_le16(start_seq_num << 4);
00104
00105 ieee80211_tx_skb(sdata, skb);
00106 }
00107
00108 void ieee80211_send_bar(struct ieee80211_vif *vif, u8 *ra, u16 tid, u16 ssn)
00109 {
00110 struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
00111 struct ieee80211_local *local = sdata->local;
00112 struct sk_buff *skb;
00113 struct ieee80211_bar *bar;
00114 u16 bar_control = 0;
00115
00116 skb = dev_alloc_skb(sizeof(*bar) + local->hw.extra_tx_headroom);
00117 if (!skb)
00118 return;
00119
00120 skb_reserve(skb, local->hw.extra_tx_headroom);
00121 bar = (struct ieee80211_bar *)skb_put(skb, sizeof(*bar));
00122 memset(bar, 0, sizeof(*bar));
00123 bar->frame_control = cpu_to_le16(IEEE80211_FTYPE_CTL |
00124 IEEE80211_STYPE_BACK_REQ);
00125 memcpy(bar->ra, ra, ETH_ALEN);
00126 memcpy(bar->ta, sdata->vif.addr, ETH_ALEN);
00127 bar_control |= (u16)IEEE80211_BAR_CTRL_ACK_POLICY_NORMAL;
00128 bar_control |= (u16)IEEE80211_BAR_CTRL_CBMTID_COMPRESSED_BA;
00129 bar_control |= (u16)(tid << IEEE80211_BAR_CTRL_TID_INFO_SHIFT);
00130 bar->control = cpu_to_le16(bar_control);
00131 bar->start_seq_num = cpu_to_le16(ssn);
00132
00133 IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT;
00134 ieee80211_tx_skb(sdata, skb);
00135 }
00136 EXPORT_SYMBOL(ieee80211_send_bar);
00137
00138 void ieee80211_assign_tid_tx(struct sta_info *sta, int tid,
00139 struct tid_ampdu_tx *tid_tx)
00140 {
00141 lockdep_assert_held(&sta->ampdu_mlme.mtx);
00142 lockdep_assert_held(&sta->lock);
00143 rcu_assign_pointer(sta->ampdu_mlme.tid_tx[tid], tid_tx);
00144 }
00145
00146 int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid,
00147 enum ieee80211_back_parties initiator,
00148 bool tx)
00149 {
00150 struct ieee80211_local *local = sta->local;
00151 struct tid_ampdu_tx *tid_tx;
00152 int ret;
00153
00154 lockdep_assert_held(&sta->ampdu_mlme.mtx);
00155
00156 spin_lock_bh(&sta->lock);
00157
00158 tid_tx = rcu_dereference_protected_tid_tx(sta, tid);
00159 if (!tid_tx) {
00160 spin_unlock_bh(&sta->lock);
00161 return -ENOENT;
00162 }
00163
00164
00165 if (test_bit(HT_AGG_STATE_STOPPING, &tid_tx->state)) {
00166 spin_unlock_bh(&sta->lock);
00167 return -EALREADY;
00168 }
00169
00170 if (test_bit(HT_AGG_STATE_WANT_START, &tid_tx->state)) {
00171
00172 ieee80211_assign_tid_tx(sta, tid, NULL);
00173 spin_unlock_bh(&sta->lock);
00174 kfree_rcu(tid_tx, rcu_head);
00175 return 0;
00176 }
00177
00178 set_bit(HT_AGG_STATE_STOPPING, &tid_tx->state);
00179
00180 spin_unlock_bh(&sta->lock);
00181
00182 #ifdef CONFIG_MAC80211_HT_DEBUG
00183 printk(KERN_DEBUG "Tx BA session stop requested for %pM tid %u\n",
00184 sta->sta.addr, tid);
00185 #endif
00186
00187 del_timer_sync(&tid_tx->addba_resp_timer);
00188
00189
00190
00191
00192
00193
00194 clear_bit(HT_AGG_STATE_OPERATIONAL, &tid_tx->state);
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208 synchronize_net();
00209
00210 tid_tx->stop_initiator = initiator;
00211 tid_tx->tx_stop = tx;
00212
00213 ret = drv_ampdu_action(local, sta->sdata,
00214 IEEE80211_AMPDU_TX_STOP,
00215 &sta->sta, tid, NULL, 0);
00216
00217
00218 if (WARN_ON(ret)) {
00219
00220
00221
00222
00223 }
00224
00225 return ret;
00226 }
00227
00228
00229
00230
00231
00232
00233 static void sta_addba_resp_timer_expired(unsigned long data)
00234 {
00235
00236
00237
00238
00239 u16 tid = *(u8 *)data;
00240 struct sta_info *sta = container_of((void *)data,
00241 struct sta_info, timer_to_tid[tid]);
00242 struct tid_ampdu_tx *tid_tx;
00243
00244
00245 rcu_read_lock();
00246 tid_tx = rcu_dereference(sta->ampdu_mlme.tid_tx[tid]);
00247 if (!tid_tx ||
00248 test_bit(HT_AGG_STATE_RESPONSE_RECEIVED, &tid_tx->state)) {
00249 rcu_read_unlock();
00250 #ifdef CONFIG_MAC80211_HT_DEBUG
00251 printk(KERN_DEBUG "timer expired on tid %d but we are not "
00252 "(or no longer) expecting addBA response there\n",
00253 tid);
00254 #endif
00255 return;
00256 }
00257
00258 #ifdef CONFIG_MAC80211_HT_DEBUG
00259 printk(KERN_DEBUG "addBA response timer expired on tid %d\n", tid);
00260 #endif
00261
00262 ieee80211_stop_tx_ba_session(&sta->sta, tid);
00263 rcu_read_unlock();
00264 }
00265
00266 static inline int ieee80211_ac_from_tid(int tid)
00267 {
00268 return ieee802_1d_to_ac[tid & 7];
00269 }
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282 static void __acquires(agg_queue)
00283 ieee80211_stop_queue_agg(struct ieee80211_local *local, int tid)
00284 {
00285 int queue = ieee80211_ac_from_tid(tid);
00286
00287 if (atomic_inc_return(&local->agg_queue_stop[queue]) == 1)
00288 ieee80211_stop_queue_by_reason(
00289 &local->hw, queue,
00290 IEEE80211_QUEUE_STOP_REASON_AGGREGATION);
00291 __acquire(agg_queue);
00292 }
00293
00294 static void __releases(agg_queue)
00295 ieee80211_wake_queue_agg(struct ieee80211_local *local, int tid)
00296 {
00297 int queue = ieee80211_ac_from_tid(tid);
00298
00299 if (atomic_dec_return(&local->agg_queue_stop[queue]) == 0)
00300 ieee80211_wake_queue_by_reason(
00301 &local->hw, queue,
00302 IEEE80211_QUEUE_STOP_REASON_AGGREGATION);
00303 __release(agg_queue);
00304 }
00305
00306
00307
00308
00309
00310 static void __acquires(agg_queue)
00311 ieee80211_agg_splice_packets(struct ieee80211_local *local,
00312 struct tid_ampdu_tx *tid_tx, u16 tid)
00313 {
00314 int queue = ieee80211_ac_from_tid(tid);
00315 unsigned long flags;
00316
00317 ieee80211_stop_queue_agg(local, tid);
00318
00319 if (WARN(!tid_tx, "TID %d gone but expected when splicing aggregates"
00320 " from the pending queue\n", tid))
00321 return;
00322
00323 if (!skb_queue_empty(&tid_tx->pending)) {
00324 spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
00325
00326 skb_queue_splice_tail_init(&tid_tx->pending,
00327 &local->pending[queue]);
00328 spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
00329 }
00330 }
00331
00332 static void __releases(agg_queue)
00333 ieee80211_agg_splice_finish(struct ieee80211_local *local, u16 tid)
00334 {
00335 ieee80211_wake_queue_agg(local, tid);
00336 }
00337
00338 void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid)
00339 {
00340 struct tid_ampdu_tx *tid_tx;
00341 struct ieee80211_local *local = sta->local;
00342 struct ieee80211_sub_if_data *sdata = sta->sdata;
00343 u16 start_seq_num;
00344 int ret;
00345
00346 tid_tx = rcu_dereference_protected_tid_tx(sta, tid);
00347
00348
00349
00350
00351
00352
00353 clear_bit(HT_AGG_STATE_WANT_START, &tid_tx->state);
00354
00355
00356
00357
00358
00359
00360
00361 synchronize_net();
00362
00363 start_seq_num = sta->tid_seq[tid] >> 4;
00364
00365 ret = drv_ampdu_action(local, sdata, IEEE80211_AMPDU_TX_START,
00366 &sta->sta, tid, &start_seq_num, 0);
00367 if (ret) {
00368 #ifdef CONFIG_MAC80211_HT_DEBUG
00369 printk(KERN_DEBUG "BA request denied - HW unavailable for"
00370 " tid %d\n", tid);
00371 #endif
00372 spin_lock_bh(&sta->lock);
00373 ieee80211_agg_splice_packets(local, tid_tx, tid);
00374 ieee80211_assign_tid_tx(sta, tid, NULL);
00375 ieee80211_agg_splice_finish(local, tid);
00376 spin_unlock_bh(&sta->lock);
00377
00378 kfree_rcu(tid_tx, rcu_head);
00379 return;
00380 }
00381
00382
00383 mod_timer(&tid_tx->addba_resp_timer, jiffies + ADDBA_RESP_INTERVAL);
00384 #ifdef CONFIG_MAC80211_HT_DEBUG
00385 printk(KERN_DEBUG "activated addBA response timer on tid %d\n", tid);
00386 #endif
00387
00388 spin_lock_bh(&sta->lock);
00389 sta->ampdu_mlme.addba_req_num[tid]++;
00390 spin_unlock_bh(&sta->lock);
00391
00392
00393 ieee80211_send_addba_request(sdata, sta->sta.addr, tid,
00394 tid_tx->dialog_token, start_seq_num,
00395 local->hw.max_tx_aggregation_subframes,
00396 tid_tx->timeout);
00397 }
00398
00399 int ieee80211_start_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid,
00400 u16 timeout)
00401 {
00402 struct sta_info *sta = container_of(pubsta, struct sta_info, sta);
00403 struct ieee80211_sub_if_data *sdata = sta->sdata;
00404 struct ieee80211_local *local = sdata->local;
00405 struct tid_ampdu_tx *tid_tx;
00406 int ret = 0;
00407
00408 trace_api_start_tx_ba_session(pubsta, tid);
00409
00410 if (WARN_ON(!local->ops->ampdu_action))
00411 return -EINVAL;
00412
00413 if ((tid >= STA_TID_NUM) ||
00414 !(local->hw.flags & IEEE80211_HW_AMPDU_AGGREGATION) ||
00415 (local->hw.flags & IEEE80211_HW_TX_AMPDU_SETUP_IN_HW))
00416 return -EINVAL;
00417
00418 #ifdef CONFIG_MAC80211_HT_DEBUG
00419 printk(KERN_DEBUG "Open BA session requested for %pM tid %u\n",
00420 pubsta->addr, tid);
00421 #endif
00422
00423
00424
00425
00426
00427
00428
00429 if (sdata->vif.type != NL80211_IFTYPE_STATION &&
00430 sdata->vif.type != NL80211_IFTYPE_AP_VLAN &&
00431 sdata->vif.type != NL80211_IFTYPE_AP)
00432 return -EINVAL;
00433
00434 if (test_sta_flag(sta, WLAN_STA_BLOCK_BA)) {
00435 #ifdef CONFIG_MAC80211_HT_DEBUG
00436 printk(KERN_DEBUG "BA sessions blocked. "
00437 "Denying BA session request\n");
00438 #endif
00439 return -EINVAL;
00440 }
00441
00442 spin_lock_bh(&sta->lock);
00443
00444
00445 if (sta->ampdu_mlme.addba_req_num[tid] > HT_AGG_MAX_RETRIES) {
00446 ret = -EBUSY;
00447 goto err_unlock_sta;
00448 }
00449
00450 tid_tx = rcu_dereference_protected_tid_tx(sta, tid);
00451
00452 if (tid_tx || sta->ampdu_mlme.tid_start_tx[tid]) {
00453 #ifdef CONFIG_MAC80211_HT_DEBUG
00454 printk(KERN_DEBUG "BA request denied - session is not "
00455 "idle on tid %u\n", tid);
00456 #endif
00457 ret = -EAGAIN;
00458 goto err_unlock_sta;
00459 }
00460
00461
00462 tid_tx = kzalloc(sizeof(struct tid_ampdu_tx), GFP_ATOMIC);
00463 if (!tid_tx) {
00464 ret = -ENOMEM;
00465 goto err_unlock_sta;
00466 }
00467
00468 skb_queue_head_init(&tid_tx->pending);
00469 __set_bit(HT_AGG_STATE_WANT_START, &tid_tx->state);
00470
00471 tid_tx->timeout = timeout;
00472
00473
00474 tid_tx->addba_resp_timer.function = sta_addba_resp_timer_expired;
00475 tid_tx->addba_resp_timer.data = (unsigned long)&sta->timer_to_tid[tid];
00476 init_timer(&tid_tx->addba_resp_timer);
00477
00478
00479 sta->ampdu_mlme.dialog_token_allocator++;
00480 tid_tx->dialog_token = sta->ampdu_mlme.dialog_token_allocator;
00481
00482
00483
00484
00485
00486 sta->ampdu_mlme.tid_start_tx[tid] = tid_tx;
00487
00488 ieee80211_queue_work(&local->hw, &sta->ampdu_mlme.work);
00489
00490
00491 err_unlock_sta:
00492 spin_unlock_bh(&sta->lock);
00493 return ret;
00494 }
00495 EXPORT_SYMBOL(ieee80211_start_tx_ba_session);
00496
00497 static void ieee80211_agg_tx_operational(struct ieee80211_local *local,
00498 struct sta_info *sta, u16 tid)
00499 {
00500 struct tid_ampdu_tx *tid_tx;
00501
00502 lockdep_assert_held(&sta->ampdu_mlme.mtx);
00503
00504 tid_tx = rcu_dereference_protected_tid_tx(sta, tid);
00505
00506 #ifdef CONFIG_MAC80211_HT_DEBUG
00507 printk(KERN_DEBUG "Aggregation is on for tid %d\n", tid);
00508 #endif
00509
00510 drv_ampdu_action(local, sta->sdata,
00511 IEEE80211_AMPDU_TX_OPERATIONAL,
00512 &sta->sta, tid, NULL, tid_tx->buf_size);
00513
00514
00515
00516
00517
00518 spin_lock_bh(&sta->lock);
00519
00520 ieee80211_agg_splice_packets(local, tid_tx, tid);
00521
00522
00523
00524
00525
00526 set_bit(HT_AGG_STATE_OPERATIONAL, &tid_tx->state);
00527 ieee80211_agg_splice_finish(local, tid);
00528
00529 spin_unlock_bh(&sta->lock);
00530 }
00531
00532 void ieee80211_start_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u16 tid)
00533 {
00534 struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
00535 struct ieee80211_local *local = sdata->local;
00536 struct sta_info *sta;
00537 struct tid_ampdu_tx *tid_tx;
00538
00539 trace_api_start_tx_ba_cb(sdata, ra, tid);
00540
00541 if (tid >= STA_TID_NUM) {
00542 #ifdef CONFIG_MAC80211_HT_DEBUG
00543 printk(KERN_DEBUG "Bad TID value: tid = %d (>= %d)\n",
00544 tid, STA_TID_NUM);
00545 #endif
00546 return;
00547 }
00548
00549 mutex_lock(&local->sta_mtx);
00550 sta = sta_info_get(sdata, ra);
00551 if (!sta) {
00552 mutex_unlock(&local->sta_mtx);
00553 #ifdef CONFIG_MAC80211_HT_DEBUG
00554 printk(KERN_DEBUG "Could not find station: %pM\n", ra);
00555 #endif
00556 return;
00557 }
00558
00559 mutex_lock(&sta->ampdu_mlme.mtx);
00560 tid_tx = rcu_dereference_protected_tid_tx(sta, tid);
00561
00562 if (WARN_ON(!tid_tx)) {
00563 #ifdef CONFIG_MAC80211_HT_DEBUG
00564 printk(KERN_DEBUG "addBA was not requested!\n");
00565 #endif
00566 goto unlock;
00567 }
00568
00569 if (WARN_ON(test_and_set_bit(HT_AGG_STATE_DRV_READY, &tid_tx->state)))
00570 goto unlock;
00571
00572 if (test_bit(HT_AGG_STATE_RESPONSE_RECEIVED, &tid_tx->state))
00573 ieee80211_agg_tx_operational(local, sta, tid);
00574
00575 unlock:
00576 mutex_unlock(&sta->ampdu_mlme.mtx);
00577 mutex_unlock(&local->sta_mtx);
00578 }
00579
00580 void ieee80211_start_tx_ba_cb_irqsafe(struct ieee80211_vif *vif,
00581 const u8 *ra, u16 tid)
00582 {
00583 struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
00584 struct ieee80211_local *local = sdata->local;
00585 struct ieee80211_ra_tid *ra_tid;
00586 struct sk_buff *skb = dev_alloc_skb(0);
00587
00588 if (unlikely(!skb))
00589 return;
00590
00591 ra_tid = (struct ieee80211_ra_tid *) &skb->cb;
00592 memcpy(&ra_tid->ra, ra, ETH_ALEN);
00593 ra_tid->tid = tid;
00594
00595 skb->pkt_type = IEEE80211_SDATA_QUEUE_AGG_START;
00596 skb_queue_tail(&sdata->skb_queue, skb);
00597 ieee80211_queue_work(&local->hw, &sdata->work);
00598 }
00599 EXPORT_SYMBOL(ieee80211_start_tx_ba_cb_irqsafe);
00600
00601 int __ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid,
00602 enum ieee80211_back_parties initiator,
00603 bool tx)
00604 {
00605 int ret;
00606
00607 mutex_lock(&sta->ampdu_mlme.mtx);
00608
00609 ret = ___ieee80211_stop_tx_ba_session(sta, tid, initiator, tx);
00610
00611 mutex_unlock(&sta->ampdu_mlme.mtx);
00612
00613 return ret;
00614 }
00615
00616 int ieee80211_stop_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid)
00617 {
00618 struct sta_info *sta = container_of(pubsta, struct sta_info, sta);
00619 struct ieee80211_sub_if_data *sdata = sta->sdata;
00620 struct ieee80211_local *local = sdata->local;
00621 struct tid_ampdu_tx *tid_tx;
00622 int ret = 0;
00623
00624 trace_api_stop_tx_ba_session(pubsta, tid);
00625
00626 if (!local->ops->ampdu_action)
00627 return -EINVAL;
00628
00629 if (tid >= STA_TID_NUM)
00630 return -EINVAL;
00631
00632 spin_lock_bh(&sta->lock);
00633 tid_tx = rcu_dereference_protected_tid_tx(sta, tid);
00634
00635 if (!tid_tx) {
00636 ret = -ENOENT;
00637 goto unlock;
00638 }
00639
00640 if (test_bit(HT_AGG_STATE_STOPPING, &tid_tx->state)) {
00641
00642 ret = 0;
00643 goto unlock;
00644 }
00645
00646 set_bit(HT_AGG_STATE_WANT_STOP, &tid_tx->state);
00647 ieee80211_queue_work(&local->hw, &sta->ampdu_mlme.work);
00648
00649 unlock:
00650 spin_unlock_bh(&sta->lock);
00651 return ret;
00652 }
00653 EXPORT_SYMBOL(ieee80211_stop_tx_ba_session);
00654
00655 void ieee80211_stop_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u8 tid)
00656 {
00657 struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
00658 struct ieee80211_local *local = sdata->local;
00659 struct sta_info *sta;
00660 struct tid_ampdu_tx *tid_tx;
00661
00662 trace_api_stop_tx_ba_cb(sdata, ra, tid);
00663
00664 if (tid >= STA_TID_NUM) {
00665 #ifdef CONFIG_MAC80211_HT_DEBUG
00666 printk(KERN_DEBUG "Bad TID value: tid = %d (>= %d)\n",
00667 tid, STA_TID_NUM);
00668 #endif
00669 return;
00670 }
00671
00672 #ifdef CONFIG_MAC80211_HT_DEBUG
00673 printk(KERN_DEBUG "Stopping Tx BA session for %pM tid %d\n",
00674 ra, tid);
00675 #endif
00676
00677 mutex_lock(&local->sta_mtx);
00678
00679 sta = sta_info_get(sdata, ra);
00680 if (!sta) {
00681 #ifdef CONFIG_MAC80211_HT_DEBUG
00682 printk(KERN_DEBUG "Could not find station: %pM\n", ra);
00683 #endif
00684 goto unlock;
00685 }
00686
00687 mutex_lock(&sta->ampdu_mlme.mtx);
00688 spin_lock_bh(&sta->lock);
00689 tid_tx = rcu_dereference_protected_tid_tx(sta, tid);
00690
00691 if (!tid_tx || !test_bit(HT_AGG_STATE_STOPPING, &tid_tx->state)) {
00692 #ifdef CONFIG_MAC80211_HT_DEBUG
00693 printk(KERN_DEBUG "unexpected callback to A-MPDU stop\n");
00694 #endif
00695 goto unlock_sta;
00696 }
00697
00698 if (tid_tx->stop_initiator == WLAN_BACK_INITIATOR && tid_tx->tx_stop)
00699 ieee80211_send_delba(sta->sdata, ra, tid,
00700 WLAN_BACK_INITIATOR, WLAN_REASON_QSTA_NOT_USE);
00701
00702
00703
00704
00705
00706
00707
00708
00709
00710
00711
00712 ieee80211_agg_splice_packets(local, tid_tx, tid);
00713
00714
00715 ieee80211_assign_tid_tx(sta, tid, NULL);
00716
00717 ieee80211_agg_splice_finish(local, tid);
00718
00719 kfree_rcu(tid_tx, rcu_head);
00720
00721 unlock_sta:
00722 spin_unlock_bh(&sta->lock);
00723 mutex_unlock(&sta->ampdu_mlme.mtx);
00724 unlock:
00725 mutex_unlock(&local->sta_mtx);
00726 }
00727
00728 void ieee80211_stop_tx_ba_cb_irqsafe(struct ieee80211_vif *vif,
00729 const u8 *ra, u16 tid)
00730 {
00731 struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
00732 struct ieee80211_local *local = sdata->local;
00733 struct ieee80211_ra_tid *ra_tid;
00734 struct sk_buff *skb = dev_alloc_skb(0);
00735
00736 if (unlikely(!skb))
00737 return;
00738
00739 ra_tid = (struct ieee80211_ra_tid *) &skb->cb;
00740 memcpy(&ra_tid->ra, ra, ETH_ALEN);
00741 ra_tid->tid = tid;
00742
00743 skb->pkt_type = IEEE80211_SDATA_QUEUE_AGG_STOP;
00744 skb_queue_tail(&sdata->skb_queue, skb);
00745 ieee80211_queue_work(&local->hw, &sdata->work);
00746 }
00747 EXPORT_SYMBOL(ieee80211_stop_tx_ba_cb_irqsafe);
00748
00749
00750 void ieee80211_process_addba_resp(struct ieee80211_local *local,
00751 struct sta_info *sta,
00752 struct ieee80211_mgmt *mgmt,
00753 size_t len)
00754 {
00755 struct tid_ampdu_tx *tid_tx;
00756 u16 capab, tid;
00757 u8 buf_size;
00758
00759 capab = le16_to_cpu(mgmt->u.action.u.addba_resp.capab);
00760 tid = (capab & IEEE80211_ADDBA_PARAM_TID_MASK) >> 2;
00761 buf_size = (capab & IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK) >> 6;
00762
00763 mutex_lock(&sta->ampdu_mlme.mtx);
00764
00765 tid_tx = rcu_dereference_protected_tid_tx(sta, tid);
00766 if (!tid_tx)
00767 goto out;
00768
00769 if (mgmt->u.action.u.addba_resp.dialog_token != tid_tx->dialog_token) {
00770 #ifdef CONFIG_MAC80211_HT_DEBUG
00771 printk(KERN_DEBUG "wrong addBA response token, tid %d\n", tid);
00772 #endif
00773 goto out;
00774 }
00775
00776 del_timer_sync(&tid_tx->addba_resp_timer);
00777
00778 #ifdef CONFIG_MAC80211_HT_DEBUG
00779 printk(KERN_DEBUG "switched off addBA timer for tid %d\n", tid);
00780 #endif
00781
00782
00783
00784
00785
00786
00787 if (test_bit(HT_AGG_STATE_WANT_STOP, &tid_tx->state) ||
00788 test_bit(HT_AGG_STATE_STOPPING, &tid_tx->state)) {
00789 #ifdef CONFIG_MAC80211_HT_DEBUG
00790 printk(KERN_DEBUG
00791 "got addBA resp for tid %d but we already gave up\n",
00792 tid);
00793 #endif
00794 goto out;
00795 }
00796
00797
00798
00799
00800
00801
00802
00803 if (le16_to_cpu(mgmt->u.action.u.addba_resp.status)
00804 == WLAN_STATUS_SUCCESS && buf_size) {
00805 if (test_and_set_bit(HT_AGG_STATE_RESPONSE_RECEIVED,
00806 &tid_tx->state)) {
00807
00808 goto out;
00809 }
00810
00811 tid_tx->buf_size = buf_size;
00812
00813 if (test_bit(HT_AGG_STATE_DRV_READY, &tid_tx->state))
00814 ieee80211_agg_tx_operational(local, sta, tid);
00815
00816 sta->ampdu_mlme.addba_req_num[tid] = 0;
00817 } else {
00818 ___ieee80211_stop_tx_ba_session(sta, tid, WLAN_BACK_INITIATOR,
00819 true);
00820 }
00821
00822 out:
00823 mutex_unlock(&sta->ampdu_mlme.mtx);
00824 }