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.c108
1 files changed, 96 insertions, 12 deletions
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index cddaf578dc8f..ab7b1f067c6e 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -19,6 +19,8 @@
19#include "ieee80211_i.h" 19#include "ieee80211_i.h"
20#include "ieee80211_rate.h" 20#include "ieee80211_rate.h"
21#include "sta_info.h" 21#include "sta_info.h"
22#include "debugfs_key.h"
23#include "debugfs_sta.h"
22 24
23/* Caller must hold local->sta_lock */ 25/* Caller must hold local->sta_lock */
24static void sta_info_hash_add(struct ieee80211_local *local, 26static void sta_info_hash_add(struct ieee80211_local *local,
@@ -120,6 +122,8 @@ static void sta_info_release(struct kref *kref)
120 } 122 }
121 rate_control_free_sta(sta->rate_ctrl, sta->rate_ctrl_priv); 123 rate_control_free_sta(sta->rate_ctrl, sta->rate_ctrl_priv);
122 rate_control_put(sta->rate_ctrl); 124 rate_control_put(sta->rate_ctrl);
125 if (sta->key)
126 ieee80211_debugfs_key_sta_del(sta->key, sta);
123 kfree(sta); 127 kfree(sta);
124} 128}
125 129
@@ -173,9 +177,42 @@ struct sta_info * sta_info_add(struct ieee80211_local *local,
173 local->mdev->name, MAC_ARG(addr)); 177 local->mdev->name, MAC_ARG(addr));
174#endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ 178#endif /* CONFIG_MAC80211_VERBOSE_DEBUG */
175 179
180#ifdef CONFIG_MAC80211_DEBUGFS
181 if (!in_interrupt()) {
182 sta->debugfs_registered = 1;
183 ieee80211_sta_debugfs_add(sta);
184 rate_control_add_sta_debugfs(sta);
185 } else {
186 /* debugfs entry adding might sleep, so schedule process
187 * context task for adding entry for STAs that do not yet
188 * have one. */
189 queue_work(local->hw.workqueue, &local->sta_debugfs_add);
190 }
191#endif
192
176 return sta; 193 return sta;
177} 194}
178 195
196static void finish_sta_info_free(struct ieee80211_local *local,
197 struct sta_info *sta)
198{
199#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
200 printk(KERN_DEBUG "%s: Removed STA " MAC_FMT "\n",
201 local->mdev->name, MAC_ARG(sta->addr));
202#endif /* CONFIG_MAC80211_VERBOSE_DEBUG */
203
204 if (sta->key) {
205 ieee80211_debugfs_key_remove(sta->key);
206 ieee80211_key_free(sta->key);
207 sta->key = NULL;
208 }
209
210 rate_control_remove_sta_debugfs(sta);
211 ieee80211_sta_debugfs_remove(sta);
212
213 sta_info_put(sta);
214}
215
179static void sta_info_remove(struct sta_info *sta) 216static void sta_info_remove(struct sta_info *sta)
180{ 217{
181 struct ieee80211_local *local = sta->local; 218 struct ieee80211_local *local = sta->local;
@@ -239,17 +276,13 @@ void sta_info_free(struct sta_info *sta, int locked)
239 sta->key_idx_compression = HW_KEY_IDX_INVALID; 276 sta->key_idx_compression = HW_KEY_IDX_INVALID;
240 } 277 }
241 278
242#ifdef CONFIG_MAC80211_VERBOSE_DEBUG 279#ifdef CONFIG_MAC80211_DEBUGFS
243 printk(KERN_DEBUG "%s: Removed STA " MAC_FMT "\n", 280 if (in_atomic()) {
244 local->mdev->name, MAC_ARG(sta->addr)); 281 list_add(&sta->list, &local->deleted_sta_list);
245#endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ 282 queue_work(local->hw.workqueue, &local->sta_debugfs_add);
246 283 } else
247 if (sta->key) { 284#endif
248 ieee80211_key_free(sta->key); 285 finish_sta_info_free(local, sta);
249 sta->key = NULL;
250 }
251
252 sta_info_put(sta);
253} 286}
254 287
255 288
@@ -322,6 +355,50 @@ static void sta_info_cleanup(unsigned long data)
322 add_timer(&local->sta_cleanup); 355 add_timer(&local->sta_cleanup);
323} 356}
324 357
358#ifdef CONFIG_MAC80211_DEBUGFS
359static void sta_info_debugfs_add_task(struct work_struct *work)
360{
361 struct ieee80211_local *local =
362 container_of(work, struct ieee80211_local, sta_debugfs_add);
363 struct sta_info *sta, *tmp;
364
365 while (1) {
366 spin_lock_bh(&local->sta_lock);
367 if (!list_empty(&local->deleted_sta_list)) {
368 sta = list_entry(local->deleted_sta_list.next,
369 struct sta_info, list);
370 list_del(local->deleted_sta_list.next);
371 } else
372 sta = NULL;
373 spin_unlock_bh(&local->sta_lock);
374 if (!sta)
375 break;
376 finish_sta_info_free(local, sta);
377 }
378
379 while (1) {
380 sta = NULL;
381 spin_lock_bh(&local->sta_lock);
382 list_for_each_entry(tmp, &local->sta_list, list) {
383 if (!tmp->debugfs_registered) {
384 sta = tmp;
385 __sta_info_get(sta);
386 break;
387 }
388 }
389 spin_unlock_bh(&local->sta_lock);
390
391 if (!sta)
392 break;
393
394 sta->debugfs_registered = 1;
395 ieee80211_sta_debugfs_add(sta);
396 rate_control_add_sta_debugfs(sta);
397 sta_info_put(sta);
398 }
399}
400#endif
401
325void sta_info_init(struct ieee80211_local *local) 402void sta_info_init(struct ieee80211_local *local)
326{ 403{
327 spin_lock_init(&local->sta_lock); 404 spin_lock_init(&local->sta_lock);
@@ -332,6 +409,10 @@ void sta_info_init(struct ieee80211_local *local)
332 local->sta_cleanup.expires = jiffies + STA_INFO_CLEANUP_INTERVAL; 409 local->sta_cleanup.expires = jiffies + STA_INFO_CLEANUP_INTERVAL;
333 local->sta_cleanup.data = (unsigned long) local; 410 local->sta_cleanup.data = (unsigned long) local;
334 local->sta_cleanup.function = sta_info_cleanup; 411 local->sta_cleanup.function = sta_info_cleanup;
412
413#ifdef CONFIG_MAC80211_DEBUGFS
414 INIT_WORK(&local->sta_debugfs_add, sta_info_debugfs_add_task);
415#endif
335} 416}
336 417
337int sta_info_start(struct ieee80211_local *local) 418int sta_info_start(struct ieee80211_local *local)
@@ -347,7 +428,10 @@ void sta_info_stop(struct ieee80211_local *local)
347 del_timer(&local->sta_cleanup); 428 del_timer(&local->sta_cleanup);
348 429
349 list_for_each_entry_safe(sta, tmp, &local->sta_list, list) { 430 list_for_each_entry_safe(sta, tmp, &local->sta_list, list) {
350 /* We don't need locking at this point. */ 431 /* sta_info_free must be called with 0 as the last
432 * parameter to ensure all debugfs sta entries are
433 * unregistered. We don't need locking at this
434 * point. */
351 sta_info_free(sta, 0); 435 sta_info_free(sta, 0);
352 } 436 }
353} 437}