aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/mac80211/mlme.c15
-rw-r--r--net/mac80211/rx.c13
-rw-r--r--net/mac80211/sta_info.c135
-rw-r--r--net/mac80211/sta_info.h30
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*/
113struct 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 */
159struct 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 */
512int 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
530static inline void __bss_tim_set(struct ieee80211_if_ap *bss, u16 aid) 445static 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)
468struct sta_info *sta_info_get(struct ieee80211_sub_if_data *sdata, 463struct sta_info *sta_info_get(struct ieee80211_sub_if_data *sdata,
469 const u8 *addr); 464 const u8 *addr);
470 465
471struct sta_info *sta_info_get_rx(struct ieee80211_sub_if_data *sdata,
472 const u8 *addr);
473
474struct sta_info *sta_info_get_bss(struct ieee80211_sub_if_data *sdata, 466struct sta_info *sta_info_get_bss(struct ieee80211_sub_if_data *sdata,
475 const u8 *addr); 467 const u8 *addr);
476 468
477struct sta_info *sta_info_get_bss_rx(struct ieee80211_sub_if_data *sdata,
478 const u8 *addr);
479
480static inline 469static inline
481void for_each_sta_info_type_check(struct ieee80211_local *local, 470void 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 */
541int sta_info_insert(struct sta_info *sta); 514int sta_info_insert(struct sta_info *sta);
542int sta_info_insert_rcu(struct sta_info *sta) __acquires(RCU); 515int sta_info_insert_rcu(struct sta_info *sta) __acquires(RCU);
543int sta_info_reinsert(struct sta_info *sta);
544 516
545int __must_check __sta_info_destroy(struct sta_info *sta); 517int __must_check __sta_info_destroy(struct sta_info *sta);
546int sta_info_destroy_addr(struct ieee80211_sub_if_data *sdata, 518int sta_info_destroy_addr(struct ieee80211_sub_if_data *sdata,