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.c175
1 files changed, 162 insertions, 13 deletions
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index 594f2318c3d8..71f370dd24bc 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -116,14 +116,15 @@ struct sta_info *sta_info_get(struct ieee80211_local *local, const u8 *addr)
116 return sta; 116 return sta;
117} 117}
118 118
119struct sta_info *sta_info_get_by_idx(struct ieee80211_local *local, int idx, 119struct sta_info *sta_info_get_by_idx(struct ieee80211_sub_if_data *sdata,
120 struct net_device *dev) 120 int idx)
121{ 121{
122 struct ieee80211_local *local = sdata->local;
122 struct sta_info *sta; 123 struct sta_info *sta;
123 int i = 0; 124 int i = 0;
124 125
125 list_for_each_entry_rcu(sta, &local->sta_list, list) { 126 list_for_each_entry_rcu(sta, &local->sta_list, list) {
126 if (dev && dev != sta->sdata->dev) 127 if (sdata != sta->sdata)
127 continue; 128 continue;
128 if (i < idx) { 129 if (i < idx) {
129 ++i; 130 ++i;
@@ -147,8 +148,10 @@ struct sta_info *sta_info_get_by_idx(struct ieee80211_local *local, int idx,
147static void __sta_info_free(struct ieee80211_local *local, 148static void __sta_info_free(struct ieee80211_local *local,
148 struct sta_info *sta) 149 struct sta_info *sta)
149{ 150{
150 rate_control_free_sta(sta); 151 if (sta->rate_ctrl) {
151 rate_control_put(sta->rate_ctrl); 152 rate_control_free_sta(sta);
153 rate_control_put(sta->rate_ctrl);
154 }
152 155
153#ifdef CONFIG_MAC80211_VERBOSE_DEBUG 156#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
154 printk(KERN_DEBUG "%s: Destroyed STA %pM\n", 157 printk(KERN_DEBUG "%s: Destroyed STA %pM\n",
@@ -171,6 +174,8 @@ void sta_info_destroy(struct sta_info *sta)
171 174
172 local = sta->local; 175 local = sta->local;
173 176
177 cancel_work_sync(&sta->drv_unblock_wk);
178
174 rate_control_remove_sta_debugfs(sta); 179 rate_control_remove_sta_debugfs(sta);
175 ieee80211_sta_debugfs_remove(sta); 180 ieee80211_sta_debugfs_remove(sta);
176 181
@@ -259,6 +264,38 @@ static void sta_info_hash_add(struct ieee80211_local *local,
259 rcu_assign_pointer(local->sta_hash[STA_HASH(sta->sta.addr)], sta); 264 rcu_assign_pointer(local->sta_hash[STA_HASH(sta->sta.addr)], sta);
260} 265}
261 266
267static void sta_unblock(struct work_struct *wk)
268{
269 struct sta_info *sta;
270
271 sta = container_of(wk, struct sta_info, drv_unblock_wk);
272
273 if (sta->dead)
274 return;
275
276 if (!test_sta_flags(sta, WLAN_STA_PS_STA))
277 ieee80211_sta_ps_deliver_wakeup(sta);
278 else if (test_and_clear_sta_flags(sta, WLAN_STA_PSPOLL))
279 ieee80211_sta_ps_deliver_poll_response(sta);
280}
281
282static int sta_prepare_rate_control(struct ieee80211_local *local,
283 struct sta_info *sta, gfp_t gfp)
284{
285 if (local->hw.flags & IEEE80211_HW_HAS_RATE_CONTROL)
286 return 0;
287
288 sta->rate_ctrl = rate_control_get(local->rate_ctrl);
289 sta->rate_ctrl_priv = rate_control_alloc_sta(sta->rate_ctrl,
290 &sta->sta, gfp);
291 if (!sta->rate_ctrl_priv) {
292 rate_control_put(sta->rate_ctrl);
293 return -ENOMEM;
294 }
295
296 return 0;
297}
298
262struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, 299struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata,
263 u8 *addr, gfp_t gfp) 300 u8 *addr, gfp_t gfp)
264{ 301{
@@ -272,16 +309,13 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata,
272 309
273 spin_lock_init(&sta->lock); 310 spin_lock_init(&sta->lock);
274 spin_lock_init(&sta->flaglock); 311 spin_lock_init(&sta->flaglock);
312 INIT_WORK(&sta->drv_unblock_wk, sta_unblock);
275 313
276 memcpy(sta->sta.addr, addr, ETH_ALEN); 314 memcpy(sta->sta.addr, addr, ETH_ALEN);
277 sta->local = local; 315 sta->local = local;
278 sta->sdata = sdata; 316 sta->sdata = sdata;
279 317
280 sta->rate_ctrl = rate_control_get(local->rate_ctrl); 318 if (sta_prepare_rate_control(local, sta, gfp)) {
281 sta->rate_ctrl_priv = rate_control_alloc_sta(sta->rate_ctrl,
282 &sta->sta, gfp);
283 if (!sta->rate_ctrl_priv) {
284 rate_control_put(sta->rate_ctrl);
285 kfree(sta); 319 kfree(sta);
286 return NULL; 320 return NULL;
287 } 321 }
@@ -478,8 +512,10 @@ static void __sta_info_unlink(struct sta_info **sta)
478 } 512 }
479 513
480 list_del(&(*sta)->list); 514 list_del(&(*sta)->list);
515 (*sta)->dead = true;
481 516
482 if (test_and_clear_sta_flags(*sta, WLAN_STA_PS)) { 517 if (test_and_clear_sta_flags(*sta,
518 WLAN_STA_PS_STA | WLAN_STA_PS_DRIVER)) {
483 BUG_ON(!sdata->bss); 519 BUG_ON(!sdata->bss);
484 520
485 atomic_dec(&sdata->bss->num_sta_ps); 521 atomic_dec(&sdata->bss->num_sta_ps);
@@ -489,6 +525,9 @@ static void __sta_info_unlink(struct sta_info **sta)
489 local->num_sta--; 525 local->num_sta--;
490 local->sta_generation++; 526 local->sta_generation++;
491 527
528 if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
529 rcu_assign_pointer(sdata->u.vlan.sta, NULL);
530
492 if (local->ops->sta_notify) { 531 if (local->ops->sta_notify) {
493 if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) 532 if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
494 sdata = container_of(sdata->bss, 533 sdata = container_of(sdata->bss,
@@ -801,8 +840,8 @@ void ieee80211_sta_expire(struct ieee80211_sub_if_data *sdata,
801 sta_info_destroy(sta); 840 sta_info_destroy(sta);
802} 841}
803 842
804struct ieee80211_sta *ieee80211_find_sta(struct ieee80211_hw *hw, 843struct ieee80211_sta *ieee80211_find_sta_by_hw(struct ieee80211_hw *hw,
805 const u8 *addr) 844 const u8 *addr)
806{ 845{
807 struct sta_info *sta = sta_info_get(hw_to_local(hw), addr); 846 struct sta_info *sta = sta_info_get(hw_to_local(hw), addr);
808 847
@@ -810,4 +849,114 @@ struct ieee80211_sta *ieee80211_find_sta(struct ieee80211_hw *hw,
810 return NULL; 849 return NULL;
811 return &sta->sta; 850 return &sta->sta;
812} 851}
852EXPORT_SYMBOL_GPL(ieee80211_find_sta_by_hw);
853
854struct ieee80211_sta *ieee80211_find_sta(struct ieee80211_vif *vif,
855 const u8 *addr)
856{
857 struct ieee80211_sub_if_data *sdata;
858
859 if (!vif)
860 return NULL;
861
862 sdata = vif_to_sdata(vif);
863
864 return ieee80211_find_sta_by_hw(&sdata->local->hw, addr);
865}
813EXPORT_SYMBOL(ieee80211_find_sta); 866EXPORT_SYMBOL(ieee80211_find_sta);
867
868/* powersave support code */
869void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta)
870{
871 struct ieee80211_sub_if_data *sdata = sta->sdata;
872 struct ieee80211_local *local = sdata->local;
873 int sent, buffered;
874
875 drv_sta_notify(local, &sdata->vif, STA_NOTIFY_AWAKE, &sta->sta);
876
877 if (!skb_queue_empty(&sta->ps_tx_buf))
878 sta_info_clear_tim_bit(sta);
879
880 /* Send all buffered frames to the station */
881 sent = ieee80211_add_pending_skbs(local, &sta->tx_filtered);
882 buffered = ieee80211_add_pending_skbs(local, &sta->ps_tx_buf);
883 sent += buffered;
884 local->total_ps_buffered -= buffered;
885
886#ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
887 printk(KERN_DEBUG "%s: STA %pM aid %d sending %d filtered/%d PS frames "
888 "since STA not sleeping anymore\n", sdata->dev->name,
889 sta->sta.addr, sta->sta.aid, sent - buffered, buffered);
890#endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */
891}
892
893void ieee80211_sta_ps_deliver_poll_response(struct sta_info *sta)
894{
895 struct ieee80211_sub_if_data *sdata = sta->sdata;
896 struct ieee80211_local *local = sdata->local;
897 struct sk_buff *skb;
898 int no_pending_pkts;
899
900 skb = skb_dequeue(&sta->tx_filtered);
901 if (!skb) {
902 skb = skb_dequeue(&sta->ps_tx_buf);
903 if (skb)
904 local->total_ps_buffered--;
905 }
906 no_pending_pkts = skb_queue_empty(&sta->tx_filtered) &&
907 skb_queue_empty(&sta->ps_tx_buf);
908
909 if (skb) {
910 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
911 struct ieee80211_hdr *hdr =
912 (struct ieee80211_hdr *) skb->data;
913
914 /*
915 * Tell TX path to send this frame even though the STA may
916 * still remain is PS mode after this frame exchange.
917 */
918 info->flags |= IEEE80211_TX_CTL_PSPOLL_RESPONSE;
919
920#ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
921 printk(KERN_DEBUG "STA %pM aid %d: PS Poll (entries after %d)\n",
922 sta->sta.addr, sta->sta.aid,
923 skb_queue_len(&sta->ps_tx_buf));
924#endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */
925
926 /* Use MoreData flag to indicate whether there are more
927 * buffered frames for this STA */
928 if (no_pending_pkts)
929 hdr->frame_control &= cpu_to_le16(~IEEE80211_FCTL_MOREDATA);
930 else
931 hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_MOREDATA);
932
933 ieee80211_add_pending_skb(local, skb);
934
935 if (no_pending_pkts)
936 sta_info_clear_tim_bit(sta);
937#ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
938 } else {
939 /*
940 * FIXME: This can be the result of a race condition between
941 * us expiring a frame and the station polling for it.
942 * Should we send it a null-func frame indicating we
943 * have nothing buffered for it?
944 */
945 printk(KERN_DEBUG "%s: STA %pM sent PS Poll even "
946 "though there are no buffered frames for it\n",
947 sdata->dev->name, sta->sta.addr);
948#endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */
949 }
950}
951
952void ieee80211_sta_block_awake(struct ieee80211_hw *hw,
953 struct ieee80211_sta *pubsta, bool block)
954{
955 struct sta_info *sta = container_of(pubsta, struct sta_info, sta);
956
957 if (block)
958 set_sta_flags(sta, WLAN_STA_PS_DRIVER);
959 else
960 ieee80211_queue_work(hw, &sta->drv_unblock_wk);
961}
962EXPORT_SYMBOL(ieee80211_sta_block_awake);