diff options
author | Christian Lamparter <chunkeey@googlemail.com> | 2013-02-04 12:44:44 -0500 |
---|---|---|
committer | Johannes Berg <johannes.berg@intel.com> | 2013-02-11 12:44:55 -0500 |
commit | f9e124fbd8cbea974b5dc7e9dafddd17d21df7e2 (patch) | |
tree | f09c89096de26a4211d73742933260d5d240b58e /net/mac80211/main.c | |
parent | 601513aa208f27ea87400a410d42c978421530ec (diff) |
mac80211: protect rx-path with spinlock
This patch fixes the problem which was discussed in
"mac80211: Fix PN corruption in case of multiple
virtual interface" [1].
Amit Shakya reported a serious issue with my patch:
mac80211: serialize rx path workers" [2]:
In case, ieee80211_rx_handlers processing is going on
for skbs received on one vif and at the same time, rx
aggregation reorder timer expires on another vif then
sta_rx_agg_reorder_timer_expired is invoked and it will
push skbs into the single queue (local->rx_skb_queue).
ieee80211_rx_handlers in the while loop assumes that
the skbs are for the same sdata and sta. This assumption
doesn't hold good in this scenario and the PN gets
corrupted by PN received in other vif's skb, causing
traffic to stop due to PN mismatch."
[1] Message-Id: http://mid.gmane.org/201302041844.44436.chunkeey@googlemail.com
[2] Commit-Id: 24a8fdad35835e8d71f7
Reported-by: Amit Shakya <amit.shakya@stericsson.com>
Signed-off-by: Christian Lamparter <chunkeey@googlemail.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net/mac80211/main.c')
-rw-r--r-- | net/mac80211/main.c | 14 |
1 files changed, 1 insertions, 13 deletions
diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 2bdd454e8bcf..2220331f4b7c 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c | |||
@@ -34,8 +34,6 @@ | |||
34 | #include "cfg.h" | 34 | #include "cfg.h" |
35 | #include "debugfs.h" | 35 | #include "debugfs.h" |
36 | 36 | ||
37 | static struct lock_class_key ieee80211_rx_skb_queue_class; | ||
38 | |||
39 | void ieee80211_configure_filter(struct ieee80211_local *local) | 37 | void ieee80211_configure_filter(struct ieee80211_local *local) |
40 | { | 38 | { |
41 | u64 mc; | 39 | u64 mc; |
@@ -613,21 +611,12 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, | |||
613 | 611 | ||
614 | mutex_init(&local->key_mtx); | 612 | mutex_init(&local->key_mtx); |
615 | spin_lock_init(&local->filter_lock); | 613 | spin_lock_init(&local->filter_lock); |
614 | spin_lock_init(&local->rx_path_lock); | ||
616 | spin_lock_init(&local->queue_stop_reason_lock); | 615 | spin_lock_init(&local->queue_stop_reason_lock); |
617 | 616 | ||
618 | INIT_LIST_HEAD(&local->chanctx_list); | 617 | INIT_LIST_HEAD(&local->chanctx_list); |
619 | mutex_init(&local->chanctx_mtx); | 618 | mutex_init(&local->chanctx_mtx); |
620 | 619 | ||
621 | /* | ||
622 | * The rx_skb_queue is only accessed from tasklets, | ||
623 | * but other SKB queues are used from within IRQ | ||
624 | * context. Therefore, this one needs a different | ||
625 | * locking class so our direct, non-irq-safe use of | ||
626 | * the queue's lock doesn't throw lockdep warnings. | ||
627 | */ | ||
628 | skb_queue_head_init_class(&local->rx_skb_queue, | ||
629 | &ieee80211_rx_skb_queue_class); | ||
630 | |||
631 | INIT_DELAYED_WORK(&local->scan_work, ieee80211_scan_work); | 620 | INIT_DELAYED_WORK(&local->scan_work, ieee80211_scan_work); |
632 | 621 | ||
633 | INIT_WORK(&local->restart_work, ieee80211_restart_work); | 622 | INIT_WORK(&local->restart_work, ieee80211_restart_work); |
@@ -1089,7 +1078,6 @@ void ieee80211_unregister_hw(struct ieee80211_hw *hw) | |||
1089 | wiphy_warn(local->hw.wiphy, "skb_queue not empty\n"); | 1078 | wiphy_warn(local->hw.wiphy, "skb_queue not empty\n"); |
1090 | skb_queue_purge(&local->skb_queue); | 1079 | skb_queue_purge(&local->skb_queue); |
1091 | skb_queue_purge(&local->skb_queue_unreliable); | 1080 | skb_queue_purge(&local->skb_queue_unreliable); |
1092 | skb_queue_purge(&local->rx_skb_queue); | ||
1093 | 1081 | ||
1094 | destroy_workqueue(local->workqueue); | 1082 | destroy_workqueue(local->workqueue); |
1095 | wiphy_unregister(local->hw.wiphy); | 1083 | wiphy_unregister(local->hw.wiphy); |