aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2013-12-04 17:12:31 -0500
committerJohannes Berg <johannes.berg@intel.com>2013-12-16 05:29:47 -0500
commitd778207b06ac1becd012eb689dafdf85feebb179 (patch)
treea6b248949b392e66908cc98aedb2b5b9defc96a1 /net/mac80211
parentc87820784454bbf7fc63a9e7d9c36762a46f393c (diff)
mac80211: optimise synchronize_net() for sta_info_flush
There's no reason to have one synchronize_net() for each removed station, refactor the code slightly to have just a single synchronize_net() for all stations. Note that this is currently useless as hostapd removes stations one by one and this coalescing never happens. Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net/mac80211')
-rw-r--r--net/mac80211/sta_info.c42
-rw-r--r--net/mac80211/sta_info.h3
2 files changed, 41 insertions, 4 deletions
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index 08e50760e092..89d449d0de6d 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -794,7 +794,7 @@ static bool sta_info_cleanup_expire_buffered(struct ieee80211_local *local,
794 return have_buffered; 794 return have_buffered;
795} 795}
796 796
797int __must_check __sta_info_destroy(struct sta_info *sta) 797static int __must_check __sta_info_destroy_part1(struct sta_info *sta)
798{ 798{
799 struct ieee80211_local *local; 799 struct ieee80211_local *local;
800 struct ieee80211_sub_if_data *sdata; 800 struct ieee80211_sub_if_data *sdata;
@@ -831,7 +831,23 @@ int __must_check __sta_info_destroy(struct sta_info *sta)
831 rcu_access_pointer(sdata->u.vlan.sta) == sta) 831 rcu_access_pointer(sdata->u.vlan.sta) == sta)
832 RCU_INIT_POINTER(sdata->u.vlan.sta, NULL); 832 RCU_INIT_POINTER(sdata->u.vlan.sta, NULL);
833 833
834 synchronize_net(); 834 return 0;
835}
836
837static void __sta_info_destroy_part2(struct sta_info *sta)
838{
839 struct ieee80211_local *local = sta->local;
840 struct ieee80211_sub_if_data *sdata = sta->sdata;
841 int ret;
842
843 /*
844 * NOTE: This assumes at least synchronize_net() was done
845 * after _part1 and before _part2!
846 */
847
848 might_sleep();
849 lockdep_assert_held(&local->sta_mtx);
850
835 /* now keys can no longer be reached */ 851 /* now keys can no longer be reached */
836 ieee80211_free_sta_keys(local, sta); 852 ieee80211_free_sta_keys(local, sta);
837 853
@@ -863,6 +879,18 @@ int __must_check __sta_info_destroy(struct sta_info *sta)
863 ieee80211_recalc_min_chandef(sdata); 879 ieee80211_recalc_min_chandef(sdata);
864 880
865 cleanup_single_sta(sta); 881 cleanup_single_sta(sta);
882}
883
884int __must_check __sta_info_destroy(struct sta_info *sta)
885{
886 int err = __sta_info_destroy_part1(sta);
887
888 if (err)
889 return err;
890
891 synchronize_net();
892
893 __sta_info_destroy_part2(sta);
866 894
867 return 0; 895 return 0;
868} 896}
@@ -936,6 +964,7 @@ int sta_info_flush(struct ieee80211_sub_if_data *sdata)
936{ 964{
937 struct ieee80211_local *local = sdata->local; 965 struct ieee80211_local *local = sdata->local;
938 struct sta_info *sta, *tmp; 966 struct sta_info *sta, *tmp;
967 LIST_HEAD(free_list);
939 int ret = 0; 968 int ret = 0;
940 969
941 might_sleep(); 970 might_sleep();
@@ -943,10 +972,17 @@ int sta_info_flush(struct ieee80211_sub_if_data *sdata)
943 mutex_lock(&local->sta_mtx); 972 mutex_lock(&local->sta_mtx);
944 list_for_each_entry_safe(sta, tmp, &local->sta_list, list) { 973 list_for_each_entry_safe(sta, tmp, &local->sta_list, list) {
945 if (sdata == sta->sdata) { 974 if (sdata == sta->sdata) {
946 WARN_ON(__sta_info_destroy(sta)); 975 if (!WARN_ON(__sta_info_destroy_part1(sta)))
976 list_add(&sta->free_list, &free_list);
947 ret++; 977 ret++;
948 } 978 }
949 } 979 }
980
981 if (!list_empty(&free_list)) {
982 synchronize_net();
983 list_for_each_entry_safe(sta, tmp, &free_list, free_list)
984 __sta_info_destroy_part2(sta);
985 }
950 mutex_unlock(&local->sta_mtx); 986 mutex_unlock(&local->sta_mtx);
951 987
952 return ret; 988 return ret;
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
index 9104f812e9de..f6081e574a28 100644
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
@@ -247,6 +247,7 @@ struct ieee80211_tx_latency_stat {
247 * mac80211 is communicating with. 247 * mac80211 is communicating with.
248 * 248 *
249 * @list: global linked list entry 249 * @list: global linked list entry
250 * @free_list: list entry for keeping track of stations to free
250 * @hnext: hash table linked list pointer 251 * @hnext: hash table linked list pointer
251 * @local: pointer to the global information 252 * @local: pointer to the global information
252 * @sdata: virtual interface this station belongs to 253 * @sdata: virtual interface this station belongs to
@@ -329,7 +330,7 @@ struct ieee80211_tx_latency_stat {
329 */ 330 */
330struct sta_info { 331struct sta_info {
331 /* General information, mostly static */ 332 /* General information, mostly static */
332 struct list_head list; 333 struct list_head list, free_list;
333 struct rcu_head rcu_head; 334 struct rcu_head rcu_head;
334 struct sta_info __rcu *hnext; 335 struct sta_info __rcu *hnext;
335 struct ieee80211_local *local; 336 struct ieee80211_local *local;