diff options
Diffstat (limited to 'net/mac80211/sta_info.c')
-rw-r--r-- | net/mac80211/sta_info.c | 107 |
1 files changed, 72 insertions, 35 deletions
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index f2ba653b9d69..7fef8ea1f5ec 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c | |||
@@ -73,11 +73,11 @@ static int sta_info_hash_del(struct ieee80211_local *local, | |||
73 | { | 73 | { |
74 | struct sta_info *s; | 74 | struct sta_info *s; |
75 | 75 | ||
76 | s = local->sta_hash[STA_HASH(sta->addr)]; | 76 | s = local->sta_hash[STA_HASH(sta->sta.addr)]; |
77 | if (!s) | 77 | if (!s) |
78 | return -ENOENT; | 78 | return -ENOENT; |
79 | if (s == sta) { | 79 | if (s == sta) { |
80 | rcu_assign_pointer(local->sta_hash[STA_HASH(sta->addr)], | 80 | rcu_assign_pointer(local->sta_hash[STA_HASH(sta->sta.addr)], |
81 | s->hnext); | 81 | s->hnext); |
82 | return 0; | 82 | return 0; |
83 | } | 83 | } |
@@ -93,26 +93,19 @@ static int sta_info_hash_del(struct ieee80211_local *local, | |||
93 | } | 93 | } |
94 | 94 | ||
95 | /* protected by RCU */ | 95 | /* protected by RCU */ |
96 | static struct sta_info *__sta_info_find(struct ieee80211_local *local, | 96 | struct sta_info *sta_info_get(struct ieee80211_local *local, const u8 *addr) |
97 | u8 *addr) | ||
98 | { | 97 | { |
99 | struct sta_info *sta; | 98 | struct sta_info *sta; |
100 | 99 | ||
101 | sta = rcu_dereference(local->sta_hash[STA_HASH(addr)]); | 100 | sta = rcu_dereference(local->sta_hash[STA_HASH(addr)]); |
102 | while (sta) { | 101 | while (sta) { |
103 | if (compare_ether_addr(sta->addr, addr) == 0) | 102 | if (compare_ether_addr(sta->sta.addr, addr) == 0) |
104 | break; | 103 | break; |
105 | sta = rcu_dereference(sta->hnext); | 104 | sta = rcu_dereference(sta->hnext); |
106 | } | 105 | } |
107 | return sta; | 106 | return sta; |
108 | } | 107 | } |
109 | 108 | ||
110 | struct sta_info *sta_info_get(struct ieee80211_local *local, u8 *addr) | ||
111 | { | ||
112 | return __sta_info_find(local, addr); | ||
113 | } | ||
114 | EXPORT_SYMBOL(sta_info_get); | ||
115 | |||
116 | struct sta_info *sta_info_get_by_idx(struct ieee80211_local *local, int idx, | 109 | struct sta_info *sta_info_get_by_idx(struct ieee80211_local *local, int idx, |
117 | struct net_device *dev) | 110 | struct net_device *dev) |
118 | { | 111 | { |
@@ -146,12 +139,12 @@ static void __sta_info_free(struct ieee80211_local *local, | |||
146 | { | 139 | { |
147 | DECLARE_MAC_BUF(mbuf); | 140 | DECLARE_MAC_BUF(mbuf); |
148 | 141 | ||
149 | rate_control_free_sta(sta->rate_ctrl, sta->rate_ctrl_priv); | 142 | rate_control_free_sta(sta); |
150 | rate_control_put(sta->rate_ctrl); | 143 | rate_control_put(sta->rate_ctrl); |
151 | 144 | ||
152 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | 145 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG |
153 | printk(KERN_DEBUG "%s: Destroyed STA %s\n", | 146 | printk(KERN_DEBUG "%s: Destroyed STA %s\n", |
154 | wiphy_name(local->hw.wiphy), print_mac(mbuf, sta->addr)); | 147 | wiphy_name(local->hw.wiphy), print_mac(mbuf, sta->sta.addr)); |
155 | #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ | 148 | #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ |
156 | 149 | ||
157 | kfree(sta); | 150 | kfree(sta); |
@@ -219,8 +212,8 @@ void sta_info_destroy(struct sta_info *sta) | |||
219 | static void sta_info_hash_add(struct ieee80211_local *local, | 212 | static void sta_info_hash_add(struct ieee80211_local *local, |
220 | struct sta_info *sta) | 213 | struct sta_info *sta) |
221 | { | 214 | { |
222 | sta->hnext = local->sta_hash[STA_HASH(sta->addr)]; | 215 | sta->hnext = local->sta_hash[STA_HASH(sta->sta.addr)]; |
223 | rcu_assign_pointer(local->sta_hash[STA_HASH(sta->addr)], sta); | 216 | rcu_assign_pointer(local->sta_hash[STA_HASH(sta->sta.addr)], sta); |
224 | } | 217 | } |
225 | 218 | ||
226 | struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, | 219 | struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, |
@@ -231,20 +224,20 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, | |||
231 | int i; | 224 | int i; |
232 | DECLARE_MAC_BUF(mbuf); | 225 | DECLARE_MAC_BUF(mbuf); |
233 | 226 | ||
234 | sta = kzalloc(sizeof(*sta), gfp); | 227 | sta = kzalloc(sizeof(*sta) + local->hw.sta_data_size, gfp); |
235 | if (!sta) | 228 | if (!sta) |
236 | return NULL; | 229 | return NULL; |
237 | 230 | ||
238 | spin_lock_init(&sta->lock); | 231 | spin_lock_init(&sta->lock); |
239 | spin_lock_init(&sta->flaglock); | 232 | spin_lock_init(&sta->flaglock); |
240 | 233 | ||
241 | memcpy(sta->addr, addr, ETH_ALEN); | 234 | memcpy(sta->sta.addr, addr, ETH_ALEN); |
242 | sta->local = local; | 235 | sta->local = local; |
243 | sta->sdata = sdata; | 236 | sta->sdata = sdata; |
244 | 237 | ||
245 | sta->rate_ctrl = rate_control_get(local->rate_ctrl); | 238 | sta->rate_ctrl = rate_control_get(local->rate_ctrl); |
246 | sta->rate_ctrl_priv = rate_control_alloc_sta(sta->rate_ctrl, | 239 | sta->rate_ctrl_priv = rate_control_alloc_sta(sta->rate_ctrl, |
247 | gfp); | 240 | &sta->sta, gfp); |
248 | if (!sta->rate_ctrl_priv) { | 241 | if (!sta->rate_ctrl_priv) { |
249 | rate_control_put(sta->rate_ctrl); | 242 | rate_control_put(sta->rate_ctrl); |
250 | kfree(sta); | 243 | kfree(sta); |
@@ -271,7 +264,7 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, | |||
271 | 264 | ||
272 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | 265 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG |
273 | printk(KERN_DEBUG "%s: Allocated STA %s\n", | 266 | printk(KERN_DEBUG "%s: Allocated STA %s\n", |
274 | wiphy_name(local->hw.wiphy), print_mac(mbuf, sta->addr)); | 267 | wiphy_name(local->hw.wiphy), print_mac(mbuf, sta->sta.addr)); |
275 | #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ | 268 | #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ |
276 | 269 | ||
277 | #ifdef CONFIG_MAC80211_MESH | 270 | #ifdef CONFIG_MAC80211_MESH |
@@ -300,15 +293,15 @@ int sta_info_insert(struct sta_info *sta) | |||
300 | goto out_free; | 293 | goto out_free; |
301 | } | 294 | } |
302 | 295 | ||
303 | if (WARN_ON(compare_ether_addr(sta->addr, sdata->dev->dev_addr) == 0 || | 296 | if (WARN_ON(compare_ether_addr(sta->sta.addr, sdata->dev->dev_addr) == 0 || |
304 | is_multicast_ether_addr(sta->addr))) { | 297 | is_multicast_ether_addr(sta->sta.addr))) { |
305 | err = -EINVAL; | 298 | err = -EINVAL; |
306 | goto out_free; | 299 | goto out_free; |
307 | } | 300 | } |
308 | 301 | ||
309 | spin_lock_irqsave(&local->sta_lock, flags); | 302 | spin_lock_irqsave(&local->sta_lock, flags); |
310 | /* check if STA exists already */ | 303 | /* check if STA exists already */ |
311 | if (__sta_info_find(local, sta->addr)) { | 304 | if (sta_info_get(local, sta->sta.addr)) { |
312 | spin_unlock_irqrestore(&local->sta_lock, flags); | 305 | spin_unlock_irqrestore(&local->sta_lock, flags); |
313 | err = -EEXIST; | 306 | err = -EEXIST; |
314 | goto out_free; | 307 | goto out_free; |
@@ -319,18 +312,18 @@ int sta_info_insert(struct sta_info *sta) | |||
319 | 312 | ||
320 | /* notify driver */ | 313 | /* notify driver */ |
321 | if (local->ops->sta_notify) { | 314 | if (local->ops->sta_notify) { |
322 | if (sdata->vif.type == IEEE80211_IF_TYPE_VLAN) | 315 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) |
323 | sdata = container_of(sdata->bss, | 316 | sdata = container_of(sdata->bss, |
324 | struct ieee80211_sub_if_data, | 317 | struct ieee80211_sub_if_data, |
325 | u.ap); | 318 | u.ap); |
326 | 319 | ||
327 | local->ops->sta_notify(local_to_hw(local), &sdata->vif, | 320 | local->ops->sta_notify(local_to_hw(local), &sdata->vif, |
328 | STA_NOTIFY_ADD, sta->addr); | 321 | STA_NOTIFY_ADD, &sta->sta); |
329 | } | 322 | } |
330 | 323 | ||
331 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | 324 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG |
332 | printk(KERN_DEBUG "%s: Inserted STA %s\n", | 325 | printk(KERN_DEBUG "%s: Inserted STA %s\n", |
333 | wiphy_name(local->hw.wiphy), print_mac(mac, sta->addr)); | 326 | wiphy_name(local->hw.wiphy), print_mac(mac, sta->sta.addr)); |
334 | #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ | 327 | #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ |
335 | 328 | ||
336 | spin_unlock_irqrestore(&local->sta_lock, flags); | 329 | spin_unlock_irqrestore(&local->sta_lock, flags); |
@@ -379,11 +372,12 @@ static void __sta_info_set_tim_bit(struct ieee80211_if_ap *bss, | |||
379 | { | 372 | { |
380 | BUG_ON(!bss); | 373 | BUG_ON(!bss); |
381 | 374 | ||
382 | __bss_tim_set(bss, sta->aid); | 375 | __bss_tim_set(bss, sta->sta.aid); |
383 | 376 | ||
384 | if (sta->local->ops->set_tim) { | 377 | if (sta->local->ops->set_tim) { |
385 | sta->local->tim_in_locked_section = true; | 378 | sta->local->tim_in_locked_section = true; |
386 | sta->local->ops->set_tim(local_to_hw(sta->local), sta->aid, 1); | 379 | sta->local->ops->set_tim(local_to_hw(sta->local), |
380 | &sta->sta, true); | ||
387 | sta->local->tim_in_locked_section = false; | 381 | sta->local->tim_in_locked_section = false; |
388 | } | 382 | } |
389 | } | 383 | } |
@@ -404,11 +398,12 @@ static void __sta_info_clear_tim_bit(struct ieee80211_if_ap *bss, | |||
404 | { | 398 | { |
405 | BUG_ON(!bss); | 399 | BUG_ON(!bss); |
406 | 400 | ||
407 | __bss_tim_clear(bss, sta->aid); | 401 | __bss_tim_clear(bss, sta->sta.aid); |
408 | 402 | ||
409 | if (sta->local->ops->set_tim) { | 403 | if (sta->local->ops->set_tim) { |
410 | sta->local->tim_in_locked_section = true; | 404 | sta->local->tim_in_locked_section = true; |
411 | sta->local->ops->set_tim(local_to_hw(sta->local), sta->aid, 0); | 405 | sta->local->ops->set_tim(local_to_hw(sta->local), |
406 | &sta->sta, false); | ||
412 | sta->local->tim_in_locked_section = false; | 407 | sta->local->tim_in_locked_section = false; |
413 | } | 408 | } |
414 | } | 409 | } |
@@ -424,7 +419,7 @@ void sta_info_clear_tim_bit(struct sta_info *sta) | |||
424 | spin_unlock_irqrestore(&sta->local->sta_lock, flags); | 419 | spin_unlock_irqrestore(&sta->local->sta_lock, flags); |
425 | } | 420 | } |
426 | 421 | ||
427 | void __sta_info_unlink(struct sta_info **sta) | 422 | static void __sta_info_unlink(struct sta_info **sta) |
428 | { | 423 | { |
429 | struct ieee80211_local *local = (*sta)->local; | 424 | struct ieee80211_local *local = (*sta)->local; |
430 | struct ieee80211_sub_if_data *sdata = (*sta)->sdata; | 425 | struct ieee80211_sub_if_data *sdata = (*sta)->sdata; |
@@ -456,13 +451,13 @@ void __sta_info_unlink(struct sta_info **sta) | |||
456 | local->num_sta--; | 451 | local->num_sta--; |
457 | 452 | ||
458 | if (local->ops->sta_notify) { | 453 | if (local->ops->sta_notify) { |
459 | if (sdata->vif.type == IEEE80211_IF_TYPE_VLAN) | 454 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) |
460 | sdata = container_of(sdata->bss, | 455 | sdata = container_of(sdata->bss, |
461 | struct ieee80211_sub_if_data, | 456 | struct ieee80211_sub_if_data, |
462 | u.ap); | 457 | u.ap); |
463 | 458 | ||
464 | local->ops->sta_notify(local_to_hw(local), &sdata->vif, | 459 | local->ops->sta_notify(local_to_hw(local), &sdata->vif, |
465 | STA_NOTIFY_REMOVE, (*sta)->addr); | 460 | STA_NOTIFY_REMOVE, &(*sta)->sta); |
466 | } | 461 | } |
467 | 462 | ||
468 | if (ieee80211_vif_is_mesh(&sdata->vif)) { | 463 | if (ieee80211_vif_is_mesh(&sdata->vif)) { |
@@ -474,7 +469,7 @@ void __sta_info_unlink(struct sta_info **sta) | |||
474 | 469 | ||
475 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | 470 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG |
476 | printk(KERN_DEBUG "%s: Removed STA %s\n", | 471 | printk(KERN_DEBUG "%s: Removed STA %s\n", |
477 | wiphy_name(local->hw.wiphy), print_mac(mbuf, (*sta)->addr)); | 472 | wiphy_name(local->hw.wiphy), print_mac(mbuf, (*sta)->sta.addr)); |
478 | #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ | 473 | #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ |
479 | 474 | ||
480 | /* | 475 | /* |
@@ -570,7 +565,7 @@ static void sta_info_cleanup_expire_buffered(struct ieee80211_local *local, | |||
570 | local->total_ps_buffered--; | 565 | local->total_ps_buffered--; |
571 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG | 566 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG |
572 | printk(KERN_DEBUG "Buffered frame expired (STA " | 567 | printk(KERN_DEBUG "Buffered frame expired (STA " |
573 | "%s)\n", print_mac(mac, sta->addr)); | 568 | "%s)\n", print_mac(mac, sta->sta.addr)); |
574 | #endif | 569 | #endif |
575 | dev_kfree_skb(skb); | 570 | dev_kfree_skb(skb); |
576 | 571 | ||
@@ -640,7 +635,12 @@ static void sta_info_debugfs_add_work(struct work_struct *work) | |||
640 | 635 | ||
641 | spin_lock_irqsave(&local->sta_lock, flags); | 636 | spin_lock_irqsave(&local->sta_lock, flags); |
642 | list_for_each_entry(tmp, &local->sta_list, list) { | 637 | list_for_each_entry(tmp, &local->sta_list, list) { |
643 | if (!tmp->debugfs.dir) { | 638 | /* |
639 | * debugfs.add_has_run will be set by | ||
640 | * ieee80211_sta_debugfs_add regardless | ||
641 | * of what else it does. | ||
642 | */ | ||
643 | if (!tmp->debugfs.add_has_run) { | ||
644 | sta = tmp; | 644 | sta = tmp; |
645 | __sta_info_pin(sta); | 645 | __sta_info_pin(sta); |
646 | break; | 646 | break; |
@@ -802,3 +802,40 @@ void sta_info_flush_delayed(struct ieee80211_sub_if_data *sdata) | |||
802 | schedule_work(&local->sta_flush_work); | 802 | schedule_work(&local->sta_flush_work); |
803 | spin_unlock_irqrestore(&local->sta_lock, flags); | 803 | spin_unlock_irqrestore(&local->sta_lock, flags); |
804 | } | 804 | } |
805 | |||
806 | void ieee80211_sta_expire(struct ieee80211_sub_if_data *sdata, | ||
807 | unsigned long exp_time) | ||
808 | { | ||
809 | struct ieee80211_local *local = sdata->local; | ||
810 | struct sta_info *sta, *tmp; | ||
811 | LIST_HEAD(tmp_list); | ||
812 | DECLARE_MAC_BUF(mac); | ||
813 | unsigned long flags; | ||
814 | |||
815 | spin_lock_irqsave(&local->sta_lock, flags); | ||
816 | list_for_each_entry_safe(sta, tmp, &local->sta_list, list) | ||
817 | if (time_after(jiffies, sta->last_rx + exp_time)) { | ||
818 | #ifdef CONFIG_MAC80211_IBSS_DEBUG | ||
819 | printk(KERN_DEBUG "%s: expiring inactive STA %s\n", | ||
820 | sdata->dev->name, print_mac(mac, sta->sta.addr)); | ||
821 | #endif | ||
822 | __sta_info_unlink(&sta); | ||
823 | if (sta) | ||
824 | list_add(&sta->list, &tmp_list); | ||
825 | } | ||
826 | spin_unlock_irqrestore(&local->sta_lock, flags); | ||
827 | |||
828 | list_for_each_entry_safe(sta, tmp, &tmp_list, list) | ||
829 | sta_info_destroy(sta); | ||
830 | } | ||
831 | |||
832 | struct ieee80211_sta *ieee80211_find_sta(struct ieee80211_hw *hw, | ||
833 | const u8 *addr) | ||
834 | { | ||
835 | struct sta_info *sta = sta_info_get(hw_to_local(hw), addr); | ||
836 | |||
837 | if (!sta) | ||
838 | return NULL; | ||
839 | return &sta->sta; | ||
840 | } | ||
841 | EXPORT_SYMBOL(ieee80211_find_sta); | ||