diff options
Diffstat (limited to 'net/mac80211/sta_info.c')
-rw-r--r-- | net/mac80211/sta_info.c | 112 |
1 files changed, 28 insertions, 84 deletions
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index c5f14e6bbde2..a360bceeba59 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c | |||
@@ -19,6 +19,7 @@ | |||
19 | 19 | ||
20 | #include <net/mac80211.h> | 20 | #include <net/mac80211.h> |
21 | #include "ieee80211_i.h" | 21 | #include "ieee80211_i.h" |
22 | #include "driver-ops.h" | ||
22 | #include "rate.h" | 23 | #include "rate.h" |
23 | #include "sta_info.h" | 24 | #include "sta_info.h" |
24 | #include "debugfs_sta.h" | 25 | #include "debugfs_sta.h" |
@@ -43,6 +44,15 @@ | |||
43 | * When the insertion fails (sta_info_insert()) returns non-zero), the | 44 | * When the insertion fails (sta_info_insert()) returns non-zero), the |
44 | * structure will have been freed by sta_info_insert()! | 45 | * structure will have been freed by sta_info_insert()! |
45 | * | 46 | * |
47 | * sta entries are added by mac80211 when you establish a link with a | ||
48 | * peer. This means different things for the different type of interfaces | ||
49 | * we support. For a regular station this mean we add the AP sta when we | ||
50 | * receive an assocation response from the AP. For IBSS this occurs when | ||
51 | * we receive a probe response or a beacon from target IBSS network. For | ||
52 | * WDS we add the sta for the peer imediately upon device open. When using | ||
53 | * AP mode we add stations for each respective station upon request from | ||
54 | * userspace through nl80211. | ||
55 | * | ||
46 | * Because there are debugfs entries for each station, and adding those | 56 | * Because there are debugfs entries for each station, and adding those |
47 | * must be able to sleep, it is also possible to "pin" a station entry, | 57 | * must be able to sleep, it is also possible to "pin" a station entry, |
48 | * that means it can be removed from the hash table but not be freed. | 58 | * that means it can be removed from the hash table but not be freed. |
@@ -292,6 +302,9 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, | |||
292 | skb_queue_head_init(&sta->ps_tx_buf); | 302 | skb_queue_head_init(&sta->ps_tx_buf); |
293 | skb_queue_head_init(&sta->tx_filtered); | 303 | skb_queue_head_init(&sta->tx_filtered); |
294 | 304 | ||
305 | for (i = 0; i < NUM_RX_DATA_QUEUES; i++) | ||
306 | sta->last_seq_ctrl[i] = cpu_to_le16(USHORT_MAX); | ||
307 | |||
295 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | 308 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG |
296 | printk(KERN_DEBUG "%s: Allocated STA %pM\n", | 309 | printk(KERN_DEBUG "%s: Allocated STA %pM\n", |
297 | wiphy_name(local->hw.wiphy), sta->sta.addr); | 310 | wiphy_name(local->hw.wiphy), sta->sta.addr); |
@@ -346,8 +359,7 @@ int sta_info_insert(struct sta_info *sta) | |||
346 | struct ieee80211_sub_if_data, | 359 | struct ieee80211_sub_if_data, |
347 | u.ap); | 360 | u.ap); |
348 | 361 | ||
349 | local->ops->sta_notify(local_to_hw(local), &sdata->vif, | 362 | drv_sta_notify(local, &sdata->vif, STA_NOTIFY_ADD, &sta->sta); |
350 | STA_NOTIFY_ADD, &sta->sta); | ||
351 | } | 363 | } |
352 | 364 | ||
353 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | 365 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG |
@@ -405,8 +417,7 @@ static void __sta_info_set_tim_bit(struct ieee80211_if_ap *bss, | |||
405 | 417 | ||
406 | if (sta->local->ops->set_tim) { | 418 | if (sta->local->ops->set_tim) { |
407 | sta->local->tim_in_locked_section = true; | 419 | sta->local->tim_in_locked_section = true; |
408 | sta->local->ops->set_tim(local_to_hw(sta->local), | 420 | drv_set_tim(sta->local, &sta->sta, true); |
409 | &sta->sta, true); | ||
410 | sta->local->tim_in_locked_section = false; | 421 | sta->local->tim_in_locked_section = false; |
411 | } | 422 | } |
412 | } | 423 | } |
@@ -431,8 +442,7 @@ static void __sta_info_clear_tim_bit(struct ieee80211_if_ap *bss, | |||
431 | 442 | ||
432 | if (sta->local->ops->set_tim) { | 443 | if (sta->local->ops->set_tim) { |
433 | sta->local->tim_in_locked_section = true; | 444 | sta->local->tim_in_locked_section = true; |
434 | sta->local->ops->set_tim(local_to_hw(sta->local), | 445 | drv_set_tim(sta->local, &sta->sta, false); |
435 | &sta->sta, false); | ||
436 | sta->local->tim_in_locked_section = false; | 446 | sta->local->tim_in_locked_section = false; |
437 | } | 447 | } |
438 | } | 448 | } |
@@ -482,8 +492,8 @@ static void __sta_info_unlink(struct sta_info **sta) | |||
482 | struct ieee80211_sub_if_data, | 492 | struct ieee80211_sub_if_data, |
483 | u.ap); | 493 | u.ap); |
484 | 494 | ||
485 | local->ops->sta_notify(local_to_hw(local), &sdata->vif, | 495 | drv_sta_notify(local, &sdata->vif, STA_NOTIFY_REMOVE, |
486 | STA_NOTIFY_REMOVE, &(*sta)->sta); | 496 | &(*sta)->sta); |
487 | } | 497 | } |
488 | 498 | ||
489 | if (ieee80211_vif_is_mesh(&sdata->vif)) { | 499 | if (ieee80211_vif_is_mesh(&sdata->vif)) { |
@@ -543,9 +553,8 @@ void sta_info_unlink(struct sta_info **sta) | |||
543 | spin_unlock_irqrestore(&local->sta_lock, flags); | 553 | spin_unlock_irqrestore(&local->sta_lock, flags); |
544 | } | 554 | } |
545 | 555 | ||
546 | static inline int sta_info_buffer_expired(struct ieee80211_local *local, | 556 | static int sta_info_buffer_expired(struct sta_info *sta, |
547 | struct sta_info *sta, | 557 | struct sk_buff *skb) |
548 | struct sk_buff *skb) | ||
549 | { | 558 | { |
550 | struct ieee80211_tx_info *info; | 559 | struct ieee80211_tx_info *info; |
551 | int timeout; | 560 | int timeout; |
@@ -556,8 +565,9 @@ static inline int sta_info_buffer_expired(struct ieee80211_local *local, | |||
556 | info = IEEE80211_SKB_CB(skb); | 565 | info = IEEE80211_SKB_CB(skb); |
557 | 566 | ||
558 | /* Timeout: (2 * listen_interval * beacon_int * 1024 / 1000000) sec */ | 567 | /* Timeout: (2 * listen_interval * beacon_int * 1024 / 1000000) sec */ |
559 | timeout = (sta->listen_interval * local->hw.conf.beacon_int * 32 / | 568 | timeout = (sta->listen_interval * |
560 | 15625) * HZ; | 569 | sta->sdata->vif.bss_conf.beacon_int * |
570 | 32 / 15625) * HZ; | ||
561 | if (timeout < STA_TX_BUFFER_EXPIRE) | 571 | if (timeout < STA_TX_BUFFER_EXPIRE) |
562 | timeout = STA_TX_BUFFER_EXPIRE; | 572 | timeout = STA_TX_BUFFER_EXPIRE; |
563 | return time_after(jiffies, info->control.jiffies + timeout); | 573 | return time_after(jiffies, info->control.jiffies + timeout); |
@@ -577,7 +587,7 @@ static void sta_info_cleanup_expire_buffered(struct ieee80211_local *local, | |||
577 | for (;;) { | 587 | for (;;) { |
578 | spin_lock_irqsave(&sta->ps_tx_buf.lock, flags); | 588 | spin_lock_irqsave(&sta->ps_tx_buf.lock, flags); |
579 | skb = skb_peek(&sta->ps_tx_buf); | 589 | skb = skb_peek(&sta->ps_tx_buf); |
580 | if (sta_info_buffer_expired(local, sta, skb)) | 590 | if (sta_info_buffer_expired(sta, skb)) |
581 | skb = __skb_dequeue(&sta->ps_tx_buf); | 591 | skb = __skb_dequeue(&sta->ps_tx_buf); |
582 | else | 592 | else |
583 | skb = NULL; | 593 | skb = NULL; |
@@ -610,6 +620,9 @@ static void sta_info_cleanup(unsigned long data) | |||
610 | sta_info_cleanup_expire_buffered(local, sta); | 620 | sta_info_cleanup_expire_buffered(local, sta); |
611 | rcu_read_unlock(); | 621 | rcu_read_unlock(); |
612 | 622 | ||
623 | if (local->quiescing) | ||
624 | return; | ||
625 | |||
613 | local->sta_cleanup.expires = | 626 | local->sta_cleanup.expires = |
614 | round_jiffies(jiffies + STA_INFO_CLEANUP_INTERVAL); | 627 | round_jiffies(jiffies + STA_INFO_CLEANUP_INTERVAL); |
615 | add_timer(&local->sta_cleanup); | 628 | add_timer(&local->sta_cleanup); |
@@ -686,41 +699,10 @@ static void sta_info_debugfs_add_work(struct work_struct *work) | |||
686 | } | 699 | } |
687 | #endif | 700 | #endif |
688 | 701 | ||
689 | static void __ieee80211_run_pending_flush(struct ieee80211_local *local) | ||
690 | { | ||
691 | struct sta_info *sta; | ||
692 | unsigned long flags; | ||
693 | |||
694 | ASSERT_RTNL(); | ||
695 | |||
696 | spin_lock_irqsave(&local->sta_lock, flags); | ||
697 | while (!list_empty(&local->sta_flush_list)) { | ||
698 | sta = list_first_entry(&local->sta_flush_list, | ||
699 | struct sta_info, list); | ||
700 | list_del(&sta->list); | ||
701 | spin_unlock_irqrestore(&local->sta_lock, flags); | ||
702 | sta_info_destroy(sta); | ||
703 | spin_lock_irqsave(&local->sta_lock, flags); | ||
704 | } | ||
705 | spin_unlock_irqrestore(&local->sta_lock, flags); | ||
706 | } | ||
707 | |||
708 | static void ieee80211_sta_flush_work(struct work_struct *work) | ||
709 | { | ||
710 | struct ieee80211_local *local = | ||
711 | container_of(work, struct ieee80211_local, sta_flush_work); | ||
712 | |||
713 | rtnl_lock(); | ||
714 | __ieee80211_run_pending_flush(local); | ||
715 | rtnl_unlock(); | ||
716 | } | ||
717 | |||
718 | void sta_info_init(struct ieee80211_local *local) | 702 | void sta_info_init(struct ieee80211_local *local) |
719 | { | 703 | { |
720 | spin_lock_init(&local->sta_lock); | 704 | spin_lock_init(&local->sta_lock); |
721 | INIT_LIST_HEAD(&local->sta_list); | 705 | INIT_LIST_HEAD(&local->sta_list); |
722 | INIT_LIST_HEAD(&local->sta_flush_list); | ||
723 | INIT_WORK(&local->sta_flush_work, ieee80211_sta_flush_work); | ||
724 | 706 | ||
725 | setup_timer(&local->sta_cleanup, sta_info_cleanup, | 707 | setup_timer(&local->sta_cleanup, sta_info_cleanup, |
726 | (unsigned long)local); | 708 | (unsigned long)local); |
@@ -741,7 +723,6 @@ int sta_info_start(struct ieee80211_local *local) | |||
741 | void sta_info_stop(struct ieee80211_local *local) | 723 | void sta_info_stop(struct ieee80211_local *local) |
742 | { | 724 | { |
743 | del_timer(&local->sta_cleanup); | 725 | del_timer(&local->sta_cleanup); |
744 | cancel_work_sync(&local->sta_flush_work); | ||
745 | #ifdef CONFIG_MAC80211_DEBUGFS | 726 | #ifdef CONFIG_MAC80211_DEBUGFS |
746 | /* | 727 | /* |
747 | * Make sure the debugfs adding work isn't pending after this | 728 | * Make sure the debugfs adding work isn't pending after this |
@@ -752,10 +733,7 @@ void sta_info_stop(struct ieee80211_local *local) | |||
752 | cancel_work_sync(&local->sta_debugfs_add); | 733 | cancel_work_sync(&local->sta_debugfs_add); |
753 | #endif | 734 | #endif |
754 | 735 | ||
755 | rtnl_lock(); | ||
756 | sta_info_flush(local, NULL); | 736 | sta_info_flush(local, NULL); |
757 | __ieee80211_run_pending_flush(local); | ||
758 | rtnl_unlock(); | ||
759 | } | 737 | } |
760 | 738 | ||
761 | /** | 739 | /** |
@@ -767,7 +745,7 @@ void sta_info_stop(struct ieee80211_local *local) | |||
767 | * @sdata: matching rule for the net device (sta->dev) or %NULL to match all STAs | 745 | * @sdata: matching rule for the net device (sta->dev) or %NULL to match all STAs |
768 | */ | 746 | */ |
769 | int sta_info_flush(struct ieee80211_local *local, | 747 | int sta_info_flush(struct ieee80211_local *local, |
770 | struct ieee80211_sub_if_data *sdata) | 748 | struct ieee80211_sub_if_data *sdata) |
771 | { | 749 | { |
772 | struct sta_info *sta, *tmp; | 750 | struct sta_info *sta, *tmp; |
773 | LIST_HEAD(tmp_list); | 751 | LIST_HEAD(tmp_list); |
@@ -775,7 +753,6 @@ int sta_info_flush(struct ieee80211_local *local, | |||
775 | unsigned long flags; | 753 | unsigned long flags; |
776 | 754 | ||
777 | might_sleep(); | 755 | might_sleep(); |
778 | ASSERT_RTNL(); | ||
779 | 756 | ||
780 | spin_lock_irqsave(&local->sta_lock, flags); | 757 | spin_lock_irqsave(&local->sta_lock, flags); |
781 | list_for_each_entry_safe(sta, tmp, &local->sta_list, list) { | 758 | list_for_each_entry_safe(sta, tmp, &local->sta_list, list) { |
@@ -795,39 +772,6 @@ int sta_info_flush(struct ieee80211_local *local, | |||
795 | return ret; | 772 | return ret; |
796 | } | 773 | } |
797 | 774 | ||
798 | /** | ||
799 | * sta_info_flush_delayed - flush matching STA entries from the STA table | ||
800 | * | ||
801 | * This function unlinks all stations for a given interface and queues | ||
802 | * them for freeing. Note that the workqueue function scheduled here has | ||
803 | * to run before any new keys can be added to the system to avoid set_key() | ||
804 | * callback ordering issues. | ||
805 | * | ||
806 | * @sdata: the interface | ||
807 | */ | ||
808 | void sta_info_flush_delayed(struct ieee80211_sub_if_data *sdata) | ||
809 | { | ||
810 | struct ieee80211_local *local = sdata->local; | ||
811 | struct sta_info *sta, *tmp; | ||
812 | unsigned long flags; | ||
813 | bool work = false; | ||
814 | |||
815 | spin_lock_irqsave(&local->sta_lock, flags); | ||
816 | list_for_each_entry_safe(sta, tmp, &local->sta_list, list) { | ||
817 | if (sdata == sta->sdata) { | ||
818 | __sta_info_unlink(&sta); | ||
819 | if (sta) { | ||
820 | list_add_tail(&sta->list, | ||
821 | &local->sta_flush_list); | ||
822 | work = true; | ||
823 | } | ||
824 | } | ||
825 | } | ||
826 | if (work) | ||
827 | schedule_work(&local->sta_flush_work); | ||
828 | spin_unlock_irqrestore(&local->sta_lock, flags); | ||
829 | } | ||
830 | |||
831 | void ieee80211_sta_expire(struct ieee80211_sub_if_data *sdata, | 775 | void ieee80211_sta_expire(struct ieee80211_sub_if_data *sdata, |
832 | unsigned long exp_time) | 776 | unsigned long exp_time) |
833 | { | 777 | { |