aboutsummaryrefslogtreecommitdiff
path: root/net/mac80211/sta_info.c
diff options
context:
space:
mode:
authorJohannes Berg <johannes@sipsolutions.net>2008-02-25 16:27:49 +0100
committerJohn W. Linville <linville@tuxdriver.com>2008-03-06 15:30:47 -0500
commit44213b5e13c907bf4aa2e73941944f90184c8772 (patch)
treedb680fc6b4913b072a8f85cf0fac622aea2edb5d /net/mac80211/sta_info.c
parent693b1bbcc47b3fd436068f294147357f90cd1296 (diff)
mac80211: remove STA entries when taking down interface
When we take down an interface, we need to remove the STA info items that belong to it because otherwise we might invoke a sta_notify() callback in the driver when we later delete the STA entries, but in that case the driver will already have removed its knowledge of the interface they belonged to leading to confusion. Also, we could invoke the set_tim() callback after the driver removed its knowledge of the interface, which can lead to a crash if it requests a beacon with a then-invalid vif pointer! A side effect of this patch is that, because it was easier, it disallows changing the WDS peer while an interface is up. Should that actually be necessary, it can be added back, but the WDS peer STA entry may not be added while the interface is UP so for now I've simplified the WDS peer's STA entry lifetime management. Signed-off-by: Johannes Berg <johannes@sipsolutions.net> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/mac80211/sta_info.c')
-rw-r--r--net/mac80211/sta_info.c14
1 files changed, 12 insertions, 2 deletions
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index a230a959739..a767042ec4f 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -258,6 +258,8 @@ int sta_info_insert(struct sta_info *sta)
unsigned long flags;
DECLARE_MAC_BUF(mac);
+ WARN_ON(!netif_running(sdata->dev));
+
spin_lock_irqsave(&local->sta_lock, flags);
/* check if STA exists already */
if (__sta_info_find(local, sta->addr)) {
@@ -608,14 +610,18 @@ void sta_info_stop(struct ieee80211_local *local)
/**
* sta_info_flush - flush matching STA entries from the STA table
+ *
+ * Returns the number of removed STA entries.
+ *
* @local: local interface data
* @sdata: matching rule for the net device (sta->dev) or %NULL to match all STAs
*/
-void sta_info_flush(struct ieee80211_local *local,
+int sta_info_flush(struct ieee80211_local *local,
struct ieee80211_sub_if_data *sdata)
{
struct sta_info *sta, *tmp;
LIST_HEAD(tmp_list);
+ int ret = 0;
unsigned long flags;
might_sleep();
@@ -624,8 +630,10 @@ void sta_info_flush(struct ieee80211_local *local,
list_for_each_entry_safe(sta, tmp, &local->sta_list, list) {
if (!sdata || sdata == sta->sdata) {
__sta_info_unlink(&sta);
- if (sta)
+ if (sta) {
list_add_tail(&sta->list, &tmp_list);
+ ret++;
+ }
}
}
spin_unlock_irqrestore(&local->sta_lock, flags);
@@ -634,4 +642,6 @@ void sta_info_flush(struct ieee80211_local *local,
list_for_each_entry_safe(sta, tmp, &tmp_list, list)
sta_info_destroy(sta);
+
+ return ret;
}