aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/sta_info.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/mac80211/sta_info.c')
-rw-r--r--net/mac80211/sta_info.c42
1 files changed, 39 insertions, 3 deletions
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index e384e6632d97..1f3c9eb98500 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -21,6 +21,9 @@
21#include "ieee80211_rate.h" 21#include "ieee80211_rate.h"
22#include "sta_info.h" 22#include "sta_info.h"
23#include "debugfs_sta.h" 23#include "debugfs_sta.h"
24#ifdef CONFIG_MAC80211_MESH
25#include "mesh.h"
26#endif
24 27
25/* Caller must hold local->sta_lock */ 28/* Caller must hold local->sta_lock */
26static void sta_info_hash_add(struct ieee80211_local *local, 29static void sta_info_hash_add(struct ieee80211_local *local,
@@ -84,6 +87,27 @@ struct sta_info *sta_info_get(struct ieee80211_local *local, u8 *addr)
84} 87}
85EXPORT_SYMBOL(sta_info_get); 88EXPORT_SYMBOL(sta_info_get);
86 89
90struct sta_info *sta_info_get_by_idx(struct ieee80211_local *local, int idx,
91 struct net_device *dev)
92{
93 struct sta_info *sta;
94 int i = 0;
95
96 read_lock_bh(&local->sta_lock);
97 list_for_each_entry(sta, &local->sta_list, list) {
98 if (i < idx) {
99 ++i;
100 continue;
101 } else if (!dev || dev == sta->dev) {
102 __sta_info_get(sta);
103 read_unlock_bh(&local->sta_lock);
104 return sta;
105 }
106 }
107 read_unlock_bh(&local->sta_lock);
108
109 return NULL;
110}
87 111
88static void sta_info_release(struct kref *kref) 112static void sta_info_release(struct kref *kref)
89{ 113{
@@ -284,12 +308,19 @@ void sta_info_remove(struct sta_info *sta)
284 __sta_info_clear_tim_bit(sdata->bss, sta); 308 __sta_info_clear_tim_bit(sdata->bss, sta);
285 } 309 }
286 local->num_sta--; 310 local->num_sta--;
311
312#ifdef CONFIG_MAC80211_MESH
313 if (sdata->vif.type == IEEE80211_IF_TYPE_MESH_POINT)
314 mesh_accept_plinks_update(sdata->dev);
315#endif
287} 316}
288 317
289void sta_info_free(struct sta_info *sta) 318void sta_info_free(struct sta_info *sta)
290{ 319{
291 struct sk_buff *skb; 320 struct sk_buff *skb;
292 struct ieee80211_local *local = sta->local; 321 struct ieee80211_local *local = sta->local;
322 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(sta->dev);
323
293 DECLARE_MAC_BUF(mac); 324 DECLARE_MAC_BUF(mac);
294 325
295 might_sleep(); 326 might_sleep();
@@ -298,6 +329,14 @@ void sta_info_free(struct sta_info *sta)
298 sta_info_remove(sta); 329 sta_info_remove(sta);
299 write_unlock_bh(&local->sta_lock); 330 write_unlock_bh(&local->sta_lock);
300 331
332#ifdef CONFIG_MAC80211_MESH
333 if (sdata->vif.type == IEEE80211_IF_TYPE_MESH_POINT) {
334 spin_lock_bh(&sta->plink_lock);
335 mesh_plink_deactivate(sta);
336 spin_unlock_bh(&sta->plink_lock);
337 }
338#endif
339
301 while ((skb = skb_dequeue(&sta->ps_tx_buf)) != NULL) { 340 while ((skb = skb_dequeue(&sta->ps_tx_buf)) != NULL) {
302 local->total_ps_buffered--; 341 local->total_ps_buffered--;
303 dev_kfree_skb(skb); 342 dev_kfree_skb(skb);
@@ -315,9 +354,6 @@ void sta_info_free(struct sta_info *sta)
315 WARN_ON(sta->key); 354 WARN_ON(sta->key);
316 355
317 if (local->ops->sta_notify) { 356 if (local->ops->sta_notify) {
318 struct ieee80211_sub_if_data *sdata;
319
320 sdata = IEEE80211_DEV_TO_SUB_IF(sta->dev);
321 357
322 if (sdata->vif.type == IEEE80211_IF_TYPE_VLAN) 358 if (sdata->vif.type == IEEE80211_IF_TYPE_VLAN)
323 sdata = sdata->u.vlan.ap; 359 sdata = sdata->u.vlan.ap;