aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/sta_info.c
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2011-09-29 10:04:27 -0400
committerJohn W. Linville <linville@tuxdriver.com>2011-09-30 15:57:10 -0400
commitc868cb35d013896ab6a80a554fb88baef06cedcd (patch)
tree48ed06dcf3c815e61f38f867e517d5a5dcfa6d79 /net/mac80211/sta_info.c
parent042ec4533720122e6cb93dd9f3b6a75fe2fcff16 (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.c99
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
644static void __sta_info_set_tim_bit(struct ieee80211_if_ap *bss, 644void 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
658void 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
669static 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
683void 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
694static bool sta_info_buffer_expired(struct sta_info *sta, struct sk_buff *skb) 682static 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}
1131EXPORT_SYMBOL(ieee80211_sta_set_buffered); 1116EXPORT_SYMBOL(ieee80211_sta_set_buffered);