diff options
Diffstat (limited to 'net/mac80211/rx.c')
-rw-r--r-- | net/mac80211/rx.c | 81 |
1 files changed, 46 insertions, 35 deletions
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index c98be0593756..b5f1bba7ffe1 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -668,9 +668,9 @@ static inline u16 seq_sub(u16 sq1, u16 sq2) | |||
668 | 668 | ||
669 | static void ieee80211_release_reorder_frame(struct ieee80211_sub_if_data *sdata, | 669 | static void ieee80211_release_reorder_frame(struct ieee80211_sub_if_data *sdata, |
670 | struct tid_ampdu_rx *tid_agg_rx, | 670 | struct tid_ampdu_rx *tid_agg_rx, |
671 | int index) | 671 | int index, |
672 | struct sk_buff_head *frames) | ||
672 | { | 673 | { |
673 | struct ieee80211_local *local = sdata->local; | ||
674 | struct sk_buff *skb = tid_agg_rx->reorder_buf[index]; | 674 | struct sk_buff *skb = tid_agg_rx->reorder_buf[index]; |
675 | struct ieee80211_rx_status *status; | 675 | struct ieee80211_rx_status *status; |
676 | 676 | ||
@@ -684,7 +684,7 @@ static void ieee80211_release_reorder_frame(struct ieee80211_sub_if_data *sdata, | |||
684 | tid_agg_rx->reorder_buf[index] = NULL; | 684 | tid_agg_rx->reorder_buf[index] = NULL; |
685 | status = IEEE80211_SKB_RXCB(skb); | 685 | status = IEEE80211_SKB_RXCB(skb); |
686 | status->rx_flags |= IEEE80211_RX_DEFERRED_RELEASE; | 686 | status->rx_flags |= IEEE80211_RX_DEFERRED_RELEASE; |
687 | skb_queue_tail(&local->rx_skb_queue, skb); | 687 | __skb_queue_tail(frames, skb); |
688 | 688 | ||
689 | no_frame: | 689 | no_frame: |
690 | tid_agg_rx->head_seq_num = seq_inc(tid_agg_rx->head_seq_num); | 690 | tid_agg_rx->head_seq_num = seq_inc(tid_agg_rx->head_seq_num); |
@@ -692,7 +692,8 @@ no_frame: | |||
692 | 692 | ||
693 | static void ieee80211_release_reorder_frames(struct ieee80211_sub_if_data *sdata, | 693 | static void ieee80211_release_reorder_frames(struct ieee80211_sub_if_data *sdata, |
694 | struct tid_ampdu_rx *tid_agg_rx, | 694 | struct tid_ampdu_rx *tid_agg_rx, |
695 | u16 head_seq_num) | 695 | u16 head_seq_num, |
696 | struct sk_buff_head *frames) | ||
696 | { | 697 | { |
697 | int index; | 698 | int index; |
698 | 699 | ||
@@ -701,7 +702,8 @@ static void ieee80211_release_reorder_frames(struct ieee80211_sub_if_data *sdata | |||
701 | while (seq_less(tid_agg_rx->head_seq_num, head_seq_num)) { | 702 | while (seq_less(tid_agg_rx->head_seq_num, head_seq_num)) { |
702 | index = seq_sub(tid_agg_rx->head_seq_num, tid_agg_rx->ssn) % | 703 | index = seq_sub(tid_agg_rx->head_seq_num, tid_agg_rx->ssn) % |
703 | tid_agg_rx->buf_size; | 704 | tid_agg_rx->buf_size; |
704 | ieee80211_release_reorder_frame(sdata, tid_agg_rx, index); | 705 | ieee80211_release_reorder_frame(sdata, tid_agg_rx, index, |
706 | frames); | ||
705 | } | 707 | } |
706 | } | 708 | } |
707 | 709 | ||
@@ -717,7 +719,8 @@ static void ieee80211_release_reorder_frames(struct ieee80211_sub_if_data *sdata | |||
717 | #define HT_RX_REORDER_BUF_TIMEOUT (HZ / 10) | 719 | #define HT_RX_REORDER_BUF_TIMEOUT (HZ / 10) |
718 | 720 | ||
719 | static void ieee80211_sta_reorder_release(struct ieee80211_sub_if_data *sdata, | 721 | static void ieee80211_sta_reorder_release(struct ieee80211_sub_if_data *sdata, |
720 | struct tid_ampdu_rx *tid_agg_rx) | 722 | struct tid_ampdu_rx *tid_agg_rx, |
723 | struct sk_buff_head *frames) | ||
721 | { | 724 | { |
722 | int index, j; | 725 | int index, j; |
723 | 726 | ||
@@ -746,7 +749,8 @@ static void ieee80211_sta_reorder_release(struct ieee80211_sub_if_data *sdata, | |||
746 | 749 | ||
747 | ht_dbg_ratelimited(sdata, | 750 | ht_dbg_ratelimited(sdata, |
748 | "release an RX reorder frame due to timeout on earlier frames\n"); | 751 | "release an RX reorder frame due to timeout on earlier frames\n"); |
749 | ieee80211_release_reorder_frame(sdata, tid_agg_rx, j); | 752 | ieee80211_release_reorder_frame(sdata, tid_agg_rx, j, |
753 | frames); | ||
750 | 754 | ||
751 | /* | 755 | /* |
752 | * Increment the head seq# also for the skipped slots. | 756 | * Increment the head seq# also for the skipped slots. |
@@ -756,7 +760,8 @@ static void ieee80211_sta_reorder_release(struct ieee80211_sub_if_data *sdata, | |||
756 | skipped = 0; | 760 | skipped = 0; |
757 | } | 761 | } |
758 | } else while (tid_agg_rx->reorder_buf[index]) { | 762 | } else while (tid_agg_rx->reorder_buf[index]) { |
759 | ieee80211_release_reorder_frame(sdata, tid_agg_rx, index); | 763 | ieee80211_release_reorder_frame(sdata, tid_agg_rx, index, |
764 | frames); | ||
760 | index = seq_sub(tid_agg_rx->head_seq_num, tid_agg_rx->ssn) % | 765 | index = seq_sub(tid_agg_rx->head_seq_num, tid_agg_rx->ssn) % |
761 | tid_agg_rx->buf_size; | 766 | tid_agg_rx->buf_size; |
762 | } | 767 | } |
@@ -788,7 +793,8 @@ static void ieee80211_sta_reorder_release(struct ieee80211_sub_if_data *sdata, | |||
788 | */ | 793 | */ |
789 | static bool ieee80211_sta_manage_reorder_buf(struct ieee80211_sub_if_data *sdata, | 794 | static bool ieee80211_sta_manage_reorder_buf(struct ieee80211_sub_if_data *sdata, |
790 | struct tid_ampdu_rx *tid_agg_rx, | 795 | struct tid_ampdu_rx *tid_agg_rx, |
791 | struct sk_buff *skb) | 796 | struct sk_buff *skb, |
797 | struct sk_buff_head *frames) | ||
792 | { | 798 | { |
793 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | 799 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; |
794 | u16 sc = le16_to_cpu(hdr->seq_ctrl); | 800 | u16 sc = le16_to_cpu(hdr->seq_ctrl); |
@@ -816,7 +822,7 @@ static bool ieee80211_sta_manage_reorder_buf(struct ieee80211_sub_if_data *sdata | |||
816 | head_seq_num = seq_inc(seq_sub(mpdu_seq_num, buf_size)); | 822 | head_seq_num = seq_inc(seq_sub(mpdu_seq_num, buf_size)); |
817 | /* release stored frames up to new head to stack */ | 823 | /* release stored frames up to new head to stack */ |
818 | ieee80211_release_reorder_frames(sdata, tid_agg_rx, | 824 | ieee80211_release_reorder_frames(sdata, tid_agg_rx, |
819 | head_seq_num); | 825 | head_seq_num, frames); |
820 | } | 826 | } |
821 | 827 | ||
822 | /* Now the new frame is always in the range of the reordering buffer */ | 828 | /* Now the new frame is always in the range of the reordering buffer */ |
@@ -846,7 +852,7 @@ static bool ieee80211_sta_manage_reorder_buf(struct ieee80211_sub_if_data *sdata | |||
846 | tid_agg_rx->reorder_buf[index] = skb; | 852 | tid_agg_rx->reorder_buf[index] = skb; |
847 | tid_agg_rx->reorder_time[index] = jiffies; | 853 | tid_agg_rx->reorder_time[index] = jiffies; |
848 | tid_agg_rx->stored_mpdu_num++; | 854 | tid_agg_rx->stored_mpdu_num++; |
849 | ieee80211_sta_reorder_release(sdata, tid_agg_rx); | 855 | ieee80211_sta_reorder_release(sdata, tid_agg_rx, frames); |
850 | 856 | ||
851 | out: | 857 | out: |
852 | spin_unlock(&tid_agg_rx->reorder_lock); | 858 | spin_unlock(&tid_agg_rx->reorder_lock); |
@@ -857,7 +863,8 @@ static bool ieee80211_sta_manage_reorder_buf(struct ieee80211_sub_if_data *sdata | |||
857 | * Reorder MPDUs from A-MPDUs, keeping them on a buffer. Returns | 863 | * Reorder MPDUs from A-MPDUs, keeping them on a buffer. Returns |
858 | * true if the MPDU was buffered, false if it should be processed. | 864 | * true if the MPDU was buffered, false if it should be processed. |
859 | */ | 865 | */ |
860 | static void ieee80211_rx_reorder_ampdu(struct ieee80211_rx_data *rx) | 866 | static void ieee80211_rx_reorder_ampdu(struct ieee80211_rx_data *rx, |
867 | struct sk_buff_head *frames) | ||
861 | { | 868 | { |
862 | struct sk_buff *skb = rx->skb; | 869 | struct sk_buff *skb = rx->skb; |
863 | struct ieee80211_local *local = rx->local; | 870 | struct ieee80211_local *local = rx->local; |
@@ -922,11 +929,12 @@ static void ieee80211_rx_reorder_ampdu(struct ieee80211_rx_data *rx) | |||
922 | * sure that we cannot get to it any more before doing | 929 | * sure that we cannot get to it any more before doing |
923 | * anything with it. | 930 | * anything with it. |
924 | */ | 931 | */ |
925 | if (ieee80211_sta_manage_reorder_buf(rx->sdata, tid_agg_rx, skb)) | 932 | if (ieee80211_sta_manage_reorder_buf(rx->sdata, tid_agg_rx, skb, |
933 | frames)) | ||
926 | return; | 934 | return; |
927 | 935 | ||
928 | dont_reorder: | 936 | dont_reorder: |
929 | skb_queue_tail(&local->rx_skb_queue, skb); | 937 | __skb_queue_tail(frames, skb); |
930 | } | 938 | } |
931 | 939 | ||
932 | static ieee80211_rx_result debug_noinline | 940 | static ieee80211_rx_result debug_noinline |
@@ -2184,7 +2192,7 @@ ieee80211_rx_h_data(struct ieee80211_rx_data *rx) | |||
2184 | } | 2192 | } |
2185 | 2193 | ||
2186 | static ieee80211_rx_result debug_noinline | 2194 | static ieee80211_rx_result debug_noinline |
2187 | ieee80211_rx_h_ctrl(struct ieee80211_rx_data *rx) | 2195 | ieee80211_rx_h_ctrl(struct ieee80211_rx_data *rx, struct sk_buff_head *frames) |
2188 | { | 2196 | { |
2189 | struct sk_buff *skb = rx->skb; | 2197 | struct sk_buff *skb = rx->skb; |
2190 | struct ieee80211_bar *bar = (struct ieee80211_bar *)skb->data; | 2198 | struct ieee80211_bar *bar = (struct ieee80211_bar *)skb->data; |
@@ -2223,7 +2231,7 @@ ieee80211_rx_h_ctrl(struct ieee80211_rx_data *rx) | |||
2223 | spin_lock(&tid_agg_rx->reorder_lock); | 2231 | spin_lock(&tid_agg_rx->reorder_lock); |
2224 | /* release stored frames up to start of BAR */ | 2232 | /* release stored frames up to start of BAR */ |
2225 | ieee80211_release_reorder_frames(rx->sdata, tid_agg_rx, | 2233 | ieee80211_release_reorder_frames(rx->sdata, tid_agg_rx, |
2226 | start_seq_num); | 2234 | start_seq_num, frames); |
2227 | spin_unlock(&tid_agg_rx->reorder_lock); | 2235 | spin_unlock(&tid_agg_rx->reorder_lock); |
2228 | 2236 | ||
2229 | kfree_skb(skb); | 2237 | kfree_skb(skb); |
@@ -2808,7 +2816,8 @@ static void ieee80211_rx_handlers_result(struct ieee80211_rx_data *rx, | |||
2808 | } | 2816 | } |
2809 | } | 2817 | } |
2810 | 2818 | ||
2811 | static void ieee80211_rx_handlers(struct ieee80211_rx_data *rx) | 2819 | static void ieee80211_rx_handlers(struct ieee80211_rx_data *rx, |
2820 | struct sk_buff_head *frames) | ||
2812 | { | 2821 | { |
2813 | ieee80211_rx_result res = RX_DROP_MONITOR; | 2822 | ieee80211_rx_result res = RX_DROP_MONITOR; |
2814 | struct sk_buff *skb; | 2823 | struct sk_buff *skb; |
@@ -2820,15 +2829,9 @@ static void ieee80211_rx_handlers(struct ieee80211_rx_data *rx) | |||
2820 | goto rxh_next; \ | 2829 | goto rxh_next; \ |
2821 | } while (0); | 2830 | } while (0); |
2822 | 2831 | ||
2823 | spin_lock(&rx->local->rx_skb_queue.lock); | 2832 | spin_lock_bh(&rx->local->rx_path_lock); |
2824 | if (rx->local->running_rx_handler) | ||
2825 | goto unlock; | ||
2826 | |||
2827 | rx->local->running_rx_handler = true; | ||
2828 | |||
2829 | while ((skb = __skb_dequeue(&rx->local->rx_skb_queue))) { | ||
2830 | spin_unlock(&rx->local->rx_skb_queue.lock); | ||
2831 | 2833 | ||
2834 | while ((skb = __skb_dequeue(frames))) { | ||
2832 | /* | 2835 | /* |
2833 | * all the other fields are valid across frames | 2836 | * all the other fields are valid across frames |
2834 | * that belong to an aMPDU since they are on the | 2837 | * that belong to an aMPDU since they are on the |
@@ -2849,7 +2852,12 @@ static void ieee80211_rx_handlers(struct ieee80211_rx_data *rx) | |||
2849 | #endif | 2852 | #endif |
2850 | CALL_RXH(ieee80211_rx_h_amsdu) | 2853 | CALL_RXH(ieee80211_rx_h_amsdu) |
2851 | CALL_RXH(ieee80211_rx_h_data) | 2854 | CALL_RXH(ieee80211_rx_h_data) |
2852 | CALL_RXH(ieee80211_rx_h_ctrl); | 2855 | |
2856 | /* special treatment -- needs the queue */ | ||
2857 | res = ieee80211_rx_h_ctrl(rx, frames); | ||
2858 | if (res != RX_CONTINUE) | ||
2859 | goto rxh_next; | ||
2860 | |||
2853 | CALL_RXH(ieee80211_rx_h_mgmt_check) | 2861 | CALL_RXH(ieee80211_rx_h_mgmt_check) |
2854 | CALL_RXH(ieee80211_rx_h_action) | 2862 | CALL_RXH(ieee80211_rx_h_action) |
2855 | CALL_RXH(ieee80211_rx_h_userspace_mgmt) | 2863 | CALL_RXH(ieee80211_rx_h_userspace_mgmt) |
@@ -2858,20 +2866,20 @@ static void ieee80211_rx_handlers(struct ieee80211_rx_data *rx) | |||
2858 | 2866 | ||
2859 | rxh_next: | 2867 | rxh_next: |
2860 | ieee80211_rx_handlers_result(rx, res); | 2868 | ieee80211_rx_handlers_result(rx, res); |
2861 | spin_lock(&rx->local->rx_skb_queue.lock); | 2869 | |
2862 | #undef CALL_RXH | 2870 | #undef CALL_RXH |
2863 | } | 2871 | } |
2864 | 2872 | ||
2865 | rx->local->running_rx_handler = false; | 2873 | spin_unlock_bh(&rx->local->rx_path_lock); |
2866 | |||
2867 | unlock: | ||
2868 | spin_unlock(&rx->local->rx_skb_queue.lock); | ||
2869 | } | 2874 | } |
2870 | 2875 | ||
2871 | static void ieee80211_invoke_rx_handlers(struct ieee80211_rx_data *rx) | 2876 | static void ieee80211_invoke_rx_handlers(struct ieee80211_rx_data *rx) |
2872 | { | 2877 | { |
2878 | struct sk_buff_head reorder_release; | ||
2873 | ieee80211_rx_result res = RX_DROP_MONITOR; | 2879 | ieee80211_rx_result res = RX_DROP_MONITOR; |
2874 | 2880 | ||
2881 | __skb_queue_head_init(&reorder_release); | ||
2882 | |||
2875 | #define CALL_RXH(rxh) \ | 2883 | #define CALL_RXH(rxh) \ |
2876 | do { \ | 2884 | do { \ |
2877 | res = rxh(rx); \ | 2885 | res = rxh(rx); \ |
@@ -2881,9 +2889,9 @@ static void ieee80211_invoke_rx_handlers(struct ieee80211_rx_data *rx) | |||
2881 | 2889 | ||
2882 | CALL_RXH(ieee80211_rx_h_check) | 2890 | CALL_RXH(ieee80211_rx_h_check) |
2883 | 2891 | ||
2884 | ieee80211_rx_reorder_ampdu(rx); | 2892 | ieee80211_rx_reorder_ampdu(rx, &reorder_release); |
2885 | 2893 | ||
2886 | ieee80211_rx_handlers(rx); | 2894 | ieee80211_rx_handlers(rx, &reorder_release); |
2887 | return; | 2895 | return; |
2888 | 2896 | ||
2889 | rxh_next: | 2897 | rxh_next: |
@@ -2898,6 +2906,7 @@ static void ieee80211_invoke_rx_handlers(struct ieee80211_rx_data *rx) | |||
2898 | */ | 2906 | */ |
2899 | void ieee80211_release_reorder_timeout(struct sta_info *sta, int tid) | 2907 | void ieee80211_release_reorder_timeout(struct sta_info *sta, int tid) |
2900 | { | 2908 | { |
2909 | struct sk_buff_head frames; | ||
2901 | struct ieee80211_rx_data rx = { | 2910 | struct ieee80211_rx_data rx = { |
2902 | .sta = sta, | 2911 | .sta = sta, |
2903 | .sdata = sta->sdata, | 2912 | .sdata = sta->sdata, |
@@ -2913,11 +2922,13 @@ void ieee80211_release_reorder_timeout(struct sta_info *sta, int tid) | |||
2913 | if (!tid_agg_rx) | 2922 | if (!tid_agg_rx) |
2914 | return; | 2923 | return; |
2915 | 2924 | ||
2925 | __skb_queue_head_init(&frames); | ||
2926 | |||
2916 | spin_lock(&tid_agg_rx->reorder_lock); | 2927 | spin_lock(&tid_agg_rx->reorder_lock); |
2917 | ieee80211_sta_reorder_release(sta->sdata, tid_agg_rx); | 2928 | ieee80211_sta_reorder_release(sta->sdata, tid_agg_rx, &frames); |
2918 | spin_unlock(&tid_agg_rx->reorder_lock); | 2929 | spin_unlock(&tid_agg_rx->reorder_lock); |
2919 | 2930 | ||
2920 | ieee80211_rx_handlers(&rx); | 2931 | ieee80211_rx_handlers(&rx, &frames); |
2921 | } | 2932 | } |
2922 | 2933 | ||
2923 | /* main receive path */ | 2934 | /* main receive path */ |