diff options
Diffstat (limited to 'net/mac80211')
-rw-r--r-- | net/mac80211/sta_info.c | 29 |
1 files changed, 23 insertions, 6 deletions
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index 7e1e87257647..bfdaf5c82f9d 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c | |||
@@ -351,7 +351,7 @@ int sta_info_insert(struct sta_info *sta) | |||
351 | * NOTE: due to auto-freeing semantics this may only be done | 351 | * NOTE: due to auto-freeing semantics this may only be done |
352 | * if the insertion is successful! | 352 | * if the insertion is successful! |
353 | */ | 353 | */ |
354 | queue_work(local->hw.workqueue, &local->sta_debugfs_add); | 354 | schedule_work(&local->sta_debugfs_add); |
355 | #endif | 355 | #endif |
356 | 356 | ||
357 | if (ieee80211_vif_is_mesh(&sdata->vif)) | 357 | if (ieee80211_vif_is_mesh(&sdata->vif)) |
@@ -476,16 +476,23 @@ void __sta_info_unlink(struct sta_info **sta) | |||
476 | * | 476 | * |
477 | * The rules are not trivial, but not too complex either: | 477 | * The rules are not trivial, but not too complex either: |
478 | * (1) pin_status is only modified under the sta_lock | 478 | * (1) pin_status is only modified under the sta_lock |
479 | * (2) sta_info_debugfs_add_work() will set the status | 479 | * (2) STAs may only be pinned under the RTNL so that |
480 | * sta_info_flush() is guaranteed to actually destroy | ||
481 | * all STAs that are active for a given interface, this | ||
482 | * is required for correctness because otherwise we | ||
483 | * could notify a driver that an interface is going | ||
484 | * away and only after that (!) notify it about a STA | ||
485 | * on that interface going away. | ||
486 | * (3) sta_info_debugfs_add_work() will set the status | ||
480 | * to PINNED when it found an item that needs a new | 487 | * to PINNED when it found an item that needs a new |
481 | * debugfs directory created. In that case, that item | 488 | * debugfs directory created. In that case, that item |
482 | * must not be freed although all *RCU* users are done | 489 | * must not be freed although all *RCU* users are done |
483 | * with it. Hence, we tell the caller of _unlink() | 490 | * with it. Hence, we tell the caller of _unlink() |
484 | * that the item is already gone (as can happen when | 491 | * that the item is already gone (as can happen when |
485 | * two tasks try to unlink/destroy at the same time) | 492 | * two tasks try to unlink/destroy at the same time) |
486 | * (3) We set the pin_status to DESTROY here when we | 493 | * (4) We set the pin_status to DESTROY here when we |
487 | * find such an item. | 494 | * find such an item. |
488 | * (4) sta_info_debugfs_add_work() will reset the pin_status | 495 | * (5) sta_info_debugfs_add_work() will reset the pin_status |
489 | * from PINNED to NORMAL when it is done with the item, | 496 | * from PINNED to NORMAL when it is done with the item, |
490 | * but will check for DESTROY before resetting it in | 497 | * but will check for DESTROY before resetting it in |
491 | * which case it will free the item. | 498 | * which case it will free the item. |
@@ -617,6 +624,8 @@ static void sta_info_debugfs_add_work(struct work_struct *work) | |||
617 | struct sta_info *sta, *tmp; | 624 | struct sta_info *sta, *tmp; |
618 | unsigned long flags; | 625 | unsigned long flags; |
619 | 626 | ||
627 | /* We need to keep the RTNL across the whole pinned status. */ | ||
628 | rtnl_lock(); | ||
620 | while (1) { | 629 | while (1) { |
621 | sta = NULL; | 630 | sta = NULL; |
622 | 631 | ||
@@ -637,10 +646,9 @@ static void sta_info_debugfs_add_work(struct work_struct *work) | |||
637 | rate_control_add_sta_debugfs(sta); | 646 | rate_control_add_sta_debugfs(sta); |
638 | 647 | ||
639 | sta = __sta_info_unpin(sta); | 648 | sta = __sta_info_unpin(sta); |
640 | rtnl_lock(); | ||
641 | sta_info_destroy(sta); | 649 | sta_info_destroy(sta); |
642 | rtnl_unlock(); | ||
643 | } | 650 | } |
651 | rtnl_unlock(); | ||
644 | } | 652 | } |
645 | #endif | 653 | #endif |
646 | 654 | ||
@@ -700,6 +708,15 @@ void sta_info_stop(struct ieee80211_local *local) | |||
700 | { | 708 | { |
701 | del_timer(&local->sta_cleanup); | 709 | del_timer(&local->sta_cleanup); |
702 | cancel_work_sync(&local->sta_flush_work); | 710 | cancel_work_sync(&local->sta_flush_work); |
711 | #ifdef CONFIG_MAC80211_DEBUGFS | ||
712 | /* | ||
713 | * Make sure the debugfs adding work isn't pending after this | ||
714 | * because we're about to be destroyed. It doesn't matter | ||
715 | * whether it ran or not since we're going to flush all STAs | ||
716 | * anyway. | ||
717 | */ | ||
718 | cancel_work_sync(&local->sta_debugfs_add); | ||
719 | #endif | ||
703 | 720 | ||
704 | rtnl_lock(); | 721 | rtnl_lock(); |
705 | sta_info_flush(local, NULL); | 722 | sta_info_flush(local, NULL); |