aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2011-12-15 05:17:37 -0500
committerJohn W. Linville <linville@tuxdriver.com>2011-12-15 14:46:34 -0500
commit8bf11d8d081106c3cce8281a0150e716f8ac5d22 (patch)
tree2b026b9638f7acad90d4712f1675d80f3247a0d1 /net/mac80211
parent56544160d44c3043c0a7faffa506f616c1bb45f0 (diff)
mac80211: delay IBSS station insertion
In order to notify drivers and simplify the station management code, defer IBSS station insertion to a work item and don't do it directly while receiving a frame. This increases the complexity in IBSS a little bit, but it's pretty straight forward and it allows us to reduce the station management complexity (next patch) considerably. Signed-off-by: Johannes Berg <johannes.berg@intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/mac80211')
-rw-r--r--net/mac80211/ibss.c154
-rw-r--r--net/mac80211/ieee80211_i.h8
-rw-r--r--net/mac80211/rx.c4
-rw-r--r--net/mac80211/sta_info.c31
4 files changed, 140 insertions, 57 deletions
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c
index 47e2db9133cb..f8a32bf98216 100644
--- a/net/mac80211/ibss.c
+++ b/net/mac80211/ibss.c
@@ -275,6 +275,80 @@ static void ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
275 cbss->tsf); 275 cbss->tsf);
276} 276}
277 277
278static struct sta_info *ieee80211_ibss_finish_sta(struct sta_info *sta)
279 __acquires(RCU)
280{
281 struct ieee80211_sub_if_data *sdata = sta->sdata;
282 u8 addr[ETH_ALEN];
283
284 memcpy(addr, sta->sta.addr, ETH_ALEN);
285
286#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
287 wiphy_debug(sdata->local->hw.wiphy,
288 "Adding new IBSS station %pM (dev=%s)\n",
289 addr, sdata->name);
290#endif
291
292 sta_info_move_state(sta, IEEE80211_STA_AUTH);
293 sta_info_move_state(sta, IEEE80211_STA_ASSOC);
294 sta_info_move_state(sta, IEEE80211_STA_AUTHORIZED);
295
296 rate_control_rate_init(sta);
297
298 /* If it fails, maybe we raced another insertion? */
299 if (sta_info_insert_rcu(sta))
300 return sta_info_get(sdata, addr);
301 return sta;
302}
303
304static struct sta_info *
305ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata,
306 const u8 *bssid, const u8 *addr,
307 u32 supp_rates)
308 __acquires(RCU)
309{
310 struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
311 struct ieee80211_local *local = sdata->local;
312 struct sta_info *sta;
313 int band = local->hw.conf.channel->band;
314
315 /*
316 * XXX: Consider removing the least recently used entry and
317 * allow new one to be added.
318 */
319 if (local->num_sta >= IEEE80211_IBSS_MAX_STA_ENTRIES) {
320 if (net_ratelimit())
321 printk(KERN_DEBUG "%s: No room for a new IBSS STA entry %pM\n",
322 sdata->name, addr);
323 rcu_read_lock();
324 return NULL;
325 }
326
327 if (ifibss->state == IEEE80211_IBSS_MLME_SEARCH) {
328 rcu_read_lock();
329 return NULL;
330 }
331
332 if (compare_ether_addr(bssid, sdata->u.ibss.bssid)) {
333 rcu_read_lock();
334 return NULL;
335 }
336
337 sta = sta_info_alloc(sdata, addr, GFP_KERNEL);
338 if (!sta) {
339 rcu_read_lock();
340 return NULL;
341 }
342
343 sta->last_rx = jiffies;
344
345 /* make sure mandatory rates are always added */
346 sta->sta.supp_rates[band] = supp_rates |
347 ieee80211_mandatory_rates(local, band);
348
349 return ieee80211_ibss_finish_sta(sta);
350}
351
278static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, 352static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
279 struct ieee80211_mgmt *mgmt, 353 struct ieee80211_mgmt *mgmt,
280 size_t len, 354 size_t len,
@@ -334,10 +408,11 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
334#endif 408#endif
335 rates_updated = true; 409 rates_updated = true;
336 } 410 }
337 } else 411 } else {
412 rcu_read_unlock();
338 sta = ieee80211_ibss_add_sta(sdata, mgmt->bssid, 413 sta = ieee80211_ibss_add_sta(sdata, mgmt->bssid,
339 mgmt->sa, supp_rates, 414 mgmt->sa, supp_rates);
340 GFP_ATOMIC); 415 }
341 } 416 }
342 417
343 if (sta && elems->wmm_info) 418 if (sta && elems->wmm_info)
@@ -464,21 +539,17 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
464 ieee80211_sta_join_ibss(sdata, bss); 539 ieee80211_sta_join_ibss(sdata, bss);
465 supp_rates = ieee80211_sta_get_rates(local, elems, band); 540 supp_rates = ieee80211_sta_get_rates(local, elems, band);
466 ieee80211_ibss_add_sta(sdata, mgmt->bssid, mgmt->sa, 541 ieee80211_ibss_add_sta(sdata, mgmt->bssid, mgmt->sa,
467 supp_rates, GFP_KERNEL); 542 supp_rates);
543 rcu_read_unlock();
468 } 544 }
469 545
470 put_bss: 546 put_bss:
471 ieee80211_rx_bss_put(local, bss); 547 ieee80211_rx_bss_put(local, bss);
472} 548}
473 549
474/* 550void ieee80211_ibss_rx_no_sta(struct ieee80211_sub_if_data *sdata,
475 * Add a new IBSS station, will also be called by the RX code when, 551 const u8 *bssid, const u8 *addr,
476 * in IBSS mode, receiving a frame from a yet-unknown station, hence 552 u32 supp_rates)
477 * must be callable in atomic context.
478 */
479struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata,
480 u8 *bssid, u8 *addr, u32 supp_rates,
481 gfp_t gfp)
482{ 553{
483 struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; 554 struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
484 struct ieee80211_local *local = sdata->local; 555 struct ieee80211_local *local = sdata->local;
@@ -493,40 +564,29 @@ struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata,
493 if (net_ratelimit()) 564 if (net_ratelimit())
494 printk(KERN_DEBUG "%s: No room for a new IBSS STA entry %pM\n", 565 printk(KERN_DEBUG "%s: No room for a new IBSS STA entry %pM\n",
495 sdata->name, addr); 566 sdata->name, addr);
496 return NULL; 567 return;
497 } 568 }
498 569
499 if (ifibss->state == IEEE80211_IBSS_MLME_SEARCH) 570 if (ifibss->state == IEEE80211_IBSS_MLME_SEARCH)
500 return NULL; 571 return;
501 572
502 if (compare_ether_addr(bssid, sdata->u.ibss.bssid)) 573 if (compare_ether_addr(bssid, sdata->u.ibss.bssid))
503 return NULL; 574 return;
504
505#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
506 wiphy_debug(local->hw.wiphy, "Adding new IBSS station %pM (dev=%s)\n",
507 addr, sdata->name);
508#endif
509 575
510 sta = sta_info_alloc(sdata, addr, gfp); 576 sta = sta_info_alloc(sdata, addr, GFP_ATOMIC);
511 if (!sta) 577 if (!sta)
512 return NULL; 578 return;
513 579
514 sta->last_rx = jiffies; 580 sta->last_rx = jiffies;
515 581
516 sta_info_move_state(sta, IEEE80211_STA_AUTH);
517 sta_info_move_state(sta, IEEE80211_STA_ASSOC);
518 sta_info_move_state(sta, IEEE80211_STA_AUTHORIZED);
519
520 /* make sure mandatory rates are always added */ 582 /* make sure mandatory rates are always added */
521 sta->sta.supp_rates[band] = supp_rates | 583 sta->sta.supp_rates[band] = supp_rates |
522 ieee80211_mandatory_rates(local, band); 584 ieee80211_mandatory_rates(local, band);
523 585
524 rate_control_rate_init(sta); 586 spin_lock(&ifibss->incomplete_lock);
525 587 list_add(&sta->list, &ifibss->incomplete_stations);
526 /* If it fails, maybe we raced another insertion? */ 588 spin_unlock(&ifibss->incomplete_lock);
527 if (sta_info_insert(sta)) 589 ieee80211_queue_work(&local->hw, &sdata->work);
528 return sta_info_get(sdata, addr);
529 return sta;
530} 590}
531 591
532static int ieee80211_sta_active_ibss(struct ieee80211_sub_if_data *sdata) 592static int ieee80211_sta_active_ibss(struct ieee80211_sub_if_data *sdata)
@@ -865,6 +925,7 @@ void ieee80211_ibss_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
865void ieee80211_ibss_work(struct ieee80211_sub_if_data *sdata) 925void ieee80211_ibss_work(struct ieee80211_sub_if_data *sdata)
866{ 926{
867 struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; 927 struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
928 struct sta_info *sta;
868 929
869 mutex_lock(&ifibss->mtx); 930 mutex_lock(&ifibss->mtx);
870 931
@@ -876,6 +937,19 @@ void ieee80211_ibss_work(struct ieee80211_sub_if_data *sdata)
876 if (!ifibss->ssid_len) 937 if (!ifibss->ssid_len)
877 goto out; 938 goto out;
878 939
940 spin_lock_bh(&ifibss->incomplete_lock);
941 while (!list_empty(&ifibss->incomplete_stations)) {
942 sta = list_first_entry(&ifibss->incomplete_stations,
943 struct sta_info, list);
944 list_del(&sta->list);
945 spin_unlock_bh(&ifibss->incomplete_lock);
946
947 ieee80211_ibss_finish_sta(sta);
948 rcu_read_unlock();
949 spin_lock_bh(&ifibss->incomplete_lock);
950 }
951 spin_unlock_bh(&ifibss->incomplete_lock);
952
879 switch (ifibss->state) { 953 switch (ifibss->state) {
880 case IEEE80211_IBSS_MLME_SEARCH: 954 case IEEE80211_IBSS_MLME_SEARCH:
881 ieee80211_sta_find_ibss(sdata); 955 ieee80211_sta_find_ibss(sdata);
@@ -934,6 +1008,8 @@ void ieee80211_ibss_setup_sdata(struct ieee80211_sub_if_data *sdata)
934 setup_timer(&ifibss->timer, ieee80211_ibss_timer, 1008 setup_timer(&ifibss->timer, ieee80211_ibss_timer,
935 (unsigned long) sdata); 1009 (unsigned long) sdata);
936 mutex_init(&ifibss->mtx); 1010 mutex_init(&ifibss->mtx);
1011 INIT_LIST_HEAD(&ifibss->incomplete_stations);
1012 spin_lock_init(&ifibss->incomplete_lock);
937} 1013}
938 1014
939/* scan finished notification */ 1015/* scan finished notification */
@@ -1053,6 +1129,7 @@ int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata)
1053 struct cfg80211_bss *cbss; 1129 struct cfg80211_bss *cbss;
1054 u16 capability; 1130 u16 capability;
1055 int active_ibss; 1131 int active_ibss;
1132 struct sta_info *sta;
1056 1133
1057 mutex_lock(&sdata->u.ibss.mtx); 1134 mutex_lock(&sdata->u.ibss.mtx);
1058 1135
@@ -1081,6 +1158,19 @@ int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata)
1081 } 1158 }
1082 1159
1083 sta_info_flush(sdata->local, sdata); 1160 sta_info_flush(sdata->local, sdata);
1161
1162 spin_lock_bh(&ifibss->incomplete_lock);
1163 while (!list_empty(&ifibss->incomplete_stations)) {
1164 sta = list_first_entry(&ifibss->incomplete_stations,
1165 struct sta_info, list);
1166 list_del(&sta->list);
1167 spin_unlock_bh(&ifibss->incomplete_lock);
1168
1169 sta_info_free(local, sta);
1170 spin_lock_bh(&ifibss->incomplete_lock);
1171 }
1172 spin_unlock_bh(&ifibss->incomplete_lock);
1173
1084 netif_carrier_off(sdata->dev); 1174 netif_carrier_off(sdata->dev);
1085 1175
1086 /* remove beacon */ 1176 /* remove beacon */
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 9516c3088fba..eca6063e287c 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -482,6 +482,9 @@ struct ieee80211_if_ibss {
482 struct sk_buff __rcu *presp; 482 struct sk_buff __rcu *presp;
483 struct sk_buff *skb; 483 struct sk_buff *skb;
484 484
485 spinlock_t incomplete_lock;
486 struct list_head incomplete_stations;
487
485 enum { 488 enum {
486 IEEE80211_IBSS_MLME_SEARCH, 489 IEEE80211_IBSS_MLME_SEARCH,
487 IEEE80211_IBSS_MLME_JOINED, 490 IEEE80211_IBSS_MLME_JOINED,
@@ -1172,9 +1175,8 @@ void ieee80211_sta_reset_conn_monitor(struct ieee80211_sub_if_data *sdata);
1172/* IBSS code */ 1175/* IBSS code */
1173void ieee80211_ibss_notify_scan_completed(struct ieee80211_local *local); 1176void ieee80211_ibss_notify_scan_completed(struct ieee80211_local *local);
1174void ieee80211_ibss_setup_sdata(struct ieee80211_sub_if_data *sdata); 1177void ieee80211_ibss_setup_sdata(struct ieee80211_sub_if_data *sdata);
1175struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata, 1178void ieee80211_ibss_rx_no_sta(struct ieee80211_sub_if_data *sdata,
1176 u8 *bssid, u8 *addr, u32 supp_rates, 1179 const u8 *bssid, const u8 *addr, u32 supp_rates);
1177 gfp_t gfp);
1178int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata, 1180int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata,
1179 struct cfg80211_ibss_params *params); 1181 struct cfg80211_ibss_params *params);
1180int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata); 1182int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata);
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 7d226417ef46..2be5b7d69ad7 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -2775,8 +2775,8 @@ static int prepare_for_handlers(struct ieee80211_rx_data *rx,
2775 rate_idx = 0; /* TODO: HT rates */ 2775 rate_idx = 0; /* TODO: HT rates */
2776 else 2776 else
2777 rate_idx = status->rate_idx; 2777 rate_idx = status->rate_idx;
2778 rx->sta = ieee80211_ibss_add_sta(sdata, bssid, 2778 ieee80211_ibss_rx_no_sta(sdata, bssid, hdr->addr2,
2779 hdr->addr2, BIT(rate_idx), GFP_ATOMIC); 2779 BIT(rate_idx));
2780 } 2780 }
2781 break; 2781 break;
2782 case NL80211_IFTYPE_MESH_POINT: 2782 case NL80211_IFTYPE_MESH_POINT:
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index 16de3bd16107..aa9293d7f3f0 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -354,35 +354,26 @@ static int sta_info_finish_insert(struct sta_info *sta,
354 /* notify driver */ 354 /* notify driver */
355 err = drv_sta_add(local, sdata, &sta->sta); 355 err = drv_sta_add(local, sdata, &sta->sta);
356 if (err) { 356 if (err) {
357 if (!async) 357 if (sdata->vif.type != NL80211_IFTYPE_ADHOC)
358 return err; 358 return err;
359 printk(KERN_DEBUG "%s: failed to add IBSS STA %pM to " 359 printk(KERN_DEBUG "%s: failed to add IBSS STA %pM to "
360 "driver (%d) - keeping it anyway.\n", 360 "driver (%d) - keeping it anyway.\n",
361 sdata->name, sta->sta.addr, err); 361 sdata->name, sta->sta.addr, err);
362 } else { 362 } else
363 sta->uploaded = true; 363 sta->uploaded = true;
364#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
365 if (async)
366 wiphy_debug(local->hw.wiphy,
367 "Finished adding IBSS STA %pM\n",
368 sta->sta.addr);
369#endif
370 }
371 364
372 sdata = sta->sdata; 365 sdata = sta->sdata;
373 } 366 }
374 367
375 if (!dummy_reinsert) { 368 if (!dummy_reinsert) {
376 if (!async) { 369 local->num_sta++;
377 local->num_sta++; 370 local->sta_generation++;
378 local->sta_generation++; 371 smp_mb();
379 smp_mb(); 372
380 373 /* make the station visible */
381 /* make the station visible */ 374 spin_lock_irqsave(&local->sta_lock, flags);
382 spin_lock_irqsave(&local->sta_lock, flags); 375 sta_info_hash_add(local, sta);
383 sta_info_hash_add(local, sta); 376 spin_unlock_irqrestore(&local->sta_lock, flags);
384 spin_unlock_irqrestore(&local->sta_lock, flags);
385 }
386 377
387 list_add(&sta->list, &local->sta_list); 378 list_add(&sta->list, &local->sta_list);
388 } else { 379 } else {
@@ -1546,7 +1537,7 @@ EXPORT_SYMBOL(ieee80211_sta_set_buffered);
1546int sta_info_move_state_checked(struct sta_info *sta, 1537int sta_info_move_state_checked(struct sta_info *sta,
1547 enum ieee80211_sta_state new_state) 1538 enum ieee80211_sta_state new_state)
1548{ 1539{
1549 /* might_sleep(); -- for driver notify later, fix IBSS first */ 1540 might_sleep();
1550 1541
1551 if (sta->sta_state == new_state) 1542 if (sta->sta_state == new_state)
1552 return 0; 1543 return 0;