aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/mac80211/mlme.c59
-rw-r--r--net/mac80211/rx.c21
-rw-r--r--net/mac80211/sta_info.c186
-rw-r--r--net/mac80211/sta_info.h30
4 files changed, 236 insertions, 60 deletions
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index d6470c7fd6ce..60a6f273cd30 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -1482,10 +1482,14 @@ static bool ieee80211_assoc_success(struct ieee80211_work *wk,
1482 1482
1483 ifmgd->aid = aid; 1483 ifmgd->aid = aid;
1484 1484
1485 sta = sta_info_alloc(sdata, cbss->bssid, GFP_KERNEL); 1485 mutex_lock(&sdata->local->sta_mtx);
1486 if (!sta) { 1486 /*
1487 printk(KERN_DEBUG "%s: failed to alloc STA entry for" 1487 * station info was already allocated and inserted before
1488 " the AP\n", sdata->name); 1488 * the association and should be available to us
1489 */
1490 sta = sta_info_get_rx(sdata, cbss->bssid);
1491 if (WARN_ON(!sta)) {
1492 mutex_unlock(&sdata->local->sta_mtx);
1489 return false; 1493 return false;
1490 } 1494 }
1491 1495
@@ -1556,7 +1560,8 @@ static bool ieee80211_assoc_success(struct ieee80211_work *wk,
1556 if (elems.wmm_param) 1560 if (elems.wmm_param)
1557 set_sta_flags(sta, WLAN_STA_WME); 1561 set_sta_flags(sta, WLAN_STA_WME);
1558 1562
1559 err = sta_info_insert(sta); 1563 /* sta_info_reinsert will also unlock the mutex lock */
1564 err = sta_info_reinsert(sta);
1560 sta = NULL; 1565 sta = NULL;
1561 if (err) { 1566 if (err) {
1562 printk(KERN_DEBUG "%s: failed to insert STA entry for" 1567 printk(KERN_DEBUG "%s: failed to insert STA entry for"
@@ -2429,6 +2434,32 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata,
2429 return 0; 2434 return 0;
2430} 2435}
2431 2436
2437/* create and insert a dummy station entry */
2438static int ieee80211_pre_assoc(struct ieee80211_sub_if_data *sdata,
2439 u8 *bssid) {
2440 struct sta_info *sta;
2441 int err;
2442
2443 sta = sta_info_alloc(sdata, bssid, GFP_KERNEL);
2444 if (!sta) {
2445 printk(KERN_DEBUG "%s: failed to alloc STA entry for"
2446 " the AP\n", sdata->name);
2447 return -ENOMEM;
2448 }
2449
2450 sta->dummy = true;
2451
2452 err = sta_info_insert(sta);
2453 sta = NULL;
2454 if (err) {
2455 printk(KERN_DEBUG "%s: failed to insert Dummy STA entry for"
2456 " the AP (error %d)\n", sdata->name, err);
2457 return err;
2458 }
2459
2460 return 0;
2461}
2462
2432static enum work_done_result ieee80211_assoc_done(struct ieee80211_work *wk, 2463static enum work_done_result ieee80211_assoc_done(struct ieee80211_work *wk,
2433 struct sk_buff *skb) 2464 struct sk_buff *skb)
2434{ 2465{
@@ -2436,9 +2467,11 @@ static enum work_done_result ieee80211_assoc_done(struct ieee80211_work *wk,
2436 struct ieee80211_mgmt *mgmt; 2467 struct ieee80211_mgmt *mgmt;
2437 struct ieee80211_rx_status *rx_status; 2468 struct ieee80211_rx_status *rx_status;
2438 struct ieee802_11_elems elems; 2469 struct ieee802_11_elems elems;
2470 struct cfg80211_bss *cbss = wk->assoc.bss;
2439 u16 status; 2471 u16 status;
2440 2472
2441 if (!skb) { 2473 if (!skb) {
2474 sta_info_destroy_addr(wk->sdata, cbss->bssid);
2442 cfg80211_send_assoc_timeout(wk->sdata->dev, wk->filter_ta); 2475 cfg80211_send_assoc_timeout(wk->sdata->dev, wk->filter_ta);
2443 goto destroy; 2476 goto destroy;
2444 } 2477 }
@@ -2468,12 +2501,16 @@ static enum work_done_result ieee80211_assoc_done(struct ieee80211_work *wk,
2468 if (!ieee80211_assoc_success(wk, mgmt, skb->len)) { 2501 if (!ieee80211_assoc_success(wk, mgmt, skb->len)) {
2469 mutex_unlock(&wk->sdata->u.mgd.mtx); 2502 mutex_unlock(&wk->sdata->u.mgd.mtx);
2470 /* oops -- internal error -- send timeout for now */ 2503 /* oops -- internal error -- send timeout for now */
2504 sta_info_destroy_addr(wk->sdata, cbss->bssid);
2471 cfg80211_send_assoc_timeout(wk->sdata->dev, 2505 cfg80211_send_assoc_timeout(wk->sdata->dev,
2472 wk->filter_ta); 2506 wk->filter_ta);
2473 return WORK_DONE_DESTROY; 2507 return WORK_DONE_DESTROY;
2474 } 2508 }
2475 2509
2476 mutex_unlock(&wk->sdata->u.mgd.mtx); 2510 mutex_unlock(&wk->sdata->u.mgd.mtx);
2511 } else {
2512 /* assoc failed - destroy the dummy station entry */
2513 sta_info_destroy_addr(wk->sdata, cbss->bssid);
2477 } 2514 }
2478 2515
2479 cfg80211_send_rx_assoc(wk->sdata->dev, skb->data, skb->len); 2516 cfg80211_send_rx_assoc(wk->sdata->dev, skb->data, skb->len);
@@ -2492,7 +2529,7 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
2492 struct ieee80211_bss *bss = (void *)req->bss->priv; 2529 struct ieee80211_bss *bss = (void *)req->bss->priv;
2493 struct ieee80211_work *wk; 2530 struct ieee80211_work *wk;
2494 const u8 *ssid; 2531 const u8 *ssid;
2495 int i; 2532 int i, err;
2496 2533
2497 mutex_lock(&ifmgd->mtx); 2534 mutex_lock(&ifmgd->mtx);
2498 if (ifmgd->associated) { 2535 if (ifmgd->associated) {
@@ -2517,6 +2554,16 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
2517 if (!wk) 2554 if (!wk)
2518 return -ENOMEM; 2555 return -ENOMEM;
2519 2556
2557 /*
2558 * create a dummy station info entry in order
2559 * to start accepting incoming EAPOL packets from the station
2560 */
2561 err = ieee80211_pre_assoc(sdata, req->bss->bssid);
2562 if (err) {
2563 kfree(wk);
2564 return err;
2565 }
2566
2520 ifmgd->flags &= ~IEEE80211_STA_DISABLE_11N; 2567 ifmgd->flags &= ~IEEE80211_STA_DISABLE_11N;
2521 ifmgd->flags &= ~IEEE80211_STA_NULLFUNC_ACKED; 2568 ifmgd->flags &= ~IEEE80211_STA_NULLFUNC_ACKED;
2522 2569
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index c4453fdd6e11..edd46193af6f 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -850,8 +850,21 @@ ieee80211_rx_h_check(struct ieee80211_rx_data *rx)
850 ieee80211_is_pspoll(hdr->frame_control)) && 850 ieee80211_is_pspoll(hdr->frame_control)) &&
851 rx->sdata->vif.type != NL80211_IFTYPE_ADHOC && 851 rx->sdata->vif.type != NL80211_IFTYPE_ADHOC &&
852 rx->sdata->vif.type != NL80211_IFTYPE_WDS && 852 rx->sdata->vif.type != NL80211_IFTYPE_WDS &&
853 (!rx->sta || !test_sta_flags(rx->sta, WLAN_STA_ASSOC)))) 853 (!rx->sta || !test_sta_flags(rx->sta, WLAN_STA_ASSOC)))) {
854 if (rx->sta && rx->sta->dummy &&
855 ieee80211_is_data_present(hdr->frame_control)) {
856 u16 ethertype;
857 u8 *payload;
858
859 payload = rx->skb->data +
860 ieee80211_hdrlen(hdr->frame_control);
861 ethertype = (payload[6] << 8) | payload[7];
862 if (cpu_to_be16(ethertype) ==
863 rx->sdata->control_port_protocol)
864 return RX_CONTINUE;
865 }
854 return RX_DROP_MONITOR; 866 return RX_DROP_MONITOR;
867 }
855 868
856 return RX_CONTINUE; 869 return RX_CONTINUE;
857} 870}
@@ -2808,7 +2821,7 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
2808 if (ieee80211_is_data(fc)) { 2821 if (ieee80211_is_data(fc)) {
2809 prev_sta = NULL; 2822 prev_sta = NULL;
2810 2823
2811 for_each_sta_info(local, hdr->addr2, sta, tmp) { 2824 for_each_sta_info_rx(local, hdr->addr2, sta, tmp) {
2812 if (!prev_sta) { 2825 if (!prev_sta) {
2813 prev_sta = sta; 2826 prev_sta = sta;
2814 continue; 2827 continue;
@@ -2852,7 +2865,7 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
2852 continue; 2865 continue;
2853 } 2866 }
2854 2867
2855 rx.sta = sta_info_get_bss(prev, hdr->addr2); 2868 rx.sta = sta_info_get_bss_rx(prev, hdr->addr2);
2856 rx.sdata = prev; 2869 rx.sdata = prev;
2857 ieee80211_prepare_and_rx_handle(&rx, skb, false); 2870 ieee80211_prepare_and_rx_handle(&rx, skb, false);
2858 2871
@@ -2860,7 +2873,7 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
2860 } 2873 }
2861 2874
2862 if (prev) { 2875 if (prev) {
2863 rx.sta = sta_info_get_bss(prev, hdr->addr2); 2876 rx.sta = sta_info_get_bss_rx(prev, hdr->addr2);
2864 rx.sdata = prev; 2877 rx.sdata = prev;
2865 2878
2866 if (ieee80211_prepare_and_rx_handle(&rx, skb, true)) 2879 if (ieee80211_prepare_and_rx_handle(&rx, skb, true))
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index d469d9d2b499..17caba27040b 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -100,6 +100,27 @@ struct sta_info *sta_info_get(struct ieee80211_sub_if_data *sdata,
100 lockdep_is_held(&local->sta_lock) || 100 lockdep_is_held(&local->sta_lock) ||
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_lock) ||
108 lockdep_is_held(&local->sta_mtx));
109 }
110 return sta;
111}
112
113/* get a station info entry even if it is a dummy station*/
114struct sta_info *sta_info_get_rx(struct ieee80211_sub_if_data *sdata,
115 const u8 *addr)
116{
117 struct ieee80211_local *local = sdata->local;
118 struct sta_info *sta;
119
120 sta = rcu_dereference_check(local->sta_hash[STA_HASH(addr)],
121 lockdep_is_held(&local->sta_lock) ||
122 lockdep_is_held(&local->sta_mtx));
123 while (sta) {
103 if (sta->sdata == sdata && 124 if (sta->sdata == sdata &&
104 memcmp(sta->sta.addr, addr, ETH_ALEN) == 0) 125 memcmp(sta->sta.addr, addr, ETH_ALEN) == 0)
105 break; 126 break;
@@ -126,6 +147,32 @@ struct sta_info *sta_info_get_bss(struct ieee80211_sub_if_data *sdata,
126 while (sta) { 147 while (sta) {
127 if ((sta->sdata == sdata || 148 if ((sta->sdata == sdata ||
128 (sta->sdata->bss && sta->sdata->bss == sdata->bss)) && 149 (sta->sdata->bss && sta->sdata->bss == sdata->bss)) &&
150 !sta->dummy &&
151 memcmp(sta->sta.addr, addr, ETH_ALEN) == 0)
152 break;
153 sta = rcu_dereference_check(sta->hnext,
154 lockdep_is_held(&local->sta_lock) ||
155 lockdep_is_held(&local->sta_mtx));
156 }
157 return sta;
158}
159
160/*
161 * Get sta info either from the specified interface
162 * or from one of its vlans (including dummy stations)
163 */
164struct sta_info *sta_info_get_bss_rx(struct ieee80211_sub_if_data *sdata,
165 const u8 *addr)
166{
167 struct ieee80211_local *local = sdata->local;
168 struct sta_info *sta;
169
170 sta = rcu_dereference_check(local->sta_hash[STA_HASH(addr)],
171 lockdep_is_held(&local->sta_lock) ||
172 lockdep_is_held(&local->sta_mtx));
173 while (sta) {
174 if ((sta->sdata == sdata ||
175 (sta->sdata->bss && sta->sdata->bss == sdata->bss)) &&
129 memcmp(sta->sta.addr, addr, ETH_ALEN) == 0) 176 memcmp(sta->sta.addr, addr, ETH_ALEN) == 0)
130 break; 177 break;
131 sta = rcu_dereference_check(sta->hnext, 178 sta = rcu_dereference_check(sta->hnext,
@@ -280,7 +327,8 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata,
280 return sta; 327 return sta;
281} 328}
282 329
283static int sta_info_finish_insert(struct sta_info *sta, bool async) 330static int sta_info_finish_insert(struct sta_info *sta,
331 bool async, bool dummy_reinsert)
284{ 332{
285 struct ieee80211_local *local = sta->local; 333 struct ieee80211_local *local = sta->local;
286 struct ieee80211_sub_if_data *sdata = sta->sdata; 334 struct ieee80211_sub_if_data *sdata = sta->sdata;
@@ -290,51 +338,58 @@ static int sta_info_finish_insert(struct sta_info *sta, bool async)
290 338
291 lockdep_assert_held(&local->sta_mtx); 339 lockdep_assert_held(&local->sta_mtx);
292 340
293 /* notify driver */ 341 if (!sta->dummy || dummy_reinsert) {
294 if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) 342 /* notify driver */
295 sdata = container_of(sdata->bss, 343 if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
296 struct ieee80211_sub_if_data, 344 sdata = container_of(sdata->bss,
297 u.ap); 345 struct ieee80211_sub_if_data,
298 err = drv_sta_add(local, sdata, &sta->sta); 346 u.ap);
299 if (err) { 347 err = drv_sta_add(local, sdata, &sta->sta);
300 if (!async) 348 if (err) {
301 return err; 349 if (!async)
302 printk(KERN_DEBUG "%s: failed to add IBSS STA %pM to driver (%d)" 350 return err;
303 " - keeping it anyway.\n", 351 printk(KERN_DEBUG "%s: failed to add IBSS STA %pM to "
304 sdata->name, sta->sta.addr, err); 352 "driver (%d) - keeping it anyway.\n",
305 } else { 353 sdata->name, sta->sta.addr, err);
306 sta->uploaded = true; 354 } else {
355 sta->uploaded = true;
307#ifdef CONFIG_MAC80211_VERBOSE_DEBUG 356#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
308 if (async) 357 if (async)
309 wiphy_debug(local->hw.wiphy, 358 wiphy_debug(local->hw.wiphy,
310 "Finished adding IBSS STA %pM\n", 359 "Finished adding IBSS STA %pM\n",
311 sta->sta.addr); 360 sta->sta.addr);
312#endif 361#endif
362 }
363
364 sdata = sta->sdata;
313 } 365 }
314 366
315 sdata = sta->sdata; 367 if (!dummy_reinsert) {
368 if (!async) {
369 local->num_sta++;
370 local->sta_generation++;
371 smp_mb();
316 372
317 if (!async) { 373 /* make the station visible */
318 local->num_sta++; 374 spin_lock_irqsave(&local->sta_lock, flags);
319 local->sta_generation++; 375 sta_info_hash_add(local, sta);
320 smp_mb(); 376 spin_unlock_irqrestore(&local->sta_lock, flags);
377 }
321 378
322 /* make the station visible */ 379 list_add(&sta->list, &local->sta_list);
323 spin_lock_irqsave(&local->sta_lock, flags); 380 } else {
324 sta_info_hash_add(local, sta); 381 sta->dummy = false;
325 spin_unlock_irqrestore(&local->sta_lock, flags);
326 } 382 }
327 383
328 list_add(&sta->list, &local->sta_list); 384 if (!sta->dummy) {
329 385 ieee80211_sta_debugfs_add(sta);
330 ieee80211_sta_debugfs_add(sta); 386 rate_control_add_sta_debugfs(sta);
331 rate_control_add_sta_debugfs(sta);
332
333 memset(&sinfo, 0, sizeof(sinfo));
334 sinfo.filled = 0;
335 sinfo.generation = local->sta_generation;
336 cfg80211_new_sta(sdata->dev, sta->sta.addr, &sinfo, GFP_KERNEL);
337 387
388 memset(&sinfo, 0, sizeof(sinfo));
389 sinfo.filled = 0;
390 sinfo.generation = local->sta_generation;
391 cfg80211_new_sta(sdata->dev, sta->sta.addr, &sinfo, GFP_KERNEL);
392 }
338 393
339 return 0; 394 return 0;
340} 395}
@@ -351,7 +406,7 @@ static void sta_info_finish_pending(struct ieee80211_local *local)
351 list_del(&sta->list); 406 list_del(&sta->list);
352 spin_unlock_irqrestore(&local->sta_lock, flags); 407 spin_unlock_irqrestore(&local->sta_lock, flags);
353 408
354 sta_info_finish_insert(sta, true); 409 sta_info_finish_insert(sta, true, false);
355 410
356 spin_lock_irqsave(&local->sta_lock, flags); 411 spin_lock_irqsave(&local->sta_lock, flags);
357 } 412 }
@@ -395,7 +450,7 @@ static int sta_info_insert_ibss(struct sta_info *sta) __acquires(RCU)
395 450
396 spin_lock_irqsave(&local->sta_lock, flags); 451 spin_lock_irqsave(&local->sta_lock, flags);
397 /* check if STA exists already */ 452 /* check if STA exists already */
398 if (sta_info_get_bss(sdata, sta->sta.addr)) { 453 if (sta_info_get_bss_rx(sdata, sta->sta.addr)) {
399 spin_unlock_irqrestore(&local->sta_lock, flags); 454 spin_unlock_irqrestore(&local->sta_lock, flags);
400 rcu_read_lock(); 455 rcu_read_lock();
401 return -EEXIST; 456 return -EEXIST;
@@ -431,6 +486,8 @@ static int sta_info_insert_non_ibss(struct sta_info *sta) __acquires(RCU)
431 struct ieee80211_local *local = sta->local; 486 struct ieee80211_local *local = sta->local;
432 struct ieee80211_sub_if_data *sdata = sta->sdata; 487 struct ieee80211_sub_if_data *sdata = sta->sdata;
433 unsigned long flags; 488 unsigned long flags;
489 struct sta_info *exist_sta;
490 bool dummy_reinsert = false;
434 int err = 0; 491 int err = 0;
435 492
436 lockdep_assert_held(&local->sta_mtx); 493 lockdep_assert_held(&local->sta_mtx);
@@ -446,17 +503,28 @@ static int sta_info_insert_non_ibss(struct sta_info *sta) __acquires(RCU)
446 */ 503 */
447 504
448 spin_lock_irqsave(&local->sta_lock, flags); 505 spin_lock_irqsave(&local->sta_lock, flags);
449 /* check if STA exists already */ 506 /*
450 if (sta_info_get_bss(sdata, sta->sta.addr)) { 507 * check if STA exists already.
451 spin_unlock_irqrestore(&local->sta_lock, flags); 508 * only accept a scenario of a second call to sta_info_insert_non_ibss
452 mutex_unlock(&local->sta_mtx); 509 * with a dummy station entry that was inserted earlier
453 rcu_read_lock(); 510 * in that case - assume that the dummy station flag should
454 return -EEXIST; 511 * be removed.
512 */
513 exist_sta = sta_info_get_bss_rx(sdata, sta->sta.addr);
514 if (exist_sta) {
515 if (exist_sta == sta && sta->dummy) {
516 dummy_reinsert = true;
517 } else {
518 spin_unlock_irqrestore(&local->sta_lock, flags);
519 mutex_unlock(&local->sta_mtx);
520 rcu_read_lock();
521 return -EEXIST;
522 }
455 } 523 }
456 524
457 spin_unlock_irqrestore(&local->sta_lock, flags); 525 spin_unlock_irqrestore(&local->sta_lock, flags);
458 526
459 err = sta_info_finish_insert(sta, false); 527 err = sta_info_finish_insert(sta, false, dummy_reinsert);
460 if (err) { 528 if (err) {
461 mutex_unlock(&local->sta_mtx); 529 mutex_unlock(&local->sta_mtx);
462 rcu_read_lock(); 530 rcu_read_lock();
@@ -464,7 +532,8 @@ static int sta_info_insert_non_ibss(struct sta_info *sta) __acquires(RCU)
464 } 532 }
465 533
466#ifdef CONFIG_MAC80211_VERBOSE_DEBUG 534#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
467 wiphy_debug(local->hw.wiphy, "Inserted STA %pM\n", sta->sta.addr); 535 wiphy_debug(local->hw.wiphy, "Inserted %sSTA %pM\n",
536 sta->dummy ? "dummy " : "", sta->sta.addr);
468#endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ 537#endif /* CONFIG_MAC80211_VERBOSE_DEBUG */
469 538
470 /* move reference to rcu-protected */ 539 /* move reference to rcu-protected */
@@ -535,6 +604,25 @@ int sta_info_insert(struct sta_info *sta)
535 return err; 604 return err;
536} 605}
537 606
607/* Caller must hold sta->local->sta_mtx */
608int sta_info_reinsert(struct sta_info *sta)
609{
610 struct ieee80211_local *local = sta->local;
611 int err = 0;
612
613 err = sta_info_insert_check(sta);
614 if (err) {
615 mutex_unlock(&local->sta_mtx);
616 return err;
617 }
618
619 might_sleep();
620
621 err = sta_info_insert_non_ibss(sta);
622 rcu_read_unlock();
623 return err;
624}
625
538static inline void __bss_tim_set(struct ieee80211_if_ap *bss, u16 aid) 626static inline void __bss_tim_set(struct ieee80211_if_ap *bss, u16 aid)
539{ 627{
540 /* 628 /*
@@ -775,7 +863,7 @@ int sta_info_destroy_addr(struct ieee80211_sub_if_data *sdata, const u8 *addr)
775 int ret; 863 int ret;
776 864
777 mutex_lock(&sdata->local->sta_mtx); 865 mutex_lock(&sdata->local->sta_mtx);
778 sta = sta_info_get(sdata, addr); 866 sta = sta_info_get_rx(sdata, addr);
779 ret = __sta_info_destroy(sta); 867 ret = __sta_info_destroy(sta);
780 mutex_unlock(&sdata->local->sta_mtx); 868 mutex_unlock(&sdata->local->sta_mtx);
781 869
@@ -789,7 +877,7 @@ int sta_info_destroy_addr_bss(struct ieee80211_sub_if_data *sdata,
789 int ret; 877 int ret;
790 878
791 mutex_lock(&sdata->local->sta_mtx); 879 mutex_lock(&sdata->local->sta_mtx);
792 sta = sta_info_get_bss(sdata, addr); 880 sta = sta_info_get_bss_rx(sdata, addr);
793 ret = __sta_info_destroy(sta); 881 ret = __sta_info_destroy(sta);
794 mutex_unlock(&sdata->local->sta_mtx); 882 mutex_unlock(&sdata->local->sta_mtx);
795 883
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
index 28beb78e601e..e9eb565506da 100644
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
@@ -238,10 +238,12 @@ struct sta_ampdu_mlme {
238 * @plink_timer: peer link watch timer 238 * @plink_timer: peer link watch timer
239 * @plink_timer_was_running: used by suspend/resume to restore timers 239 * @plink_timer_was_running: used by suspend/resume to restore timers
240 * @debugfs: debug filesystem info 240 * @debugfs: debug filesystem info
241 * @sta: station information we share with the driver
242 * @dead: set to true when sta is unlinked 241 * @dead: set to true when sta is unlinked
243 * @uploaded: set to true when sta is uploaded to the driver 242 * @uploaded: set to true when sta is uploaded to the driver
244 * @lost_packets: number of consecutive lost packets 243 * @lost_packets: number of consecutive lost packets
244 * @dummy: indicate a dummy station created for receiving
245 * EAP frames before association
246 * @sta: station information we share with the driver
245 */ 247 */
246struct sta_info { 248struct sta_info {
247 /* General information, mostly static */ 249 /* General information, mostly static */
@@ -336,6 +338,9 @@ struct sta_info {
336 338
337 unsigned int lost_packets; 339 unsigned int lost_packets;
338 340
341 /* should be right in front of sta to be in the same cache line */
342 bool dummy;
343
339 /* keep last! */ 344 /* keep last! */
340 struct ieee80211_sta sta; 345 struct ieee80211_sta sta;
341}; 346};
@@ -436,9 +441,15 @@ rcu_dereference_protected_tid_tx(struct sta_info *sta, int tid)
436struct sta_info *sta_info_get(struct ieee80211_sub_if_data *sdata, 441struct sta_info *sta_info_get(struct ieee80211_sub_if_data *sdata,
437 const u8 *addr); 442 const u8 *addr);
438 443
444struct sta_info *sta_info_get_rx(struct ieee80211_sub_if_data *sdata,
445 const u8 *addr);
446
439struct sta_info *sta_info_get_bss(struct ieee80211_sub_if_data *sdata, 447struct sta_info *sta_info_get_bss(struct ieee80211_sub_if_data *sdata,
440 const u8 *addr); 448 const u8 *addr);
441 449
450struct sta_info *sta_info_get_bss_rx(struct ieee80211_sub_if_data *sdata,
451 const u8 *addr);
452
442static inline 453static inline
443void for_each_sta_info_type_check(struct ieee80211_local *local, 454void for_each_sta_info_type_check(struct ieee80211_local *local,
444 const u8 *addr, 455 const u8 *addr,
@@ -459,6 +470,22 @@ void for_each_sta_info_type_check(struct ieee80211_local *local,
459 _sta = nxt, \ 470 _sta = nxt, \
460 nxt = _sta ? rcu_dereference(_sta->hnext) : NULL \ 471 nxt = _sta ? rcu_dereference(_sta->hnext) : NULL \
461 ) \ 472 ) \
473 /* run code only if address matches and it's not a dummy sta */ \
474 if (memcmp(_sta->sta.addr, (_addr), ETH_ALEN) == 0 && \
475 !_sta->dummy)
476
477#define for_each_sta_info_rx(local, _addr, _sta, nxt) \
478 for ( /* initialise loop */ \
479 _sta = rcu_dereference(local->sta_hash[STA_HASH(_addr)]),\
480 nxt = _sta ? rcu_dereference(_sta->hnext) : NULL; \
481 /* typecheck */ \
482 for_each_sta_info_type_check(local, (_addr), _sta, nxt),\
483 /* continue condition */ \
484 _sta; \
485 /* advance loop */ \
486 _sta = nxt, \
487 nxt = _sta ? rcu_dereference(_sta->hnext) : NULL \
488 ) \
462 /* compare address and run code only if it matches */ \ 489 /* compare address and run code only if it matches */ \
463 if (memcmp(_sta->sta.addr, (_addr), ETH_ALEN) == 0) 490 if (memcmp(_sta->sta.addr, (_addr), ETH_ALEN) == 0)
464 491
@@ -484,6 +511,7 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata,
484int sta_info_insert(struct sta_info *sta); 511int sta_info_insert(struct sta_info *sta);
485int sta_info_insert_rcu(struct sta_info *sta) __acquires(RCU); 512int sta_info_insert_rcu(struct sta_info *sta) __acquires(RCU);
486int sta_info_insert_atomic(struct sta_info *sta); 513int sta_info_insert_atomic(struct sta_info *sta);
514int sta_info_reinsert(struct sta_info *sta);
487 515
488int sta_info_destroy_addr(struct ieee80211_sub_if_data *sdata, 516int sta_info_destroy_addr(struct ieee80211_sub_if_data *sdata,
489 const u8 *addr); 517 const u8 *addr);