diff options
Diffstat (limited to 'net/mac80211/sta_info.c')
-rw-r--r-- | net/mac80211/sta_info.c | 108 |
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 */ |
24 | static void sta_info_hash_add(struct ieee80211_local *local, | 26 | static 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 | ||
196 | static 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 | |||
179 | static void sta_info_remove(struct sta_info *sta) | 216 | static 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 | ||
359 | static 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 | |||
325 | void sta_info_init(struct ieee80211_local *local) | 402 | void 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 | ||
337 | int sta_info_start(struct ieee80211_local *local) | 418 | int 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 | } |