diff options
-rw-r--r-- | net/mac80211/mlme.c | 15 | ||||
-rw-r--r-- | net/mac80211/rx.c | 13 | ||||
-rw-r--r-- | net/mac80211/sta_info.c | 135 | ||||
-rw-r--r-- | net/mac80211/sta_info.h | 30 |
4 files changed, 38 insertions, 155 deletions
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 40b929d57a97..d04811a29cdf 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -1581,7 +1581,7 @@ static bool ieee80211_assoc_success(struct ieee80211_work *wk, | |||
1581 | * station info was already allocated and inserted before | 1581 | * station info was already allocated and inserted before |
1582 | * the association and should be available to us | 1582 | * the association and should be available to us |
1583 | */ | 1583 | */ |
1584 | sta = sta_info_get_rx(sdata, cbss->bssid); | 1584 | sta = sta_info_get(sdata, cbss->bssid); |
1585 | if (WARN_ON(!sta)) { | 1585 | if (WARN_ON(!sta)) { |
1586 | mutex_unlock(&sdata->local->sta_mtx); | 1586 | mutex_unlock(&sdata->local->sta_mtx); |
1587 | return false; | 1587 | return false; |
@@ -1648,14 +1648,7 @@ static bool ieee80211_assoc_success(struct ieee80211_work *wk, | |||
1648 | return false; | 1648 | return false; |
1649 | } | 1649 | } |
1650 | 1650 | ||
1651 | /* sta_info_reinsert will also unlock the mutex lock */ | 1651 | mutex_unlock(&sdata->local->sta_mtx); |
1652 | err = sta_info_reinsert(sta); | ||
1653 | sta = NULL; | ||
1654 | if (err) { | ||
1655 | printk(KERN_DEBUG "%s: failed to insert STA entry for" | ||
1656 | " the AP (error %d)\n", sdata->name, err); | ||
1657 | return false; | ||
1658 | } | ||
1659 | 1652 | ||
1660 | /* | 1653 | /* |
1661 | * Always handle WMM once after association regardless | 1654 | * Always handle WMM once after association regardless |
@@ -2536,12 +2529,10 @@ static int ieee80211_pre_assoc(struct ieee80211_sub_if_data *sdata, | |||
2536 | if (!sta) | 2529 | if (!sta) |
2537 | return -ENOMEM; | 2530 | return -ENOMEM; |
2538 | 2531 | ||
2539 | sta->dummy = true; | ||
2540 | |||
2541 | err = sta_info_insert(sta); | 2532 | err = sta_info_insert(sta); |
2542 | sta = NULL; | 2533 | sta = NULL; |
2543 | if (err) { | 2534 | if (err) { |
2544 | printk(KERN_DEBUG "%s: failed to insert Dummy STA entry for" | 2535 | printk(KERN_DEBUG "%s: failed to insert STA entry for" |
2545 | " the AP (error %d)\n", sdata->name, err); | 2536 | " the AP (error %d)\n", sdata->name, err); |
2546 | return err; | 2537 | return err; |
2547 | } | 2538 | } |
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index ab29253fb4f2..8d6fa674f53e 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -859,7 +859,12 @@ ieee80211_rx_h_check(struct ieee80211_rx_data *rx) | |||
859 | rx->sdata->vif.type != NL80211_IFTYPE_ADHOC && | 859 | rx->sdata->vif.type != NL80211_IFTYPE_ADHOC && |
860 | rx->sdata->vif.type != NL80211_IFTYPE_WDS && | 860 | rx->sdata->vif.type != NL80211_IFTYPE_WDS && |
861 | (!rx->sta || !test_sta_flag(rx->sta, WLAN_STA_ASSOC)))) { | 861 | (!rx->sta || !test_sta_flag(rx->sta, WLAN_STA_ASSOC)))) { |
862 | if (rx->sta && rx->sta->dummy && | 862 | /* |
863 | * accept port control frames from the AP even when it's not | ||
864 | * yet marked ASSOC to prevent a race where we don't set the | ||
865 | * assoc bit quickly enough before it sends the first frame | ||
866 | */ | ||
867 | if (rx->sta && rx->sdata->vif.type == NL80211_IFTYPE_STATION && | ||
863 | ieee80211_is_data_present(hdr->frame_control)) { | 868 | ieee80211_is_data_present(hdr->frame_control)) { |
864 | u16 ethertype; | 869 | u16 ethertype; |
865 | u8 *payload; | 870 | u8 *payload; |
@@ -2949,7 +2954,7 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, | |||
2949 | if (ieee80211_is_data(fc)) { | 2954 | if (ieee80211_is_data(fc)) { |
2950 | prev_sta = NULL; | 2955 | prev_sta = NULL; |
2951 | 2956 | ||
2952 | for_each_sta_info_rx(local, hdr->addr2, sta, tmp) { | 2957 | for_each_sta_info(local, hdr->addr2, sta, tmp) { |
2953 | if (!prev_sta) { | 2958 | if (!prev_sta) { |
2954 | prev_sta = sta; | 2959 | prev_sta = sta; |
2955 | continue; | 2960 | continue; |
@@ -2993,7 +2998,7 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, | |||
2993 | continue; | 2998 | continue; |
2994 | } | 2999 | } |
2995 | 3000 | ||
2996 | rx.sta = sta_info_get_bss_rx(prev, hdr->addr2); | 3001 | rx.sta = sta_info_get_bss(prev, hdr->addr2); |
2997 | rx.sdata = prev; | 3002 | rx.sdata = prev; |
2998 | ieee80211_prepare_and_rx_handle(&rx, skb, false); | 3003 | ieee80211_prepare_and_rx_handle(&rx, skb, false); |
2999 | 3004 | ||
@@ -3001,7 +3006,7 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, | |||
3001 | } | 3006 | } |
3002 | 3007 | ||
3003 | if (prev) { | 3008 | if (prev) { |
3004 | rx.sta = sta_info_get_bss_rx(prev, hdr->addr2); | 3009 | rx.sta = sta_info_get_bss(prev, hdr->addr2); |
3005 | rx.sdata = prev; | 3010 | rx.sdata = prev; |
3006 | 3011 | ||
3007 | if (ieee80211_prepare_and_rx_handle(&rx, skb, true)) | 3012 | if (ieee80211_prepare_and_rx_handle(&rx, skb, true)) |
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index 5e577bd0e6aa..31cd6d92531c 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c | |||
@@ -100,25 +100,6 @@ struct sta_info *sta_info_get(struct ieee80211_sub_if_data *sdata, | |||
100 | sta = rcu_dereference_check(local->sta_hash[STA_HASH(addr)], | 100 | sta = rcu_dereference_check(local->sta_hash[STA_HASH(addr)], |
101 | lockdep_is_held(&local->sta_mtx)); | 101 | lockdep_is_held(&local->sta_mtx)); |
102 | while (sta) { | 102 | while (sta) { |
103 | if (sta->sdata == sdata && !sta->dummy && | ||
104 | memcmp(sta->sta.addr, addr, ETH_ALEN) == 0) | ||
105 | break; | ||
106 | sta = rcu_dereference_check(sta->hnext, | ||
107 | lockdep_is_held(&local->sta_mtx)); | ||
108 | } | ||
109 | return sta; | ||
110 | } | ||
111 | |||
112 | /* get a station info entry even if it is a dummy station*/ | ||
113 | struct sta_info *sta_info_get_rx(struct ieee80211_sub_if_data *sdata, | ||
114 | const u8 *addr) | ||
115 | { | ||
116 | struct ieee80211_local *local = sdata->local; | ||
117 | struct sta_info *sta; | ||
118 | |||
119 | sta = rcu_dereference_check(local->sta_hash[STA_HASH(addr)], | ||
120 | lockdep_is_held(&local->sta_mtx)); | ||
121 | while (sta) { | ||
122 | if (sta->sdata == sdata && | 103 | if (sta->sdata == sdata && |
123 | memcmp(sta->sta.addr, addr, ETH_ALEN) == 0) | 104 | memcmp(sta->sta.addr, addr, ETH_ALEN) == 0) |
124 | break; | 105 | break; |
@@ -143,30 +124,6 @@ struct sta_info *sta_info_get_bss(struct ieee80211_sub_if_data *sdata, | |||
143 | while (sta) { | 124 | while (sta) { |
144 | if ((sta->sdata == sdata || | 125 | if ((sta->sdata == sdata || |
145 | (sta->sdata->bss && sta->sdata->bss == sdata->bss)) && | 126 | (sta->sdata->bss && sta->sdata->bss == sdata->bss)) && |
146 | !sta->dummy && | ||
147 | memcmp(sta->sta.addr, addr, ETH_ALEN) == 0) | ||
148 | break; | ||
149 | sta = rcu_dereference_check(sta->hnext, | ||
150 | lockdep_is_held(&local->sta_mtx)); | ||
151 | } | ||
152 | return sta; | ||
153 | } | ||
154 | |||
155 | /* | ||
156 | * Get sta info either from the specified interface | ||
157 | * or from one of its vlans (including dummy stations) | ||
158 | */ | ||
159 | struct sta_info *sta_info_get_bss_rx(struct ieee80211_sub_if_data *sdata, | ||
160 | const u8 *addr) | ||
161 | { | ||
162 | struct ieee80211_local *local = sdata->local; | ||
163 | struct sta_info *sta; | ||
164 | |||
165 | sta = rcu_dereference_check(local->sta_hash[STA_HASH(addr)], | ||
166 | lockdep_is_held(&local->sta_mtx)); | ||
167 | while (sta) { | ||
168 | if ((sta->sdata == sdata || | ||
169 | (sta->sdata->bss && sta->sdata->bss == sdata->bss)) && | ||
170 | memcmp(sta->sta.addr, addr, ETH_ALEN) == 0) | 127 | memcmp(sta->sta.addr, addr, ETH_ALEN) == 0) |
171 | break; | 128 | break; |
172 | sta = rcu_dereference_check(sta->hnext, | 129 | sta = rcu_dereference_check(sta->hnext, |
@@ -397,66 +354,43 @@ static int sta_info_insert_finish(struct sta_info *sta) __acquires(RCU) | |||
397 | { | 354 | { |
398 | struct ieee80211_local *local = sta->local; | 355 | struct ieee80211_local *local = sta->local; |
399 | struct ieee80211_sub_if_data *sdata = sta->sdata; | 356 | struct ieee80211_sub_if_data *sdata = sta->sdata; |
400 | struct sta_info *exist_sta; | 357 | struct station_info sinfo; |
401 | bool dummy_reinsert = false; | ||
402 | int err = 0; | 358 | int err = 0; |
403 | 359 | ||
404 | lockdep_assert_held(&local->sta_mtx); | 360 | lockdep_assert_held(&local->sta_mtx); |
405 | 361 | ||
406 | /* | 362 | /* check if STA exists already */ |
407 | * check if STA exists already. | 363 | if (sta_info_get_bss(sdata, sta->sta.addr)) { |
408 | * only accept a scenario of a second call to sta_info_insert_finish | 364 | err = -EEXIST; |
409 | * with a dummy station entry that was inserted earlier | 365 | goto out_err; |
410 | * in that case - assume that the dummy station flag should | ||
411 | * be removed. | ||
412 | */ | ||
413 | exist_sta = sta_info_get_bss_rx(sdata, sta->sta.addr); | ||
414 | if (exist_sta) { | ||
415 | if (exist_sta == sta && sta->dummy) { | ||
416 | dummy_reinsert = true; | ||
417 | } else { | ||
418 | err = -EEXIST; | ||
419 | goto out_err; | ||
420 | } | ||
421 | } | ||
422 | |||
423 | if (!sta->dummy || dummy_reinsert) { | ||
424 | /* notify driver */ | ||
425 | err = sta_info_insert_drv_state(local, sdata, sta); | ||
426 | if (err) | ||
427 | goto out_err; | ||
428 | } | 366 | } |
429 | 367 | ||
430 | if (!dummy_reinsert) { | 368 | /* notify driver */ |
431 | local->num_sta++; | 369 | err = sta_info_insert_drv_state(local, sdata, sta); |
432 | local->sta_generation++; | 370 | if (err) |
433 | smp_mb(); | 371 | goto out_err; |
434 | 372 | ||
435 | /* make the station visible */ | 373 | local->num_sta++; |
436 | sta_info_hash_add(local, sta); | 374 | local->sta_generation++; |
375 | smp_mb(); | ||
437 | 376 | ||
438 | list_add(&sta->list, &local->sta_list); | 377 | /* make the station visible */ |
378 | sta_info_hash_add(local, sta); | ||
439 | 379 | ||
440 | set_sta_flag(sta, WLAN_STA_INSERTED); | 380 | list_add(&sta->list, &local->sta_list); |
441 | } else { | ||
442 | sta->dummy = false; | ||
443 | } | ||
444 | 381 | ||
445 | if (!sta->dummy) { | 382 | set_sta_flag(sta, WLAN_STA_INSERTED); |
446 | struct station_info sinfo; | ||
447 | 383 | ||
448 | ieee80211_sta_debugfs_add(sta); | 384 | ieee80211_sta_debugfs_add(sta); |
449 | rate_control_add_sta_debugfs(sta); | 385 | rate_control_add_sta_debugfs(sta); |
450 | 386 | ||
451 | memset(&sinfo, 0, sizeof(sinfo)); | 387 | memset(&sinfo, 0, sizeof(sinfo)); |
452 | sinfo.filled = 0; | 388 | sinfo.filled = 0; |
453 | sinfo.generation = local->sta_generation; | 389 | sinfo.generation = local->sta_generation; |
454 | cfg80211_new_sta(sdata->dev, sta->sta.addr, &sinfo, GFP_KERNEL); | 390 | cfg80211_new_sta(sdata->dev, sta->sta.addr, &sinfo, GFP_KERNEL); |
455 | } | ||
456 | 391 | ||
457 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | 392 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG |
458 | wiphy_debug(local->hw.wiphy, "Inserted %sSTA %pM\n", | 393 | wiphy_debug(local->hw.wiphy, "Inserted STA %pM\n", sta->sta.addr); |
459 | sta->dummy ? "dummy " : "", sta->sta.addr); | ||
460 | #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ | 394 | #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ |
461 | 395 | ||
462 | /* move reference to rcu-protected */ | 396 | /* move reference to rcu-protected */ |
@@ -508,25 +442,6 @@ int sta_info_insert(struct sta_info *sta) | |||
508 | return err; | 442 | return err; |
509 | } | 443 | } |
510 | 444 | ||
511 | /* Caller must hold sta->local->sta_mtx */ | ||
512 | int sta_info_reinsert(struct sta_info *sta) | ||
513 | { | ||
514 | struct ieee80211_local *local = sta->local; | ||
515 | int err = 0; | ||
516 | |||
517 | err = sta_info_insert_check(sta); | ||
518 | if (err) { | ||
519 | mutex_unlock(&local->sta_mtx); | ||
520 | return err; | ||
521 | } | ||
522 | |||
523 | might_sleep(); | ||
524 | |||
525 | err = sta_info_insert_finish(sta); | ||
526 | rcu_read_unlock(); | ||
527 | return err; | ||
528 | } | ||
529 | |||
530 | static inline void __bss_tim_set(struct ieee80211_if_ap *bss, u16 aid) | 445 | static inline void __bss_tim_set(struct ieee80211_if_ap *bss, u16 aid) |
531 | { | 446 | { |
532 | /* | 447 | /* |
@@ -873,7 +788,7 @@ int sta_info_destroy_addr(struct ieee80211_sub_if_data *sdata, const u8 *addr) | |||
873 | int ret; | 788 | int ret; |
874 | 789 | ||
875 | mutex_lock(&sdata->local->sta_mtx); | 790 | mutex_lock(&sdata->local->sta_mtx); |
876 | sta = sta_info_get_rx(sdata, addr); | 791 | sta = sta_info_get(sdata, addr); |
877 | ret = __sta_info_destroy(sta); | 792 | ret = __sta_info_destroy(sta); |
878 | mutex_unlock(&sdata->local->sta_mtx); | 793 | mutex_unlock(&sdata->local->sta_mtx); |
879 | 794 | ||
@@ -887,7 +802,7 @@ int sta_info_destroy_addr_bss(struct ieee80211_sub_if_data *sdata, | |||
887 | int ret; | 802 | int ret; |
888 | 803 | ||
889 | mutex_lock(&sdata->local->sta_mtx); | 804 | mutex_lock(&sdata->local->sta_mtx); |
890 | sta = sta_info_get_bss_rx(sdata, addr); | 805 | sta = sta_info_get_bss(sdata, addr); |
891 | ret = __sta_info_destroy(sta); | 806 | ret = __sta_info_destroy(sta); |
892 | mutex_unlock(&sdata->local->sta_mtx); | 807 | mutex_unlock(&sdata->local->sta_mtx); |
893 | 808 | ||
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index 2ee808860007..03f249bc2766 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h | |||
@@ -265,8 +265,6 @@ struct sta_ampdu_mlme { | |||
265 | * @dead: set to true when sta is unlinked | 265 | * @dead: set to true when sta is unlinked |
266 | * @uploaded: set to true when sta is uploaded to the driver | 266 | * @uploaded: set to true when sta is uploaded to the driver |
267 | * @lost_packets: number of consecutive lost packets | 267 | * @lost_packets: number of consecutive lost packets |
268 | * @dummy: indicate a dummy station created for receiving | ||
269 | * EAP frames before association | ||
270 | * @sta: station information we share with the driver | 268 | * @sta: station information we share with the driver |
271 | * @sta_state: duplicates information about station state (for debug) | 269 | * @sta_state: duplicates information about station state (for debug) |
272 | * @beacon_loss_count: number of times beacon loss has triggered | 270 | * @beacon_loss_count: number of times beacon loss has triggered |
@@ -364,9 +362,6 @@ struct sta_info { | |||
364 | unsigned int lost_packets; | 362 | unsigned int lost_packets; |
365 | unsigned int beacon_loss_count; | 363 | unsigned int beacon_loss_count; |
366 | 364 | ||
367 | /* should be right in front of sta to be in the same cache line */ | ||
368 | bool dummy; | ||
369 | |||
370 | /* keep last! */ | 365 | /* keep last! */ |
371 | struct ieee80211_sta sta; | 366 | struct ieee80211_sta sta; |
372 | }; | 367 | }; |
@@ -468,15 +463,9 @@ rcu_dereference_protected_tid_tx(struct sta_info *sta, int tid) | |||
468 | struct sta_info *sta_info_get(struct ieee80211_sub_if_data *sdata, | 463 | struct sta_info *sta_info_get(struct ieee80211_sub_if_data *sdata, |
469 | const u8 *addr); | 464 | const u8 *addr); |
470 | 465 | ||
471 | struct sta_info *sta_info_get_rx(struct ieee80211_sub_if_data *sdata, | ||
472 | const u8 *addr); | ||
473 | |||
474 | struct sta_info *sta_info_get_bss(struct ieee80211_sub_if_data *sdata, | 466 | struct sta_info *sta_info_get_bss(struct ieee80211_sub_if_data *sdata, |
475 | const u8 *addr); | 467 | const u8 *addr); |
476 | 468 | ||
477 | struct sta_info *sta_info_get_bss_rx(struct ieee80211_sub_if_data *sdata, | ||
478 | const u8 *addr); | ||
479 | |||
480 | static inline | 469 | static inline |
481 | void for_each_sta_info_type_check(struct ieee80211_local *local, | 470 | void for_each_sta_info_type_check(struct ieee80211_local *local, |
482 | const u8 *addr, | 471 | const u8 *addr, |
@@ -485,23 +474,7 @@ void for_each_sta_info_type_check(struct ieee80211_local *local, | |||
485 | { | 474 | { |
486 | } | 475 | } |
487 | 476 | ||
488 | #define for_each_sta_info(local, _addr, _sta, nxt) \ | 477 | #define for_each_sta_info(local, _addr, _sta, nxt) \ |
489 | for ( /* initialise loop */ \ | ||
490 | _sta = rcu_dereference(local->sta_hash[STA_HASH(_addr)]),\ | ||
491 | nxt = _sta ? rcu_dereference(_sta->hnext) : NULL; \ | ||
492 | /* typecheck */ \ | ||
493 | for_each_sta_info_type_check(local, (_addr), _sta, nxt),\ | ||
494 | /* continue condition */ \ | ||
495 | _sta; \ | ||
496 | /* advance loop */ \ | ||
497 | _sta = nxt, \ | ||
498 | nxt = _sta ? rcu_dereference(_sta->hnext) : NULL \ | ||
499 | ) \ | ||
500 | /* run code only if address matches and it's not a dummy sta */ \ | ||
501 | if (memcmp(_sta->sta.addr, (_addr), ETH_ALEN) == 0 && \ | ||
502 | !_sta->dummy) | ||
503 | |||
504 | #define for_each_sta_info_rx(local, _addr, _sta, nxt) \ | ||
505 | for ( /* initialise loop */ \ | 478 | for ( /* initialise loop */ \ |
506 | _sta = rcu_dereference(local->sta_hash[STA_HASH(_addr)]),\ | 479 | _sta = rcu_dereference(local->sta_hash[STA_HASH(_addr)]),\ |
507 | nxt = _sta ? rcu_dereference(_sta->hnext) : NULL; \ | 480 | nxt = _sta ? rcu_dereference(_sta->hnext) : NULL; \ |
@@ -540,7 +513,6 @@ void sta_info_free(struct ieee80211_local *local, struct sta_info *sta); | |||
540 | */ | 513 | */ |
541 | int sta_info_insert(struct sta_info *sta); | 514 | int sta_info_insert(struct sta_info *sta); |
542 | int sta_info_insert_rcu(struct sta_info *sta) __acquires(RCU); | 515 | int sta_info_insert_rcu(struct sta_info *sta) __acquires(RCU); |
543 | int sta_info_reinsert(struct sta_info *sta); | ||
544 | 516 | ||
545 | int __must_check __sta_info_destroy(struct sta_info *sta); | 517 | int __must_check __sta_info_destroy(struct sta_info *sta); |
546 | int sta_info_destroy_addr(struct ieee80211_sub_if_data *sdata, | 518 | int sta_info_destroy_addr(struct ieee80211_sub_if_data *sdata, |