aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/sta_info.c
diff options
context:
space:
mode:
authorJohannes Berg <johannes@sipsolutions.net>2008-02-25 10:27:49 -0500
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 a230a9597398..a767042ec4fd 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)
258 unsigned long flags; 258 unsigned long flags;
259 DECLARE_MAC_BUF(mac); 259 DECLARE_MAC_BUF(mac);
260 260
261 WARN_ON(!netif_running(sdata->dev));
262
261 spin_lock_irqsave(&local->sta_lock, flags); 263 spin_lock_irqsave(&local->sta_lock, flags);
262 /* check if STA exists already */ 264 /* check if STA exists already */
263 if (__sta_info_find(local, sta->addr)) { 265 if (__sta_info_find(local, sta->addr)) {
@@ -608,14 +610,18 @@ void sta_info_stop(struct ieee80211_local *local)
608 610
609/** 611/**
610 * sta_info_flush - flush matching STA entries from the STA table 612 * sta_info_flush - flush matching STA entries from the STA table
613 *
614 * Returns the number of removed STA entries.
615 *
611 * @local: local interface data 616 * @local: local interface data
612 * @sdata: matching rule for the net device (sta->dev) or %NULL to match all STAs 617 * @sdata: matching rule for the net device (sta->dev) or %NULL to match all STAs
613 */ 618 */
614void sta_info_flush(struct ieee80211_local *local, 619int sta_info_flush(struct ieee80211_local *local,
615 struct ieee80211_sub_if_data *sdata) 620 struct ieee80211_sub_if_data *sdata)
616{ 621{
617 struct sta_info *sta, *tmp; 622 struct sta_info *sta, *tmp;
618 LIST_HEAD(tmp_list); 623 LIST_HEAD(tmp_list);
624 int ret = 0;
619 unsigned long flags; 625 unsigned long flags;
620 626
621 might_sleep(); 627 might_sleep();
@@ -624,8 +630,10 @@ void sta_info_flush(struct ieee80211_local *local,
624 list_for_each_entry_safe(sta, tmp, &local->sta_list, list) { 630 list_for_each_entry_safe(sta, tmp, &local->sta_list, list) {
625 if (!sdata || sdata == sta->sdata) { 631 if (!sdata || sdata == sta->sdata) {
626 __sta_info_unlink(&sta); 632 __sta_info_unlink(&sta);
627 if (sta) 633 if (sta) {
628 list_add_tail(&sta->list, &tmp_list); 634 list_add_tail(&sta->list, &tmp_list);
635 ret++;
636 }
629 } 637 }
630 } 638 }
631 spin_unlock_irqrestore(&local->sta_lock, flags); 639 spin_unlock_irqrestore(&local->sta_lock, flags);
@@ -634,4 +642,6 @@ void sta_info_flush(struct ieee80211_local *local,
634 642
635 list_for_each_entry_safe(sta, tmp, &tmp_list, list) 643 list_for_each_entry_safe(sta, tmp, &tmp_list, list)
636 sta_info_destroy(sta); 644 sta_info_destroy(sta);
645
646 return ret;
637} 647}