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); | ||
