1
2
3
4
5
6
7
8
9
10
11
12
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
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61static 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 struct ieee80211_local *local = sdata->local;
67 struct sk_buff *skb;
68 struct ieee80211_mgmt *mgmt;
69 u16 capab;
70
71 skb = dev_alloc_skb(sizeof(*mgmt) + local->hw.extra_tx_headroom);
72
73 if (!skb)
74 return;
75
76 skb_reserve(skb, local->hw.extra_tx_headroom);
77 mgmt = skb_put_zero(skb, 24);
78 memcpy(mgmt->da, da, ETH_ALEN);
79 memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN);
80 if (sdata->vif.type == NL80211_IFTYPE_AP ||
81 sdata->vif.type == NL80211_IFTYPE_AP_VLAN ||
82 sdata->vif.type == NL80211_IFTYPE_MESH_POINT)
83 memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN);
84 else if (sdata->vif.type == NL80211_IFTYPE_STATION)
85 memcpy(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN);
86 else if (sdata->vif.type == NL80211_IFTYPE_ADHOC)
87 memcpy(mgmt->bssid, sdata->u.ibss.bssid, ETH_ALEN);
88
89 mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
90 IEEE80211_STYPE_ACTION);
91
92 skb_put(skb, 1 + sizeof(mgmt->u.action.u.addba_req));
93
94 mgmt->u.action.category = WLAN_CATEGORY_BACK;
95 mgmt->u.action.u.addba_req.action_code = WLAN_ACTION_ADDBA_REQ;
96
97 mgmt->u.action.u.addba_req.dialog_token = dialog_token;
98 capab = IEEE80211_ADDBA_PARAM_AMSDU_MASK;
99 capab |= IEEE80211_ADDBA_PARAM_POLICY_MASK;
100 capab |= u16_encode_bits(tid, IEEE80211_ADDBA_PARAM_TID_MASK);
101 capab |= u16_encode_bits(agg_size, IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK);
102
103 mgmt->u.action.u.addba_req.capab = cpu_to_le16(capab);
104
105 mgmt->u.action.u.addba_req.timeout = cpu_to_le16(timeout);
106 mgmt->u.action.u.addba_req.start_seq_num =
107 cpu_to_le16(start_seq_num << 4);
108
109 ieee80211_tx_skb(sdata, skb);
110}
111
112void ieee80211_send_bar(struct ieee80211_vif *vif, u8 *ra, u16 tid, u16 ssn)
113{
114 struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
115 struct ieee80211_local *local = sdata->local;
116 struct sk_buff *skb;
117 struct ieee80211_bar *bar;
118 u16 bar_control = 0;
119
120 skb = dev_alloc_skb(sizeof(*bar) + local->hw.extra_tx_headroom);
121 if (!skb)
122 return;
123
124 skb_reserve(skb, local->hw.extra_tx_headroom);
125 bar = skb_put_zero(skb, sizeof(*bar));
126 bar->frame_control = cpu_to_le16(IEEE80211_FTYPE_CTL |
127 IEEE80211_STYPE_BACK_REQ);
128 memcpy(bar->ra, ra, ETH_ALEN);
129 memcpy(bar->ta, sdata->vif.addr, ETH_ALEN);
130 bar_control |= (u16)IEEE80211_BAR_CTRL_ACK_POLICY_NORMAL;
131 bar_control |= (u16)IEEE80211_BAR_CTRL_CBMTID_COMPRESSED_BA;
132 bar_control |= (u16)(tid << IEEE80211_BAR_CTRL_TID_INFO_SHIFT);
133 bar->control = cpu_to_le16(bar_control);
134 bar->start_seq_num = cpu_to_le16(ssn);
135
136 IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT |
137 IEEE80211_TX_CTL_REQ_TX_STATUS;
138 ieee80211_tx_skb_tid(sdata, skb, tid);
139}
140EXPORT_SYMBOL(ieee80211_send_bar);
141
142void ieee80211_assign_tid_tx(struct sta_info *sta, int tid,
143 struct tid_ampdu_tx *tid_tx)
144{
145 lockdep_assert_held(&sta->ampdu_mlme.mtx);
146 lockdep_assert_held(&sta->lock);
147 rcu_assign_pointer(sta->ampdu_mlme.tid_tx[tid], tid_tx);
148}
149
150
151
152
153
154
155
156
157
158
159
160
161static void __acquires(agg_queue)
162ieee80211_stop_queue_agg(struct ieee80211_sub_if_data *sdata, int tid)
163{
164 int queue = sdata->vif.hw_queue[ieee80211_ac_from_tid(tid)];
165
166
167
168 if (atomic_inc_return(&sdata->local->agg_queue_stop[queue]) == 1)
169 ieee80211_stop_queue_by_reason(
170 &sdata->local->hw, queue,
171 IEEE80211_QUEUE_STOP_REASON_AGGREGATION,
172 false);
173 __acquire(agg_queue);
174}
175
176static void __releases(agg_queue)
177ieee80211_wake_queue_agg(struct ieee80211_sub_if_data *sdata, int tid)
178{
179 int queue = sdata->vif.hw_queue[ieee80211_ac_from_tid(tid)];
180
181 if (atomic_dec_return(&sdata->local->agg_queue_stop[queue]) == 0)
182 ieee80211_wake_queue_by_reason(
183 &sdata->local->hw, queue,
184 IEEE80211_QUEUE_STOP_REASON_AGGREGATION,
185 false);
186 __release(agg_queue);
187}
188
189static void
190ieee80211_agg_stop_txq(struct sta_info *sta, int tid)
191{
192 struct ieee80211_txq *txq = sta->sta.txq[tid];
193 struct ieee80211_sub_if_data *sdata;
194 struct fq *fq;
195 struct txq_info *txqi;
196
197 if (!txq)
198 return;
199
200 txqi = to_txq_info(txq);
201 sdata = vif_to_sdata(txq->vif);
202 fq = &sdata->local->fq;
203
204
205 spin_lock_bh(&fq->lock);
206 set_bit(IEEE80211_TXQ_STOP, &txqi->flags);
207 spin_unlock_bh(&fq->lock);
208}
209
210static void
211ieee80211_agg_start_txq(struct sta_info *sta, int tid, bool enable)
212{
213 struct ieee80211_txq *txq = sta->sta.txq[tid];
214 struct txq_info *txqi;
215
216 if (!txq)
217 return;
218
219 txqi = to_txq_info(txq);
220
221 if (enable)
222 set_bit(IEEE80211_TXQ_AMPDU, &txqi->flags);
223 else
224 clear_bit(IEEE80211_TXQ_AMPDU, &txqi->flags);
225
226 clear_bit(IEEE80211_TXQ_STOP, &txqi->flags);
227 local_bh_disable();
228 rcu_read_lock();
229 schedule_and_wake_txq(sta->sdata->local, txqi);
230 rcu_read_unlock();
231 local_bh_enable();
232}
233
234
235
236
237
238static void __acquires(agg_queue)
239ieee80211_agg_splice_packets(struct ieee80211_sub_if_data *sdata,
240 struct tid_ampdu_tx *tid_tx, u16 tid)
241{
242 struct ieee80211_local *local = sdata->local;
243 int queue = sdata->vif.hw_queue[ieee80211_ac_from_tid(tid)];
244 unsigned long flags;
245
246 ieee80211_stop_queue_agg(sdata, tid);
247
248 if (WARN(!tid_tx,
249 "TID %d gone but expected when splicing aggregates from the pending queue\n",
250 tid))
251 return;
252
253 if (!skb_queue_empty(&tid_tx->pending)) {
254 spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
255
256 skb_queue_splice_tail_init(&tid_tx->pending,
257 &local->pending[queue]);
258 spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
259 }
260}
261
262static void __releases(agg_queue)
263ieee80211_agg_splice_finish(struct ieee80211_sub_if_data *sdata, u16 tid)
264{
265 ieee80211_wake_queue_agg(sdata, tid);
266}
267
268static void ieee80211_remove_tid_tx(struct sta_info *sta, int tid)
269{
270 struct tid_ampdu_tx *tid_tx;
271
272 lockdep_assert_held(&sta->ampdu_mlme.mtx);
273 lockdep_assert_held(&sta->lock);
274
275 tid_tx = rcu_dereference_protected_tid_tx(sta, tid);
276
277
278
279
280
281
282
283
284
285
286
287 ieee80211_agg_splice_packets(sta->sdata, tid_tx, tid);
288
289
290 ieee80211_assign_tid_tx(sta, tid, NULL);
291
292 ieee80211_agg_splice_finish(sta->sdata, tid);
293 ieee80211_agg_start_txq(sta, tid, false);
294
295 kfree_rcu(tid_tx, rcu_head);
296}
297
298int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid,
299 enum ieee80211_agg_stop_reason reason)
300{
301 struct ieee80211_local *local = sta->local;
302 struct tid_ampdu_tx *tid_tx;
303 struct ieee80211_ampdu_params params = {
304 .sta = &sta->sta,
305 .tid = tid,
306 .buf_size = 0,
307 .amsdu = false,
308 .timeout = 0,
309 .ssn = 0,
310 };
311 int ret;
312
313 lockdep_assert_held(&sta->ampdu_mlme.mtx);
314
315 switch (reason) {
316 case AGG_STOP_DECLINED:
317 case AGG_STOP_LOCAL_REQUEST:
318 case AGG_STOP_PEER_REQUEST:
319 params.action = IEEE80211_AMPDU_TX_STOP_CONT;
320 break;
321 case AGG_STOP_DESTROY_STA:
322 params.action = IEEE80211_AMPDU_TX_STOP_FLUSH;
323 break;
324 default:
325 WARN_ON_ONCE(1);
326 return -EINVAL;
327 }
328
329 spin_lock_bh(&sta->lock);
330
331
332 tid_tx = sta->ampdu_mlme.tid_start_tx[tid];
333 kfree(tid_tx);
334 sta->ampdu_mlme.tid_start_tx[tid] = NULL;
335
336 tid_tx = rcu_dereference_protected_tid_tx(sta, tid);
337 if (!tid_tx) {
338 spin_unlock_bh(&sta->lock);
339 return -ENOENT;
340 }
341
342
343
344
345
346 if (test_bit(HT_AGG_STATE_STOPPING, &tid_tx->state)) {
347 spin_unlock_bh(&sta->lock);
348 if (reason != AGG_STOP_DESTROY_STA)
349 return -EALREADY;
350 params.action = IEEE80211_AMPDU_TX_STOP_FLUSH_CONT;
351 ret = drv_ampdu_action(local, sta->sdata, ¶ms);
352 WARN_ON_ONCE(ret);
353 return 0;
354 }
355
356 if (test_bit(HT_AGG_STATE_WANT_START, &tid_tx->state)) {
357
358 ieee80211_assign_tid_tx(sta, tid, NULL);
359 spin_unlock_bh(&sta->lock);
360 kfree_rcu(tid_tx, rcu_head);
361 return 0;
362 }
363
364 set_bit(HT_AGG_STATE_STOPPING, &tid_tx->state);
365
366 ieee80211_agg_stop_txq(sta, tid);
367
368 spin_unlock_bh(&sta->lock);
369
370 ht_dbg(sta->sdata, "Tx BA session stop requested for %pM tid %u\n",
371 sta->sta.addr, tid);
372
373 del_timer_sync(&tid_tx->addba_resp_timer);
374 del_timer_sync(&tid_tx->session_timer);
375
376
377
378
379
380
381 clear_bit(HT_AGG_STATE_OPERATIONAL, &tid_tx->state);
382
383
384
385
386
387
388
389
390
391
392
393
394
395 if (!local->in_reconfig)
396 synchronize_net();
397
398 tid_tx->stop_initiator = reason == AGG_STOP_PEER_REQUEST ?
399 WLAN_BACK_RECIPIENT :
400 WLAN_BACK_INITIATOR;
401 tid_tx->tx_stop = reason == AGG_STOP_LOCAL_REQUEST;
402
403 ret = drv_ampdu_action(local, sta->sdata, ¶ms);
404
405
406 if (WARN_ON(ret)) {
407
408
409
410
411 }
412
413
414
415
416
417
418
419
420
421
422
423 return 0;
424}
425
426
427
428
429
430
431static void sta_addba_resp_timer_expired(struct timer_list *t)
432{
433 struct tid_ampdu_tx *tid_tx = from_timer(tid_tx, t, addba_resp_timer);
434 struct sta_info *sta = tid_tx->sta;
435 u8 tid = tid_tx->tid;
436
437
438 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 ht_dbg(sta->sdata, "addBA response timer expired on %pM tid %d\n",
446 sta->sta.addr, tid);
447
448 ieee80211_stop_tx_ba_session(&sta->sta, tid);
449}
450
451static void ieee80211_send_addba_with_timeout(struct sta_info *sta,
452 struct tid_ampdu_tx *tid_tx)
453{
454 struct ieee80211_sub_if_data *sdata = sta->sdata;
455 struct ieee80211_local *local = sta->local;
456 u8 tid = tid_tx->tid;
457 u16 buf_size;
458
459
460 mod_timer(&tid_tx->addba_resp_timer, jiffies + ADDBA_RESP_INTERVAL);
461 ht_dbg(sdata, "activated addBA response timer on %pM tid %d\n",
462 sta->sta.addr, tid);
463
464 spin_lock_bh(&sta->lock);
465 sta->ampdu_mlme.last_addba_req_time[tid] = jiffies;
466 sta->ampdu_mlme.addba_req_num[tid]++;
467 spin_unlock_bh(&sta->lock);
468
469 if (sta->sta.he_cap.has_he) {
470 buf_size = local->hw.max_tx_aggregation_subframes;
471 } else {
472
473
474
475
476
477
478 buf_size = IEEE80211_MAX_AMPDU_BUF_HT;
479 }
480
481
482 ieee80211_send_addba_request(sdata, sta->sta.addr, tid,
483 tid_tx->dialog_token,
484 sta->tid_seq[tid] >> 4,
485 buf_size, tid_tx->timeout);
486
487 WARN_ON(test_and_set_bit(HT_AGG_STATE_SENT_ADDBA, &tid_tx->state));
488}
489
490void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid)
491{
492 struct tid_ampdu_tx *tid_tx;
493 struct ieee80211_local *local = sta->local;
494 struct ieee80211_sub_if_data *sdata = sta->sdata;
495 struct ieee80211_ampdu_params params = {
496 .sta = &sta->sta,
497 .action = IEEE80211_AMPDU_TX_START,
498 .tid = tid,
499 .buf_size = 0,
500 .amsdu = false,
501 .timeout = 0,
502 };
503 int ret;
504
505 tid_tx = rcu_dereference_protected_tid_tx(sta, tid);
506
507
508
509
510
511
512 clear_bit(HT_AGG_STATE_WANT_START, &tid_tx->state);
513
514 ieee80211_agg_stop_txq(sta, tid);
515
516
517
518
519
520
521
522 synchronize_net();
523
524 params.ssn = sta->tid_seq[tid] >> 4;
525 ret = drv_ampdu_action(local, sdata, ¶ms);
526 if (ret == IEEE80211_AMPDU_TX_START_DELAY_ADDBA) {
527 return;
528 } else if (ret == IEEE80211_AMPDU_TX_START_IMMEDIATE) {
529
530
531
532
533
534 set_bit(HT_AGG_STATE_DRV_READY, &tid_tx->state);
535 } else if (ret) {
536 ht_dbg(sdata,
537 "BA request denied - HW unavailable for %pM tid %d\n",
538 sta->sta.addr, tid);
539 spin_lock_bh(&sta->lock);
540 ieee80211_agg_splice_packets(sdata, tid_tx, tid);
541 ieee80211_assign_tid_tx(sta, tid, NULL);
542 ieee80211_agg_splice_finish(sdata, tid);
543 spin_unlock_bh(&sta->lock);
544
545 ieee80211_agg_start_txq(sta, tid, false);
546
547 kfree_rcu(tid_tx, rcu_head);
548 return;
549 }
550
551 ieee80211_send_addba_with_timeout(sta, tid_tx);
552}
553
554
555
556
557
558static void sta_tx_agg_session_timer_expired(struct timer_list *t)
559{
560 struct tid_ampdu_tx *tid_tx = from_timer(tid_tx, t, session_timer);
561 struct sta_info *sta = tid_tx->sta;
562 u8 tid = tid_tx->tid;
563 unsigned long timeout;
564
565 if (test_bit(HT_AGG_STATE_STOPPING, &tid_tx->state)) {
566 return;
567 }
568
569 timeout = tid_tx->last_tx + TU_TO_JIFFIES(tid_tx->timeout);
570 if (time_is_after_jiffies(timeout)) {
571 mod_timer(&tid_tx->session_timer, timeout);
572 return;
573 }
574
575 ht_dbg(sta->sdata, "tx session timer expired on %pM tid %d\n",
576 sta->sta.addr, tid);
577
578 ieee80211_stop_tx_ba_session(&sta->sta, tid);
579}
580
581int ieee80211_start_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid,
582 u16 timeout)
583{
584 struct sta_info *sta = container_of(pubsta, struct sta_info, sta);
585 struct ieee80211_sub_if_data *sdata = sta->sdata;
586 struct ieee80211_local *local = sdata->local;
587 struct tid_ampdu_tx *tid_tx;
588 int ret = 0;
589
590 trace_api_start_tx_ba_session(pubsta, tid);
591
592 if (WARN(sta->reserved_tid == tid,
593 "Requested to start BA session on reserved tid=%d", tid))
594 return -EINVAL;
595
596 if (!pubsta->ht_cap.ht_supported &&
597 sta->sdata->vif.bss_conf.chandef.chan->band != NL80211_BAND_6GHZ)
598 return -EINVAL;
599
600 if (WARN_ON_ONCE(!local->ops->ampdu_action))
601 return -EINVAL;
602
603 if ((tid >= IEEE80211_NUM_TIDS) ||
604 !ieee80211_hw_check(&local->hw, AMPDU_AGGREGATION) ||
605 ieee80211_hw_check(&local->hw, TX_AMPDU_SETUP_IN_HW))
606 return -EINVAL;
607
608 if (WARN_ON(tid >= IEEE80211_FIRST_TSPEC_TSID))
609 return -EINVAL;
610
611 ht_dbg(sdata, "Open BA session requested for %pM tid %u\n",
612 pubsta->addr, tid);
613
614 if (sdata->vif.type != NL80211_IFTYPE_STATION &&
615 sdata->vif.type != NL80211_IFTYPE_MESH_POINT &&
616 sdata->vif.type != NL80211_IFTYPE_AP_VLAN &&
617 sdata->vif.type != NL80211_IFTYPE_AP &&
618 sdata->vif.type != NL80211_IFTYPE_ADHOC)
619 return -EINVAL;
620
621 if (test_sta_flag(sta, WLAN_STA_BLOCK_BA)) {
622 ht_dbg(sdata,
623 "BA sessions blocked - Denying BA session request %pM tid %d\n",
624 sta->sta.addr, tid);
625 return -EINVAL;
626 }
627
628
629
630
631
632
633
634
635
636
637
638
639
640 if (sta->sdata->vif.type == NL80211_IFTYPE_ADHOC &&
641 !sta->sta.ht_cap.ht_supported) {
642 ht_dbg(sdata,
643 "BA request denied - IBSS STA %pM does not advertise HT support\n",
644 pubsta->addr);
645 return -EINVAL;
646 }
647
648 spin_lock_bh(&sta->lock);
649
650
651 if (sta->ampdu_mlme.addba_req_num[tid] > HT_AGG_MAX_RETRIES) {
652 ret = -EBUSY;
653 goto err_unlock_sta;
654 }
655
656
657
658
659
660
661 if (sta->ampdu_mlme.addba_req_num[tid] > HT_AGG_BURST_RETRIES &&
662 time_before(jiffies, sta->ampdu_mlme.last_addba_req_time[tid] +
663 HT_AGG_RETRIES_PERIOD)) {
664 ht_dbg(sdata,
665 "BA request denied - %d failed requests on %pM tid %u\n",
666 sta->ampdu_mlme.addba_req_num[tid], sta->sta.addr, tid);
667 ret = -EBUSY;
668 goto err_unlock_sta;
669 }
670
671 tid_tx = rcu_dereference_protected_tid_tx(sta, tid);
672
673 if (tid_tx || sta->ampdu_mlme.tid_start_tx[tid]) {
674 ht_dbg(sdata,
675 "BA request denied - session is not idle on %pM tid %u\n",
676 sta->sta.addr, tid);
677 ret = -EAGAIN;
678 goto err_unlock_sta;
679 }
680
681
682 tid_tx = kzalloc(sizeof(struct tid_ampdu_tx), GFP_ATOMIC);
683 if (!tid_tx) {
684 ret = -ENOMEM;
685 goto err_unlock_sta;
686 }
687
688 skb_queue_head_init(&tid_tx->pending);
689 __set_bit(HT_AGG_STATE_WANT_START, &tid_tx->state);
690
691 tid_tx->timeout = timeout;
692 tid_tx->sta = sta;
693 tid_tx->tid = tid;
694
695
696 timer_setup(&tid_tx->addba_resp_timer, sta_addba_resp_timer_expired, 0);
697
698
699 timer_setup(&tid_tx->session_timer,
700 sta_tx_agg_session_timer_expired, TIMER_DEFERRABLE);
701
702
703 sta->ampdu_mlme.dialog_token_allocator++;
704 tid_tx->dialog_token = sta->ampdu_mlme.dialog_token_allocator;
705
706
707
708
709
710 sta->ampdu_mlme.tid_start_tx[tid] = tid_tx;
711
712 ieee80211_queue_work(&local->hw, &sta->ampdu_mlme.work);
713
714
715 err_unlock_sta:
716 spin_unlock_bh(&sta->lock);
717 return ret;
718}
719EXPORT_SYMBOL(ieee80211_start_tx_ba_session);
720
721static void ieee80211_agg_tx_operational(struct ieee80211_local *local,
722 struct sta_info *sta, u16 tid)
723{
724 struct tid_ampdu_tx *tid_tx;
725 struct ieee80211_ampdu_params params = {
726 .sta = &sta->sta,
727 .action = IEEE80211_AMPDU_TX_OPERATIONAL,
728 .tid = tid,
729 .timeout = 0,
730 .ssn = 0,
731 };
732
733 lockdep_assert_held(&sta->ampdu_mlme.mtx);
734
735 tid_tx = rcu_dereference_protected_tid_tx(sta, tid);
736 params.buf_size = tid_tx->buf_size;
737 params.amsdu = tid_tx->amsdu;
738
739 ht_dbg(sta->sdata, "Aggregation is on for %pM tid %d\n",
740 sta->sta.addr, tid);
741
742 drv_ampdu_action(local, sta->sdata, ¶ms);
743
744
745
746
747
748 spin_lock_bh(&sta->lock);
749
750 ieee80211_agg_splice_packets(sta->sdata, tid_tx, tid);
751
752
753
754
755
756 set_bit(HT_AGG_STATE_OPERATIONAL, &tid_tx->state);
757 ieee80211_agg_splice_finish(sta->sdata, tid);
758
759 spin_unlock_bh(&sta->lock);
760
761 ieee80211_agg_start_txq(sta, tid, true);
762}
763
764void ieee80211_start_tx_ba_cb(struct sta_info *sta, int tid,
765 struct tid_ampdu_tx *tid_tx)
766{
767 struct ieee80211_sub_if_data *sdata = sta->sdata;
768 struct ieee80211_local *local = sdata->local;
769
770 if (WARN_ON(test_and_set_bit(HT_AGG_STATE_DRV_READY, &tid_tx->state)))
771 return;
772
773 if (!test_bit(HT_AGG_STATE_SENT_ADDBA, &tid_tx->state)) {
774 ieee80211_send_addba_with_timeout(sta, tid_tx);
775
776 return;
777 }
778
779 if (test_bit(HT_AGG_STATE_RESPONSE_RECEIVED, &tid_tx->state))
780 ieee80211_agg_tx_operational(local, sta, tid);
781}
782
783static struct tid_ampdu_tx *
784ieee80211_lookup_tid_tx(struct ieee80211_sub_if_data *sdata,
785 const u8 *ra, u16 tid, struct sta_info **sta)
786{
787 struct tid_ampdu_tx *tid_tx;
788
789 if (tid >= IEEE80211_NUM_TIDS) {
790 ht_dbg(sdata, "Bad TID value: tid = %d (>= %d)\n",
791 tid, IEEE80211_NUM_TIDS);
792 return NULL;
793 }
794
795 *sta = sta_info_get_bss(sdata, ra);
796 if (!*sta) {
797 ht_dbg(sdata, "Could not find station: %pM\n", ra);
798 return NULL;
799 }
800
801 tid_tx = rcu_dereference((*sta)->ampdu_mlme.tid_tx[tid]);
802
803 if (WARN_ON(!tid_tx))
804 ht_dbg(sdata, "addBA was not requested!\n");
805
806 return tid_tx;
807}
808
809void ieee80211_start_tx_ba_cb_irqsafe(struct ieee80211_vif *vif,
810 const u8 *ra, u16 tid)
811{
812 struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
813 struct ieee80211_local *local = sdata->local;
814 struct sta_info *sta;
815 struct tid_ampdu_tx *tid_tx;
816
817 trace_api_start_tx_ba_cb(sdata, ra, tid);
818
819 rcu_read_lock();
820 tid_tx = ieee80211_lookup_tid_tx(sdata, ra, tid, &sta);
821 if (!tid_tx)
822 goto out;
823
824 set_bit(HT_AGG_STATE_START_CB, &tid_tx->state);
825 ieee80211_queue_work(&local->hw, &sta->ampdu_mlme.work);
826 out:
827 rcu_read_unlock();
828}
829EXPORT_SYMBOL(ieee80211_start_tx_ba_cb_irqsafe);
830
831int __ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid,
832 enum ieee80211_agg_stop_reason reason)
833{
834 int ret;
835
836 mutex_lock(&sta->ampdu_mlme.mtx);
837
838 ret = ___ieee80211_stop_tx_ba_session(sta, tid, reason);
839
840 mutex_unlock(&sta->ampdu_mlme.mtx);
841
842 return ret;
843}
844
845int ieee80211_stop_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid)
846{
847 struct sta_info *sta = container_of(pubsta, struct sta_info, sta);
848 struct ieee80211_sub_if_data *sdata = sta->sdata;
849 struct ieee80211_local *local = sdata->local;
850 struct tid_ampdu_tx *tid_tx;
851 int ret = 0;
852
853 trace_api_stop_tx_ba_session(pubsta, tid);
854
855 if (!local->ops->ampdu_action)
856 return -EINVAL;
857
858 if (tid >= IEEE80211_NUM_TIDS)
859 return -EINVAL;
860
861 spin_lock_bh(&sta->lock);
862 tid_tx = rcu_dereference_protected_tid_tx(sta, tid);
863
864 if (!tid_tx) {
865 ret = -ENOENT;
866 goto unlock;
867 }
868
869 WARN(sta->reserved_tid == tid,
870 "Requested to stop BA session on reserved tid=%d", tid);
871
872 if (test_bit(HT_AGG_STATE_STOPPING, &tid_tx->state)) {
873
874 ret = 0;
875 goto unlock;
876 }
877
878 set_bit(HT_AGG_STATE_WANT_STOP, &tid_tx->state);
879 ieee80211_queue_work(&local->hw, &sta->ampdu_mlme.work);
880
881 unlock:
882 spin_unlock_bh(&sta->lock);
883 return ret;
884}
885EXPORT_SYMBOL(ieee80211_stop_tx_ba_session);
886
887void ieee80211_stop_tx_ba_cb(struct sta_info *sta, int tid,
888 struct tid_ampdu_tx *tid_tx)
889{
890 struct ieee80211_sub_if_data *sdata = sta->sdata;
891 bool send_delba = false;
892
893 ht_dbg(sdata, "Stopping Tx BA session for %pM tid %d\n",
894 sta->sta.addr, tid);
895
896 spin_lock_bh(&sta->lock);
897
898 if (!test_bit(HT_AGG_STATE_STOPPING, &tid_tx->state)) {
899 ht_dbg(sdata,
900 "unexpected callback to A-MPDU stop for %pM tid %d\n",
901 sta->sta.addr, tid);
902 goto unlock_sta;
903 }
904
905 if (tid_tx->stop_initiator == WLAN_BACK_INITIATOR && tid_tx->tx_stop)
906 send_delba = true;
907
908 ieee80211_remove_tid_tx(sta, tid);
909
910 unlock_sta:
911 spin_unlock_bh(&sta->lock);
912
913 if (send_delba)
914 ieee80211_send_delba(sdata, sta->sta.addr, tid,
915 WLAN_BACK_INITIATOR, WLAN_REASON_QSTA_NOT_USE);
916}
917
918void ieee80211_stop_tx_ba_cb_irqsafe(struct ieee80211_vif *vif,
919 const u8 *ra, u16 tid)
920{
921 struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
922 struct ieee80211_local *local = sdata->local;
923 struct sta_info *sta;
924 struct tid_ampdu_tx *tid_tx;
925
926 trace_api_stop_tx_ba_cb(sdata, ra, tid);
927
928 rcu_read_lock();
929 tid_tx = ieee80211_lookup_tid_tx(sdata, ra, tid, &sta);
930 if (!tid_tx)
931 goto out;
932
933 set_bit(HT_AGG_STATE_STOP_CB, &tid_tx->state);
934 ieee80211_queue_work(&local->hw, &sta->ampdu_mlme.work);
935 out:
936 rcu_read_unlock();
937}
938EXPORT_SYMBOL(ieee80211_stop_tx_ba_cb_irqsafe);
939
940
941void ieee80211_process_addba_resp(struct ieee80211_local *local,
942 struct sta_info *sta,
943 struct ieee80211_mgmt *mgmt,
944 size_t len)
945{
946 struct tid_ampdu_tx *tid_tx;
947 struct ieee80211_txq *txq;
948 u16 capab, tid, buf_size;
949 bool amsdu;
950
951 capab = le16_to_cpu(mgmt->u.action.u.addba_resp.capab);
952 amsdu = capab & IEEE80211_ADDBA_PARAM_AMSDU_MASK;
953 tid = u16_get_bits(capab, IEEE80211_ADDBA_PARAM_TID_MASK);
954 buf_size = u16_get_bits(capab, IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK);
955 buf_size = min(buf_size, local->hw.max_tx_aggregation_subframes);
956
957 txq = sta->sta.txq[tid];
958 if (!amsdu && txq)
959 set_bit(IEEE80211_TXQ_NO_AMSDU, &to_txq_info(txq)->flags);
960
961 mutex_lock(&sta->ampdu_mlme.mtx);
962
963 tid_tx = rcu_dereference_protected_tid_tx(sta, tid);
964 if (!tid_tx)
965 goto out;
966
967 if (mgmt->u.action.u.addba_resp.dialog_token != tid_tx->dialog_token) {
968 ht_dbg(sta->sdata, "wrong addBA response token, %pM tid %d\n",
969 sta->sta.addr, tid);
970 goto out;
971 }
972
973 del_timer_sync(&tid_tx->addba_resp_timer);
974
975 ht_dbg(sta->sdata, "switched off addBA timer for %pM tid %d\n",
976 sta->sta.addr, tid);
977
978
979
980
981
982
983 if (test_bit(HT_AGG_STATE_WANT_STOP, &tid_tx->state) ||
984 test_bit(HT_AGG_STATE_STOPPING, &tid_tx->state)) {
985 ht_dbg(sta->sdata,
986 "got addBA resp for %pM tid %d but we already gave up\n",
987 sta->sta.addr, tid);
988 goto out;
989 }
990
991
992
993
994
995
996
997 if (le16_to_cpu(mgmt->u.action.u.addba_resp.status)
998 == WLAN_STATUS_SUCCESS && buf_size) {
999 if (test_and_set_bit(HT_AGG_STATE_RESPONSE_RECEIVED,
1000 &tid_tx->state)) {
1001
1002 goto out;
1003 }
1004
1005 tid_tx->buf_size = buf_size;
1006 tid_tx->amsdu = amsdu;
1007
1008 if (test_bit(HT_AGG_STATE_DRV_READY, &tid_tx->state))
1009 ieee80211_agg_tx_operational(local, sta, tid);
1010
1011 sta->ampdu_mlme.addba_req_num[tid] = 0;
1012
1013 tid_tx->timeout =
1014 le16_to_cpu(mgmt->u.action.u.addba_resp.timeout);
1015
1016 if (tid_tx->timeout) {
1017 mod_timer(&tid_tx->session_timer,
1018 TU_TO_EXP_TIME(tid_tx->timeout));
1019 tid_tx->last_tx = jiffies;
1020 }
1021
1022 } else {
1023 ___ieee80211_stop_tx_ba_session(sta, tid, AGG_STOP_DECLINED);
1024 }
1025
1026 out:
1027 mutex_unlock(&sta->ampdu_mlme.mtx);
1028}
1029