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