diff options
author | Johannes Berg <johannes.berg@intel.com> | 2012-12-13 17:49:02 -0500 |
---|---|---|
committer | Johannes Berg <johannes.berg@intel.com> | 2013-01-03 07:01:17 -0500 |
commit | 051007d9e281cd8ea603a4cc4c96b0170b26c7e9 (patch) | |
tree | 3c7b62d4290774d41b24562537d781847a6c5b36 /net/mac80211/iface.c | |
parent | 09f4114e02aac9cbf40553a17580b07ab29715d8 (diff) |
mac80211: optimise roaming time again
The last fixes re-added the RCU synchronize penalty
on roaming to fix the races. Split up sta_info_flush()
now to get rid of that again, and let managed mode
(and only it) delay the actual destruction.
Tested-by: Ben Greear <greearb@candelatech.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, 10 insertions, 5 deletions
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 604b4aae3364..12341efb109e 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c | |||
@@ -775,8 +775,10 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, | |||
775 | * This is relevant only in WDS mode, in all other modes we've | 775 | * This is relevant only in WDS mode, in all other modes we've |
776 | * already removed all stations when disconnecting or similar, | 776 | * already removed all stations when disconnecting or similar, |
777 | * so warn otherwise. | 777 | * so warn otherwise. |
778 | * | ||
779 | * We call sta_info_flush_cleanup() later, to combine RCU waits. | ||
778 | */ | 780 | */ |
779 | flushed = sta_info_flush(sdata); | 781 | flushed = sta_info_flush_defer(sdata); |
780 | WARN_ON_ONCE((sdata->vif.type != NL80211_IFTYPE_WDS && flushed > 0) || | 782 | WARN_ON_ONCE((sdata->vif.type != NL80211_IFTYPE_WDS && flushed > 0) || |
781 | (sdata->vif.type == NL80211_IFTYPE_WDS && flushed != 1)); | 783 | (sdata->vif.type == NL80211_IFTYPE_WDS && flushed != 1)); |
782 | 784 | ||
@@ -861,11 +863,14 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, | |||
861 | cancel_work_sync(&sdata->work); | 863 | cancel_work_sync(&sdata->work); |
862 | /* | 864 | /* |
863 | * When we get here, the interface is marked down. | 865 | * When we get here, the interface is marked down. |
864 | * Call synchronize_rcu() to wait for the RX path | 866 | * sta_info_flush_cleanup() calls rcu_barrier to |
865 | * should it be using the interface and enqueuing | 867 | * wait for the station call_rcu() calls to complete, |
866 | * frames at this very time on another CPU. | 868 | * here we require it to wait for the RX path in case |
869 | * it is using the interface and enqueuing frames at | ||
870 | * this very time on another CPU. | ||
867 | */ | 871 | */ |
868 | synchronize_rcu(); | 872 | sta_info_flush_cleanup(sdata); |
873 | |||
869 | skb_queue_purge(&sdata->skb_queue); | 874 | skb_queue_purge(&sdata->skb_queue); |
870 | 875 | ||
871 | /* | 876 | /* |