diff options
author | Johannes Berg <johannes.berg@intel.com> | 2011-09-29 10:04:27 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2011-09-30 15:57:10 -0400 |
commit | c868cb35d013896ab6a80a554fb88baef06cedcd (patch) | |
tree | 48ed06dcf3c815e61f38f867e517d5a5dcfa6d79 /net/mac80211/sta_info.c | |
parent | 042ec4533720122e6cb93dd9f3b6a75fe2fcff16 (diff) |
mac80211: unify TIM bit handling
Currently, the TIM bit for a given station is set
and cleared all over the place. Since the logic to
set/clear it will become much more complex when we
add uAPSD support, as a first step let's collect
the entire logic in one place. This requires a few
small adjustments to other places.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/mac80211/sta_info.c')
-rw-r--r-- | net/mac80211/sta_info.c | 99 |
1 files changed, 42 insertions, 57 deletions
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index 016742d4c48e..863d59fe6886 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c | |||
@@ -641,54 +641,42 @@ static inline void __bss_tim_clear(struct ieee80211_if_ap *bss, u16 aid) | |||
641 | bss->tim[aid / 8] &= ~(1 << (aid % 8)); | 641 | bss->tim[aid / 8] &= ~(1 << (aid % 8)); |
642 | } | 642 | } |
643 | 643 | ||
644 | static void __sta_info_set_tim_bit(struct ieee80211_if_ap *bss, | 644 | void sta_info_recalc_tim(struct sta_info *sta) |
645 | struct sta_info *sta) | ||
646 | { | ||
647 | BUG_ON(!bss); | ||
648 | |||
649 | __bss_tim_set(bss, sta->sta.aid); | ||
650 | |||
651 | if (sta->local->ops->set_tim) { | ||
652 | sta->local->tim_in_locked_section = true; | ||
653 | drv_set_tim(sta->local, &sta->sta, true); | ||
654 | sta->local->tim_in_locked_section = false; | ||
655 | } | ||
656 | } | ||
657 | |||
658 | void sta_info_set_tim_bit(struct sta_info *sta) | ||
659 | { | 645 | { |
646 | struct ieee80211_local *local = sta->local; | ||
647 | struct ieee80211_if_ap *bss = sta->sdata->bss; | ||
660 | unsigned long flags; | 648 | unsigned long flags; |
649 | bool have_data = false; | ||
661 | 650 | ||
662 | BUG_ON(!sta->sdata->bss); | 651 | if (WARN_ON_ONCE(!sta->sdata->bss)) |
652 | return; | ||
663 | 653 | ||
664 | spin_lock_irqsave(&sta->local->sta_lock, flags); | 654 | /* No need to do anything if the driver does all */ |
665 | __sta_info_set_tim_bit(sta->sdata->bss, sta); | 655 | if (local->hw.flags & IEEE80211_HW_AP_LINK_PS) |
666 | spin_unlock_irqrestore(&sta->local->sta_lock, flags); | 656 | return; |
667 | } | ||
668 | 657 | ||
669 | static void __sta_info_clear_tim_bit(struct ieee80211_if_ap *bss, | 658 | if (sta->dead) |
670 | struct sta_info *sta) | 659 | goto done; |
671 | { | ||
672 | BUG_ON(!bss); | ||
673 | 660 | ||
674 | __bss_tim_clear(bss, sta->sta.aid); | 661 | have_data = test_sta_flags(sta, WLAN_STA_PS_DRIVER_BUF) || |
662 | !skb_queue_empty(&sta->tx_filtered) || | ||
663 | !skb_queue_empty(&sta->ps_tx_buf); | ||
675 | 664 | ||
676 | if (sta->local->ops->set_tim) { | 665 | done: |
677 | sta->local->tim_in_locked_section = true; | 666 | spin_lock_irqsave(&local->sta_lock, flags); |
678 | drv_set_tim(sta->local, &sta->sta, false); | ||
679 | sta->local->tim_in_locked_section = false; | ||
680 | } | ||
681 | } | ||
682 | 667 | ||
683 | void sta_info_clear_tim_bit(struct sta_info *sta) | 668 | if (have_data) |
684 | { | 669 | __bss_tim_set(bss, sta->sta.aid); |
685 | unsigned long flags; | 670 | else |
671 | __bss_tim_clear(bss, sta->sta.aid); | ||
686 | 672 | ||
687 | BUG_ON(!sta->sdata->bss); | 673 | if (local->ops->set_tim) { |
674 | local->tim_in_locked_section = true; | ||
675 | drv_set_tim(local, &sta->sta, have_data); | ||
676 | local->tim_in_locked_section = false; | ||
677 | } | ||
688 | 678 | ||
689 | spin_lock_irqsave(&sta->local->sta_lock, flags); | 679 | spin_unlock_irqrestore(&local->sta_lock, flags); |
690 | __sta_info_clear_tim_bit(sta->sdata->bss, sta); | ||
691 | spin_unlock_irqrestore(&sta->local->sta_lock, flags); | ||
692 | } | 680 | } |
693 | 681 | ||
694 | static bool sta_info_buffer_expired(struct sta_info *sta, struct sk_buff *skb) | 682 | static bool sta_info_buffer_expired(struct sta_info *sta, struct sk_buff *skb) |
@@ -717,6 +705,10 @@ static bool sta_info_cleanup_expire_buffered(struct ieee80211_local *local, | |||
717 | unsigned long flags; | 705 | unsigned long flags; |
718 | struct sk_buff *skb; | 706 | struct sk_buff *skb; |
719 | 707 | ||
708 | /* This is only necessary for stations on BSS interfaces */ | ||
709 | if (!sta->sdata->bss) | ||
710 | return false; | ||
711 | |||
720 | for (;;) { | 712 | for (;;) { |
721 | spin_lock_irqsave(&sta->ps_tx_buf.lock, flags); | 713 | spin_lock_irqsave(&sta->ps_tx_buf.lock, flags); |
722 | skb = skb_peek(&sta->ps_tx_buf); | 714 | skb = skb_peek(&sta->ps_tx_buf); |
@@ -736,9 +728,9 @@ static bool sta_info_cleanup_expire_buffered(struct ieee80211_local *local, | |||
736 | #endif | 728 | #endif |
737 | dev_kfree_skb(skb); | 729 | dev_kfree_skb(skb); |
738 | 730 | ||
739 | if (skb_queue_empty(&sta->ps_tx_buf) && | 731 | /* if the queue is now empty recalc TIM bit */ |
740 | !test_sta_flags(sta, WLAN_STA_PS_DRIVER_BUF)) | 732 | if (skb_queue_empty(&sta->ps_tx_buf)) |
741 | sta_info_clear_tim_bit(sta); | 733 | sta_info_recalc_tim(sta); |
742 | } | 734 | } |
743 | 735 | ||
744 | return !skb_queue_empty(&sta->ps_tx_buf); | 736 | return !skb_queue_empty(&sta->ps_tx_buf); |
@@ -748,7 +740,6 @@ static int __must_check __sta_info_destroy(struct sta_info *sta) | |||
748 | { | 740 | { |
749 | struct ieee80211_local *local; | 741 | struct ieee80211_local *local; |
750 | struct ieee80211_sub_if_data *sdata; | 742 | struct ieee80211_sub_if_data *sdata; |
751 | struct sk_buff *skb; | ||
752 | unsigned long flags; | 743 | unsigned long flags; |
753 | int ret, i; | 744 | int ret, i; |
754 | 745 | ||
@@ -792,7 +783,7 @@ static int __must_check __sta_info_destroy(struct sta_info *sta) | |||
792 | BUG_ON(!sdata->bss); | 783 | BUG_ON(!sdata->bss); |
793 | 784 | ||
794 | atomic_dec(&sdata->bss->num_sta_ps); | 785 | atomic_dec(&sdata->bss->num_sta_ps); |
795 | sta_info_clear_tim_bit(sta); | 786 | sta_info_recalc_tim(sta); |
796 | } | 787 | } |
797 | 788 | ||
798 | local->num_sta--; | 789 | local->num_sta--; |
@@ -818,6 +809,10 @@ static int __must_check __sta_info_destroy(struct sta_info *sta) | |||
818 | */ | 809 | */ |
819 | synchronize_rcu(); | 810 | synchronize_rcu(); |
820 | 811 | ||
812 | local->total_ps_buffered -= skb_queue_len(&sta->ps_tx_buf); | ||
813 | __skb_queue_purge(&sta->ps_tx_buf); | ||
814 | __skb_queue_purge(&sta->tx_filtered); | ||
815 | |||
821 | #ifdef CONFIG_MAC80211_MESH | 816 | #ifdef CONFIG_MAC80211_MESH |
822 | if (ieee80211_vif_is_mesh(&sdata->vif)) | 817 | if (ieee80211_vif_is_mesh(&sdata->vif)) |
823 | mesh_accept_plinks_update(sdata); | 818 | mesh_accept_plinks_update(sdata); |
@@ -840,14 +835,6 @@ static int __must_check __sta_info_destroy(struct sta_info *sta) | |||
840 | } | 835 | } |
841 | #endif | 836 | #endif |
842 | 837 | ||
843 | while ((skb = skb_dequeue(&sta->ps_tx_buf)) != NULL) { | ||
844 | local->total_ps_buffered--; | ||
845 | dev_kfree_skb_any(skb); | ||
846 | } | ||
847 | |||
848 | while ((skb = skb_dequeue(&sta->tx_filtered)) != NULL) | ||
849 | dev_kfree_skb_any(skb); | ||
850 | |||
851 | __sta_info_free(local, sta); | 838 | __sta_info_free(local, sta); |
852 | 839 | ||
853 | return 0; | 840 | return 0; |
@@ -1027,9 +1014,6 @@ void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta) | |||
1027 | if (!(local->hw.flags & IEEE80211_HW_AP_LINK_PS)) | 1014 | if (!(local->hw.flags & IEEE80211_HW_AP_LINK_PS)) |
1028 | drv_sta_notify(local, sdata, STA_NOTIFY_AWAKE, &sta->sta); | 1015 | drv_sta_notify(local, sdata, STA_NOTIFY_AWAKE, &sta->sta); |
1029 | 1016 | ||
1030 | if (!skb_queue_empty(&sta->ps_tx_buf)) | ||
1031 | sta_info_clear_tim_bit(sta); | ||
1032 | |||
1033 | /* Send all buffered frames to the station */ | 1017 | /* Send all buffered frames to the station */ |
1034 | sent = ieee80211_add_pending_skbs(local, &sta->tx_filtered); | 1018 | sent = ieee80211_add_pending_skbs(local, &sta->tx_filtered); |
1035 | buffered = ieee80211_add_pending_skbs_fn(local, &sta->ps_tx_buf, | 1019 | buffered = ieee80211_add_pending_skbs_fn(local, &sta->ps_tx_buf, |
@@ -1037,6 +1021,8 @@ void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta) | |||
1037 | sent += buffered; | 1021 | sent += buffered; |
1038 | local->total_ps_buffered -= buffered; | 1022 | local->total_ps_buffered -= buffered; |
1039 | 1023 | ||
1024 | sta_info_recalc_tim(sta); | ||
1025 | |||
1040 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG | 1026 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG |
1041 | printk(KERN_DEBUG "%s: STA %pM aid %d sending %d filtered/%d PS frames " | 1027 | printk(KERN_DEBUG "%s: STA %pM aid %d sending %d filtered/%d PS frames " |
1042 | "since STA not sleeping anymore\n", sdata->name, | 1028 | "since STA not sleeping anymore\n", sdata->name, |
@@ -1086,8 +1072,7 @@ void ieee80211_sta_ps_deliver_poll_response(struct sta_info *sta) | |||
1086 | 1072 | ||
1087 | ieee80211_add_pending_skb(local, skb); | 1073 | ieee80211_add_pending_skb(local, skb); |
1088 | 1074 | ||
1089 | if (no_pending_pkts) | 1075 | sta_info_recalc_tim(sta); |
1090 | sta_info_clear_tim_bit(sta); | ||
1091 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG | 1076 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG |
1092 | } else { | 1077 | } else { |
1093 | /* | 1078 | /* |
@@ -1126,6 +1111,6 @@ void ieee80211_sta_set_buffered(struct ieee80211_sta *pubsta, | |||
1126 | return; | 1111 | return; |
1127 | 1112 | ||
1128 | set_sta_flags(sta, WLAN_STA_PS_DRIVER_BUF); | 1113 | set_sta_flags(sta, WLAN_STA_PS_DRIVER_BUF); |
1129 | sta_info_set_tim_bit(sta); | 1114 | sta_info_recalc_tim(sta); |
1130 | } | 1115 | } |
1131 | EXPORT_SYMBOL(ieee80211_sta_set_buffered); | 1116 | EXPORT_SYMBOL(ieee80211_sta_set_buffered); |