diff options
author | Johannes Berg <johannes@sipsolutions.net> | 2008-02-25 10:27:49 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2008-03-06 15:30:47 -0500 |
commit | 44213b5e13c907bf4aa2e73941944f90184c8772 (patch) | |
tree | db680fc6b4913b072a8f85cf0fac622aea2edb5d /net/mac80211/ieee80211_iface.c | |
parent | 693b1bbcc47b3fd436068f294147357f90cd1296 (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/ieee80211_iface.c')
-rw-r--r-- | net/mac80211/ieee80211_iface.c | 22 |
1 files changed, 4 insertions, 18 deletions
diff --git a/net/mac80211/ieee80211_iface.c b/net/mac80211/ieee80211_iface.c index 98b22736e883..80954a512185 100644 --- a/net/mac80211/ieee80211_iface.c +++ b/net/mac80211/ieee80211_iface.c | |||
@@ -187,8 +187,8 @@ void ieee80211_if_reinit(struct net_device *dev) | |||
187 | { | 187 | { |
188 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 188 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); |
189 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 189 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
190 | struct sta_info *sta; | ||
191 | struct sk_buff *skb; | 190 | struct sk_buff *skb; |
191 | int flushed; | ||
192 | 192 | ||
193 | ASSERT_RTNL(); | 193 | ASSERT_RTNL(); |
194 | 194 | ||
@@ -240,21 +240,7 @@ void ieee80211_if_reinit(struct net_device *dev) | |||
240 | break; | 240 | break; |
241 | } | 241 | } |
242 | case IEEE80211_IF_TYPE_WDS: | 242 | case IEEE80211_IF_TYPE_WDS: |
243 | rcu_read_lock(); | 243 | /* nothing to do */ |
244 | sta = sta_info_get(local, sdata->u.wds.remote_addr); | ||
245 | if (sta) { | ||
246 | sta_info_unlink(&sta); | ||
247 | } else { | ||
248 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | ||
249 | printk(KERN_DEBUG "%s: Someone had deleted my STA " | ||
250 | "entry for the WDS link\n", dev->name); | ||
251 | #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ | ||
252 | } | ||
253 | rcu_read_unlock(); | ||
254 | if (sta) { | ||
255 | synchronize_rcu(); | ||
256 | sta_info_destroy(sta); | ||
257 | } | ||
258 | break; | 244 | break; |
259 | case IEEE80211_IF_TYPE_MESH_POINT: | 245 | case IEEE80211_IF_TYPE_MESH_POINT: |
260 | case IEEE80211_IF_TYPE_STA: | 246 | case IEEE80211_IF_TYPE_STA: |
@@ -279,8 +265,8 @@ void ieee80211_if_reinit(struct net_device *dev) | |||
279 | break; | 265 | break; |
280 | } | 266 | } |
281 | 267 | ||
282 | /* remove all STAs that are bound to this virtual interface */ | 268 | flushed = sta_info_flush(local, sdata); |
283 | sta_info_flush(local, sdata); | 269 | WARN_ON(flushed); |
284 | 270 | ||
285 | memset(&sdata->u, 0, sizeof(sdata->u)); | 271 | memset(&sdata->u, 0, sizeof(sdata->u)); |
286 | ieee80211_if_sdata_init(sdata); | 272 | ieee80211_if_sdata_init(sdata); |