mac80211: optimise mixed AP/VLAN station removal
authorJohannes Berg <johannes.berg@intel.com>
Wed, 4 Dec 2013 22:18:37 +0000 (23:18 +0100)
committerJohannes Berg <johannes.berg@intel.com>
Mon, 16 Dec 2013 10:29:47 +0000 (11:29 +0100)
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: Johannes Berg <johannes.berg@intel.com>
net/mac80211/cfg.c
net/mac80211/sta_info.c
net/mac80211/sta_info.h

index e11bdb63167ac3273b62055e922c14457911bc78..18b56fb7911ef192fc221e9a97d3711bb0c90444 100644 (file)
@@ -1097,9 +1097,7 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev)
        if (old_probe_resp)
                kfree_rcu(old_probe_resp, rcu_head);
 
-       list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list)
-               sta_info_flush(vlan);
-       sta_info_flush(sdata);
+       __sta_info_flush(sdata, true);
        synchronize_net();
        list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list)
                ieee80211_free_keys(vlan);
index 89d449d0de6d35e26e90d630c4df850577ed876b..4576ba0ff2211af31664b10dd40e996e490286df 100644 (file)
@@ -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 sta_info *sta, *tmp;
@@ -969,9 +969,13 @@ int sta_info_flush(struct ieee80211_sub_if_data *sdata)
 
        might_sleep();
 
+       WARN_ON(vlans && sdata->vif.type != NL80211_IFTYPE_AP);
+       WARN_ON(vlans && !sdata->bss);
+
        mutex_lock(&local->sta_mtx);
        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)))
                                list_add(&sta->free_list, &free_list);
                        ret++;
index f6081e574a2845a5ff3d5d10889f65e105b39e21..d77ff70906303855458734a5bfac0526460056eb 100644 (file)
@@ -613,8 +613,14 @@ void sta_info_stop(struct ieee80211_local *local);
  * Returns the number of removed STA entries.
  *
  * @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,
                          const struct ieee80211_tx_rate *rate,