aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/sta_info.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/mac80211/sta_info.c')
-rw-r--r--net/mac80211/sta_info.c252
1 files changed, 116 insertions, 136 deletions
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index fa0823892b2d..4034ee616022 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,
@@ -293,6 +250,8 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata,
293 sta->sdata = sdata; 250 sta->sdata = sdata;
294 sta->last_rx = jiffies; 251 sta->last_rx = jiffies;
295 252
253 sta->sta_state = IEEE80211_STA_NONE;
254
296 do_posix_clock_monotonic_gettime(&uptime); 255 do_posix_clock_monotonic_gettime(&uptime);
297 sta->last_connected = uptime.tv_sec; 256 sta->last_connected = uptime.tv_sec;
298 ewma_init(&sta->avg_signal, 1024, 8); 257 ewma_init(&sta->avg_signal, 1024, 8);
@@ -349,6 +308,43 @@ static int sta_info_insert_check(struct sta_info *sta)
349 return 0; 308 return 0;
350} 309}
351 310
311static int sta_info_insert_drv_state(struct ieee80211_local *local,
312 struct ieee80211_sub_if_data *sdata,
313 struct sta_info *sta)
314{
315 enum ieee80211_sta_state state;
316 int err = 0;
317
318 for (state = IEEE80211_STA_NOTEXIST; state < sta->sta_state; state++) {
319 err = drv_sta_state(local, sdata, sta, state, state + 1);
320 if (err)
321 break;
322 }
323
324 if (!err) {
325 /*
326 * Drivers using legacy sta_add/sta_remove callbacks only
327 * get uploaded set to true after sta_add is called.
328 */
329 if (!local->ops->sta_add)
330 sta->uploaded = true;
331 return 0;
332 }
333
334 if (sdata->vif.type == NL80211_IFTYPE_ADHOC) {
335 printk(KERN_DEBUG
336 "%s: failed to move IBSS STA %pM to state %d (%d) - keeping it anyway.\n",
337 sdata->name, sta->sta.addr, state + 1, err);
338 err = 0;
339 }
340
341 /* unwind on error */
342 for (; state > IEEE80211_STA_NOTEXIST; state--)
343 WARN_ON(drv_sta_state(local, sdata, sta, state, state - 1));
344
345 return err;
346}
347
352/* 348/*
353 * should be called with sta_mtx locked 349 * should be called with sta_mtx locked
354 * this function replaces the mutex lock 350 * this function replaces the mutex lock
@@ -358,72 +354,43 @@ static int sta_info_insert_finish(struct sta_info *sta) __acquires(RCU)
358{ 354{
359 struct ieee80211_local *local = sta->local; 355 struct ieee80211_local *local = sta->local;
360 struct ieee80211_sub_if_data *sdata = sta->sdata; 356 struct ieee80211_sub_if_data *sdata = sta->sdata;
361 struct sta_info *exist_sta; 357 struct station_info sinfo;
362 bool dummy_reinsert = false;
363 int err = 0; 358 int err = 0;
364 359
365 lockdep_assert_held(&local->sta_mtx); 360 lockdep_assert_held(&local->sta_mtx);
366 361
367 /* 362 /* check if STA exists already */
368 * check if STA exists already. 363 if (sta_info_get_bss(sdata, sta->sta.addr)) {
369 * only accept a scenario of a second call to sta_info_insert_finish 364 err = -EEXIST;
370 * with a dummy station entry that was inserted earlier 365 goto out_err;
371 * in that case - assume that the dummy station flag should
372 * be removed.
373 */
374 exist_sta = sta_info_get_bss_rx(sdata, sta->sta.addr);
375 if (exist_sta) {
376 if (exist_sta == sta && sta->dummy) {
377 dummy_reinsert = true;
378 } else {
379 err = -EEXIST;
380 goto out_err;
381 }
382 }
383
384 if (!sta->dummy || dummy_reinsert) {
385 /* notify driver */
386 err = drv_sta_add(local, sdata, &sta->sta);
387 if (err) {
388 if (sdata->vif.type != NL80211_IFTYPE_ADHOC)
389 goto out_err;
390 printk(KERN_DEBUG "%s: failed to add IBSS STA %pM to "
391 "driver (%d) - keeping it anyway.\n",
392 sdata->name, sta->sta.addr, err);
393 } else
394 sta->uploaded = true;
395 } 366 }
396 367
397 if (!dummy_reinsert) { 368 /* notify driver */
398 local->num_sta++; 369 err = sta_info_insert_drv_state(local, sdata, sta);
399 local->sta_generation++; 370 if (err)
400 smp_mb(); 371 goto out_err;
401 372
402 /* make the station visible */ 373 local->num_sta++;
403 sta_info_hash_add(local, sta); 374 local->sta_generation++;
375 smp_mb();
404 376
405 list_add(&sta->list, &local->sta_list); 377 /* make the station visible */
378 sta_info_hash_add(local, sta);
406 379
407 set_sta_flag(sta, WLAN_STA_INSERTED); 380 list_add(&sta->list, &local->sta_list);
408 } else {
409 sta->dummy = false;
410 }
411 381
412 if (!sta->dummy) { 382 set_sta_flag(sta, WLAN_STA_INSERTED);
413 struct station_info sinfo;
414 383
415 ieee80211_sta_debugfs_add(sta); 384 ieee80211_sta_debugfs_add(sta);
416 rate_control_add_sta_debugfs(sta); 385 rate_control_add_sta_debugfs(sta);
417 386
418 memset(&sinfo, 0, sizeof(sinfo)); 387 memset(&sinfo, 0, sizeof(sinfo));
419 sinfo.filled = 0; 388 sinfo.filled = 0;
420 sinfo.generation = local->sta_generation; 389 sinfo.generation = local->sta_generation;
421 cfg80211_new_sta(sdata->dev, sta->sta.addr, &sinfo, GFP_KERNEL); 390 cfg80211_new_sta(sdata->dev, sta->sta.addr, &sinfo, GFP_KERNEL);
422 }
423 391
424#ifdef CONFIG_MAC80211_VERBOSE_DEBUG 392#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
425 wiphy_debug(local->hw.wiphy, "Inserted %sSTA %pM\n", 393 wiphy_debug(local->hw.wiphy, "Inserted STA %pM\n", sta->sta.addr);
426 sta->dummy ? "dummy " : "", sta->sta.addr);
427#endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ 394#endif /* CONFIG_MAC80211_VERBOSE_DEBUG */
428 395
429 /* move reference to rcu-protected */ 396 /* move reference to rcu-protected */
@@ -475,25 +442,6 @@ int sta_info_insert(struct sta_info *sta)
475 return err; 442 return err;
476} 443}
477 444
478/* Caller must hold sta->local->sta_mtx */
479int sta_info_reinsert(struct sta_info *sta)
480{
481 struct ieee80211_local *local = sta->local;
482 int err = 0;
483
484 err = sta_info_insert_check(sta);
485 if (err) {
486 mutex_unlock(&local->sta_mtx);
487 return err;
488 }
489
490 might_sleep();
491
492 err = sta_info_insert_finish(sta);
493 rcu_read_unlock();
494 return err;
495}
496
497static 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)
498{ 446{
499 /* 447 /*
@@ -757,20 +705,17 @@ int __must_check __sta_info_destroy(struct sta_info *sta)
757 RCU_INIT_POINTER(sdata->u.vlan.sta, NULL); 705 RCU_INIT_POINTER(sdata->u.vlan.sta, NULL);
758 706
759 while (sta->sta_state > IEEE80211_STA_NONE) { 707 while (sta->sta_state > IEEE80211_STA_NONE) {
760 int err = sta_info_move_state(sta, sta->sta_state - 1); 708 ret = sta_info_move_state(sta, sta->sta_state - 1);
761 if (err) { 709 if (ret) {
762 WARN_ON_ONCE(1); 710 WARN_ON_ONCE(1);
763 break; 711 break;
764 } 712 }
765 } 713 }
766 714
767 if (sta->uploaded) { 715 if (sta->uploaded) {
768 if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) 716 ret = drv_sta_state(local, sdata, sta, IEEE80211_STA_NONE,
769 sdata = container_of(sdata->bss, 717 IEEE80211_STA_NOTEXIST);
770 struct ieee80211_sub_if_data, 718 WARN_ON_ONCE(ret != 0);
771 u.ap);
772 drv_sta_remove(local, sdata, &sta->sta);
773 sdata = sta->sdata;
774 } 719 }
775 720
776 /* 721 /*
@@ -843,7 +788,7 @@ int sta_info_destroy_addr(struct ieee80211_sub_if_data *sdata, const u8 *addr)
843 int ret; 788 int ret;
844 789
845 mutex_lock(&sdata->local->sta_mtx); 790 mutex_lock(&sdata->local->sta_mtx);
846 sta = sta_info_get_rx(sdata, addr); 791 sta = sta_info_get(sdata, addr);
847 ret = __sta_info_destroy(sta); 792 ret = __sta_info_destroy(sta);
848 mutex_unlock(&sdata->local->sta_mtx); 793 mutex_unlock(&sdata->local->sta_mtx);
849 794
@@ -857,7 +802,7 @@ int sta_info_destroy_addr_bss(struct ieee80211_sub_if_data *sdata,
857 int ret; 802 int ret;
858 803
859 mutex_lock(&sdata->local->sta_mtx); 804 mutex_lock(&sdata->local->sta_mtx);
860 sta = sta_info_get_bss_rx(sdata, addr); 805 sta = sta_info_get_bss(sdata, addr);
861 ret = __sta_info_destroy(sta); 806 ret = __sta_info_destroy(sta);
862 mutex_unlock(&sdata->local->sta_mtx); 807 mutex_unlock(&sdata->local->sta_mtx);
863 808
@@ -1408,20 +1353,60 @@ int sta_info_move_state(struct sta_info *sta,
1408 if (sta->sta_state == new_state) 1353 if (sta->sta_state == new_state)
1409 return 0; 1354 return 0;
1410 1355
1356 /* check allowed transitions first */
1357
1358 switch (new_state) {
1359 case IEEE80211_STA_NONE:
1360 if (sta->sta_state != IEEE80211_STA_AUTH)
1361 return -EINVAL;
1362 break;
1363 case IEEE80211_STA_AUTH:
1364 if (sta->sta_state != IEEE80211_STA_NONE &&
1365 sta->sta_state != IEEE80211_STA_ASSOC)
1366 return -EINVAL;
1367 break;
1368 case IEEE80211_STA_ASSOC:
1369 if (sta->sta_state != IEEE80211_STA_AUTH &&
1370 sta->sta_state != IEEE80211_STA_AUTHORIZED)
1371 return -EINVAL;
1372 break;
1373 case IEEE80211_STA_AUTHORIZED:
1374 if (sta->sta_state != IEEE80211_STA_ASSOC)
1375 return -EINVAL;
1376 break;
1377 default:
1378 WARN(1, "invalid state %d", new_state);
1379 return -EINVAL;
1380 }
1381
1382#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
1383 printk(KERN_DEBUG "%s: moving STA %pM to state %d\n",
1384 sta->sdata->name, sta->sta.addr, new_state);
1385#endif
1386
1387 /*
1388 * notify the driver before the actual changes so it can
1389 * fail the transition
1390 */
1391 if (test_sta_flag(sta, WLAN_STA_INSERTED)) {
1392 int err = drv_sta_state(sta->local, sta->sdata, sta,
1393 sta->sta_state, new_state);
1394 if (err)
1395 return err;
1396 }
1397
1398 /* reflect the change in all state variables */
1399
1411 switch (new_state) { 1400 switch (new_state) {
1412 case IEEE80211_STA_NONE: 1401 case IEEE80211_STA_NONE:
1413 if (sta->sta_state == IEEE80211_STA_AUTH) 1402 if (sta->sta_state == IEEE80211_STA_AUTH)
1414 clear_bit(WLAN_STA_AUTH, &sta->_flags); 1403 clear_bit(WLAN_STA_AUTH, &sta->_flags);
1415 else
1416 return -EINVAL;
1417 break; 1404 break;
1418 case IEEE80211_STA_AUTH: 1405 case IEEE80211_STA_AUTH:
1419 if (sta->sta_state == IEEE80211_STA_NONE) 1406 if (sta->sta_state == IEEE80211_STA_NONE)
1420 set_bit(WLAN_STA_AUTH, &sta->_flags); 1407 set_bit(WLAN_STA_AUTH, &sta->_flags);
1421 else if (sta->sta_state == IEEE80211_STA_ASSOC) 1408 else if (sta->sta_state == IEEE80211_STA_ASSOC)
1422 clear_bit(WLAN_STA_ASSOC, &sta->_flags); 1409 clear_bit(WLAN_STA_ASSOC, &sta->_flags);
1423 else
1424 return -EINVAL;
1425 break; 1410 break;
1426 case IEEE80211_STA_ASSOC: 1411 case IEEE80211_STA_ASSOC:
1427 if (sta->sta_state == IEEE80211_STA_AUTH) { 1412 if (sta->sta_state == IEEE80211_STA_AUTH) {
@@ -1430,24 +1415,19 @@ int sta_info_move_state(struct sta_info *sta,
1430 if (sta->sdata->vif.type == NL80211_IFTYPE_AP) 1415 if (sta->sdata->vif.type == NL80211_IFTYPE_AP)
1431 atomic_dec(&sta->sdata->u.ap.num_sta_authorized); 1416 atomic_dec(&sta->sdata->u.ap.num_sta_authorized);
1432 clear_bit(WLAN_STA_AUTHORIZED, &sta->_flags); 1417 clear_bit(WLAN_STA_AUTHORIZED, &sta->_flags);
1433 } else 1418 }
1434 return -EINVAL;
1435 break; 1419 break;
1436 case IEEE80211_STA_AUTHORIZED: 1420 case IEEE80211_STA_AUTHORIZED:
1437 if (sta->sta_state == IEEE80211_STA_ASSOC) { 1421 if (sta->sta_state == IEEE80211_STA_ASSOC) {
1438 if (sta->sdata->vif.type == NL80211_IFTYPE_AP) 1422 if (sta->sdata->vif.type == NL80211_IFTYPE_AP)
1439 atomic_inc(&sta->sdata->u.ap.num_sta_authorized); 1423 atomic_inc(&sta->sdata->u.ap.num_sta_authorized);
1440 set_bit(WLAN_STA_AUTHORIZED, &sta->_flags); 1424 set_bit(WLAN_STA_AUTHORIZED, &sta->_flags);
1441 } else 1425 }
1442 return -EINVAL;
1443 break; 1426 break;
1444 default: 1427 default:
1445 WARN(1, "invalid state %d", new_state); 1428 break;
1446 return -EINVAL;
1447 } 1429 }
1448 1430
1449 printk(KERN_DEBUG "%s: moving STA %pM to state %d\n",
1450 sta->sdata->name, sta->sta.addr, new_state);
1451 sta->sta_state = new_state; 1431 sta->sta_state = new_state;
1452 1432
1453 return 0; 1433 return 0;