aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2013-12-04 16:46:11 -0500
committerJohannes Berg <johannes.berg@intel.com>2013-12-16 05:29:45 -0500
commitd34ba2168a3c10e7301cca06069c39865b4c3ec6 (patch)
tree709e9c81eba18202588852e39d66fcf893334451 /net/mac80211
parenta710c8160dd93e981163759aad754f758850273a (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')
-rw-r--r--net/mac80211/cfg.c10
-rw-r--r--net/mac80211/ieee80211_i.h4
-rw-r--r--net/mac80211/iface.c27
-rw-r--r--net/mac80211/mlme.c2
-rw-r--r--net/mac80211/pm.c3
-rw-r--r--net/mac80211/sta_info.c58
-rw-r--r--net/mac80211/sta_info.h27
7 files changed, 12 insertions, 119 deletions
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 8b790e7b221e..e11bdb63167a 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -1098,15 +1098,11 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev)
1098 kfree_rcu(old_probe_resp, rcu_head); 1098 kfree_rcu(old_probe_resp, rcu_head);
1099 1099
1100 list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list) 1100 list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list)
1101 sta_info_flush_defer(vlan); 1101 sta_info_flush(vlan);
1102 sta_info_flush_defer(sdata); 1102 sta_info_flush(sdata);
1103 synchronize_net(); 1103 synchronize_net();
1104 rcu_barrier(); 1104 list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list)
1105 list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list) {
1106 sta_info_flush_cleanup(vlan);
1107 ieee80211_free_keys(vlan); 1105 ieee80211_free_keys(vlan);
1108 }
1109 sta_info_flush_cleanup(sdata);
1110 ieee80211_free_keys(sdata); 1106 ieee80211_free_keys(sdata);
1111 1107
1112 sdata->vif.bss_conf.enable_beacon = false; 1108 sdata->vif.bss_conf.enable_beacon = false;
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index ed5bf8b4b5c2..44330b8e1c14 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -776,10 +776,6 @@ struct ieee80211_sub_if_data {
776 u32 mntr_flags; 776 u32 mntr_flags;
777 } u; 777 } u;
778 778
779 spinlock_t cleanup_stations_lock;
780 struct list_head cleanup_stations;
781 struct work_struct cleanup_stations_wk;
782
783#ifdef CONFIG_MAC80211_DEBUGFS 779#ifdef CONFIG_MAC80211_DEBUGFS
784 struct { 780 struct {
785 struct dentry *subdir_stations; 781 struct dentry *subdir_stations;
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index 1fe5d5810fc9..687d4eacd6ff 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -786,10 +786,8 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
786 * This is relevant only in WDS mode, in all other modes we've 786 * This is relevant only in WDS mode, in all other modes we've
787 * already removed all stations when disconnecting or similar, 787 * already removed all stations when disconnecting or similar,
788 * so warn otherwise. 788 * so warn otherwise.
789 *
790 * We call sta_info_flush_cleanup() later, to combine RCU waits.
791 */ 789 */
792 flushed = sta_info_flush_defer(sdata); 790 flushed = sta_info_flush(sdata);
793 WARN_ON_ONCE((sdata->vif.type != NL80211_IFTYPE_WDS && flushed > 0) || 791 WARN_ON_ONCE((sdata->vif.type != NL80211_IFTYPE_WDS && flushed > 0) ||
794 (sdata->vif.type == NL80211_IFTYPE_WDS && flushed != 1)); 792 (sdata->vif.type == NL80211_IFTYPE_WDS && flushed != 1));
795 793
@@ -892,16 +890,11 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
892 /* 890 /*
893 * When we get here, the interface is marked down. 891 * When we get here, the interface is marked down.
894 * 892 *
895 * sta_info_flush_cleanup() requires rcu_barrier() 893 * We need synchronize_rcu() to wait for the RX path in
896 * first to wait for the station call_rcu() calls 894 * case it is using the interface and enqueuing frames
897 * to complete, and we also need synchronize_rcu() 895 * at this very time on another CPU.
898 * to wait for the RX path in case it is using the
899 * interface and enqueuing frames at this very time on
900 * another CPU.
901 */ 896 */
902 synchronize_rcu(); 897 synchronize_rcu();
903 rcu_barrier();
904 sta_info_flush_cleanup(sdata);
905 898
906 /* 899 /*
907 * Free all remaining keys, there shouldn't be any, 900 * Free all remaining keys, there shouldn't be any,
@@ -1568,15 +1561,6 @@ static void ieee80211_assign_perm_addr(struct ieee80211_local *local,
1568 mutex_unlock(&local->iflist_mtx); 1561 mutex_unlock(&local->iflist_mtx);
1569} 1562}
1570 1563
1571static void ieee80211_cleanup_sdata_stas_wk(struct work_struct *wk)
1572{
1573 struct ieee80211_sub_if_data *sdata;
1574
1575 sdata = container_of(wk, struct ieee80211_sub_if_data, cleanup_stations_wk);
1576
1577 ieee80211_cleanup_sdata_stas(sdata);
1578}
1579
1580int ieee80211_if_add(struct ieee80211_local *local, const char *name, 1564int ieee80211_if_add(struct ieee80211_local *local, const char *name,
1581 struct wireless_dev **new_wdev, enum nl80211_iftype type, 1565 struct wireless_dev **new_wdev, enum nl80211_iftype type,
1582 struct vif_params *params) 1566 struct vif_params *params)
@@ -1649,9 +1633,6 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name,
1649 1633
1650 INIT_LIST_HEAD(&sdata->key_list); 1634 INIT_LIST_HEAD(&sdata->key_list);
1651 1635
1652 spin_lock_init(&sdata->cleanup_stations_lock);
1653 INIT_LIST_HEAD(&sdata->cleanup_stations);
1654 INIT_WORK(&sdata->cleanup_stations_wk, ieee80211_cleanup_sdata_stas_wk);
1655 INIT_DELAYED_WORK(&sdata->dfs_cac_timer_work, 1636 INIT_DELAYED_WORK(&sdata->dfs_cac_timer_work,
1656 ieee80211_dfs_cac_timer_work); 1637 ieee80211_dfs_cac_timer_work);
1657 INIT_DELAYED_WORK(&sdata->dec_tailroom_needed_wk, 1638 INIT_DELAYED_WORK(&sdata->dec_tailroom_needed_wk,
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 900ead344f5b..9c2c7ee2cc30 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -1698,7 +1698,7 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
1698 memset(ifmgd->bssid, 0, ETH_ALEN); 1698 memset(ifmgd->bssid, 0, ETH_ALEN);
1699 1699
1700 /* remove AP and TDLS peers */ 1700 /* remove AP and TDLS peers */
1701 sta_info_flush_defer(sdata); 1701 sta_info_flush(sdata);
1702 1702
1703 /* finally reset all BSS / config parameters */ 1703 /* finally reset all BSS / config parameters */
1704 changed |= ieee80211_reset_erp_info(sdata); 1704 changed |= ieee80211_reset_erp_info(sdata);
diff --git a/net/mac80211/pm.c b/net/mac80211/pm.c
index 340126204343..af64fb8e8add 100644
--- a/net/mac80211/pm.c
+++ b/net/mac80211/pm.c
@@ -37,9 +37,8 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
37 IEEE80211_MAX_QUEUE_MAP, 37 IEEE80211_MAX_QUEUE_MAP,
38 IEEE80211_QUEUE_STOP_REASON_SUSPEND); 38 IEEE80211_QUEUE_STOP_REASON_SUSPEND);
39 39
40 /* flush out all packets and station cleanup call_rcu()s */ 40 /* flush out all packets */
41 synchronize_net(); 41 synchronize_net();
42 rcu_barrier();
43 42
44 ieee80211_flush_queues(local, NULL); 43 ieee80211_flush_queues(local, NULL);
45 44
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
163void 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
182static 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 */
195struct sta_info *sta_info_get(struct ieee80211_sub_if_data *sdata, 147struct 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
982int sta_info_flush_defer(struct ieee80211_sub_if_data *sdata) 934int 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
1002void 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
1008void ieee80211_sta_expire(struct ieee80211_sub_if_data *sdata, 954void ieee80211_sta_expire(struct ieee80211_sub_if_data *sdata,
1009 unsigned long exp_time) 955 unsigned long exp_time)
1010{ 956{
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
index 0218caf5c14a..9104f812e9de 100644
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
@@ -605,21 +605,6 @@ void sta_info_recalc_tim(struct sta_info *sta);
605 605
606void sta_info_init(struct ieee80211_local *local); 606void sta_info_init(struct ieee80211_local *local);
607void sta_info_stop(struct ieee80211_local *local); 607void sta_info_stop(struct ieee80211_local *local);
608int sta_info_flush_defer(struct ieee80211_sub_if_data *sdata);
609
610/**
611 * sta_info_flush_cleanup - flush the sta_info cleanup queue
612 * @sdata: the interface
613 *
614 * Flushes the sta_info cleanup queue for a given interface;
615 * this is necessary before the interface is removed or, for
616 * AP/mesh interfaces, before it is deconfigured.
617 *
618 * Note an rcu_barrier() must precede the function, after all
619 * stations have been flushed/removed to ensure the call_rcu()
620 * calls that add stations to the cleanup queue have completed.
621 */
622void sta_info_flush_cleanup(struct ieee80211_sub_if_data *sdata);
623 608
624/** 609/**
625 * sta_info_flush - flush matching STA entries from the STA table 610 * sta_info_flush - flush matching STA entries from the STA table
@@ -628,15 +613,7 @@ void sta_info_flush_cleanup(struct ieee80211_sub_if_data *sdata);
628 * 613 *
629 * @sdata: sdata to remove all stations from 614 * @sdata: sdata to remove all stations from
630 */ 615 */
631static inline int sta_info_flush(struct ieee80211_sub_if_data *sdata) 616int sta_info_flush(struct ieee80211_sub_if_data *sdata);
632{
633 int ret = sta_info_flush_defer(sdata);
634
635 rcu_barrier();
636 sta_info_flush_cleanup(sdata);
637
638 return ret;
639}
640 617
641void sta_set_rate_info_tx(struct sta_info *sta, 618void sta_set_rate_info_tx(struct sta_info *sta,
642 const struct ieee80211_tx_rate *rate, 619 const struct ieee80211_tx_rate *rate,
@@ -651,6 +628,4 @@ void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta);
651void ieee80211_sta_ps_deliver_poll_response(struct sta_info *sta); 628void ieee80211_sta_ps_deliver_poll_response(struct sta_info *sta);
652void ieee80211_sta_ps_deliver_uapsd(struct sta_info *sta); 629void ieee80211_sta_ps_deliver_uapsd(struct sta_info *sta);
653 630
654void ieee80211_cleanup_sdata_stas(struct ieee80211_sub_if_data *sdata);
655
656#endif /* STA_INFO_H */ 631#endif /* STA_INFO_H */