diff options
author | Eliad Peller <eliad@wizery.com> | 2012-09-09 07:43:51 -0400 |
---|---|---|
committer | Johannes Berg <johannes.berg@intel.com> | 2012-09-10 06:44:17 -0400 |
commit | b22cfcfcae5b2c1e9b43543b6a23e5ef517de8f8 (patch) | |
tree | b87ec8f76a6ccdd4d8d5ed9752d4bfedf3ea04c3 /net/mac80211/iface.c | |
parent | e548c49e6dc6b08b59042930a2e90c69c13c9293 (diff) |
mac80211: use call_rcu() on sta deletion
mac80211 calls synchronize_rcu() on sta deletion,
which increase the roaming time significantly.
Convert it into a call_rcu() mechanism, in order
to avoid blocking. Since some of the cleanup
functions might sleep, schedule from the call_rcu
callback a new work that will do the actual cleanup.
In order to make sure the cleanup occurs before
the interface went down, flush local->workqueue
on ieee80211_do_stop().
Signed-off-by: Yoni Divinsky <yoni.divinsky@ti.com>
Signed-off-by: Eliad Peller <eliad@wizery.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net/mac80211/iface.c')
-rw-r--r-- | net/mac80211/iface.c | 15 |
1 files changed, 12 insertions, 3 deletions
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index d747da541747..6f8a73c64fb3 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c | |||
@@ -793,11 +793,20 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, | |||
793 | flush_work(&sdata->work); | 793 | flush_work(&sdata->work); |
794 | /* | 794 | /* |
795 | * When we get here, the interface is marked down. | 795 | * When we get here, the interface is marked down. |
796 | * Call synchronize_rcu() to wait for the RX path | 796 | * Call rcu_barrier() to wait both for the RX path |
797 | * should it be using the interface and enqueuing | 797 | * should it be using the interface and enqueuing |
798 | * frames at this very time on another CPU. | 798 | * frames at this very time on another CPU, and |
799 | * for the sta free call_rcu callbacks. | ||
799 | */ | 800 | */ |
800 | synchronize_rcu(); | 801 | rcu_barrier(); |
802 | |||
803 | /* | ||
804 | * free_sta_rcu() enqueues a work for the actual | ||
805 | * sta cleanup, so we need to flush it while | ||
806 | * sdata is still valid. | ||
807 | */ | ||
808 | flush_workqueue(local->workqueue); | ||
809 | |||
801 | skb_queue_purge(&sdata->skb_queue); | 810 | skb_queue_purge(&sdata->skb_queue); |
802 | 811 | ||
803 | /* | 812 | /* |