aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/sta_info.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/mac80211/sta_info.c')
-rw-r--r--net/mac80211/sta_info.c136
1 files changed, 133 insertions, 3 deletions
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index 594f2318c3d8..be59456e8a42 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -171,6 +171,8 @@ void sta_info_destroy(struct sta_info *sta)
171 171
172 local = sta->local; 172 local = sta->local;
173 173
174 cancel_work_sync(&sta->drv_unblock_wk);
175
174 rate_control_remove_sta_debugfs(sta); 176 rate_control_remove_sta_debugfs(sta);
175 ieee80211_sta_debugfs_remove(sta); 177 ieee80211_sta_debugfs_remove(sta);
176 178
@@ -259,6 +261,21 @@ static void sta_info_hash_add(struct ieee80211_local *local,
259 rcu_assign_pointer(local->sta_hash[STA_HASH(sta->sta.addr)], sta); 261 rcu_assign_pointer(local->sta_hash[STA_HASH(sta->sta.addr)], sta);
260} 262}
261 263
264static void sta_unblock(struct work_struct *wk)
265{
266 struct sta_info *sta;
267
268 sta = container_of(wk, struct sta_info, drv_unblock_wk);
269
270 if (sta->dead)
271 return;
272
273 if (!test_sta_flags(sta, WLAN_STA_PS_STA))
274 ieee80211_sta_ps_deliver_wakeup(sta);
275 else if (test_and_clear_sta_flags(sta, WLAN_STA_PSPOLL))
276 ieee80211_sta_ps_deliver_poll_response(sta);
277}
278
262struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, 279struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata,
263 u8 *addr, gfp_t gfp) 280 u8 *addr, gfp_t gfp)
264{ 281{
@@ -272,6 +289,7 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata,
272 289
273 spin_lock_init(&sta->lock); 290 spin_lock_init(&sta->lock);
274 spin_lock_init(&sta->flaglock); 291 spin_lock_init(&sta->flaglock);
292 INIT_WORK(&sta->drv_unblock_wk, sta_unblock);
275 293
276 memcpy(sta->sta.addr, addr, ETH_ALEN); 294 memcpy(sta->sta.addr, addr, ETH_ALEN);
277 sta->local = local; 295 sta->local = local;
@@ -478,8 +496,10 @@ static void __sta_info_unlink(struct sta_info **sta)
478 } 496 }
479 497
480 list_del(&(*sta)->list); 498 list_del(&(*sta)->list);
499 (*sta)->dead = true;
481 500
482 if (test_and_clear_sta_flags(*sta, WLAN_STA_PS)) { 501 if (test_and_clear_sta_flags(*sta,
502 WLAN_STA_PS_STA | WLAN_STA_PS_DRIVER)) {
483 BUG_ON(!sdata->bss); 503 BUG_ON(!sdata->bss);
484 504
485 atomic_dec(&sdata->bss->num_sta_ps); 505 atomic_dec(&sdata->bss->num_sta_ps);
@@ -801,8 +821,8 @@ void ieee80211_sta_expire(struct ieee80211_sub_if_data *sdata,
801 sta_info_destroy(sta); 821 sta_info_destroy(sta);
802} 822}
803 823
804struct ieee80211_sta *ieee80211_find_sta(struct ieee80211_hw *hw, 824struct ieee80211_sta *ieee80211_find_sta_by_hw(struct ieee80211_hw *hw,
805 const u8 *addr) 825 const u8 *addr)
806{ 826{
807 struct sta_info *sta = sta_info_get(hw_to_local(hw), addr); 827 struct sta_info *sta = sta_info_get(hw_to_local(hw), addr);
808 828
@@ -810,4 +830,114 @@ struct ieee80211_sta *ieee80211_find_sta(struct ieee80211_hw *hw,
810 return NULL; 830 return NULL;
811 return &sta->sta; 831 return &sta->sta;
812} 832}
833EXPORT_SYMBOL_GPL(ieee80211_find_sta_by_hw);
834
835struct ieee80211_sta *ieee80211_find_sta(struct ieee80211_vif *vif,
836 const u8 *addr)
837{
838 struct ieee80211_sub_if_data *sdata;
839
840 if (!vif)
841 return NULL;
842
843 sdata = vif_to_sdata(vif);
844
845 return ieee80211_find_sta_by_hw(&sdata->local->hw, addr);
846}
813EXPORT_SYMBOL(ieee80211_find_sta); 847EXPORT_SYMBOL(ieee80211_find_sta);
848
849/* powersave support code */
850void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta)
851{
852 struct ieee80211_sub_if_data *sdata = sta->sdata;
853 struct ieee80211_local *local = sdata->local;
854 int sent, buffered;
855
856 drv_sta_notify(local, &sdata->vif, STA_NOTIFY_AWAKE, &sta->sta);
857
858 if (!skb_queue_empty(&sta->ps_tx_buf))
859 sta_info_clear_tim_bit(sta);
860
861 /* Send all buffered frames to the station */
862 sent = ieee80211_add_pending_skbs(local, &sta->tx_filtered);
863 buffered = ieee80211_add_pending_skbs(local, &sta->ps_tx_buf);
864 sent += buffered;
865 local->total_ps_buffered -= buffered;
866
867#ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
868 printk(KERN_DEBUG "%s: STA %pM aid %d sending %d filtered/%d PS frames "
869 "since STA not sleeping anymore\n", sdata->dev->name,
870 sta->sta.addr, sta->sta.aid, sent - buffered, buffered);
871#endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */
872}
873
874void ieee80211_sta_ps_deliver_poll_response(struct sta_info *sta)
875{
876 struct ieee80211_sub_if_data *sdata = sta->sdata;
877 struct ieee80211_local *local = sdata->local;
878 struct sk_buff *skb;
879 int no_pending_pkts;
880
881 skb = skb_dequeue(&sta->tx_filtered);
882 if (!skb) {
883 skb = skb_dequeue(&sta->ps_tx_buf);
884 if (skb)
885 local->total_ps_buffered--;
886 }
887 no_pending_pkts = skb_queue_empty(&sta->tx_filtered) &&
888 skb_queue_empty(&sta->ps_tx_buf);
889
890 if (skb) {
891 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
892 struct ieee80211_hdr *hdr =
893 (struct ieee80211_hdr *) skb->data;
894
895 /*
896 * Tell TX path to send this frame even though the STA may
897 * still remain is PS mode after this frame exchange.
898 */
899 info->flags |= IEEE80211_TX_CTL_PSPOLL_RESPONSE;
900
901#ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
902 printk(KERN_DEBUG "STA %pM aid %d: PS Poll (entries after %d)\n",
903 sta->sta.addr, sta->sta.aid,
904 skb_queue_len(&sta->ps_tx_buf));
905#endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */
906
907 /* Use MoreData flag to indicate whether there are more
908 * buffered frames for this STA */
909 if (no_pending_pkts)
910 hdr->frame_control &= cpu_to_le16(~IEEE80211_FCTL_MOREDATA);
911 else
912 hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_MOREDATA);
913
914 ieee80211_add_pending_skb(local, skb);
915
916 if (no_pending_pkts)
917 sta_info_clear_tim_bit(sta);
918#ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
919 } else {
920 /*
921 * FIXME: This can be the result of a race condition between
922 * us expiring a frame and the station polling for it.
923 * Should we send it a null-func frame indicating we
924 * have nothing buffered for it?
925 */
926 printk(KERN_DEBUG "%s: STA %pM sent PS Poll even "
927 "though there are no buffered frames for it\n",
928 sdata->dev->name, sta->sta.addr);
929#endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */
930 }
931}
932
933void ieee80211_sta_block_awake(struct ieee80211_hw *hw,
934 struct ieee80211_sta *pubsta, bool block)
935{
936 struct sta_info *sta = container_of(pubsta, struct sta_info, sta);
937
938 if (block)
939 set_sta_flags(sta, WLAN_STA_PS_DRIVER);
940 else
941 ieee80211_queue_work(hw, &sta->drv_unblock_wk);
942}
943EXPORT_SYMBOL(ieee80211_sta_block_awake);