diff options
author | Johannes Berg <johannes@sipsolutions.net> | 2008-09-08 11:44:29 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2008-09-11 15:53:37 -0400 |
commit | bacac545f10f2bf6e5ceff0d8e2b82dfc493602a (patch) | |
tree | 16c590d0c71e5368e75e7a108fa4df0fa196767f /net/mac80211/main.c | |
parent | 44d414dbff9d5bf46fc09f2e68567b5848cbbfd3 (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/mac80211/main.c')
-rw-r--r-- | net/mac80211/main.c | 373 |
1 files changed, 0 insertions, 373 deletions
diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 6df4a2e1509..f90254a5948 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 | ||
596 | int 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 | |||
725 | err_unlock_queue: | ||
726 | kfree(sta->ampdu_mlme.tid_tx[tid]); | ||
727 | sta->ampdu_mlme.tid_tx[tid] = NULL; | ||
728 | ret = -EBUSY; | ||
729 | err_unlock_sta: | ||
730 | spin_unlock_bh(&sta->lock); | ||
731 | exit: | ||
732 | rcu_read_unlock(); | ||
733 | return ret; | ||
734 | } | ||
735 | EXPORT_SYMBOL(ieee80211_start_tx_ba_session); | ||
736 | |||
737 | int 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 | |||
788 | stop_BA_exit: | ||
789 | spin_unlock_bh(&sta->lock); | ||
790 | rcu_read_unlock(); | ||
791 | return ret; | ||
792 | } | ||
793 | EXPORT_SYMBOL(ieee80211_stop_tx_ba_session); | ||
794 | |||
795 | void 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 | } | ||
847 | EXPORT_SYMBOL(ieee80211_start_tx_ba_cb); | ||
848 | |||
849 | void 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 | } | ||
917 | EXPORT_SYMBOL(ieee80211_stop_tx_ba_cb); | ||
918 | |||
919 | void 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 | } | ||
942 | EXPORT_SYMBOL(ieee80211_start_tx_ba_cb_irqsafe); | ||
943 | |||
944 | void 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 | } | ||
967 | EXPORT_SYMBOL(ieee80211_stop_tx_ba_cb_irqsafe); | ||
968 | |||
969 | static void ieee80211_set_multicast_list(struct net_device *dev) | 596 | static 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); |