aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorJohannes Berg <johannes@sipsolutions.net>2008-09-08 11:44:29 -0400
committerJohn W. Linville <linville@tuxdriver.com>2008-09-11 15:53:37 -0400
commitbacac545f10f2bf6e5ceff0d8e2b82dfc493602a (patch)
tree16c590d0c71e5368e75e7a108fa4df0fa196767f /net
parent44d414dbff9d5bf46fc09f2e68567b5848cbbfd3 (diff)
mac80211: move some HT code out of main.c
Now that I've created ht.c, I can move the aggregation code from main.c into it. Signed-off-by: Johannes Berg <johannes@sipsolutions.net> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net')
-rw-r--r--net/mac80211/ht.c377
-rw-r--r--net/mac80211/main.c373
2 files changed, 375 insertions, 375 deletions
diff --git a/net/mac80211/ht.c b/net/mac80211/ht.c
index 5ccf1bc17466..c72b3fe3ccdb 100644
--- a/net/mac80211/ht.c
+++ b/net/mac80211/ht.c
@@ -2,8 +2,8 @@
2 * HT handling 2 * HT handling
3 * 3 *
4 * Copyright 2003, Jouni Malinen <jkmaline@cc.hut.fi> 4 * Copyright 2003, Jouni Malinen <jkmaline@cc.hut.fi>
5 * Copyright 2004, Instant802 Networks, Inc. 5 * Copyright 2002-2005, Instant802 Networks, Inc.
6 * Copyright 2005, Devicescape Software, Inc. 6 * Copyright 2005-2006, Devicescape Software, Inc.
7 * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz> 7 * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz>
8 * Copyright 2007, Michael Wu <flamingice@sourmilk.net> 8 * Copyright 2007, Michael Wu <flamingice@sourmilk.net>
9 * Copyright 2007-2008, Intel Corporation 9 * Copyright 2007-2008, Intel Corporation
@@ -18,6 +18,7 @@
18#include <net/mac80211.h> 18#include <net/mac80211.h>
19#include "ieee80211_i.h" 19#include "ieee80211_i.h"
20#include "sta_info.h" 20#include "sta_info.h"
21#include "wme.h"
21 22
22int ieee80211_ht_cap_ie_to_ht_info(struct ieee80211_ht_cap *ht_cap_ie, 23int ieee80211_ht_cap_ie_to_ht_info(struct ieee80211_ht_cap *ht_cap_ie,
23 struct ieee80211_ht_info *ht_info) 24 struct ieee80211_ht_info *ht_info)
@@ -326,3 +327,375 @@ void ieee80211_sta_tear_down_BA_sessions(struct ieee80211_sub_if_data *sdata, u8
326 } 327 }
327} 328}
328 329
330int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid)
331{
332 struct ieee80211_local *local = hw_to_local(hw);
333 struct sta_info *sta;
334 struct ieee80211_sub_if_data *sdata;
335 u16 start_seq_num;
336 u8 *state;
337 int ret;
338 DECLARE_MAC_BUF(mac);
339
340 if (tid >= STA_TID_NUM)
341 return -EINVAL;
342
343#ifdef CONFIG_MAC80211_HT_DEBUG
344 printk(KERN_DEBUG "Open BA session requested for %s tid %u\n",
345 print_mac(mac, ra), tid);
346#endif /* CONFIG_MAC80211_HT_DEBUG */
347
348 rcu_read_lock();
349
350 sta = sta_info_get(local, ra);
351 if (!sta) {
352#ifdef CONFIG_MAC80211_HT_DEBUG
353 printk(KERN_DEBUG "Could not find the station\n");
354#endif
355 ret = -ENOENT;
356 goto exit;
357 }
358
359 spin_lock_bh(&sta->lock);
360
361 /* we have tried too many times, receiver does not want A-MPDU */
362 if (sta->ampdu_mlme.addba_req_num[tid] > HT_AGG_MAX_RETRIES) {
363 ret = -EBUSY;
364 goto err_unlock_sta;
365 }
366
367 state = &sta->ampdu_mlme.tid_state_tx[tid];
368 /* check if the TID is not in aggregation flow already */
369 if (*state != HT_AGG_STATE_IDLE) {
370#ifdef CONFIG_MAC80211_HT_DEBUG
371 printk(KERN_DEBUG "BA request denied - session is not "
372 "idle on tid %u\n", tid);
373#endif /* CONFIG_MAC80211_HT_DEBUG */
374 ret = -EAGAIN;
375 goto err_unlock_sta;
376 }
377
378 /* prepare A-MPDU MLME for Tx aggregation */
379 sta->ampdu_mlme.tid_tx[tid] =
380 kmalloc(sizeof(struct tid_ampdu_tx), GFP_ATOMIC);
381 if (!sta->ampdu_mlme.tid_tx[tid]) {
382#ifdef CONFIG_MAC80211_HT_DEBUG
383 if (net_ratelimit())
384 printk(KERN_ERR "allocate tx mlme to tid %d failed\n",
385 tid);
386#endif
387 ret = -ENOMEM;
388 goto err_unlock_sta;
389 }
390 /* Tx timer */
391 sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer.function =
392 sta_addba_resp_timer_expired;
393 sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer.data =
394 (unsigned long)&sta->timer_to_tid[tid];
395 init_timer(&sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer);
396
397 /* create a new queue for this aggregation */
398 ret = ieee80211_ht_agg_queue_add(local, sta, tid);
399
400 /* case no queue is available to aggregation
401 * don't switch to aggregation */
402 if (ret) {
403#ifdef CONFIG_MAC80211_HT_DEBUG
404 printk(KERN_DEBUG "BA request denied - queue unavailable for"
405 " tid %d\n", tid);
406#endif /* CONFIG_MAC80211_HT_DEBUG */
407 goto err_unlock_queue;
408 }
409 sdata = sta->sdata;
410
411 /* Ok, the Addba frame hasn't been sent yet, but if the driver calls the
412 * call back right away, it must see that the flow has begun */
413 *state |= HT_ADDBA_REQUESTED_MSK;
414
415 /* This is slightly racy because the queue isn't stopped */
416 start_seq_num = sta->tid_seq[tid];
417
418 if (local->ops->ampdu_action)
419 ret = local->ops->ampdu_action(hw, IEEE80211_AMPDU_TX_START,
420 ra, tid, &start_seq_num);
421
422 if (ret) {
423 /* No need to requeue the packets in the agg queue, since we
424 * held the tx lock: no packet could be enqueued to the newly
425 * allocated queue */
426 ieee80211_ht_agg_queue_remove(local, sta, tid, 0);
427#ifdef CONFIG_MAC80211_HT_DEBUG
428 printk(KERN_DEBUG "BA request denied - HW unavailable for"
429 " tid %d\n", tid);
430#endif /* CONFIG_MAC80211_HT_DEBUG */
431 *state = HT_AGG_STATE_IDLE;
432 goto err_unlock_queue;
433 }
434
435 /* Will put all the packets in the new SW queue */
436 ieee80211_requeue(local, ieee802_1d_to_ac[tid]);
437 spin_unlock_bh(&sta->lock);
438
439 /* send an addBA request */
440 sta->ampdu_mlme.dialog_token_allocator++;
441 sta->ampdu_mlme.tid_tx[tid]->dialog_token =
442 sta->ampdu_mlme.dialog_token_allocator;
443 sta->ampdu_mlme.tid_tx[tid]->ssn = start_seq_num;
444
445
446 ieee80211_send_addba_request(sta->sdata, ra, tid,
447 sta->ampdu_mlme.tid_tx[tid]->dialog_token,
448 sta->ampdu_mlme.tid_tx[tid]->ssn,
449 0x40, 5000);
450 /* activate the timer for the recipient's addBA response */
451 sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer.expires =
452 jiffies + ADDBA_RESP_INTERVAL;
453 add_timer(&sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer);
454#ifdef CONFIG_MAC80211_HT_DEBUG
455 printk(KERN_DEBUG "activated addBA response timer on tid %d\n", tid);
456#endif
457 goto exit;
458
459err_unlock_queue:
460 kfree(sta->ampdu_mlme.tid_tx[tid]);
461 sta->ampdu_mlme.tid_tx[tid] = NULL;
462 ret = -EBUSY;
463err_unlock_sta:
464 spin_unlock_bh(&sta->lock);
465exit:
466 rcu_read_unlock();
467 return ret;
468}
469EXPORT_SYMBOL(ieee80211_start_tx_ba_session);
470
471int ieee80211_stop_tx_ba_session(struct ieee80211_hw *hw,
472 u8 *ra, u16 tid,
473 enum ieee80211_back_parties initiator)
474{
475 struct ieee80211_local *local = hw_to_local(hw);
476 struct sta_info *sta;
477 u8 *state;
478 int ret = 0;
479 DECLARE_MAC_BUF(mac);
480
481 if (tid >= STA_TID_NUM)
482 return -EINVAL;
483
484 rcu_read_lock();
485 sta = sta_info_get(local, ra);
486 if (!sta) {
487 rcu_read_unlock();
488 return -ENOENT;
489 }
490
491 /* check if the TID is in aggregation */
492 state = &sta->ampdu_mlme.tid_state_tx[tid];
493 spin_lock_bh(&sta->lock);
494
495 if (*state != HT_AGG_STATE_OPERATIONAL) {
496 ret = -ENOENT;
497 goto stop_BA_exit;
498 }
499
500#ifdef CONFIG_MAC80211_HT_DEBUG
501 printk(KERN_DEBUG "Tx BA session stop requested for %s tid %u\n",
502 print_mac(mac, ra), tid);
503#endif /* CONFIG_MAC80211_HT_DEBUG */
504
505 ieee80211_stop_queue(hw, sta->tid_to_tx_q[tid]);
506
507 *state = HT_AGG_STATE_REQ_STOP_BA_MSK |
508 (initiator << HT_AGG_STATE_INITIATOR_SHIFT);
509
510 if (local->ops->ampdu_action)
511 ret = local->ops->ampdu_action(hw, IEEE80211_AMPDU_TX_STOP,
512 ra, tid, NULL);
513
514 /* case HW denied going back to legacy */
515 if (ret) {
516 WARN_ON(ret != -EBUSY);
517 *state = HT_AGG_STATE_OPERATIONAL;
518 ieee80211_wake_queue(hw, sta->tid_to_tx_q[tid]);
519 goto stop_BA_exit;
520 }
521
522stop_BA_exit:
523 spin_unlock_bh(&sta->lock);
524 rcu_read_unlock();
525 return ret;
526}
527EXPORT_SYMBOL(ieee80211_stop_tx_ba_session);
528
529void ieee80211_start_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u16 tid)
530{
531 struct ieee80211_local *local = hw_to_local(hw);
532 struct sta_info *sta;
533 u8 *state;
534 DECLARE_MAC_BUF(mac);
535
536 if (tid >= STA_TID_NUM) {
537#ifdef CONFIG_MAC80211_HT_DEBUG
538 printk(KERN_DEBUG "Bad TID value: tid = %d (>= %d)\n",
539 tid, STA_TID_NUM);
540#endif
541 return;
542 }
543
544 rcu_read_lock();
545 sta = sta_info_get(local, ra);
546 if (!sta) {
547 rcu_read_unlock();
548#ifdef CONFIG_MAC80211_HT_DEBUG
549 printk(KERN_DEBUG "Could not find station: %s\n",
550 print_mac(mac, ra));
551#endif
552 return;
553 }
554
555 state = &sta->ampdu_mlme.tid_state_tx[tid];
556 spin_lock_bh(&sta->lock);
557
558 if (!(*state & HT_ADDBA_REQUESTED_MSK)) {
559#ifdef CONFIG_MAC80211_HT_DEBUG
560 printk(KERN_DEBUG "addBA was not requested yet, state is %d\n",
561 *state);
562#endif
563 spin_unlock_bh(&sta->lock);
564 rcu_read_unlock();
565 return;
566 }
567
568 WARN_ON_ONCE(*state & HT_ADDBA_DRV_READY_MSK);
569
570 *state |= HT_ADDBA_DRV_READY_MSK;
571
572 if (*state == HT_AGG_STATE_OPERATIONAL) {
573#ifdef CONFIG_MAC80211_HT_DEBUG
574 printk(KERN_DEBUG "Aggregation is on for tid %d \n", tid);
575#endif
576 ieee80211_wake_queue(hw, sta->tid_to_tx_q[tid]);
577 }
578 spin_unlock_bh(&sta->lock);
579 rcu_read_unlock();
580}
581EXPORT_SYMBOL(ieee80211_start_tx_ba_cb);
582
583void ieee80211_stop_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u8 tid)
584{
585 struct ieee80211_local *local = hw_to_local(hw);
586 struct sta_info *sta;
587 u8 *state;
588 int agg_queue;
589 DECLARE_MAC_BUF(mac);
590
591 if (tid >= STA_TID_NUM) {
592#ifdef CONFIG_MAC80211_HT_DEBUG
593 printk(KERN_DEBUG "Bad TID value: tid = %d (>= %d)\n",
594 tid, STA_TID_NUM);
595#endif
596 return;
597 }
598
599#ifdef CONFIG_MAC80211_HT_DEBUG
600 printk(KERN_DEBUG "Stopping Tx BA session for %s tid %d\n",
601 print_mac(mac, ra), tid);
602#endif /* CONFIG_MAC80211_HT_DEBUG */
603
604 rcu_read_lock();
605 sta = sta_info_get(local, ra);
606 if (!sta) {
607#ifdef CONFIG_MAC80211_HT_DEBUG
608 printk(KERN_DEBUG "Could not find station: %s\n",
609 print_mac(mac, ra));
610#endif
611 rcu_read_unlock();
612 return;
613 }
614 state = &sta->ampdu_mlme.tid_state_tx[tid];
615
616 /* NOTE: no need to use sta->lock in this state check, as
617 * ieee80211_stop_tx_ba_session will let only one stop call to
618 * pass through per sta/tid
619 */
620 if ((*state & HT_AGG_STATE_REQ_STOP_BA_MSK) == 0) {
621#ifdef CONFIG_MAC80211_HT_DEBUG
622 printk(KERN_DEBUG "unexpected callback to A-MPDU stop\n");
623#endif
624 rcu_read_unlock();
625 return;
626 }
627
628 if (*state & HT_AGG_STATE_INITIATOR_MSK)
629 ieee80211_send_delba(sta->sdata, ra, tid,
630 WLAN_BACK_INITIATOR, WLAN_REASON_QSTA_NOT_USE);
631
632 agg_queue = sta->tid_to_tx_q[tid];
633
634 ieee80211_ht_agg_queue_remove(local, sta, tid, 1);
635
636 /* We just requeued the all the frames that were in the
637 * removed queue, and since we might miss a softirq we do
638 * netif_schedule_queue. ieee80211_wake_queue is not used
639 * here as this queue is not necessarily stopped
640 */
641 netif_schedule_queue(netdev_get_tx_queue(local->mdev, agg_queue));
642 spin_lock_bh(&sta->lock);
643 *state = HT_AGG_STATE_IDLE;
644 sta->ampdu_mlme.addba_req_num[tid] = 0;
645 kfree(sta->ampdu_mlme.tid_tx[tid]);
646 sta->ampdu_mlme.tid_tx[tid] = NULL;
647 spin_unlock_bh(&sta->lock);
648
649 rcu_read_unlock();
650}
651EXPORT_SYMBOL(ieee80211_stop_tx_ba_cb);
652
653void ieee80211_start_tx_ba_cb_irqsafe(struct ieee80211_hw *hw,
654 const u8 *ra, u16 tid)
655{
656 struct ieee80211_local *local = hw_to_local(hw);
657 struct ieee80211_ra_tid *ra_tid;
658 struct sk_buff *skb = dev_alloc_skb(0);
659
660 if (unlikely(!skb)) {
661#ifdef CONFIG_MAC80211_HT_DEBUG
662 if (net_ratelimit())
663 printk(KERN_WARNING "%s: Not enough memory, "
664 "dropping start BA session", skb->dev->name);
665#endif
666 return;
667 }
668 ra_tid = (struct ieee80211_ra_tid *) &skb->cb;
669 memcpy(&ra_tid->ra, ra, ETH_ALEN);
670 ra_tid->tid = tid;
671
672 skb->pkt_type = IEEE80211_ADDBA_MSG;
673 skb_queue_tail(&local->skb_queue, skb);
674 tasklet_schedule(&local->tasklet);
675}
676EXPORT_SYMBOL(ieee80211_start_tx_ba_cb_irqsafe);
677
678void ieee80211_stop_tx_ba_cb_irqsafe(struct ieee80211_hw *hw,
679 const u8 *ra, u16 tid)
680{
681 struct ieee80211_local *local = hw_to_local(hw);
682 struct ieee80211_ra_tid *ra_tid;
683 struct sk_buff *skb = dev_alloc_skb(0);
684
685 if (unlikely(!skb)) {
686#ifdef CONFIG_MAC80211_HT_DEBUG
687 if (net_ratelimit())
688 printk(KERN_WARNING "%s: Not enough memory, "
689 "dropping stop BA session", skb->dev->name);
690#endif
691 return;
692 }
693 ra_tid = (struct ieee80211_ra_tid *) &skb->cb;
694 memcpy(&ra_tid->ra, ra, ETH_ALEN);
695 ra_tid->tid = tid;
696
697 skb->pkt_type = IEEE80211_DELBA_MSG;
698 skb_queue_tail(&local->skb_queue, skb);
699 tasklet_schedule(&local->tasklet);
700}
701EXPORT_SYMBOL(ieee80211_stop_tx_ba_cb_irqsafe);
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index 6df4a2e15098..f90254a5948e 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -593,379 +593,6 @@ static int ieee80211_stop(struct net_device *dev)
593 return 0; 593 return 0;
594} 594}
595 595
596int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid)
597{
598 struct ieee80211_local *local = hw_to_local(hw);
599 struct sta_info *sta;
600 struct ieee80211_sub_if_data *sdata;
601 u16 start_seq_num;
602 u8 *state;
603 int ret;
604 DECLARE_MAC_BUF(mac);
605
606 if (tid >= STA_TID_NUM)
607 return -EINVAL;
608
609#ifdef CONFIG_MAC80211_HT_DEBUG
610 printk(KERN_DEBUG "Open BA session requested for %s tid %u\n",
611 print_mac(mac, ra), tid);
612#endif /* CONFIG_MAC80211_HT_DEBUG */
613
614 rcu_read_lock();
615
616 sta = sta_info_get(local, ra);
617 if (!sta) {
618#ifdef CONFIG_MAC80211_HT_DEBUG
619 printk(KERN_DEBUG "Could not find the station\n");
620#endif
621 ret = -ENOENT;
622 goto exit;
623 }
624
625 spin_lock_bh(&sta->lock);
626
627 /* we have tried too many times, receiver does not want A-MPDU */
628 if (sta->ampdu_mlme.addba_req_num[tid] > HT_AGG_MAX_RETRIES) {
629 ret = -EBUSY;
630 goto err_unlock_sta;
631 }
632
633 state = &sta->ampdu_mlme.tid_state_tx[tid];
634 /* check if the TID is not in aggregation flow already */
635 if (*state != HT_AGG_STATE_IDLE) {
636#ifdef CONFIG_MAC80211_HT_DEBUG
637 printk(KERN_DEBUG "BA request denied - session is not "
638 "idle on tid %u\n", tid);
639#endif /* CONFIG_MAC80211_HT_DEBUG */
640 ret = -EAGAIN;
641 goto err_unlock_sta;
642 }
643
644 /* prepare A-MPDU MLME for Tx aggregation */
645 sta->ampdu_mlme.tid_tx[tid] =
646 kmalloc(sizeof(struct tid_ampdu_tx), GFP_ATOMIC);
647 if (!sta->ampdu_mlme.tid_tx[tid]) {
648#ifdef CONFIG_MAC80211_HT_DEBUG
649 if (net_ratelimit())
650 printk(KERN_ERR "allocate tx mlme to tid %d failed\n",
651 tid);
652#endif
653 ret = -ENOMEM;
654 goto err_unlock_sta;
655 }
656 /* Tx timer */
657 sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer.function =
658 sta_addba_resp_timer_expired;
659 sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer.data =
660 (unsigned long)&sta->timer_to_tid[tid];
661 init_timer(&sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer);
662
663 /* create a new queue for this aggregation */
664 ret = ieee80211_ht_agg_queue_add(local, sta, tid);
665
666 /* case no queue is available to aggregation
667 * don't switch to aggregation */
668 if (ret) {
669#ifdef CONFIG_MAC80211_HT_DEBUG
670 printk(KERN_DEBUG "BA request denied - queue unavailable for"
671 " tid %d\n", tid);
672#endif /* CONFIG_MAC80211_HT_DEBUG */
673 goto err_unlock_queue;
674 }
675 sdata = sta->sdata;
676
677 /* Ok, the Addba frame hasn't been sent yet, but if the driver calls the
678 * call back right away, it must see that the flow has begun */
679 *state |= HT_ADDBA_REQUESTED_MSK;
680
681 /* This is slightly racy because the queue isn't stopped */
682 start_seq_num = sta->tid_seq[tid];
683
684 if (local->ops->ampdu_action)
685 ret = local->ops->ampdu_action(hw, IEEE80211_AMPDU_TX_START,
686 ra, tid, &start_seq_num);
687
688 if (ret) {
689 /* No need to requeue the packets in the agg queue, since we
690 * held the tx lock: no packet could be enqueued to the newly
691 * allocated queue */
692 ieee80211_ht_agg_queue_remove(local, sta, tid, 0);
693#ifdef CONFIG_MAC80211_HT_DEBUG
694 printk(KERN_DEBUG "BA request denied - HW unavailable for"
695 " tid %d\n", tid);
696#endif /* CONFIG_MAC80211_HT_DEBUG */
697 *state = HT_AGG_STATE_IDLE;
698 goto err_unlock_queue;
699 }
700
701 /* Will put all the packets in the new SW queue */
702 ieee80211_requeue(local, ieee802_1d_to_ac[tid]);
703 spin_unlock_bh(&sta->lock);
704
705 /* send an addBA request */
706 sta->ampdu_mlme.dialog_token_allocator++;
707 sta->ampdu_mlme.tid_tx[tid]->dialog_token =
708 sta->ampdu_mlme.dialog_token_allocator;
709 sta->ampdu_mlme.tid_tx[tid]->ssn = start_seq_num;
710
711
712 ieee80211_send_addba_request(sta->sdata, ra, tid,
713 sta->ampdu_mlme.tid_tx[tid]->dialog_token,
714 sta->ampdu_mlme.tid_tx[tid]->ssn,
715 0x40, 5000);
716 /* activate the timer for the recipient's addBA response */
717 sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer.expires =
718 jiffies + ADDBA_RESP_INTERVAL;
719 add_timer(&sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer);
720#ifdef CONFIG_MAC80211_HT_DEBUG
721 printk(KERN_DEBUG "activated addBA response timer on tid %d\n", tid);
722#endif
723 goto exit;
724
725err_unlock_queue:
726 kfree(sta->ampdu_mlme.tid_tx[tid]);
727 sta->ampdu_mlme.tid_tx[tid] = NULL;
728 ret = -EBUSY;
729err_unlock_sta:
730 spin_unlock_bh(&sta->lock);
731exit:
732 rcu_read_unlock();
733 return ret;
734}
735EXPORT_SYMBOL(ieee80211_start_tx_ba_session);
736
737int ieee80211_stop_tx_ba_session(struct ieee80211_hw *hw,
738 u8 *ra, u16 tid,
739 enum ieee80211_back_parties initiator)
740{
741 struct ieee80211_local *local = hw_to_local(hw);
742 struct sta_info *sta;
743 u8 *state;
744 int ret = 0;
745 DECLARE_MAC_BUF(mac);
746
747 if (tid >= STA_TID_NUM)
748 return -EINVAL;
749
750 rcu_read_lock();
751 sta = sta_info_get(local, ra);
752 if (!sta) {
753 rcu_read_unlock();
754 return -ENOENT;
755 }
756
757 /* check if the TID is in aggregation */
758 state = &sta->ampdu_mlme.tid_state_tx[tid];
759 spin_lock_bh(&sta->lock);
760
761 if (*state != HT_AGG_STATE_OPERATIONAL) {
762 ret = -ENOENT;
763 goto stop_BA_exit;
764 }
765
766#ifdef CONFIG_MAC80211_HT_DEBUG
767 printk(KERN_DEBUG "Tx BA session stop requested for %s tid %u\n",
768 print_mac(mac, ra), tid);
769#endif /* CONFIG_MAC80211_HT_DEBUG */
770
771 ieee80211_stop_queue(hw, sta->tid_to_tx_q[tid]);
772
773 *state = HT_AGG_STATE_REQ_STOP_BA_MSK |
774 (initiator << HT_AGG_STATE_INITIATOR_SHIFT);
775
776 if (local->ops->ampdu_action)
777 ret = local->ops->ampdu_action(hw, IEEE80211_AMPDU_TX_STOP,
778 ra, tid, NULL);
779
780 /* case HW denied going back to legacy */
781 if (ret) {
782 WARN_ON(ret != -EBUSY);
783 *state = HT_AGG_STATE_OPERATIONAL;
784 ieee80211_wake_queue(hw, sta->tid_to_tx_q[tid]);
785 goto stop_BA_exit;
786 }
787
788stop_BA_exit:
789 spin_unlock_bh(&sta->lock);
790 rcu_read_unlock();
791 return ret;
792}
793EXPORT_SYMBOL(ieee80211_stop_tx_ba_session);
794
795void ieee80211_start_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u16 tid)
796{
797 struct ieee80211_local *local = hw_to_local(hw);
798 struct sta_info *sta;
799 u8 *state;
800 DECLARE_MAC_BUF(mac);
801
802 if (tid >= STA_TID_NUM) {
803#ifdef CONFIG_MAC80211_HT_DEBUG
804 printk(KERN_DEBUG "Bad TID value: tid = %d (>= %d)\n",
805 tid, STA_TID_NUM);
806#endif
807 return;
808 }
809
810 rcu_read_lock();
811 sta = sta_info_get(local, ra);
812 if (!sta) {
813 rcu_read_unlock();
814#ifdef CONFIG_MAC80211_HT_DEBUG
815 printk(KERN_DEBUG "Could not find station: %s\n",
816 print_mac(mac, ra));
817#endif
818 return;
819 }
820
821 state = &sta->ampdu_mlme.tid_state_tx[tid];
822 spin_lock_bh(&sta->lock);
823
824 if (!(*state & HT_ADDBA_REQUESTED_MSK)) {
825#ifdef CONFIG_MAC80211_HT_DEBUG
826 printk(KERN_DEBUG "addBA was not requested yet, state is %d\n",
827 *state);
828#endif
829 spin_unlock_bh(&sta->lock);
830 rcu_read_unlock();
831 return;
832 }
833
834 WARN_ON_ONCE(*state & HT_ADDBA_DRV_READY_MSK);
835
836 *state |= HT_ADDBA_DRV_READY_MSK;
837
838 if (*state == HT_AGG_STATE_OPERATIONAL) {
839#ifdef CONFIG_MAC80211_HT_DEBUG
840 printk(KERN_DEBUG "Aggregation is on for tid %d \n", tid);
841#endif
842 ieee80211_wake_queue(hw, sta->tid_to_tx_q[tid]);
843 }
844 spin_unlock_bh(&sta->lock);
845 rcu_read_unlock();
846}
847EXPORT_SYMBOL(ieee80211_start_tx_ba_cb);
848
849void ieee80211_stop_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u8 tid)
850{
851 struct ieee80211_local *local = hw_to_local(hw);
852 struct sta_info *sta;
853 u8 *state;
854 int agg_queue;
855 DECLARE_MAC_BUF(mac);
856
857 if (tid >= STA_TID_NUM) {
858#ifdef CONFIG_MAC80211_HT_DEBUG
859 printk(KERN_DEBUG "Bad TID value: tid = %d (>= %d)\n",
860 tid, STA_TID_NUM);
861#endif
862 return;
863 }
864
865#ifdef CONFIG_MAC80211_HT_DEBUG
866 printk(KERN_DEBUG "Stopping Tx BA session for %s tid %d\n",
867 print_mac(mac, ra), tid);
868#endif /* CONFIG_MAC80211_HT_DEBUG */
869
870 rcu_read_lock();
871 sta = sta_info_get(local, ra);
872 if (!sta) {
873#ifdef CONFIG_MAC80211_HT_DEBUG
874 printk(KERN_DEBUG "Could not find station: %s\n",
875 print_mac(mac, ra));
876#endif
877 rcu_read_unlock();
878 return;
879 }
880 state = &sta->ampdu_mlme.tid_state_tx[tid];
881
882 /* NOTE: no need to use sta->lock in this state check, as
883 * ieee80211_stop_tx_ba_session will let only one stop call to
884 * pass through per sta/tid
885 */
886 if ((*state & HT_AGG_STATE_REQ_STOP_BA_MSK) == 0) {
887#ifdef CONFIG_MAC80211_HT_DEBUG
888 printk(KERN_DEBUG "unexpected callback to A-MPDU stop\n");
889#endif
890 rcu_read_unlock();
891 return;
892 }
893
894 if (*state & HT_AGG_STATE_INITIATOR_MSK)
895 ieee80211_send_delba(sta->sdata, ra, tid,
896 WLAN_BACK_INITIATOR, WLAN_REASON_QSTA_NOT_USE);
897
898 agg_queue = sta->tid_to_tx_q[tid];
899
900 ieee80211_ht_agg_queue_remove(local, sta, tid, 1);
901
902 /* We just requeued the all the frames that were in the
903 * removed queue, and since we might miss a softirq we do
904 * netif_schedule_queue. ieee80211_wake_queue is not used
905 * here as this queue is not necessarily stopped
906 */
907 netif_schedule_queue(netdev_get_tx_queue(local->mdev, agg_queue));
908 spin_lock_bh(&sta->lock);
909 *state = HT_AGG_STATE_IDLE;
910 sta->ampdu_mlme.addba_req_num[tid] = 0;
911 kfree(sta->ampdu_mlme.tid_tx[tid]);
912 sta->ampdu_mlme.tid_tx[tid] = NULL;
913 spin_unlock_bh(&sta->lock);
914
915 rcu_read_unlock();
916}
917EXPORT_SYMBOL(ieee80211_stop_tx_ba_cb);
918
919void ieee80211_start_tx_ba_cb_irqsafe(struct ieee80211_hw *hw,
920 const u8 *ra, u16 tid)
921{
922 struct ieee80211_local *local = hw_to_local(hw);
923 struct ieee80211_ra_tid *ra_tid;
924 struct sk_buff *skb = dev_alloc_skb(0);
925
926 if (unlikely(!skb)) {
927#ifdef CONFIG_MAC80211_HT_DEBUG
928 if (net_ratelimit())
929 printk(KERN_WARNING "%s: Not enough memory, "
930 "dropping start BA session", skb->dev->name);
931#endif
932 return;
933 }
934 ra_tid = (struct ieee80211_ra_tid *) &skb->cb;
935 memcpy(&ra_tid->ra, ra, ETH_ALEN);
936 ra_tid->tid = tid;
937
938 skb->pkt_type = IEEE80211_ADDBA_MSG;
939 skb_queue_tail(&local->skb_queue, skb);
940 tasklet_schedule(&local->tasklet);
941}
942EXPORT_SYMBOL(ieee80211_start_tx_ba_cb_irqsafe);
943
944void ieee80211_stop_tx_ba_cb_irqsafe(struct ieee80211_hw *hw,
945 const u8 *ra, u16 tid)
946{
947 struct ieee80211_local *local = hw_to_local(hw);
948 struct ieee80211_ra_tid *ra_tid;
949 struct sk_buff *skb = dev_alloc_skb(0);
950
951 if (unlikely(!skb)) {
952#ifdef CONFIG_MAC80211_HT_DEBUG
953 if (net_ratelimit())
954 printk(KERN_WARNING "%s: Not enough memory, "
955 "dropping stop BA session", skb->dev->name);
956#endif
957 return;
958 }
959 ra_tid = (struct ieee80211_ra_tid *) &skb->cb;
960 memcpy(&ra_tid->ra, ra, ETH_ALEN);
961 ra_tid->tid = tid;
962
963 skb->pkt_type = IEEE80211_DELBA_MSG;
964 skb_queue_tail(&local->skb_queue, skb);
965 tasklet_schedule(&local->tasklet);
966}
967EXPORT_SYMBOL(ieee80211_stop_tx_ba_cb_irqsafe);
968
969static void ieee80211_set_multicast_list(struct net_device *dev) 596static void ieee80211_set_multicast_list(struct net_device *dev)
970{ 597{
971 struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); 598 struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);