Commit e716251d authored by Johannes Berg's avatar Johannes Berg

mac80211: optimise mixed AP/VLAN station removal

Teach sta_info_flush() to optionally also remove stations
from all VLANs associated with an AP interface to optimise
the station removal (in particular, synchronize_net().)

To not have to add the vlans argument throughout, do some
refactoring.
Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent d778207b
...@@ -1097,9 +1097,7 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev) ...@@ -1097,9 +1097,7 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev)
if (old_probe_resp) if (old_probe_resp)
kfree_rcu(old_probe_resp, rcu_head); kfree_rcu(old_probe_resp, rcu_head);
list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list) __sta_info_flush(sdata, true);
sta_info_flush(vlan);
sta_info_flush(sdata);
synchronize_net(); synchronize_net();
list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list) list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list)
ieee80211_free_keys(vlan); ieee80211_free_keys(vlan);
......
...@@ -960,7 +960,7 @@ void sta_info_stop(struct ieee80211_local *local) ...@@ -960,7 +960,7 @@ void sta_info_stop(struct ieee80211_local *local)
} }
int sta_info_flush(struct ieee80211_sub_if_data *sdata) int __sta_info_flush(struct ieee80211_sub_if_data *sdata, bool vlans)
{ {
struct ieee80211_local *local = sdata->local; struct ieee80211_local *local = sdata->local;
struct sta_info *sta, *tmp; struct sta_info *sta, *tmp;
...@@ -969,9 +969,13 @@ int sta_info_flush(struct ieee80211_sub_if_data *sdata) ...@@ -969,9 +969,13 @@ int sta_info_flush(struct ieee80211_sub_if_data *sdata)
might_sleep(); might_sleep();
WARN_ON(vlans && sdata->vif.type != NL80211_IFTYPE_AP);
WARN_ON(vlans && !sdata->bss);
mutex_lock(&local->sta_mtx); mutex_lock(&local->sta_mtx);
list_for_each_entry_safe(sta, tmp, &local->sta_list, list) { list_for_each_entry_safe(sta, tmp, &local->sta_list, list) {
if (sdata == sta->sdata) { if (sdata == sta->sdata ||
(vlans && sdata->bss == sta->sdata->bss)) {
if (!WARN_ON(__sta_info_destroy_part1(sta))) if (!WARN_ON(__sta_info_destroy_part1(sta)))
list_add(&sta->free_list, &free_list); list_add(&sta->free_list, &free_list);
ret++; ret++;
......
...@@ -613,8 +613,14 @@ void sta_info_stop(struct ieee80211_local *local); ...@@ -613,8 +613,14 @@ void sta_info_stop(struct ieee80211_local *local);
* Returns the number of removed STA entries. * Returns the number of removed STA entries.
* *
* @sdata: sdata to remove all stations from * @sdata: sdata to remove all stations from
* @vlans: if the given interface is an AP interface, also flush VLANs
*/ */
int sta_info_flush(struct ieee80211_sub_if_data *sdata); int __sta_info_flush(struct ieee80211_sub_if_data *sdata, bool vlans);
static inline int sta_info_flush(struct ieee80211_sub_if_data *sdata)
{
return __sta_info_flush(sdata, false);
}
void sta_set_rate_info_tx(struct sta_info *sta, void sta_set_rate_info_tx(struct sta_info *sta,
const struct ieee80211_tx_rate *rate, const struct ieee80211_tx_rate *rate,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment