diff options
Diffstat (limited to 'net/mac80211/sta_info.c')
-rw-r--r-- | net/mac80211/sta_info.c | 89 |
1 files changed, 64 insertions, 25 deletions
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index f2ba653b9d69..d9774ac2e0f7 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 | } |
@@ -94,13 +94,13 @@ static int sta_info_hash_del(struct ieee80211_local *local, | |||
94 | 94 | ||
95 | /* protected by RCU */ | 95 | /* protected by RCU */ |
96 | static struct sta_info *__sta_info_find(struct ieee80211_local *local, | 96 | static struct sta_info *__sta_info_find(struct ieee80211_local *local, |
97 | u8 *addr) | 97 | const u8 *addr) |
98 | { | 98 | { |
99 | struct sta_info *sta; | 99 | struct sta_info *sta; |
100 | 100 | ||
101 | sta = rcu_dereference(local->sta_hash[STA_HASH(addr)]); | 101 | sta = rcu_dereference(local->sta_hash[STA_HASH(addr)]); |
102 | while (sta) { | 102 | while (sta) { |
103 | if (compare_ether_addr(sta->addr, addr) == 0) | 103 | if (compare_ether_addr(sta->sta.addr, addr) == 0) |
104 | break; | 104 | break; |
105 | sta = rcu_dereference(sta->hnext); | 105 | sta = rcu_dereference(sta->hnext); |
106 | } | 106 | } |
@@ -151,7 +151,7 @@ static void __sta_info_free(struct ieee80211_local *local, | |||
151 | 151 | ||
152 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | 152 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG |
153 | printk(KERN_DEBUG "%s: Destroyed STA %s\n", | 153 | printk(KERN_DEBUG "%s: Destroyed STA %s\n", |
154 | wiphy_name(local->hw.wiphy), print_mac(mbuf, sta->addr)); | 154 | wiphy_name(local->hw.wiphy), print_mac(mbuf, sta->sta.addr)); |
155 | #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ | 155 | #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ |
156 | 156 | ||
157 | kfree(sta); | 157 | kfree(sta); |
@@ -219,8 +219,8 @@ void sta_info_destroy(struct sta_info *sta) | |||
219 | static void sta_info_hash_add(struct ieee80211_local *local, | 219 | static void sta_info_hash_add(struct ieee80211_local *local, |
220 | struct sta_info *sta) | 220 | struct sta_info *sta) |
221 | { | 221 | { |
222 | sta->hnext = local->sta_hash[STA_HASH(sta->addr)]; | 222 | sta->hnext = local->sta_hash[STA_HASH(sta->sta.addr)]; |
223 | rcu_assign_pointer(local->sta_hash[STA_HASH(sta->addr)], sta); | 223 | rcu_assign_pointer(local->sta_hash[STA_HASH(sta->sta.addr)], sta); |
224 | } | 224 | } |
225 | 225 | ||
226 | struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, | 226 | struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, |
@@ -231,14 +231,14 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, | |||
231 | int i; | 231 | int i; |
232 | DECLARE_MAC_BUF(mbuf); | 232 | DECLARE_MAC_BUF(mbuf); |
233 | 233 | ||
234 | sta = kzalloc(sizeof(*sta), gfp); | 234 | sta = kzalloc(sizeof(*sta) + local->hw.sta_data_size, gfp); |
235 | if (!sta) | 235 | if (!sta) |
236 | return NULL; | 236 | return NULL; |
237 | 237 | ||
238 | spin_lock_init(&sta->lock); | 238 | spin_lock_init(&sta->lock); |
239 | spin_lock_init(&sta->flaglock); | 239 | spin_lock_init(&sta->flaglock); |
240 | 240 | ||
241 | memcpy(sta->addr, addr, ETH_ALEN); | 241 | memcpy(sta->sta.addr, addr, ETH_ALEN); |
242 | sta->local = local; | 242 | sta->local = local; |
243 | sta->sdata = sdata; | 243 | sta->sdata = sdata; |
244 | 244 | ||
@@ -271,7 +271,7 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, | |||
271 | 271 | ||
272 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | 272 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG |
273 | printk(KERN_DEBUG "%s: Allocated STA %s\n", | 273 | printk(KERN_DEBUG "%s: Allocated STA %s\n", |
274 | wiphy_name(local->hw.wiphy), print_mac(mbuf, sta->addr)); | 274 | wiphy_name(local->hw.wiphy), print_mac(mbuf, sta->sta.addr)); |
275 | #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ | 275 | #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ |
276 | 276 | ||
277 | #ifdef CONFIG_MAC80211_MESH | 277 | #ifdef CONFIG_MAC80211_MESH |
@@ -300,15 +300,15 @@ int sta_info_insert(struct sta_info *sta) | |||
300 | goto out_free; | 300 | goto out_free; |
301 | } | 301 | } |
302 | 302 | ||
303 | if (WARN_ON(compare_ether_addr(sta->addr, sdata->dev->dev_addr) == 0 || | 303 | if (WARN_ON(compare_ether_addr(sta->sta.addr, sdata->dev->dev_addr) == 0 || |
304 | is_multicast_ether_addr(sta->addr))) { | 304 | is_multicast_ether_addr(sta->sta.addr))) { |
305 | err = -EINVAL; | 305 | err = -EINVAL; |
306 | goto out_free; | 306 | goto out_free; |
307 | } | 307 | } |
308 | 308 | ||
309 | spin_lock_irqsave(&local->sta_lock, flags); | 309 | spin_lock_irqsave(&local->sta_lock, flags); |
310 | /* check if STA exists already */ | 310 | /* check if STA exists already */ |
311 | if (__sta_info_find(local, sta->addr)) { | 311 | if (__sta_info_find(local, sta->sta.addr)) { |
312 | spin_unlock_irqrestore(&local->sta_lock, flags); | 312 | spin_unlock_irqrestore(&local->sta_lock, flags); |
313 | err = -EEXIST; | 313 | err = -EEXIST; |
314 | goto out_free; | 314 | goto out_free; |
@@ -319,18 +319,18 @@ int sta_info_insert(struct sta_info *sta) | |||
319 | 319 | ||
320 | /* notify driver */ | 320 | /* notify driver */ |
321 | if (local->ops->sta_notify) { | 321 | if (local->ops->sta_notify) { |
322 | if (sdata->vif.type == IEEE80211_IF_TYPE_VLAN) | 322 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) |
323 | sdata = container_of(sdata->bss, | 323 | sdata = container_of(sdata->bss, |
324 | struct ieee80211_sub_if_data, | 324 | struct ieee80211_sub_if_data, |
325 | u.ap); | 325 | u.ap); |
326 | 326 | ||
327 | local->ops->sta_notify(local_to_hw(local), &sdata->vif, | 327 | local->ops->sta_notify(local_to_hw(local), &sdata->vif, |
328 | STA_NOTIFY_ADD, sta->addr); | 328 | STA_NOTIFY_ADD, &sta->sta); |
329 | } | 329 | } |
330 | 330 | ||
331 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | 331 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG |
332 | printk(KERN_DEBUG "%s: Inserted STA %s\n", | 332 | printk(KERN_DEBUG "%s: Inserted STA %s\n", |
333 | wiphy_name(local->hw.wiphy), print_mac(mac, sta->addr)); | 333 | wiphy_name(local->hw.wiphy), print_mac(mac, sta->sta.addr)); |
334 | #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ | 334 | #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ |
335 | 335 | ||
336 | spin_unlock_irqrestore(&local->sta_lock, flags); | 336 | spin_unlock_irqrestore(&local->sta_lock, flags); |
@@ -379,11 +379,12 @@ static void __sta_info_set_tim_bit(struct ieee80211_if_ap *bss, | |||
379 | { | 379 | { |
380 | BUG_ON(!bss); | 380 | BUG_ON(!bss); |
381 | 381 | ||
382 | __bss_tim_set(bss, sta->aid); | 382 | __bss_tim_set(bss, sta->sta.aid); |
383 | 383 | ||
384 | if (sta->local->ops->set_tim) { | 384 | if (sta->local->ops->set_tim) { |
385 | sta->local->tim_in_locked_section = true; | 385 | sta->local->tim_in_locked_section = true; |
386 | sta->local->ops->set_tim(local_to_hw(sta->local), sta->aid, 1); | 386 | sta->local->ops->set_tim(local_to_hw(sta->local), |
387 | &sta->sta, true); | ||
387 | sta->local->tim_in_locked_section = false; | 388 | sta->local->tim_in_locked_section = false; |
388 | } | 389 | } |
389 | } | 390 | } |
@@ -404,11 +405,12 @@ static void __sta_info_clear_tim_bit(struct ieee80211_if_ap *bss, | |||
404 | { | 405 | { |
405 | BUG_ON(!bss); | 406 | BUG_ON(!bss); |
406 | 407 | ||
407 | __bss_tim_clear(bss, sta->aid); | 408 | __bss_tim_clear(bss, sta->sta.aid); |
408 | 409 | ||
409 | if (sta->local->ops->set_tim) { | 410 | if (sta->local->ops->set_tim) { |
410 | sta->local->tim_in_locked_section = true; | 411 | sta->local->tim_in_locked_section = true; |
411 | sta->local->ops->set_tim(local_to_hw(sta->local), sta->aid, 0); | 412 | sta->local->ops->set_tim(local_to_hw(sta->local), |
413 | &sta->sta, false); | ||
412 | sta->local->tim_in_locked_section = false; | 414 | sta->local->tim_in_locked_section = false; |
413 | } | 415 | } |
414 | } | 416 | } |
@@ -424,7 +426,7 @@ void sta_info_clear_tim_bit(struct sta_info *sta) | |||
424 | spin_unlock_irqrestore(&sta->local->sta_lock, flags); | 426 | spin_unlock_irqrestore(&sta->local->sta_lock, flags); |
425 | } | 427 | } |
426 | 428 | ||
427 | void __sta_info_unlink(struct sta_info **sta) | 429 | static void __sta_info_unlink(struct sta_info **sta) |
428 | { | 430 | { |
429 | struct ieee80211_local *local = (*sta)->local; | 431 | struct ieee80211_local *local = (*sta)->local; |
430 | struct ieee80211_sub_if_data *sdata = (*sta)->sdata; | 432 | struct ieee80211_sub_if_data *sdata = (*sta)->sdata; |
@@ -456,13 +458,13 @@ void __sta_info_unlink(struct sta_info **sta) | |||
456 | local->num_sta--; | 458 | local->num_sta--; |
457 | 459 | ||
458 | if (local->ops->sta_notify) { | 460 | if (local->ops->sta_notify) { |
459 | if (sdata->vif.type == IEEE80211_IF_TYPE_VLAN) | 461 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) |
460 | sdata = container_of(sdata->bss, | 462 | sdata = container_of(sdata->bss, |
461 | struct ieee80211_sub_if_data, | 463 | struct ieee80211_sub_if_data, |
462 | u.ap); | 464 | u.ap); |
463 | 465 | ||
464 | local->ops->sta_notify(local_to_hw(local), &sdata->vif, | 466 | local->ops->sta_notify(local_to_hw(local), &sdata->vif, |
465 | STA_NOTIFY_REMOVE, (*sta)->addr); | 467 | STA_NOTIFY_REMOVE, &(*sta)->sta); |
466 | } | 468 | } |
467 | 469 | ||
468 | if (ieee80211_vif_is_mesh(&sdata->vif)) { | 470 | if (ieee80211_vif_is_mesh(&sdata->vif)) { |
@@ -474,7 +476,7 @@ void __sta_info_unlink(struct sta_info **sta) | |||
474 | 476 | ||
475 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | 477 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG |
476 | printk(KERN_DEBUG "%s: Removed STA %s\n", | 478 | printk(KERN_DEBUG "%s: Removed STA %s\n", |
477 | wiphy_name(local->hw.wiphy), print_mac(mbuf, (*sta)->addr)); | 479 | wiphy_name(local->hw.wiphy), print_mac(mbuf, (*sta)->sta.addr)); |
478 | #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ | 480 | #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ |
479 | 481 | ||
480 | /* | 482 | /* |
@@ -570,7 +572,7 @@ static void sta_info_cleanup_expire_buffered(struct ieee80211_local *local, | |||
570 | local->total_ps_buffered--; | 572 | local->total_ps_buffered--; |
571 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG | 573 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG |
572 | printk(KERN_DEBUG "Buffered frame expired (STA " | 574 | printk(KERN_DEBUG "Buffered frame expired (STA " |
573 | "%s)\n", print_mac(mac, sta->addr)); | 575 | "%s)\n", print_mac(mac, sta->sta.addr)); |
574 | #endif | 576 | #endif |
575 | dev_kfree_skb(skb); | 577 | dev_kfree_skb(skb); |
576 | 578 | ||
@@ -802,3 +804,40 @@ void sta_info_flush_delayed(struct ieee80211_sub_if_data *sdata) | |||
802 | schedule_work(&local->sta_flush_work); | 804 | schedule_work(&local->sta_flush_work); |
803 | spin_unlock_irqrestore(&local->sta_lock, flags); | 805 | spin_unlock_irqrestore(&local->sta_lock, flags); |
804 | } | 806 | } |
807 | |||
808 | void ieee80211_sta_expire(struct ieee80211_sub_if_data *sdata, | ||
809 | unsigned long exp_time) | ||
810 | { | ||
811 | struct ieee80211_local *local = sdata->local; | ||
812 | struct sta_info *sta, *tmp; | ||
813 | LIST_HEAD(tmp_list); | ||
814 | DECLARE_MAC_BUF(mac); | ||
815 | unsigned long flags; | ||
816 | |||
817 | spin_lock_irqsave(&local->sta_lock, flags); | ||
818 | list_for_each_entry_safe(sta, tmp, &local->sta_list, list) | ||
819 | if (time_after(jiffies, sta->last_rx + exp_time)) { | ||
820 | #ifdef CONFIG_MAC80211_IBSS_DEBUG | ||
821 | printk(KERN_DEBUG "%s: expiring inactive STA %s\n", | ||
822 | sdata->dev->name, print_mac(mac, sta->sta.addr)); | ||
823 | #endif | ||
824 | __sta_info_unlink(&sta); | ||
825 | if (sta) | ||
826 | list_add(&sta->list, &tmp_list); | ||
827 | } | ||
828 | spin_unlock_irqrestore(&local->sta_lock, flags); | ||
829 | |||
830 | list_for_each_entry_safe(sta, tmp, &tmp_list, list) | ||
831 | sta_info_destroy(sta); | ||
832 | } | ||
833 | |||
834 | struct ieee80211_sta *ieee80211_find_sta(struct ieee80211_hw *hw, | ||
835 | const u8 *addr) | ||
836 | { | ||
837 | struct sta_info *sta = __sta_info_find(hw_to_local(hw), addr); | ||
838 | |||
839 | if (!sta) | ||
840 | return NULL; | ||
841 | return &sta->sta; | ||
842 | } | ||
843 | EXPORT_SYMBOL(ieee80211_find_sta); | ||