diff options
-rw-r--r-- | net/mac80211/cfg.c | 22 | ||||
-rw-r--r-- | net/mac80211/debugfs_sta.c | 5 | ||||
-rw-r--r-- | net/mac80211/ibss.c | 6 | ||||
-rw-r--r-- | net/mac80211/iface.c | 6 | ||||
-rw-r--r-- | net/mac80211/mesh_plink.c | 6 | ||||
-rw-r--r-- | net/mac80211/mlme.c | 17 | ||||
-rw-r--r-- | net/mac80211/sta_info.c | 19 | ||||
-rw-r--r-- | net/mac80211/sta_info.h | 17 |
8 files changed, 59 insertions, 39 deletions
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 98460783c2d3..dc7420441574 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
@@ -776,12 +776,10 @@ static int sta_apply_parameters(struct ieee80211_local *local, | |||
776 | 776 | ||
777 | if (set & BIT(NL80211_STA_FLAG_AUTHENTICATED) && | 777 | if (set & BIT(NL80211_STA_FLAG_AUTHENTICATED) && |
778 | !test_sta_flag(sta, WLAN_STA_AUTH)) { | 778 | !test_sta_flag(sta, WLAN_STA_AUTH)) { |
779 | ret = sta_info_move_state_checked(sta, | 779 | ret = sta_info_move_state(sta, IEEE80211_STA_AUTH); |
780 | IEEE80211_STA_AUTH); | ||
781 | if (ret) | 780 | if (ret) |
782 | return ret; | 781 | return ret; |
783 | ret = sta_info_move_state_checked(sta, | 782 | ret = sta_info_move_state(sta, IEEE80211_STA_ASSOC); |
784 | IEEE80211_STA_ASSOC); | ||
785 | if (ret) | 783 | if (ret) |
786 | return ret; | 784 | return ret; |
787 | } | 785 | } |
@@ -789,11 +787,9 @@ static int sta_apply_parameters(struct ieee80211_local *local, | |||
789 | 787 | ||
790 | if (mask & BIT(NL80211_STA_FLAG_AUTHORIZED)) { | 788 | if (mask & BIT(NL80211_STA_FLAG_AUTHORIZED)) { |
791 | if (set & BIT(NL80211_STA_FLAG_AUTHORIZED)) | 789 | if (set & BIT(NL80211_STA_FLAG_AUTHORIZED)) |
792 | ret = sta_info_move_state_checked(sta, | 790 | ret = sta_info_move_state(sta, IEEE80211_STA_AUTHORIZED); |
793 | IEEE80211_STA_AUTHORIZED); | ||
794 | else if (test_sta_flag(sta, WLAN_STA_AUTHORIZED)) | 791 | else if (test_sta_flag(sta, WLAN_STA_AUTHORIZED)) |
795 | ret = sta_info_move_state_checked(sta, | 792 | ret = sta_info_move_state(sta, IEEE80211_STA_ASSOC); |
796 | IEEE80211_STA_ASSOC); | ||
797 | if (ret) | 793 | if (ret) |
798 | return ret; | 794 | return ret; |
799 | } | 795 | } |
@@ -805,12 +801,10 @@ static int sta_apply_parameters(struct ieee80211_local *local, | |||
805 | 801 | ||
806 | if (!(set & BIT(NL80211_STA_FLAG_AUTHENTICATED)) && | 802 | if (!(set & BIT(NL80211_STA_FLAG_AUTHENTICATED)) && |
807 | test_sta_flag(sta, WLAN_STA_AUTH)) { | 803 | test_sta_flag(sta, WLAN_STA_AUTH)) { |
808 | ret = sta_info_move_state_checked(sta, | 804 | ret = sta_info_move_state(sta, IEEE80211_STA_AUTH); |
809 | IEEE80211_STA_AUTH); | ||
810 | if (ret) | 805 | if (ret) |
811 | return ret; | 806 | return ret; |
812 | ret = sta_info_move_state_checked(sta, | 807 | ret = sta_info_move_state(sta, IEEE80211_STA_NONE); |
813 | IEEE80211_STA_NONE); | ||
814 | if (ret) | 808 | if (ret) |
815 | return ret; | 809 | return ret; |
816 | } | 810 | } |
@@ -944,8 +938,8 @@ static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev, | |||
944 | if (!sta) | 938 | if (!sta) |
945 | return -ENOMEM; | 939 | return -ENOMEM; |
946 | 940 | ||
947 | sta_info_move_state(sta, IEEE80211_STA_AUTH); | 941 | sta_info_pre_move_state(sta, IEEE80211_STA_AUTH); |
948 | sta_info_move_state(sta, IEEE80211_STA_ASSOC); | 942 | sta_info_pre_move_state(sta, IEEE80211_STA_ASSOC); |
949 | 943 | ||
950 | err = sta_apply_parameters(local, sta, params); | 944 | err = sta_apply_parameters(local, sta, params); |
951 | if (err) { | 945 | if (err) { |
diff --git a/net/mac80211/debugfs_sta.c b/net/mac80211/debugfs_sta.c index 2406b3e7393f..c8383712fdec 100644 --- a/net/mac80211/debugfs_sta.c +++ b/net/mac80211/debugfs_sta.c | |||
@@ -63,14 +63,15 @@ static ssize_t sta_flags_read(struct file *file, char __user *userbuf, | |||
63 | test_sta_flag(sta, WLAN_STA_##flg) ? #flg "\n" : "" | 63 | test_sta_flag(sta, WLAN_STA_##flg) ? #flg "\n" : "" |
64 | 64 | ||
65 | int res = scnprintf(buf, sizeof(buf), | 65 | int res = scnprintf(buf, sizeof(buf), |
66 | "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s", | 66 | "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s", |
67 | TEST(AUTH), TEST(ASSOC), TEST(PS_STA), | 67 | TEST(AUTH), TEST(ASSOC), TEST(PS_STA), |
68 | TEST(PS_DRIVER), TEST(AUTHORIZED), | 68 | TEST(PS_DRIVER), TEST(AUTHORIZED), |
69 | TEST(SHORT_PREAMBLE), | 69 | TEST(SHORT_PREAMBLE), |
70 | TEST(WME), TEST(WDS), TEST(CLEAR_PS_FILT), | 70 | TEST(WME), TEST(WDS), TEST(CLEAR_PS_FILT), |
71 | TEST(MFP), TEST(BLOCK_BA), TEST(PSPOLL), | 71 | TEST(MFP), TEST(BLOCK_BA), TEST(PSPOLL), |
72 | TEST(UAPSD), TEST(SP), TEST(TDLS_PEER), | 72 | TEST(UAPSD), TEST(SP), TEST(TDLS_PEER), |
73 | TEST(TDLS_PEER_AUTH)); | 73 | TEST(TDLS_PEER_AUTH), TEST(4ADDR_EVENT), |
74 | TEST(INSERTED)); | ||
74 | #undef TEST | 75 | #undef TEST |
75 | return simple_read_from_buffer(userbuf, count, ppos, buf, res); | 76 | return simple_read_from_buffer(userbuf, count, ppos, buf, res); |
76 | } | 77 | } |
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index d38baa41cf6c..a98d370b56f6 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c | |||
@@ -265,9 +265,9 @@ static struct sta_info *ieee80211_ibss_finish_sta(struct sta_info *sta, | |||
265 | addr, sdata->name); | 265 | addr, sdata->name); |
266 | #endif | 266 | #endif |
267 | 267 | ||
268 | sta_info_move_state(sta, IEEE80211_STA_AUTH); | 268 | sta_info_pre_move_state(sta, IEEE80211_STA_AUTH); |
269 | sta_info_move_state(sta, IEEE80211_STA_ASSOC); | 269 | sta_info_pre_move_state(sta, IEEE80211_STA_ASSOC); |
270 | sta_info_move_state(sta, IEEE80211_STA_AUTHORIZED); | 270 | sta_info_pre_move_state(sta, IEEE80211_STA_AUTHORIZED); |
271 | 271 | ||
272 | rate_control_rate_init(sta); | 272 | rate_control_rate_init(sta); |
273 | 273 | ||
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index e47768cb8cb3..6b0d70e960d4 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c | |||
@@ -318,9 +318,9 @@ static int ieee80211_do_open(struct net_device *dev, bool coming_up) | |||
318 | goto err_del_interface; | 318 | goto err_del_interface; |
319 | } | 319 | } |
320 | 320 | ||
321 | sta_info_move_state(sta, IEEE80211_STA_AUTH); | 321 | sta_info_pre_move_state(sta, IEEE80211_STA_AUTH); |
322 | sta_info_move_state(sta, IEEE80211_STA_ASSOC); | 322 | sta_info_pre_move_state(sta, IEEE80211_STA_ASSOC); |
323 | sta_info_move_state(sta, IEEE80211_STA_AUTHORIZED); | 323 | sta_info_pre_move_state(sta, IEEE80211_STA_AUTHORIZED); |
324 | 324 | ||
325 | res = sta_info_insert(sta); | 325 | res = sta_info_insert(sta); |
326 | if (res) { | 326 | if (res) { |
diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c index 41ef1b476442..bf92e2878fe6 100644 --- a/net/mac80211/mesh_plink.c +++ b/net/mac80211/mesh_plink.c | |||
@@ -96,9 +96,9 @@ static struct sta_info *mesh_plink_alloc(struct ieee80211_sub_if_data *sdata, | |||
96 | if (!sta) | 96 | if (!sta) |
97 | return NULL; | 97 | return NULL; |
98 | 98 | ||
99 | sta_info_move_state(sta, IEEE80211_STA_AUTH); | 99 | sta_info_pre_move_state(sta, IEEE80211_STA_AUTH); |
100 | sta_info_move_state(sta, IEEE80211_STA_ASSOC); | 100 | sta_info_pre_move_state(sta, IEEE80211_STA_ASSOC); |
101 | sta_info_move_state(sta, IEEE80211_STA_AUTHORIZED); | 101 | sta_info_pre_move_state(sta, IEEE80211_STA_AUTHORIZED); |
102 | 102 | ||
103 | set_sta_flag(sta, WLAN_STA_WME); | 103 | set_sta_flag(sta, WLAN_STA_WME); |
104 | 104 | ||
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index de3268c7be1e..acc11b5c16fa 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -1587,10 +1587,19 @@ static bool ieee80211_assoc_success(struct ieee80211_work *wk, | |||
1587 | return false; | 1587 | return false; |
1588 | } | 1588 | } |
1589 | 1589 | ||
1590 | sta_info_move_state(sta, IEEE80211_STA_AUTH); | 1590 | err = sta_info_move_state(sta, IEEE80211_STA_AUTH); |
1591 | sta_info_move_state(sta, IEEE80211_STA_ASSOC); | 1591 | if (!err) |
1592 | if (!(ifmgd->flags & IEEE80211_STA_CONTROL_PORT)) | 1592 | err = sta_info_move_state(sta, IEEE80211_STA_ASSOC); |
1593 | sta_info_move_state(sta, IEEE80211_STA_AUTHORIZED); | 1593 | if (!err && !(ifmgd->flags & IEEE80211_STA_CONTROL_PORT)) |
1594 | err = sta_info_move_state(sta, IEEE80211_STA_AUTHORIZED); | ||
1595 | if (err) { | ||
1596 | printk(KERN_DEBUG | ||
1597 | "%s: failed to move station %pM to desired state\n", | ||
1598 | sdata->name, sta->sta.addr); | ||
1599 | WARN_ON(__sta_info_destroy(sta)); | ||
1600 | mutex_unlock(&sdata->local->sta_mtx); | ||
1601 | return false; | ||
1602 | } | ||
1594 | 1603 | ||
1595 | rates = 0; | 1604 | rates = 0; |
1596 | basic_rates = 0; | 1605 | basic_rates = 0; |
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index f28fa02b6e54..df8f0a2f0dee 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c | |||
@@ -403,6 +403,8 @@ static int sta_info_insert_finish(struct sta_info *sta) __acquires(RCU) | |||
403 | sta_info_hash_add(local, sta); | 403 | sta_info_hash_add(local, sta); |
404 | 404 | ||
405 | list_add(&sta->list, &local->sta_list); | 405 | list_add(&sta->list, &local->sta_list); |
406 | |||
407 | set_sta_flag(sta, WLAN_STA_INSERTED); | ||
406 | } else { | 408 | } else { |
407 | sta->dummy = false; | 409 | sta->dummy = false; |
408 | } | 410 | } |
@@ -707,7 +709,7 @@ static bool sta_info_cleanup_expire_buffered(struct ieee80211_local *local, | |||
707 | return have_buffered; | 709 | return have_buffered; |
708 | } | 710 | } |
709 | 711 | ||
710 | static int __must_check __sta_info_destroy(struct sta_info *sta) | 712 | int __must_check __sta_info_destroy(struct sta_info *sta) |
711 | { | 713 | { |
712 | struct ieee80211_local *local; | 714 | struct ieee80211_local *local; |
713 | struct ieee80211_sub_if_data *sdata; | 715 | struct ieee80211_sub_if_data *sdata; |
@@ -722,6 +724,8 @@ static int __must_check __sta_info_destroy(struct sta_info *sta) | |||
722 | local = sta->local; | 724 | local = sta->local; |
723 | sdata = sta->sdata; | 725 | sdata = sta->sdata; |
724 | 726 | ||
727 | lockdep_assert_held(&local->sta_mtx); | ||
728 | |||
725 | /* | 729 | /* |
726 | * Before removing the station from the driver and | 730 | * Before removing the station from the driver and |
727 | * rate control, it might still start new aggregation | 731 | * rate control, it might still start new aggregation |
@@ -763,8 +767,13 @@ static int __must_check __sta_info_destroy(struct sta_info *sta) | |||
763 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) | 767 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) |
764 | RCU_INIT_POINTER(sdata->u.vlan.sta, NULL); | 768 | RCU_INIT_POINTER(sdata->u.vlan.sta, NULL); |
765 | 769 | ||
766 | while (sta->sta_state > IEEE80211_STA_NONE) | 770 | while (sta->sta_state > IEEE80211_STA_NONE) { |
767 | sta_info_move_state(sta, sta->sta_state - 1); | 771 | int err = sta_info_move_state(sta, sta->sta_state - 1); |
772 | if (err) { | ||
773 | WARN_ON_ONCE(1); | ||
774 | break; | ||
775 | } | ||
776 | } | ||
768 | 777 | ||
769 | if (sta->uploaded) { | 778 | if (sta->uploaded) { |
770 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) | 779 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) |
@@ -1391,8 +1400,8 @@ void ieee80211_sta_set_buffered(struct ieee80211_sta *pubsta, | |||
1391 | } | 1400 | } |
1392 | EXPORT_SYMBOL(ieee80211_sta_set_buffered); | 1401 | EXPORT_SYMBOL(ieee80211_sta_set_buffered); |
1393 | 1402 | ||
1394 | int sta_info_move_state_checked(struct sta_info *sta, | 1403 | int sta_info_move_state(struct sta_info *sta, |
1395 | enum ieee80211_sta_state new_state) | 1404 | enum ieee80211_sta_state new_state) |
1396 | { | 1405 | { |
1397 | might_sleep(); | 1406 | might_sleep(); |
1398 | 1407 | ||
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index 6f77f12dc3fc..381de37d2478 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h | |||
@@ -52,6 +52,7 @@ | |||
52 | * @WLAN_STA_SP: Station is in a service period, so don't try to | 52 | * @WLAN_STA_SP: Station is in a service period, so don't try to |
53 | * reply to other uAPSD trigger frames or PS-Poll. | 53 | * reply to other uAPSD trigger frames or PS-Poll. |
54 | * @WLAN_STA_4ADDR_EVENT: 4-addr event was already sent for this frame. | 54 | * @WLAN_STA_4ADDR_EVENT: 4-addr event was already sent for this frame. |
55 | * @WLAN_STA_INSERTED: This station is inserted into the hash table. | ||
55 | */ | 56 | */ |
56 | enum ieee80211_sta_info_flags { | 57 | enum ieee80211_sta_info_flags { |
57 | WLAN_STA_AUTH, | 58 | WLAN_STA_AUTH, |
@@ -71,6 +72,7 @@ enum ieee80211_sta_info_flags { | |||
71 | WLAN_STA_UAPSD, | 72 | WLAN_STA_UAPSD, |
72 | WLAN_STA_SP, | 73 | WLAN_STA_SP, |
73 | WLAN_STA_4ADDR_EVENT, | 74 | WLAN_STA_4ADDR_EVENT, |
75 | WLAN_STA_INSERTED, | ||
74 | }; | 76 | }; |
75 | 77 | ||
76 | enum ieee80211_sta_state { | 78 | enum ieee80211_sta_state { |
@@ -427,13 +429,17 @@ static inline int test_and_set_sta_flag(struct sta_info *sta, | |||
427 | return test_and_set_bit(flag, &sta->_flags); | 429 | return test_and_set_bit(flag, &sta->_flags); |
428 | } | 430 | } |
429 | 431 | ||
430 | int sta_info_move_state_checked(struct sta_info *sta, | 432 | int sta_info_move_state(struct sta_info *sta, |
431 | enum ieee80211_sta_state new_state); | 433 | enum ieee80211_sta_state new_state); |
432 | 434 | ||
433 | static inline void sta_info_move_state(struct sta_info *sta, | 435 | static inline void sta_info_pre_move_state(struct sta_info *sta, |
434 | enum ieee80211_sta_state new_state) | 436 | enum ieee80211_sta_state new_state) |
435 | { | 437 | { |
436 | int ret = sta_info_move_state_checked(sta, new_state); | 438 | int ret; |
439 | |||
440 | WARN_ON_ONCE(test_sta_flag(sta, WLAN_STA_INSERTED)); | ||
441 | |||
442 | ret = sta_info_move_state(sta, new_state); | ||
437 | WARN_ON_ONCE(ret); | 443 | WARN_ON_ONCE(ret); |
438 | } | 444 | } |
439 | 445 | ||
@@ -544,6 +550,7 @@ int sta_info_insert(struct sta_info *sta); | |||
544 | int sta_info_insert_rcu(struct sta_info *sta) __acquires(RCU); | 550 | int sta_info_insert_rcu(struct sta_info *sta) __acquires(RCU); |
545 | int sta_info_reinsert(struct sta_info *sta); | 551 | int sta_info_reinsert(struct sta_info *sta); |
546 | 552 | ||
553 | int __must_check __sta_info_destroy(struct sta_info *sta); | ||
547 | int sta_info_destroy_addr(struct ieee80211_sub_if_data *sdata, | 554 | int sta_info_destroy_addr(struct ieee80211_sub_if_data *sdata, |
548 | const u8 *addr); | 555 | const u8 *addr); |
549 | int sta_info_destroy_addr_bss(struct ieee80211_sub_if_data *sdata, | 556 | int sta_info_destroy_addr_bss(struct ieee80211_sub_if_data *sdata, |