diff options
author | Johannes Berg <johannes.berg@intel.com> | 2013-12-04 16:46:11 -0500 |
---|---|---|
committer | Johannes Berg <johannes.berg@intel.com> | 2013-12-16 05:29:45 -0500 |
commit | d34ba2168a3c10e7301cca06069c39865b4c3ec6 (patch) | |
tree | 709e9c81eba18202588852e39d66fcf893334451 /net/mac80211/sta_info.c | |
parent | a710c8160dd93e981163759aad754f758850273a (diff) |
mac80211: don't delay station destruction
If we can assume that stations are never referenced by the
driver after sta_state returns (and this is true since the
previous iwlmvm patch and for all other drivers) then we
don't need to delay station destruction, and don't need to
play tricks with rcu_barrier() etc.
This should speed up some scenarios like hostapd shutdown.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net/mac80211/sta_info.c')
-rw-r--r-- | net/mac80211/sta_info.c | 58 |
1 files changed, 2 insertions, 56 deletions
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index 557ac250ac10..7241f3229a27 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c | |||
@@ -99,23 +99,6 @@ static void cleanup_single_sta(struct sta_info *sta) | |||
99 | struct ieee80211_local *local = sdata->local; | 99 | struct ieee80211_local *local = sdata->local; |
100 | struct ps_data *ps; | 100 | struct ps_data *ps; |
101 | 101 | ||
102 | /* | ||
103 | * At this point, when being called as call_rcu callback, | ||
104 | * neither mac80211 nor the driver can reference this | ||
105 | * sta struct any more except by still existing timers | ||
106 | * associated with this station that we clean up below. | ||
107 | * | ||
108 | * Note though that this still uses the sdata and even | ||
109 | * calls the driver in AP and mesh mode, so interfaces | ||
110 | * of those types mush use call sta_info_flush_cleanup() | ||
111 | * (typically via sta_info_flush()) before deconfiguring | ||
112 | * the driver. | ||
113 | * | ||
114 | * In station mode, nothing happens here so it doesn't | ||
115 | * have to (and doesn't) do that, this is intentional to | ||
116 | * speed up roaming. | ||
117 | */ | ||
118 | |||
119 | if (test_sta_flag(sta, WLAN_STA_PS_STA)) { | 102 | if (test_sta_flag(sta, WLAN_STA_PS_STA)) { |
120 | if (sta->sdata->vif.type == NL80211_IFTYPE_AP || | 103 | if (sta->sdata->vif.type == NL80211_IFTYPE_AP || |
121 | sta->sdata->vif.type == NL80211_IFTYPE_AP_VLAN) | 104 | sta->sdata->vif.type == NL80211_IFTYPE_AP_VLAN) |
@@ -160,37 +143,6 @@ static void cleanup_single_sta(struct sta_info *sta) | |||
160 | sta_info_free(local, sta); | 143 | sta_info_free(local, sta); |
161 | } | 144 | } |
162 | 145 | ||
163 | void ieee80211_cleanup_sdata_stas(struct ieee80211_sub_if_data *sdata) | ||
164 | { | ||
165 | struct sta_info *sta; | ||
166 | |||
167 | spin_lock_bh(&sdata->cleanup_stations_lock); | ||
168 | while (!list_empty(&sdata->cleanup_stations)) { | ||
169 | sta = list_first_entry(&sdata->cleanup_stations, | ||
170 | struct sta_info, list); | ||
171 | list_del(&sta->list); | ||
172 | spin_unlock_bh(&sdata->cleanup_stations_lock); | ||
173 | |||
174 | cleanup_single_sta(sta); | ||
175 | |||
176 | spin_lock_bh(&sdata->cleanup_stations_lock); | ||
177 | } | ||
178 | |||
179 | spin_unlock_bh(&sdata->cleanup_stations_lock); | ||
180 | } | ||
181 | |||
182 | static void free_sta_rcu(struct rcu_head *h) | ||
183 | { | ||
184 | struct sta_info *sta = container_of(h, struct sta_info, rcu_head); | ||
185 | struct ieee80211_sub_if_data *sdata = sta->sdata; | ||
186 | |||
187 | spin_lock(&sdata->cleanup_stations_lock); | ||
188 | list_add_tail(&sta->list, &sdata->cleanup_stations); | ||
189 | spin_unlock(&sdata->cleanup_stations_lock); | ||
190 | |||
191 | ieee80211_queue_work(&sdata->local->hw, &sdata->cleanup_stations_wk); | ||
192 | } | ||
193 | |||
194 | /* protected by RCU */ | 146 | /* protected by RCU */ |
195 | struct sta_info *sta_info_get(struct ieee80211_sub_if_data *sdata, | 147 | struct sta_info *sta_info_get(struct ieee80211_sub_if_data *sdata, |
196 | const u8 *addr) | 148 | const u8 *addr) |
@@ -909,7 +861,7 @@ int __must_check __sta_info_destroy(struct sta_info *sta) | |||
909 | ieee80211_sta_debugfs_remove(sta); | 861 | ieee80211_sta_debugfs_remove(sta); |
910 | ieee80211_recalc_min_chandef(sdata); | 862 | ieee80211_recalc_min_chandef(sdata); |
911 | 863 | ||
912 | call_rcu(&sta->rcu_head, free_sta_rcu); | 864 | cleanup_single_sta(sta); |
913 | 865 | ||
914 | return 0; | 866 | return 0; |
915 | } | 867 | } |
@@ -979,7 +931,7 @@ void sta_info_stop(struct ieee80211_local *local) | |||
979 | } | 931 | } |
980 | 932 | ||
981 | 933 | ||
982 | int sta_info_flush_defer(struct ieee80211_sub_if_data *sdata) | 934 | int sta_info_flush(struct ieee80211_sub_if_data *sdata) |
983 | { | 935 | { |
984 | struct ieee80211_local *local = sdata->local; | 936 | struct ieee80211_local *local = sdata->local; |
985 | struct sta_info *sta, *tmp; | 937 | struct sta_info *sta, *tmp; |
@@ -999,12 +951,6 @@ int sta_info_flush_defer(struct ieee80211_sub_if_data *sdata) | |||
999 | return ret; | 951 | return ret; |
1000 | } | 952 | } |
1001 | 953 | ||
1002 | void sta_info_flush_cleanup(struct ieee80211_sub_if_data *sdata) | ||
1003 | { | ||
1004 | ieee80211_cleanup_sdata_stas(sdata); | ||
1005 | cancel_work_sync(&sdata->cleanup_stations_wk); | ||
1006 | } | ||
1007 | |||
1008 | void ieee80211_sta_expire(struct ieee80211_sub_if_data *sdata, | 954 | void ieee80211_sta_expire(struct ieee80211_sub_if_data *sdata, |
1009 | unsigned long exp_time) | 955 | unsigned long exp_time) |
1010 | { | 956 | { |