diff options
author | John W. Linville <linville@tuxdriver.com> | 2011-01-05 16:06:25 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2011-01-05 16:06:25 -0500 |
commit | c96e96354a6c9456cdf1f150eca504e2ea35301e (patch) | |
tree | 751bec601fb8152116b8e31e0f1f83d687a37d6f /net/mac80211 | |
parent | dbbe68bb12b34f3e450da7a73c20e6fa1f85d63a (diff) | |
parent | 33af88138b859f515b365a074e0a014d7cdbf846 (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6 into for-davem
Conflicts:
net/bluetooth/Makefile
Diffstat (limited to 'net/mac80211')
-rw-r--r-- | net/mac80211/ieee80211_i.h | 11 | ||||
-rw-r--r-- | net/mac80211/key.c | 44 | ||||
-rw-r--r-- | net/mac80211/main.c | 3 | ||||
-rw-r--r-- | net/mac80211/rx.c | 112 | ||||
-rw-r--r-- | net/mac80211/tx.c | 14 | ||||
-rw-r--r-- | net/mac80211/wme.c | 20 |
6 files changed, 96 insertions, 108 deletions
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index a05893a238b7..95cdd2a3f809 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -168,6 +168,7 @@ typedef unsigned __bitwise__ ieee80211_rx_result; | |||
168 | * @IEEE80211_RX_FRAGMENTED: fragmented frame | 168 | * @IEEE80211_RX_FRAGMENTED: fragmented frame |
169 | * @IEEE80211_RX_AMSDU: a-MSDU packet | 169 | * @IEEE80211_RX_AMSDU: a-MSDU packet |
170 | * @IEEE80211_RX_MALFORMED_ACTION_FRM: action frame is malformed | 170 | * @IEEE80211_RX_MALFORMED_ACTION_FRM: action frame is malformed |
171 | * @IEEE80211_RX_DEFERRED_RELEASE: frame was subjected to receive reordering | ||
171 | * | 172 | * |
172 | * These are per-frame flags that are attached to a frame in the | 173 | * These are per-frame flags that are attached to a frame in the |
173 | * @rx_flags field of &struct ieee80211_rx_status. | 174 | * @rx_flags field of &struct ieee80211_rx_status. |
@@ -178,6 +179,7 @@ enum ieee80211_packet_rx_flags { | |||
178 | IEEE80211_RX_FRAGMENTED = BIT(2), | 179 | IEEE80211_RX_FRAGMENTED = BIT(2), |
179 | IEEE80211_RX_AMSDU = BIT(3), | 180 | IEEE80211_RX_AMSDU = BIT(3), |
180 | IEEE80211_RX_MALFORMED_ACTION_FRM = BIT(4), | 181 | IEEE80211_RX_MALFORMED_ACTION_FRM = BIT(4), |
182 | IEEE80211_RX_DEFERRED_RELEASE = BIT(5), | ||
181 | }; | 183 | }; |
182 | 184 | ||
183 | /** | 185 | /** |
@@ -774,6 +776,15 @@ struct ieee80211_local { | |||
774 | struct sk_buff_head skb_queue; | 776 | struct sk_buff_head skb_queue; |
775 | struct sk_buff_head skb_queue_unreliable; | 777 | struct sk_buff_head skb_queue_unreliable; |
776 | 778 | ||
779 | /* | ||
780 | * Internal FIFO queue which is shared between multiple rx path | ||
781 | * stages. Its main task is to provide a serialization mechanism, | ||
782 | * so all rx handlers can enjoy having exclusive access to their | ||
783 | * private data structures. | ||
784 | */ | ||
785 | struct sk_buff_head rx_skb_queue; | ||
786 | bool running_rx_handler; /* protected by rx_skb_queue.lock */ | ||
787 | |||
777 | /* Station data */ | 788 | /* Station data */ |
778 | /* | 789 | /* |
779 | * The mutex only protects the list and counter, | 790 | * The mutex only protects the list and counter, |
diff --git a/net/mac80211/key.c b/net/mac80211/key.c index 84cf9196820f..8c02469b7176 100644 --- a/net/mac80211/key.c +++ b/net/mac80211/key.c | |||
@@ -30,19 +30,20 @@ | |||
30 | * keys and per-station keys. Since each station belongs to an interface, | 30 | * keys and per-station keys. Since each station belongs to an interface, |
31 | * each station key also belongs to that interface. | 31 | * each station key also belongs to that interface. |
32 | * | 32 | * |
33 | * Hardware acceleration is done on a best-effort basis, for each key | 33 | * Hardware acceleration is done on a best-effort basis for algorithms |
34 | * that is eligible the hardware is asked to enable that key but if | 34 | * that are implemented in software, for each key the hardware is asked |
35 | * it cannot do that they key is simply kept for software encryption. | 35 | * to enable that key for offloading but if it cannot do that the key is |
36 | * There is currently no way of knowing this except by looking into | 36 | * simply kept for software encryption (unless it is for an algorithm |
37 | * debugfs. | 37 | * that isn't implemented in software). |
38 | * There is currently no way of knowing whether a key is handled in SW | ||
39 | * or HW except by looking into debugfs. | ||
38 | * | 40 | * |
39 | * All key operations are protected internally. | 41 | * All key management is internally protected by a mutex. Within all |
40 | * | 42 | * other parts of mac80211, key references are, just as STA structure |
41 | * Within mac80211, key references are, just as STA structure references, | 43 | * references, protected by RCU. Note, however, that some things are |
42 | * protected by RCU. Note, however, that some things are unprotected, | 44 | * unprotected, namely the key->sta dereferences within the hardware |
43 | * namely the key->sta dereferences within the hardware acceleration | 45 | * acceleration functions. This means that sta_info_destroy() must |
44 | * functions. This means that sta_info_destroy() must remove the key | 46 | * remove the key which waits for an RCU grace period. |
45 | * which waits for an RCU grace period. | ||
46 | */ | 47 | */ |
47 | 48 | ||
48 | static const u8 bcast_addr[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; | 49 | static const u8 bcast_addr[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; |
@@ -279,13 +280,8 @@ static void __ieee80211_key_replace(struct ieee80211_sub_if_data *sdata, | |||
279 | new->conf.keyidx); | 280 | new->conf.keyidx); |
280 | } | 281 | } |
281 | 282 | ||
282 | if (old) { | 283 | if (old) |
283 | /* | 284 | list_del(&old->list); |
284 | * We'll use an empty list to indicate that the key | ||
285 | * has already been removed. | ||
286 | */ | ||
287 | list_del_init(&old->list); | ||
288 | } | ||
289 | } | 285 | } |
290 | 286 | ||
291 | struct ieee80211_key *ieee80211_key_alloc(u32 cipher, int idx, size_t key_len, | 287 | struct ieee80211_key *ieee80211_key_alloc(u32 cipher, int idx, size_t key_len, |
@@ -379,6 +375,12 @@ static void __ieee80211_key_destroy(struct ieee80211_key *key) | |||
379 | if (!key) | 375 | if (!key) |
380 | return; | 376 | return; |
381 | 377 | ||
378 | /* | ||
379 | * Synchronize so the TX path can no longer be using | ||
380 | * this key before we free/remove it. | ||
381 | */ | ||
382 | synchronize_rcu(); | ||
383 | |||
382 | if (key->local) | 384 | if (key->local) |
383 | ieee80211_key_disable_hw_accel(key); | 385 | ieee80211_key_disable_hw_accel(key); |
384 | 386 | ||
@@ -420,8 +422,8 @@ int ieee80211_key_link(struct ieee80211_key *key, | |||
420 | struct sta_info *ap; | 422 | struct sta_info *ap; |
421 | 423 | ||
422 | /* | 424 | /* |
423 | * We're getting a sta pointer in, | 425 | * We're getting a sta pointer in, so must be under |
424 | * so must be under RCU read lock. | 426 | * appropriate locking for sta_info_get(). |
425 | */ | 427 | */ |
426 | 428 | ||
427 | /* same here, the AP could be using QoS */ | 429 | /* same here, the AP could be using QoS */ |
diff --git a/net/mac80211/main.c b/net/mac80211/main.c index bbe8e0ac6e52..4b088b3c25e8 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c | |||
@@ -569,6 +569,8 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, | |||
569 | spin_lock_init(&local->filter_lock); | 569 | spin_lock_init(&local->filter_lock); |
570 | spin_lock_init(&local->queue_stop_reason_lock); | 570 | spin_lock_init(&local->queue_stop_reason_lock); |
571 | 571 | ||
572 | skb_queue_head_init(&local->rx_skb_queue); | ||
573 | |||
572 | INIT_DELAYED_WORK(&local->scan_work, ieee80211_scan_work); | 574 | INIT_DELAYED_WORK(&local->scan_work, ieee80211_scan_work); |
573 | 575 | ||
574 | ieee80211_work_init(local); | 576 | ieee80211_work_init(local); |
@@ -914,6 +916,7 @@ void ieee80211_unregister_hw(struct ieee80211_hw *hw) | |||
914 | wiphy_warn(local->hw.wiphy, "skb_queue not empty\n"); | 916 | wiphy_warn(local->hw.wiphy, "skb_queue not empty\n"); |
915 | skb_queue_purge(&local->skb_queue); | 917 | skb_queue_purge(&local->skb_queue); |
916 | skb_queue_purge(&local->skb_queue_unreliable); | 918 | skb_queue_purge(&local->skb_queue_unreliable); |
919 | skb_queue_purge(&local->rx_skb_queue); | ||
917 | 920 | ||
918 | destroy_workqueue(local->workqueue); | 921 | destroy_workqueue(local->workqueue); |
919 | wiphy_unregister(local->hw.wiphy); | 922 | wiphy_unregister(local->hw.wiphy); |
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 5e9d3bc6a2d9..a6701ed87f0d 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -533,10 +533,11 @@ static inline u16 seq_sub(u16 sq1, u16 sq2) | |||
533 | 533 | ||
534 | static void ieee80211_release_reorder_frame(struct ieee80211_hw *hw, | 534 | static void ieee80211_release_reorder_frame(struct ieee80211_hw *hw, |
535 | struct tid_ampdu_rx *tid_agg_rx, | 535 | struct tid_ampdu_rx *tid_agg_rx, |
536 | int index, | 536 | int index) |
537 | struct sk_buff_head *frames) | ||
538 | { | 537 | { |
538 | struct ieee80211_local *local = hw_to_local(hw); | ||
539 | struct sk_buff *skb = tid_agg_rx->reorder_buf[index]; | 539 | struct sk_buff *skb = tid_agg_rx->reorder_buf[index]; |
540 | struct ieee80211_rx_status *status; | ||
540 | 541 | ||
541 | lockdep_assert_held(&tid_agg_rx->reorder_lock); | 542 | lockdep_assert_held(&tid_agg_rx->reorder_lock); |
542 | 543 | ||
@@ -546,7 +547,9 @@ static void ieee80211_release_reorder_frame(struct ieee80211_hw *hw, | |||
546 | /* release the frame from the reorder ring buffer */ | 547 | /* release the frame from the reorder ring buffer */ |
547 | tid_agg_rx->stored_mpdu_num--; | 548 | tid_agg_rx->stored_mpdu_num--; |
548 | tid_agg_rx->reorder_buf[index] = NULL; | 549 | tid_agg_rx->reorder_buf[index] = NULL; |
549 | __skb_queue_tail(frames, skb); | 550 | status = IEEE80211_SKB_RXCB(skb); |
551 | status->rx_flags |= IEEE80211_RX_DEFERRED_RELEASE; | ||
552 | skb_queue_tail(&local->rx_skb_queue, skb); | ||
550 | 553 | ||
551 | no_frame: | 554 | no_frame: |
552 | tid_agg_rx->head_seq_num = seq_inc(tid_agg_rx->head_seq_num); | 555 | tid_agg_rx->head_seq_num = seq_inc(tid_agg_rx->head_seq_num); |
@@ -554,8 +557,7 @@ no_frame: | |||
554 | 557 | ||
555 | static void ieee80211_release_reorder_frames(struct ieee80211_hw *hw, | 558 | static void ieee80211_release_reorder_frames(struct ieee80211_hw *hw, |
556 | struct tid_ampdu_rx *tid_agg_rx, | 559 | struct tid_ampdu_rx *tid_agg_rx, |
557 | u16 head_seq_num, | 560 | u16 head_seq_num) |
558 | struct sk_buff_head *frames) | ||
559 | { | 561 | { |
560 | int index; | 562 | int index; |
561 | 563 | ||
@@ -564,7 +566,7 @@ static void ieee80211_release_reorder_frames(struct ieee80211_hw *hw, | |||
564 | while (seq_less(tid_agg_rx->head_seq_num, head_seq_num)) { | 566 | while (seq_less(tid_agg_rx->head_seq_num, head_seq_num)) { |
565 | index = seq_sub(tid_agg_rx->head_seq_num, tid_agg_rx->ssn) % | 567 | index = seq_sub(tid_agg_rx->head_seq_num, tid_agg_rx->ssn) % |
566 | tid_agg_rx->buf_size; | 568 | tid_agg_rx->buf_size; |
567 | ieee80211_release_reorder_frame(hw, tid_agg_rx, index, frames); | 569 | ieee80211_release_reorder_frame(hw, tid_agg_rx, index); |
568 | } | 570 | } |
569 | } | 571 | } |
570 | 572 | ||
@@ -580,8 +582,7 @@ static void ieee80211_release_reorder_frames(struct ieee80211_hw *hw, | |||
580 | #define HT_RX_REORDER_BUF_TIMEOUT (HZ / 10) | 582 | #define HT_RX_REORDER_BUF_TIMEOUT (HZ / 10) |
581 | 583 | ||
582 | static void ieee80211_sta_reorder_release(struct ieee80211_hw *hw, | 584 | static void ieee80211_sta_reorder_release(struct ieee80211_hw *hw, |
583 | struct tid_ampdu_rx *tid_agg_rx, | 585 | struct tid_ampdu_rx *tid_agg_rx) |
584 | struct sk_buff_head *frames) | ||
585 | { | 586 | { |
586 | int index, j; | 587 | int index, j; |
587 | 588 | ||
@@ -612,8 +613,7 @@ static void ieee80211_sta_reorder_release(struct ieee80211_hw *hw, | |||
612 | wiphy_debug(hw->wiphy, | 613 | wiphy_debug(hw->wiphy, |
613 | "release an RX reorder frame due to timeout on earlier frames\n"); | 614 | "release an RX reorder frame due to timeout on earlier frames\n"); |
614 | #endif | 615 | #endif |
615 | ieee80211_release_reorder_frame(hw, tid_agg_rx, | 616 | ieee80211_release_reorder_frame(hw, tid_agg_rx, j); |
616 | j, frames); | ||
617 | 617 | ||
618 | /* | 618 | /* |
619 | * Increment the head seq# also for the skipped slots. | 619 | * Increment the head seq# also for the skipped slots. |
@@ -623,31 +623,11 @@ static void ieee80211_sta_reorder_release(struct ieee80211_hw *hw, | |||
623 | skipped = 0; | 623 | skipped = 0; |
624 | } | 624 | } |
625 | } else while (tid_agg_rx->reorder_buf[index]) { | 625 | } else while (tid_agg_rx->reorder_buf[index]) { |
626 | ieee80211_release_reorder_frame(hw, tid_agg_rx, index, frames); | 626 | ieee80211_release_reorder_frame(hw, tid_agg_rx, index); |
627 | index = seq_sub(tid_agg_rx->head_seq_num, tid_agg_rx->ssn) % | 627 | index = seq_sub(tid_agg_rx->head_seq_num, tid_agg_rx->ssn) % |
628 | tid_agg_rx->buf_size; | 628 | tid_agg_rx->buf_size; |
629 | } | 629 | } |
630 | 630 | ||
631 | /* | ||
632 | * Disable the reorder release timer for now. | ||
633 | * | ||
634 | * The current implementation lacks a proper locking scheme | ||
635 | * which would protect vital statistic and debug counters | ||
636 | * from being updated by two different but concurrent BHs. | ||
637 | * | ||
638 | * More information about the topic is available from: | ||
639 | * - thread: http://marc.info/?t=128635927000001 | ||
640 | * | ||
641 | * What was wrong: | ||
642 | * => http://marc.info/?l=linux-wireless&m=128636170811964 | ||
643 | * "Basically the thing is that until your patch, the data | ||
644 | * in the struct didn't actually need locking because it | ||
645 | * was accessed by the RX path only which is not concurrent." | ||
646 | * | ||
647 | * List of what needs to be fixed: | ||
648 | * => http://marc.info/?l=linux-wireless&m=128656352920957 | ||
649 | * | ||
650 | |||
651 | if (tid_agg_rx->stored_mpdu_num) { | 631 | if (tid_agg_rx->stored_mpdu_num) { |
652 | j = index = seq_sub(tid_agg_rx->head_seq_num, | 632 | j = index = seq_sub(tid_agg_rx->head_seq_num, |
653 | tid_agg_rx->ssn) % tid_agg_rx->buf_size; | 633 | tid_agg_rx->ssn) % tid_agg_rx->buf_size; |
@@ -666,10 +646,6 @@ static void ieee80211_sta_reorder_release(struct ieee80211_hw *hw, | |||
666 | } else { | 646 | } else { |
667 | del_timer(&tid_agg_rx->reorder_timer); | 647 | del_timer(&tid_agg_rx->reorder_timer); |
668 | } | 648 | } |
669 | */ | ||
670 | |||
671 | set_release_timer: | ||
672 | return; | ||
673 | } | 649 | } |
674 | 650 | ||
675 | /* | 651 | /* |
@@ -679,8 +655,7 @@ set_release_timer: | |||
679 | */ | 655 | */ |
680 | static bool ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw, | 656 | static bool ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw, |
681 | struct tid_ampdu_rx *tid_agg_rx, | 657 | struct tid_ampdu_rx *tid_agg_rx, |
682 | struct sk_buff *skb, | 658 | struct sk_buff *skb) |
683 | struct sk_buff_head *frames) | ||
684 | { | 659 | { |
685 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | 660 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; |
686 | u16 sc = le16_to_cpu(hdr->seq_ctrl); | 661 | u16 sc = le16_to_cpu(hdr->seq_ctrl); |
@@ -707,8 +682,7 @@ static bool ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw, | |||
707 | if (!seq_less(mpdu_seq_num, head_seq_num + buf_size)) { | 682 | if (!seq_less(mpdu_seq_num, head_seq_num + buf_size)) { |
708 | head_seq_num = seq_inc(seq_sub(mpdu_seq_num, buf_size)); | 683 | head_seq_num = seq_inc(seq_sub(mpdu_seq_num, buf_size)); |
709 | /* release stored frames up to new head to stack */ | 684 | /* release stored frames up to new head to stack */ |
710 | ieee80211_release_reorder_frames(hw, tid_agg_rx, head_seq_num, | 685 | ieee80211_release_reorder_frames(hw, tid_agg_rx, head_seq_num); |
711 | frames); | ||
712 | } | 686 | } |
713 | 687 | ||
714 | /* Now the new frame is always in the range of the reordering buffer */ | 688 | /* Now the new frame is always in the range of the reordering buffer */ |
@@ -736,7 +710,7 @@ static bool ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw, | |||
736 | tid_agg_rx->reorder_buf[index] = skb; | 710 | tid_agg_rx->reorder_buf[index] = skb; |
737 | tid_agg_rx->reorder_time[index] = jiffies; | 711 | tid_agg_rx->reorder_time[index] = jiffies; |
738 | tid_agg_rx->stored_mpdu_num++; | 712 | tid_agg_rx->stored_mpdu_num++; |
739 | ieee80211_sta_reorder_release(hw, tid_agg_rx, frames); | 713 | ieee80211_sta_reorder_release(hw, tid_agg_rx); |
740 | 714 | ||
741 | out: | 715 | out: |
742 | spin_unlock(&tid_agg_rx->reorder_lock); | 716 | spin_unlock(&tid_agg_rx->reorder_lock); |
@@ -747,8 +721,7 @@ static bool ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw, | |||
747 | * Reorder MPDUs from A-MPDUs, keeping them on a buffer. Returns | 721 | * Reorder MPDUs from A-MPDUs, keeping them on a buffer. Returns |
748 | * true if the MPDU was buffered, false if it should be processed. | 722 | * true if the MPDU was buffered, false if it should be processed. |
749 | */ | 723 | */ |
750 | static void ieee80211_rx_reorder_ampdu(struct ieee80211_rx_data *rx, | 724 | static void ieee80211_rx_reorder_ampdu(struct ieee80211_rx_data *rx) |
751 | struct sk_buff_head *frames) | ||
752 | { | 725 | { |
753 | struct sk_buff *skb = rx->skb; | 726 | struct sk_buff *skb = rx->skb; |
754 | struct ieee80211_local *local = rx->local; | 727 | struct ieee80211_local *local = rx->local; |
@@ -803,11 +776,11 @@ static void ieee80211_rx_reorder_ampdu(struct ieee80211_rx_data *rx, | |||
803 | * sure that we cannot get to it any more before doing | 776 | * sure that we cannot get to it any more before doing |
804 | * anything with it. | 777 | * anything with it. |
805 | */ | 778 | */ |
806 | if (ieee80211_sta_manage_reorder_buf(hw, tid_agg_rx, skb, frames)) | 779 | if (ieee80211_sta_manage_reorder_buf(hw, tid_agg_rx, skb)) |
807 | return; | 780 | return; |
808 | 781 | ||
809 | dont_reorder: | 782 | dont_reorder: |
810 | __skb_queue_tail(frames, skb); | 783 | skb_queue_tail(&local->rx_skb_queue, skb); |
811 | } | 784 | } |
812 | 785 | ||
813 | static ieee80211_rx_result debug_noinline | 786 | static ieee80211_rx_result debug_noinline |
@@ -1189,6 +1162,7 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx) | |||
1189 | * exchange sequence. | 1162 | * exchange sequence. |
1190 | */ | 1163 | */ |
1191 | if (!ieee80211_has_morefrags(hdr->frame_control) && | 1164 | if (!ieee80211_has_morefrags(hdr->frame_control) && |
1165 | !(status->rx_flags & IEEE80211_RX_DEFERRED_RELEASE) && | ||
1192 | (rx->sdata->vif.type == NL80211_IFTYPE_AP || | 1166 | (rx->sdata->vif.type == NL80211_IFTYPE_AP || |
1193 | rx->sdata->vif.type == NL80211_IFTYPE_AP_VLAN)) { | 1167 | rx->sdata->vif.type == NL80211_IFTYPE_AP_VLAN)) { |
1194 | if (test_sta_flags(sta, WLAN_STA_PS_STA)) { | 1168 | if (test_sta_flags(sta, WLAN_STA_PS_STA)) { |
@@ -1831,11 +1805,11 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) | |||
1831 | 1805 | ||
1832 | fwd_skb = skb_copy(skb, GFP_ATOMIC); | 1806 | fwd_skb = skb_copy(skb, GFP_ATOMIC); |
1833 | 1807 | ||
1834 | if (!fwd_skb && net_ratelimit()) { | 1808 | if (!fwd_skb && net_ratelimit()) |
1835 | printk(KERN_DEBUG "%s: failed to clone mesh frame\n", | 1809 | printk(KERN_DEBUG "%s: failed to clone mesh frame\n", |
1836 | sdata->name); | 1810 | sdata->name); |
1811 | if (!fwd_skb) | ||
1837 | goto out; | 1812 | goto out; |
1838 | } | ||
1839 | 1813 | ||
1840 | fwd_hdr = (struct ieee80211_hdr *) fwd_skb->data; | 1814 | fwd_hdr = (struct ieee80211_hdr *) fwd_skb->data; |
1841 | memcpy(fwd_hdr->addr2, sdata->vif.addr, ETH_ALEN); | 1815 | memcpy(fwd_hdr->addr2, sdata->vif.addr, ETH_ALEN); |
@@ -1930,7 +1904,7 @@ ieee80211_rx_h_data(struct ieee80211_rx_data *rx) | |||
1930 | } | 1904 | } |
1931 | 1905 | ||
1932 | static ieee80211_rx_result debug_noinline | 1906 | static ieee80211_rx_result debug_noinline |
1933 | ieee80211_rx_h_ctrl(struct ieee80211_rx_data *rx, struct sk_buff_head *frames) | 1907 | ieee80211_rx_h_ctrl(struct ieee80211_rx_data *rx) |
1934 | { | 1908 | { |
1935 | struct ieee80211_local *local = rx->local; | 1909 | struct ieee80211_local *local = rx->local; |
1936 | struct ieee80211_hw *hw = &local->hw; | 1910 | struct ieee80211_hw *hw = &local->hw; |
@@ -1970,8 +1944,7 @@ ieee80211_rx_h_ctrl(struct ieee80211_rx_data *rx, struct sk_buff_head *frames) | |||
1970 | 1944 | ||
1971 | spin_lock(&tid_agg_rx->reorder_lock); | 1945 | spin_lock(&tid_agg_rx->reorder_lock); |
1972 | /* release stored frames up to start of BAR */ | 1946 | /* release stored frames up to start of BAR */ |
1973 | ieee80211_release_reorder_frames(hw, tid_agg_rx, start_seq_num, | 1947 | ieee80211_release_reorder_frames(hw, tid_agg_rx, start_seq_num); |
1974 | frames); | ||
1975 | spin_unlock(&tid_agg_rx->reorder_lock); | 1948 | spin_unlock(&tid_agg_rx->reorder_lock); |
1976 | 1949 | ||
1977 | kfree_skb(skb); | 1950 | kfree_skb(skb); |
@@ -2488,8 +2461,7 @@ static void ieee80211_rx_handlers_result(struct ieee80211_rx_data *rx, | |||
2488 | } | 2461 | } |
2489 | } | 2462 | } |
2490 | 2463 | ||
2491 | static void ieee80211_rx_handlers(struct ieee80211_rx_data *rx, | 2464 | static void ieee80211_rx_handlers(struct ieee80211_rx_data *rx) |
2492 | struct sk_buff_head *frames) | ||
2493 | { | 2465 | { |
2494 | ieee80211_rx_result res = RX_DROP_MONITOR; | 2466 | ieee80211_rx_result res = RX_DROP_MONITOR; |
2495 | struct sk_buff *skb; | 2467 | struct sk_buff *skb; |
@@ -2501,7 +2473,15 @@ static void ieee80211_rx_handlers(struct ieee80211_rx_data *rx, | |||
2501 | goto rxh_next; \ | 2473 | goto rxh_next; \ |
2502 | } while (0); | 2474 | } while (0); |
2503 | 2475 | ||
2504 | while ((skb = __skb_dequeue(frames))) { | 2476 | spin_lock(&rx->local->rx_skb_queue.lock); |
2477 | if (rx->local->running_rx_handler) | ||
2478 | goto unlock; | ||
2479 | |||
2480 | rx->local->running_rx_handler = true; | ||
2481 | |||
2482 | while ((skb = __skb_dequeue(&rx->local->rx_skb_queue))) { | ||
2483 | spin_unlock(&rx->local->rx_skb_queue.lock); | ||
2484 | |||
2505 | /* | 2485 | /* |
2506 | * all the other fields are valid across frames | 2486 | * all the other fields are valid across frames |
2507 | * that belong to an aMPDU since they are on the | 2487 | * that belong to an aMPDU since they are on the |
@@ -2524,12 +2504,7 @@ static void ieee80211_rx_handlers(struct ieee80211_rx_data *rx, | |||
2524 | CALL_RXH(ieee80211_rx_h_mesh_fwding); | 2504 | CALL_RXH(ieee80211_rx_h_mesh_fwding); |
2525 | #endif | 2505 | #endif |
2526 | CALL_RXH(ieee80211_rx_h_data) | 2506 | CALL_RXH(ieee80211_rx_h_data) |
2527 | 2507 | CALL_RXH(ieee80211_rx_h_ctrl); | |
2528 | /* special treatment -- needs the queue */ | ||
2529 | res = ieee80211_rx_h_ctrl(rx, frames); | ||
2530 | if (res != RX_CONTINUE) | ||
2531 | goto rxh_next; | ||
2532 | |||
2533 | CALL_RXH(ieee80211_rx_h_mgmt_check) | 2508 | CALL_RXH(ieee80211_rx_h_mgmt_check) |
2534 | CALL_RXH(ieee80211_rx_h_action) | 2509 | CALL_RXH(ieee80211_rx_h_action) |
2535 | CALL_RXH(ieee80211_rx_h_userspace_mgmt) | 2510 | CALL_RXH(ieee80211_rx_h_userspace_mgmt) |
@@ -2538,18 +2513,20 @@ static void ieee80211_rx_handlers(struct ieee80211_rx_data *rx, | |||
2538 | 2513 | ||
2539 | rxh_next: | 2514 | rxh_next: |
2540 | ieee80211_rx_handlers_result(rx, res); | 2515 | ieee80211_rx_handlers_result(rx, res); |
2541 | 2516 | spin_lock(&rx->local->rx_skb_queue.lock); | |
2542 | #undef CALL_RXH | 2517 | #undef CALL_RXH |
2543 | } | 2518 | } |
2519 | |||
2520 | rx->local->running_rx_handler = false; | ||
2521 | |||
2522 | unlock: | ||
2523 | spin_unlock(&rx->local->rx_skb_queue.lock); | ||
2544 | } | 2524 | } |
2545 | 2525 | ||
2546 | static void ieee80211_invoke_rx_handlers(struct ieee80211_rx_data *rx) | 2526 | static void ieee80211_invoke_rx_handlers(struct ieee80211_rx_data *rx) |
2547 | { | 2527 | { |
2548 | struct sk_buff_head reorder_release; | ||
2549 | ieee80211_rx_result res = RX_DROP_MONITOR; | 2528 | ieee80211_rx_result res = RX_DROP_MONITOR; |
2550 | 2529 | ||
2551 | __skb_queue_head_init(&reorder_release); | ||
2552 | |||
2553 | #define CALL_RXH(rxh) \ | 2530 | #define CALL_RXH(rxh) \ |
2554 | do { \ | 2531 | do { \ |
2555 | res = rxh(rx); \ | 2532 | res = rxh(rx); \ |
@@ -2560,9 +2537,9 @@ static void ieee80211_invoke_rx_handlers(struct ieee80211_rx_data *rx) | |||
2560 | CALL_RXH(ieee80211_rx_h_passive_scan) | 2537 | CALL_RXH(ieee80211_rx_h_passive_scan) |
2561 | CALL_RXH(ieee80211_rx_h_check) | 2538 | CALL_RXH(ieee80211_rx_h_check) |
2562 | 2539 | ||
2563 | ieee80211_rx_reorder_ampdu(rx, &reorder_release); | 2540 | ieee80211_rx_reorder_ampdu(rx); |
2564 | 2541 | ||
2565 | ieee80211_rx_handlers(rx, &reorder_release); | 2542 | ieee80211_rx_handlers(rx); |
2566 | return; | 2543 | return; |
2567 | 2544 | ||
2568 | rxh_next: | 2545 | rxh_next: |
@@ -2577,7 +2554,6 @@ static void ieee80211_invoke_rx_handlers(struct ieee80211_rx_data *rx) | |||
2577 | */ | 2554 | */ |
2578 | void ieee80211_release_reorder_timeout(struct sta_info *sta, int tid) | 2555 | void ieee80211_release_reorder_timeout(struct sta_info *sta, int tid) |
2579 | { | 2556 | { |
2580 | struct sk_buff_head frames; | ||
2581 | struct ieee80211_rx_data rx = { | 2557 | struct ieee80211_rx_data rx = { |
2582 | .sta = sta, | 2558 | .sta = sta, |
2583 | .sdata = sta->sdata, | 2559 | .sdata = sta->sdata, |
@@ -2590,13 +2566,11 @@ void ieee80211_release_reorder_timeout(struct sta_info *sta, int tid) | |||
2590 | if (!tid_agg_rx) | 2566 | if (!tid_agg_rx) |
2591 | return; | 2567 | return; |
2592 | 2568 | ||
2593 | __skb_queue_head_init(&frames); | ||
2594 | |||
2595 | spin_lock(&tid_agg_rx->reorder_lock); | 2569 | spin_lock(&tid_agg_rx->reorder_lock); |
2596 | ieee80211_sta_reorder_release(&sta->local->hw, tid_agg_rx, &frames); | 2570 | ieee80211_sta_reorder_release(&sta->local->hw, tid_agg_rx); |
2597 | spin_unlock(&tid_agg_rx->reorder_lock); | 2571 | spin_unlock(&tid_agg_rx->reorder_lock); |
2598 | 2572 | ||
2599 | ieee80211_rx_handlers(&rx, &frames); | 2573 | ieee80211_rx_handlers(&rx); |
2600 | } | 2574 | } |
2601 | 2575 | ||
2602 | /* main receive path */ | 2576 | /* main receive path */ |
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 68c2fbd16ebb..5950e3abead9 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
@@ -1750,6 +1750,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1750 | __le16 fc; | 1750 | __le16 fc; |
1751 | struct ieee80211_hdr hdr; | 1751 | struct ieee80211_hdr hdr; |
1752 | struct ieee80211s_hdr mesh_hdr __maybe_unused; | 1752 | struct ieee80211s_hdr mesh_hdr __maybe_unused; |
1753 | struct mesh_path *mppath = NULL; | ||
1753 | const u8 *encaps_data; | 1754 | const u8 *encaps_data; |
1754 | int encaps_len, skip_header_bytes; | 1755 | int encaps_len, skip_header_bytes; |
1755 | int nh_pos, h_pos; | 1756 | int nh_pos, h_pos; |
@@ -1810,16 +1811,23 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1810 | ret = NETDEV_TX_OK; | 1811 | ret = NETDEV_TX_OK; |
1811 | goto fail; | 1812 | goto fail; |
1812 | } | 1813 | } |
1814 | if (!is_multicast_ether_addr(skb->data)) | ||
1815 | mppath = mpp_path_lookup(skb->data, sdata); | ||
1813 | 1816 | ||
1817 | /* | ||
1818 | * Do not use address extension, if it is a packet from | ||
1819 | * the same interface and the destination is not being | ||
1820 | * proxied by any other mest point. | ||
1821 | */ | ||
1814 | if (compare_ether_addr(sdata->vif.addr, | 1822 | if (compare_ether_addr(sdata->vif.addr, |
1815 | skb->data + ETH_ALEN) == 0) { | 1823 | skb->data + ETH_ALEN) == 0 && |
1824 | (!mppath || !compare_ether_addr(mppath->mpp, skb->data))) { | ||
1816 | hdrlen = ieee80211_fill_mesh_addresses(&hdr, &fc, | 1825 | hdrlen = ieee80211_fill_mesh_addresses(&hdr, &fc, |
1817 | skb->data, skb->data + ETH_ALEN); | 1826 | skb->data, skb->data + ETH_ALEN); |
1818 | meshhdrlen = ieee80211_new_mesh_header(&mesh_hdr, | 1827 | meshhdrlen = ieee80211_new_mesh_header(&mesh_hdr, |
1819 | sdata, NULL, NULL); | 1828 | sdata, NULL, NULL); |
1820 | } else { | 1829 | } else { |
1821 | /* packet from other interface */ | 1830 | /* packet from other interface */ |
1822 | struct mesh_path *mppath; | ||
1823 | int is_mesh_mcast = 1; | 1831 | int is_mesh_mcast = 1; |
1824 | const u8 *mesh_da; | 1832 | const u8 *mesh_da; |
1825 | 1833 | ||
@@ -1830,8 +1838,6 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1830 | else { | 1838 | else { |
1831 | static const u8 bcast[ETH_ALEN] = | 1839 | static const u8 bcast[ETH_ALEN] = |
1832 | { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; | 1840 | { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; |
1833 | |||
1834 | mppath = mpp_path_lookup(skb->data, sdata); | ||
1835 | if (mppath) { | 1841 | if (mppath) { |
1836 | /* RA TA mDA mSA AE:DA SA */ | 1842 | /* RA TA mDA mSA AE:DA SA */ |
1837 | mesh_da = mppath->mpp; | 1843 | mesh_da = mppath->mpp; |
diff --git a/net/mac80211/wme.c b/net/mac80211/wme.c index 58e75bbc1f91..28bc084dbfb9 100644 --- a/net/mac80211/wme.c +++ b/net/mac80211/wme.c | |||
@@ -59,26 +59,22 @@ u16 ieee80211_select_queue(struct ieee80211_sub_if_data *sdata, | |||
59 | { | 59 | { |
60 | struct ieee80211_local *local = sdata->local; | 60 | struct ieee80211_local *local = sdata->local; |
61 | struct sta_info *sta = NULL; | 61 | struct sta_info *sta = NULL; |
62 | u32 sta_flags = 0; | ||
63 | const u8 *ra = NULL; | 62 | const u8 *ra = NULL; |
64 | bool qos = false; | 63 | bool qos = false; |
65 | 64 | ||
66 | if (local->hw.queues < 4 || skb->len < 6) { | 65 | if (local->hw.queues < 4 || skb->len < 6) { |
67 | skb->priority = 0; /* required for correct WPA/11i MIC */ | 66 | skb->priority = 0; /* required for correct WPA/11i MIC */ |
68 | return min_t(u16, local->hw.queues - 1, | 67 | return min_t(u16, local->hw.queues - 1, IEEE80211_AC_BE); |
69 | ieee802_1d_to_ac[skb->priority]); | ||
70 | } | 68 | } |
71 | 69 | ||
72 | rcu_read_lock(); | 70 | rcu_read_lock(); |
73 | switch (sdata->vif.type) { | 71 | switch (sdata->vif.type) { |
74 | case NL80211_IFTYPE_AP_VLAN: | 72 | case NL80211_IFTYPE_AP_VLAN: |
75 | rcu_read_lock(); | ||
76 | sta = rcu_dereference(sdata->u.vlan.sta); | 73 | sta = rcu_dereference(sdata->u.vlan.sta); |
77 | if (sta) | 74 | if (sta) { |
78 | sta_flags = get_sta_flags(sta); | 75 | qos = get_sta_flags(sta) & WLAN_STA_WME; |
79 | rcu_read_unlock(); | ||
80 | if (sta) | ||
81 | break; | 76 | break; |
77 | } | ||
82 | case NL80211_IFTYPE_AP: | 78 | case NL80211_IFTYPE_AP: |
83 | ra = skb->data; | 79 | ra = skb->data; |
84 | break; | 80 | break; |
@@ -107,17 +103,13 @@ u16 ieee80211_select_queue(struct ieee80211_sub_if_data *sdata, | |||
107 | if (!sta && ra && !is_multicast_ether_addr(ra)) { | 103 | if (!sta && ra && !is_multicast_ether_addr(ra)) { |
108 | sta = sta_info_get(sdata, ra); | 104 | sta = sta_info_get(sdata, ra); |
109 | if (sta) | 105 | if (sta) |
110 | sta_flags = get_sta_flags(sta); | 106 | qos = get_sta_flags(sta) & WLAN_STA_WME; |
111 | } | 107 | } |
112 | |||
113 | if (sta_flags & WLAN_STA_WME) | ||
114 | qos = true; | ||
115 | |||
116 | rcu_read_unlock(); | 108 | rcu_read_unlock(); |
117 | 109 | ||
118 | if (!qos) { | 110 | if (!qos) { |
119 | skb->priority = 0; /* required for correct WPA/11i MIC */ | 111 | skb->priority = 0; /* required for correct WPA/11i MIC */ |
120 | return ieee802_1d_to_ac[skb->priority]; | 112 | return IEEE80211_AC_BE; |
121 | } | 113 | } |
122 | 114 | ||
123 | /* use the data classifier to determine what 802.1d tag the | 115 | /* use the data classifier to determine what 802.1d tag the |