aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211
diff options
context:
space:
mode:
authorJohn W. Linville <linville@tuxdriver.com>2013-06-28 13:18:21 -0400
committerJohn W. Linville <linville@tuxdriver.com>2013-06-28 13:18:21 -0400
commit57ed5cd695d7373b8ae0ae9f10fe945e774d58f0 (patch)
tree7ee6244ea7c0be81a541d4e57783f83c4dfd7d66 /net/mac80211
parent5e6700b3bf98fe98d630bf9c939ad4c85ce95592 (diff)
parent0f817ed52d07873cd39c9d3f6d87fae962dc742f (diff)
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next into for-davem
Conflicts: net/wireless/nl80211.c
Diffstat (limited to 'net/mac80211')
-rw-r--r--net/mac80211/cfg.c14
-rw-r--r--net/mac80211/ht.c4
-rw-r--r--net/mac80211/ibss.c65
-rw-r--r--net/mac80211/ieee80211_i.h6
-rw-r--r--net/mac80211/mesh.c57
-rw-r--r--net/mac80211/mesh.h2
-rw-r--r--net/mac80211/mesh_plink.c8
-rw-r--r--net/mac80211/mlme.c35
-rw-r--r--net/mac80211/rate.c8
-rw-r--r--net/mac80211/scan.c9
-rw-r--r--net/mac80211/sta_info.c2
-rw-r--r--net/mac80211/sta_info.h1
-rw-r--r--net/mac80211/vht.c2
13 files changed, 127 insertions, 86 deletions
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 082f270b5912..8184d121ff09 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -2827,7 +2827,8 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
2827 !rcu_access_pointer(sdata->bss->beacon)) 2827 !rcu_access_pointer(sdata->bss->beacon))
2828 need_offchan = true; 2828 need_offchan = true;
2829 if (!ieee80211_is_action(mgmt->frame_control) || 2829 if (!ieee80211_is_action(mgmt->frame_control) ||
2830 mgmt->u.action.category == WLAN_CATEGORY_PUBLIC) 2830 mgmt->u.action.category == WLAN_CATEGORY_PUBLIC ||
2831 mgmt->u.action.category == WLAN_CATEGORY_SELF_PROTECTED)
2831 break; 2832 break;
2832 rcu_read_lock(); 2833 rcu_read_lock();
2833 sta = sta_info_get(sdata, mgmt->da); 2834 sta = sta_info_get(sdata, mgmt->da);
@@ -2930,19 +2931,8 @@ static void ieee80211_mgmt_frame_register(struct wiphy *wiphy,
2930 u16 frame_type, bool reg) 2931 u16 frame_type, bool reg)
2931{ 2932{
2932 struct ieee80211_local *local = wiphy_priv(wiphy); 2933 struct ieee80211_local *local = wiphy_priv(wiphy);
2933 struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
2934 2934
2935 switch (frame_type) { 2935 switch (frame_type) {
2936 case IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_AUTH:
2937 if (sdata->vif.type == NL80211_IFTYPE_ADHOC) {
2938 struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
2939
2940 if (reg)
2941 ifibss->auth_frame_registrations++;
2942 else
2943 ifibss->auth_frame_registrations--;
2944 }
2945 break;
2946 case IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_REQ: 2936 case IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_REQ:
2947 if (reg) 2937 if (reg)
2948 local->probe_req_reg++; 2938 local->probe_req_reg++;
diff --git a/net/mac80211/ht.c b/net/mac80211/ht.c
index 75dff338f581..f83534f6a2ee 100644
--- a/net/mac80211/ht.c
+++ b/net/mac80211/ht.c
@@ -281,13 +281,14 @@ void ieee80211_ba_session_work(struct work_struct *work)
281 sta, tid, WLAN_BACK_RECIPIENT, 281 sta, tid, WLAN_BACK_RECIPIENT,
282 WLAN_REASON_UNSPECIFIED, true); 282 WLAN_REASON_UNSPECIFIED, true);
283 283
284 spin_lock_bh(&sta->lock);
285
284 tid_tx = sta->ampdu_mlme.tid_start_tx[tid]; 286 tid_tx = sta->ampdu_mlme.tid_start_tx[tid];
285 if (tid_tx) { 287 if (tid_tx) {
286 /* 288 /*
287 * Assign it over to the normal tid_tx array 289 * Assign it over to the normal tid_tx array
288 * where it "goes live". 290 * where it "goes live".
289 */ 291 */
290 spin_lock_bh(&sta->lock);
291 292
292 sta->ampdu_mlme.tid_start_tx[tid] = NULL; 293 sta->ampdu_mlme.tid_start_tx[tid] = NULL;
293 /* could there be a race? */ 294 /* could there be a race? */
@@ -300,6 +301,7 @@ void ieee80211_ba_session_work(struct work_struct *work)
300 ieee80211_tx_ba_session_handle_start(sta, tid); 301 ieee80211_tx_ba_session_handle_start(sta, tid);
301 continue; 302 continue;
302 } 303 }
304 spin_unlock_bh(&sta->lock);
303 305
304 tid_tx = rcu_dereference_protected_tid_tx(sta, tid); 306 tid_tx = rcu_dereference_protected_tid_tx(sta, tid);
305 if (tid_tx && test_and_clear_bit(HT_AGG_STATE_WANT_STOP, 307 if (tid_tx && test_and_clear_bit(HT_AGG_STATE_WANT_STOP,
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c
index caa4b4f7f6e4..ea7b9c2c7e66 100644
--- a/net/mac80211/ibss.c
+++ b/net/mac80211/ibss.c
@@ -81,7 +81,7 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
81 81
82 sdata->drop_unencrypted = capability & WLAN_CAPABILITY_PRIVACY ? 1 : 0; 82 sdata->drop_unencrypted = capability & WLAN_CAPABILITY_PRIVACY ? 1 : 0;
83 83
84 cfg80211_chandef_create(&chandef, chan, ifibss->channel_type); 84 chandef = ifibss->chandef;
85 if (!cfg80211_reg_can_beacon(local->hw.wiphy, &chandef)) { 85 if (!cfg80211_reg_can_beacon(local->hw.wiphy, &chandef)) {
86 chandef.width = NL80211_CHAN_WIDTH_20; 86 chandef.width = NL80211_CHAN_WIDTH_20;
87 chandef.center_freq1 = chan->center_freq; 87 chandef.center_freq1 = chan->center_freq;
@@ -176,6 +176,8 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
176 176
177 /* add HT capability and information IEs */ 177 /* add HT capability and information IEs */
178 if (chandef.width != NL80211_CHAN_WIDTH_20_NOHT && 178 if (chandef.width != NL80211_CHAN_WIDTH_20_NOHT &&
179 chandef.width != NL80211_CHAN_WIDTH_5 &&
180 chandef.width != NL80211_CHAN_WIDTH_10 &&
179 sband->ht_cap.ht_supported) { 181 sband->ht_cap.ht_supported) {
180 pos = ieee80211_ie_build_ht_cap(pos, &sband->ht_cap, 182 pos = ieee80211_ie_build_ht_cap(pos, &sband->ht_cap,
181 sband->ht_cap.cap); 183 sband->ht_cap.cap);
@@ -298,8 +300,7 @@ static void ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
298 tsf, false); 300 tsf, false);
299} 301}
300 302
301static struct sta_info *ieee80211_ibss_finish_sta(struct sta_info *sta, 303static struct sta_info *ieee80211_ibss_finish_sta(struct sta_info *sta)
302 bool auth)
303 __acquires(RCU) 304 __acquires(RCU)
304{ 305{
305 struct ieee80211_sub_if_data *sdata = sta->sdata; 306 struct ieee80211_sub_if_data *sdata = sta->sdata;
@@ -321,20 +322,12 @@ static struct sta_info *ieee80211_ibss_finish_sta(struct sta_info *sta,
321 /* If it fails, maybe we raced another insertion? */ 322 /* If it fails, maybe we raced another insertion? */
322 if (sta_info_insert_rcu(sta)) 323 if (sta_info_insert_rcu(sta))
323 return sta_info_get(sdata, addr); 324 return sta_info_get(sdata, addr);
324 if (auth && !sdata->u.ibss.auth_frame_registrations) {
325 ibss_dbg(sdata,
326 "TX Auth SA=%pM DA=%pM BSSID=%pM (auth_transaction=1)\n",
327 sdata->vif.addr, addr, sdata->u.ibss.bssid);
328 ieee80211_send_auth(sdata, 1, WLAN_AUTH_OPEN, 0, NULL, 0,
329 addr, sdata->u.ibss.bssid, NULL, 0, 0, 0);
330 }
331 return sta; 325 return sta;
332} 326}
333 327
334static struct sta_info * 328static struct sta_info *
335ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata, 329ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata, const u8 *bssid,
336 const u8 *bssid, const u8 *addr, 330 const u8 *addr, u32 supp_rates)
337 u32 supp_rates, bool auth)
338 __acquires(RCU) 331 __acquires(RCU)
339{ 332{
340 struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; 333 struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
@@ -385,7 +378,7 @@ ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata,
385 sta->sta.supp_rates[band] = supp_rates | 378 sta->sta.supp_rates[band] = supp_rates |
386 ieee80211_mandatory_rates(sband); 379 ieee80211_mandatory_rates(sband);
387 380
388 return ieee80211_ibss_finish_sta(sta, auth); 381 return ieee80211_ibss_finish_sta(sta);
389} 382}
390 383
391static void ieee80211_rx_mgmt_deauth_ibss(struct ieee80211_sub_if_data *sdata, 384static void ieee80211_rx_mgmt_deauth_ibss(struct ieee80211_sub_if_data *sdata,
@@ -407,8 +400,6 @@ static void ieee80211_rx_mgmt_auth_ibss(struct ieee80211_sub_if_data *sdata,
407 size_t len) 400 size_t len)
408{ 401{
409 u16 auth_alg, auth_transaction; 402 u16 auth_alg, auth_transaction;
410 struct sta_info *sta;
411 u8 deauth_frame_buf[IEEE80211_DEAUTH_FRAME_LEN];
412 403
413 sdata_assert_lock(sdata); 404 sdata_assert_lock(sdata);
414 405
@@ -425,22 +416,6 @@ static void ieee80211_rx_mgmt_auth_ibss(struct ieee80211_sub_if_data *sdata,
425 if (auth_alg != WLAN_AUTH_OPEN || auth_transaction != 1) 416 if (auth_alg != WLAN_AUTH_OPEN || auth_transaction != 1)
426 return; 417 return;
427 418
428 sta_info_destroy_addr(sdata, mgmt->sa);
429 sta = ieee80211_ibss_add_sta(sdata, mgmt->bssid, mgmt->sa, 0, false);
430 rcu_read_unlock();
431
432 /*
433 * if we have any problem in allocating the new station, we reply with a
434 * DEAUTH frame to tell the other end that we had a problem
435 */
436 if (!sta) {
437 ieee80211_send_deauth_disassoc(sdata, sdata->u.ibss.bssid,
438 IEEE80211_STYPE_DEAUTH,
439 WLAN_REASON_UNSPECIFIED, true,
440 deauth_frame_buf);
441 return;
442 }
443
444 /* 419 /*
445 * IEEE 802.11 standard does not require authentication in IBSS 420 * IEEE 802.11 standard does not require authentication in IBSS
446 * networks and most implementations do not seem to use it. 421 * networks and most implementations do not seem to use it.
@@ -506,7 +481,7 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
506 } else { 481 } else {
507 rcu_read_unlock(); 482 rcu_read_unlock();
508 sta = ieee80211_ibss_add_sta(sdata, mgmt->bssid, 483 sta = ieee80211_ibss_add_sta(sdata, mgmt->bssid,
509 mgmt->sa, supp_rates, true); 484 mgmt->sa, supp_rates);
510 } 485 }
511 } 486 }
512 487
@@ -514,7 +489,9 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
514 set_sta_flag(sta, WLAN_STA_WME); 489 set_sta_flag(sta, WLAN_STA_WME);
515 490
516 if (sta && elems->ht_operation && elems->ht_cap_elem && 491 if (sta && elems->ht_operation && elems->ht_cap_elem &&
517 sdata->u.ibss.channel_type != NL80211_CHAN_NO_HT) { 492 sdata->u.ibss.chandef.width != NL80211_CHAN_WIDTH_20_NOHT &&
493 sdata->u.ibss.chandef.width != NL80211_CHAN_WIDTH_5 &&
494 sdata->u.ibss.chandef.width != NL80211_CHAN_WIDTH_10) {
518 /* we both use HT */ 495 /* we both use HT */
519 struct ieee80211_ht_cap htcap_ie; 496 struct ieee80211_ht_cap htcap_ie;
520 struct cfg80211_chan_def chandef; 497 struct cfg80211_chan_def chandef;
@@ -529,8 +506,8 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
529 * fall back to HT20 if we don't use or use 506 * fall back to HT20 if we don't use or use
530 * the other extension channel 507 * the other extension channel
531 */ 508 */
532 if (cfg80211_get_chandef_type(&chandef) != 509 if (chandef.center_freq1 !=
533 sdata->u.ibss.channel_type) 510 sdata->u.ibss.chandef.center_freq1)
534 htcap_ie.cap_info &= 511 htcap_ie.cap_info &=
535 cpu_to_le16(~IEEE80211_HT_CAP_SUP_WIDTH_20_40); 512 cpu_to_le16(~IEEE80211_HT_CAP_SUP_WIDTH_20_40);
536 513
@@ -569,7 +546,7 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
569 546
570 /* different channel */ 547 /* different channel */
571 if (sdata->u.ibss.fixed_channel && 548 if (sdata->u.ibss.fixed_channel &&
572 sdata->u.ibss.channel != cbss->channel) 549 sdata->u.ibss.chandef.chan != cbss->channel)
573 goto put_bss; 550 goto put_bss;
574 551
575 /* different SSID */ 552 /* different SSID */
@@ -610,7 +587,7 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
610 ieee80211_sta_join_ibss(sdata, bss); 587 ieee80211_sta_join_ibss(sdata, bss);
611 supp_rates = ieee80211_sta_get_rates(local, elems, band, NULL); 588 supp_rates = ieee80211_sta_get_rates(local, elems, band, NULL);
612 ieee80211_ibss_add_sta(sdata, mgmt->bssid, mgmt->sa, 589 ieee80211_ibss_add_sta(sdata, mgmt->bssid, mgmt->sa,
613 supp_rates, true); 590 supp_rates);
614 rcu_read_unlock(); 591 rcu_read_unlock();
615 } 592 }
616 593
@@ -759,7 +736,7 @@ static void ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata)
759 sdata->drop_unencrypted = 0; 736 sdata->drop_unencrypted = 0;
760 737
761 __ieee80211_sta_join_ibss(sdata, bssid, sdata->vif.bss_conf.beacon_int, 738 __ieee80211_sta_join_ibss(sdata, bssid, sdata->vif.bss_conf.beacon_int,
762 ifibss->channel, ifibss->basic_rates, 739 ifibss->chandef.chan, ifibss->basic_rates,
763 capability, 0, true); 740 capability, 0, true);
764} 741}
765 742
@@ -791,7 +768,7 @@ static void ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata)
791 if (ifibss->fixed_bssid) 768 if (ifibss->fixed_bssid)
792 bssid = ifibss->bssid; 769 bssid = ifibss->bssid;
793 if (ifibss->fixed_channel) 770 if (ifibss->fixed_channel)
794 chan = ifibss->channel; 771 chan = ifibss->chandef.chan;
795 if (!is_zero_ether_addr(ifibss->bssid)) 772 if (!is_zero_ether_addr(ifibss->bssid))
796 bssid = ifibss->bssid; 773 bssid = ifibss->bssid;
797 cbss = cfg80211_get_bss(local->hw.wiphy, chan, bssid, 774 cbss = cfg80211_get_bss(local->hw.wiphy, chan, bssid,
@@ -982,7 +959,7 @@ void ieee80211_ibss_work(struct ieee80211_sub_if_data *sdata)
982 list_del(&sta->list); 959 list_del(&sta->list);
983 spin_unlock_bh(&ifibss->incomplete_lock); 960 spin_unlock_bh(&ifibss->incomplete_lock);
984 961
985 ieee80211_ibss_finish_sta(sta, true); 962 ieee80211_ibss_finish_sta(sta);
986 rcu_read_unlock(); 963 rcu_read_unlock();
987 spin_lock_bh(&ifibss->incomplete_lock); 964 spin_lock_bh(&ifibss->incomplete_lock);
988 } 965 }
@@ -1058,9 +1035,7 @@ int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata,
1058 1035
1059 sdata->vif.bss_conf.beacon_int = params->beacon_interval; 1036 sdata->vif.bss_conf.beacon_int = params->beacon_interval;
1060 1037
1061 sdata->u.ibss.channel = params->chandef.chan; 1038 sdata->u.ibss.chandef = params->chandef;
1062 sdata->u.ibss.channel_type =
1063 cfg80211_get_chandef_type(&params->chandef);
1064 sdata->u.ibss.fixed_channel = params->channel_fixed; 1039 sdata->u.ibss.fixed_channel = params->channel_fixed;
1065 1040
1066 if (params->ie) { 1041 if (params->ie) {
@@ -1119,7 +1094,7 @@ int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata)
1119 if (ifibss->privacy) 1094 if (ifibss->privacy)
1120 capability |= WLAN_CAPABILITY_PRIVACY; 1095 capability |= WLAN_CAPABILITY_PRIVACY;
1121 1096
1122 cbss = cfg80211_get_bss(local->hw.wiphy, ifibss->channel, 1097 cbss = cfg80211_get_bss(local->hw.wiphy, ifibss->chandef.chan,
1123 ifibss->bssid, ifibss->ssid, 1098 ifibss->bssid, ifibss->ssid,
1124 ifibss->ssid_len, WLAN_CAPABILITY_IBSS | 1099 ifibss->ssid_len, WLAN_CAPABILITY_IBSS |
1125 WLAN_CAPABILITY_PRIVACY, 1100 WLAN_CAPABILITY_PRIVACY,
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index f97cd9d9105f..8412a303993a 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -94,6 +94,7 @@ struct ieee80211_bss {
94#define IEEE80211_MAX_SUPP_RATES 32 94#define IEEE80211_MAX_SUPP_RATES 32
95 u8 supp_rates[IEEE80211_MAX_SUPP_RATES]; 95 u8 supp_rates[IEEE80211_MAX_SUPP_RATES];
96 size_t supp_rates_len; 96 size_t supp_rates_len;
97 struct ieee80211_rate *beacon_rate;
97 98
98 /* 99 /*
99 * During association, we save an ERP value from a probe response so 100 * During association, we save an ERP value from a probe response so
@@ -497,14 +498,12 @@ struct ieee80211_if_ibss {
497 bool privacy; 498 bool privacy;
498 499
499 bool control_port; 500 bool control_port;
500 unsigned int auth_frame_registrations;
501 501
502 u8 bssid[ETH_ALEN] __aligned(2); 502 u8 bssid[ETH_ALEN] __aligned(2);
503 u8 ssid[IEEE80211_MAX_SSID_LEN]; 503 u8 ssid[IEEE80211_MAX_SSID_LEN];
504 u8 ssid_len, ie_len; 504 u8 ssid_len, ie_len;
505 u8 *ie; 505 u8 *ie;
506 struct ieee80211_channel *channel; 506 struct cfg80211_chan_def chandef;
507 enum nl80211_channel_type channel_type;
508 507
509 unsigned long ibss_join_req; 508 unsigned long ibss_join_req;
510 /* probe response/beacon for IBSS */ 509 /* probe response/beacon for IBSS */
@@ -543,6 +542,7 @@ struct ieee80211_if_mesh {
543 struct timer_list mesh_path_root_timer; 542 struct timer_list mesh_path_root_timer;
544 543
545 unsigned long wrkq_flags; 544 unsigned long wrkq_flags;
545 unsigned long mbss_changed;
546 546
547 u8 mesh_id[IEEE80211_MAX_MESH_ID_LEN]; 547 u8 mesh_id[IEEE80211_MAX_MESH_ID_LEN];
548 size_t mesh_id_len; 548 size_t mesh_id_len;
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c
index 6c33af482df4..447f41bbe744 100644
--- a/net/mac80211/mesh.c
+++ b/net/mac80211/mesh.c
@@ -161,11 +161,8 @@ void mesh_sta_cleanup(struct sta_info *sta)
161 del_timer_sync(&sta->plink_timer); 161 del_timer_sync(&sta->plink_timer);
162 } 162 }
163 163
164 if (changed) { 164 if (changed)
165 sdata_lock(sdata);
166 ieee80211_mbss_info_change_notify(sdata, changed); 165 ieee80211_mbss_info_change_notify(sdata, changed);
167 sdata_unlock(sdata);
168 }
169} 166}
170 167
171int mesh_rmc_init(struct ieee80211_sub_if_data *sdata) 168int mesh_rmc_init(struct ieee80211_sub_if_data *sdata)
@@ -419,7 +416,9 @@ int mesh_add_ht_cap_ie(struct ieee80211_sub_if_data *sdata,
419 416
420 sband = local->hw.wiphy->bands[band]; 417 sband = local->hw.wiphy->bands[band];
421 if (!sband->ht_cap.ht_supported || 418 if (!sband->ht_cap.ht_supported ||
422 sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_20_NOHT) 419 sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_20_NOHT ||
420 sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_5 ||
421 sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_10)
423 return 0; 422 return 0;
424 423
425 if (skb_tailroom(skb) < 2 + sizeof(struct ieee80211_ht_cap)) 424 if (skb_tailroom(skb) < 2 + sizeof(struct ieee80211_ht_cap))
@@ -719,14 +718,18 @@ ieee80211_mesh_rebuild_beacon(struct ieee80211_sub_if_data *sdata)
719void ieee80211_mbss_info_change_notify(struct ieee80211_sub_if_data *sdata, 718void ieee80211_mbss_info_change_notify(struct ieee80211_sub_if_data *sdata,
720 u32 changed) 719 u32 changed)
721{ 720{
722 if (sdata->vif.bss_conf.enable_beacon && 721 struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
723 (changed & (BSS_CHANGED_BEACON | 722 unsigned long bits = changed;
724 BSS_CHANGED_HT | 723 u32 bit;
725 BSS_CHANGED_BASIC_RATES | 724
726 BSS_CHANGED_BEACON_INT))) 725 if (!bits)
727 if (ieee80211_mesh_rebuild_beacon(sdata)) 726 return;
728 return; 727
729 ieee80211_bss_info_change_notify(sdata, changed); 728 /* if we race with running work, worst case this work becomes a noop */
729 for_each_set_bit(bit, &bits, sizeof(changed) * BITS_PER_BYTE)
730 set_bit(bit, &ifmsh->mbss_changed);
731 set_bit(MESH_WORK_MBSS_CHANGED, &ifmsh->wrkq_flags);
732 ieee80211_queue_work(&sdata->local->hw, &sdata->work);
730} 733}
731 734
732int ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata) 735int ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata)
@@ -799,6 +802,10 @@ void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata)
799 del_timer_sync(&sdata->u.mesh.mesh_path_root_timer); 802 del_timer_sync(&sdata->u.mesh.mesh_path_root_timer);
800 del_timer_sync(&sdata->u.mesh.mesh_path_timer); 803 del_timer_sync(&sdata->u.mesh.mesh_path_timer);
801 804
805 /* clear any mesh work (for next join) we may have accrued */
806 ifmsh->wrkq_flags = 0;
807 ifmsh->mbss_changed = 0;
808
802 local->fif_other_bss--; 809 local->fif_other_bss--;
803 atomic_dec(&local->iff_allmultis); 810 atomic_dec(&local->iff_allmultis);
804 ieee80211_configure_filter(local); 811 ieee80211_configure_filter(local);
@@ -965,6 +972,28 @@ out:
965 sdata_unlock(sdata); 972 sdata_unlock(sdata);
966} 973}
967 974
975static void mesh_bss_info_changed(struct ieee80211_sub_if_data *sdata)
976{
977 struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
978 u32 bit, changed = 0;
979
980 for_each_set_bit(bit, &ifmsh->mbss_changed,
981 sizeof(changed) * BITS_PER_BYTE) {
982 clear_bit(bit, &ifmsh->mbss_changed);
983 changed |= BIT(bit);
984 }
985
986 if (sdata->vif.bss_conf.enable_beacon &&
987 (changed & (BSS_CHANGED_BEACON |
988 BSS_CHANGED_HT |
989 BSS_CHANGED_BASIC_RATES |
990 BSS_CHANGED_BEACON_INT)))
991 if (ieee80211_mesh_rebuild_beacon(sdata))
992 return;
993
994 ieee80211_bss_info_change_notify(sdata, changed);
995}
996
968void ieee80211_mesh_work(struct ieee80211_sub_if_data *sdata) 997void ieee80211_mesh_work(struct ieee80211_sub_if_data *sdata)
969{ 998{
970 struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; 999 struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
@@ -995,6 +1024,8 @@ void ieee80211_mesh_work(struct ieee80211_sub_if_data *sdata)
995 if (test_and_clear_bit(MESH_WORK_DRIFT_ADJUST, &ifmsh->wrkq_flags)) 1024 if (test_and_clear_bit(MESH_WORK_DRIFT_ADJUST, &ifmsh->wrkq_flags))
996 mesh_sync_adjust_tbtt(sdata); 1025 mesh_sync_adjust_tbtt(sdata);
997 1026
1027 if (test_and_clear_bit(MESH_WORK_MBSS_CHANGED, &ifmsh->wrkq_flags))
1028 mesh_bss_info_changed(sdata);
998out: 1029out:
999 sdata_unlock(sdata); 1030 sdata_unlock(sdata);
1000} 1031}
diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h
index 01a28bca6e9b..2bc7fd2f787d 100644
--- a/net/mac80211/mesh.h
+++ b/net/mac80211/mesh.h
@@ -58,6 +58,7 @@ enum mesh_path_flags {
58 * @MESH_WORK_ROOT: the mesh root station needs to send a frame 58 * @MESH_WORK_ROOT: the mesh root station needs to send a frame
59 * @MESH_WORK_DRIFT_ADJUST: time to compensate for clock drift relative to other 59 * @MESH_WORK_DRIFT_ADJUST: time to compensate for clock drift relative to other
60 * mesh nodes 60 * mesh nodes
61 * @MESH_WORK_MBSS_CHANGED: rebuild beacon and notify driver of BSS changes
61 */ 62 */
62enum mesh_deferred_task_flags { 63enum mesh_deferred_task_flags {
63 MESH_WORK_HOUSEKEEPING, 64 MESH_WORK_HOUSEKEEPING,
@@ -65,6 +66,7 @@ enum mesh_deferred_task_flags {
65 MESH_WORK_GROW_MPP_TABLE, 66 MESH_WORK_GROW_MPP_TABLE,
66 MESH_WORK_ROOT, 67 MESH_WORK_ROOT,
67 MESH_WORK_DRIFT_ADJUST, 68 MESH_WORK_DRIFT_ADJUST,
69 MESH_WORK_MBSS_CHANGED,
68}; 70};
69 71
70/** 72/**
diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c
index 09bebed99416..02c05fa15c20 100644
--- a/net/mac80211/mesh_plink.c
+++ b/net/mac80211/mesh_plink.c
@@ -154,8 +154,14 @@ static u32 mesh_set_ht_prot_mode(struct ieee80211_sub_if_data *sdata)
154 u16 ht_opmode; 154 u16 ht_opmode;
155 bool non_ht_sta = false, ht20_sta = false; 155 bool non_ht_sta = false, ht20_sta = false;
156 156
157 if (sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_20_NOHT) 157 switch (sdata->vif.bss_conf.chandef.width) {
158 case NL80211_CHAN_WIDTH_20_NOHT:
159 case NL80211_CHAN_WIDTH_5:
160 case NL80211_CHAN_WIDTH_10:
158 return 0; 161 return 0;
162 default:
163 break;
164 }
159 165
160 rcu_read_lock(); 166 rcu_read_lock();
161 list_for_each_entry_rcu(sta, &local->sta_list, list) { 167 list_for_each_entry_rcu(sta, &local->sta_list, list) {
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 9e49f557fa5c..ae31968d42d3 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -190,6 +190,12 @@ static u32 chandef_downgrade(struct cfg80211_chan_def *c)
190 c->width = NL80211_CHAN_WIDTH_20_NOHT; 190 c->width = NL80211_CHAN_WIDTH_20_NOHT;
191 ret = IEEE80211_STA_DISABLE_HT | IEEE80211_STA_DISABLE_VHT; 191 ret = IEEE80211_STA_DISABLE_HT | IEEE80211_STA_DISABLE_VHT;
192 break; 192 break;
193 case NL80211_CHAN_WIDTH_5:
194 case NL80211_CHAN_WIDTH_10:
195 WARN_ON_ONCE(1);
196 /* keep c->width */
197 ret = IEEE80211_STA_DISABLE_HT | IEEE80211_STA_DISABLE_VHT;
198 break;
193 } 199 }
194 200
195 WARN_ON_ONCE(!cfg80211_chandef_valid(c)); 201 WARN_ON_ONCE(!cfg80211_chandef_valid(c));
@@ -1779,8 +1785,10 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata,
1779 * probably just won't work at all. 1785 * probably just won't work at all.
1780 */ 1786 */
1781 bss_conf->dtim_period = sdata->u.mgd.dtim_period ?: 1; 1787 bss_conf->dtim_period = sdata->u.mgd.dtim_period ?: 1;
1788 bss_conf->beacon_rate = bss->beacon_rate;
1782 bss_info_changed |= BSS_CHANGED_BEACON_INFO; 1789 bss_info_changed |= BSS_CHANGED_BEACON_INFO;
1783 } else { 1790 } else {
1791 bss_conf->beacon_rate = NULL;
1784 bss_conf->dtim_period = 0; 1792 bss_conf->dtim_period = 0;
1785 } 1793 }
1786 1794
@@ -1903,6 +1911,8 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
1903 del_timer_sync(&sdata->u.mgd.chswitch_timer); 1911 del_timer_sync(&sdata->u.mgd.chswitch_timer);
1904 1912
1905 sdata->vif.bss_conf.dtim_period = 0; 1913 sdata->vif.bss_conf.dtim_period = 0;
1914 sdata->vif.bss_conf.beacon_rate = NULL;
1915
1906 ifmgd->have_beacon = false; 1916 ifmgd->have_beacon = false;
1907 1917
1908 ifmgd->flags = 0; 1918 ifmgd->flags = 0;
@@ -2785,8 +2795,7 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
2785 if (!ieee80211_assoc_success(sdata, bss, mgmt, len)) { 2795 if (!ieee80211_assoc_success(sdata, bss, mgmt, len)) {
2786 /* oops -- internal error -- send timeout for now */ 2796 /* oops -- internal error -- send timeout for now */
2787 ieee80211_destroy_assoc_data(sdata, false); 2797 ieee80211_destroy_assoc_data(sdata, false);
2788 cfg80211_put_bss(sdata->local->hw.wiphy, bss); 2798 cfg80211_assoc_timeout(sdata->dev, bss);
2789 cfg80211_assoc_timeout(sdata->dev, mgmt->bssid);
2790 return; 2799 return;
2791 } 2800 }
2792 sdata_info(sdata, "associated\n"); 2801 sdata_info(sdata, "associated\n");
@@ -2827,8 +2836,10 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
2827 2836
2828 bss = ieee80211_bss_info_update(local, rx_status, mgmt, len, elems, 2837 bss = ieee80211_bss_info_update(local, rx_status, mgmt, len, elems,
2829 channel); 2838 channel);
2830 if (bss) 2839 if (bss) {
2831 ieee80211_rx_bss_put(local, bss); 2840 ieee80211_rx_bss_put(local, bss);
2841 sdata->vif.bss_conf.beacon_rate = bss->beacon_rate;
2842 }
2832 2843
2833 if (!sdata->u.mgd.associated || 2844 if (!sdata->u.mgd.associated ||
2834 !ether_addr_equal(mgmt->bssid, sdata->u.mgd.associated->bssid)) 2845 !ether_addr_equal(mgmt->bssid, sdata->u.mgd.associated->bssid))
@@ -3501,13 +3512,10 @@ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata)
3501 time_after(jiffies, ifmgd->assoc_data->timeout)) { 3512 time_after(jiffies, ifmgd->assoc_data->timeout)) {
3502 if ((ifmgd->assoc_data->need_beacon && !ifmgd->have_beacon) || 3513 if ((ifmgd->assoc_data->need_beacon && !ifmgd->have_beacon) ||
3503 ieee80211_do_assoc(sdata)) { 3514 ieee80211_do_assoc(sdata)) {
3504 u8 bssid[ETH_ALEN]; 3515 struct cfg80211_bss *bss = ifmgd->assoc_data->bss;
3505
3506 memcpy(bssid, ifmgd->assoc_data->bss->bssid, ETH_ALEN);
3507 3516
3508 ieee80211_destroy_assoc_data(sdata, false); 3517 ieee80211_destroy_assoc_data(sdata, false);
3509 3518 cfg80211_assoc_timeout(sdata->dev, bss);
3510 cfg80211_assoc_timeout(sdata->dev, bssid);
3511 } 3519 }
3512 } else if (ifmgd->assoc_data && ifmgd->assoc_data->timeout_started) 3520 } else if (ifmgd->assoc_data && ifmgd->assoc_data->timeout_started)
3513 run_again(sdata, ifmgd->assoc_data->timeout); 3521 run_again(sdata, ifmgd->assoc_data->timeout);
@@ -3838,6 +3846,12 @@ static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata,
3838 */ 3846 */
3839 ret = ieee80211_vif_use_channel(sdata, &chandef, 3847 ret = ieee80211_vif_use_channel(sdata, &chandef,
3840 IEEE80211_CHANCTX_SHARED); 3848 IEEE80211_CHANCTX_SHARED);
3849
3850 /* don't downgrade for 5 and 10 MHz channels, though. */
3851 if (chandef.width == NL80211_CHAN_WIDTH_5 ||
3852 chandef.width == NL80211_CHAN_WIDTH_10)
3853 return ret;
3854
3841 while (ret && chandef.width != NL80211_CHAN_WIDTH_20_NOHT) { 3855 while (ret && chandef.width != NL80211_CHAN_WIDTH_20_NOHT) {
3842 ifmgd->flags |= chandef_downgrade(&chandef); 3856 ifmgd->flags |= chandef_downgrade(&chandef);
3843 ret = ieee80211_vif_use_channel(sdata, &chandef, 3857 ret = ieee80211_vif_use_channel(sdata, &chandef,
@@ -4427,8 +4441,11 @@ void ieee80211_mgd_stop(struct ieee80211_sub_if_data *sdata)
4427 cancel_work_sync(&ifmgd->chswitch_work); 4441 cancel_work_sync(&ifmgd->chswitch_work);
4428 4442
4429 sdata_lock(sdata); 4443 sdata_lock(sdata);
4430 if (ifmgd->assoc_data) 4444 if (ifmgd->assoc_data) {
4445 struct cfg80211_bss *bss = ifmgd->assoc_data->bss;
4431 ieee80211_destroy_assoc_data(sdata, false); 4446 ieee80211_destroy_assoc_data(sdata, false);
4447 cfg80211_assoc_timeout(sdata->dev, bss);
4448 }
4432 if (ifmgd->auth_data) 4449 if (ifmgd->auth_data)
4433 ieee80211_destroy_auth_data(sdata, false); 4450 ieee80211_destroy_auth_data(sdata, false);
4434 del_timer_sync(&ifmgd->timer); 4451 del_timer_sync(&ifmgd->timer);
diff --git a/net/mac80211/rate.c b/net/mac80211/rate.c
index a02bef35b134..30d58d2d13e2 100644
--- a/net/mac80211/rate.c
+++ b/net/mac80211/rate.c
@@ -397,8 +397,14 @@ static void rate_idx_match_mask(struct ieee80211_tx_rate *rate,
397 return; 397 return;
398 398
399 /* if HT BSS, and we handle a data frame, also try HT rates */ 399 /* if HT BSS, and we handle a data frame, also try HT rates */
400 if (chan_width == NL80211_CHAN_WIDTH_20_NOHT) 400 switch (chan_width) {
401 case NL80211_CHAN_WIDTH_20_NOHT:
402 case NL80211_CHAN_WIDTH_5:
403 case NL80211_CHAN_WIDTH_10:
401 return; 404 return;
405 default:
406 break;
407 }
402 408
403 alt_rate.idx = 0; 409 alt_rate.idx = 0;
404 /* keep protection flags */ 410 /* keep protection flags */
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c
index 99b103921a4b..1b122a79b0d8 100644
--- a/net/mac80211/scan.c
+++ b/net/mac80211/scan.c
@@ -140,6 +140,15 @@ ieee80211_bss_info_update(struct ieee80211_local *local,
140 bss->valid_data |= IEEE80211_BSS_VALID_WMM; 140 bss->valid_data |= IEEE80211_BSS_VALID_WMM;
141 } 141 }
142 142
143 if (beacon) {
144 struct ieee80211_supported_band *sband =
145 local->hw.wiphy->bands[rx_status->band];
146 if (!(rx_status->flag & RX_FLAG_HT) &&
147 !(rx_status->flag & RX_FLAG_VHT))
148 bss->beacon_rate =
149 &sband->bitrates[rx_status->rate_idx];
150 }
151
143 return bss; 152 return bss;
144} 153}
145 154
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index b4297982d34a..aeb967a0aeed 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -149,6 +149,7 @@ static void cleanup_single_sta(struct sta_info *sta)
149 * directly by station destruction. 149 * directly by station destruction.
150 */ 150 */
151 for (i = 0; i < IEEE80211_NUM_TIDS; i++) { 151 for (i = 0; i < IEEE80211_NUM_TIDS; i++) {
152 kfree(sta->ampdu_mlme.tid_start_tx[i]);
152 tid_tx = rcu_dereference_raw(sta->ampdu_mlme.tid_tx[i]); 153 tid_tx = rcu_dereference_raw(sta->ampdu_mlme.tid_tx[i]);
153 if (!tid_tx) 154 if (!tid_tx)
154 continue; 155 continue;
@@ -346,6 +347,7 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata,
346 if (ieee80211_vif_is_mesh(&sdata->vif) && 347 if (ieee80211_vif_is_mesh(&sdata->vif) &&
347 !sdata->u.mesh.user_mpm) 348 !sdata->u.mesh.user_mpm)
348 init_timer(&sta->plink_timer); 349 init_timer(&sta->plink_timer);
350 sta->nonpeer_pm = NL80211_MESH_POWER_ACTIVE;
349#endif 351#endif
350 352
351 memcpy(sta->sta.addr, addr, ETH_ALEN); 353 memcpy(sta->sta.addr, addr, ETH_ALEN);
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
index bd12fc54266c..4208dbd5861f 100644
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
@@ -203,6 +203,7 @@ struct tid_ampdu_rx {
203 * driver requested to close until the work for it runs 203 * driver requested to close until the work for it runs
204 * @mtx: mutex to protect all TX data (except non-NULL assignments 204 * @mtx: mutex to protect all TX data (except non-NULL assignments
205 * to tid_tx[idx], which are protected by the sta spinlock) 205 * to tid_tx[idx], which are protected by the sta spinlock)
206 * tid_start_tx is also protected by sta->lock.
206 */ 207 */
207struct sta_ampdu_mlme { 208struct sta_ampdu_mlme {
208 struct mutex mtx; 209 struct mutex mtx;
diff --git a/net/mac80211/vht.c b/net/mac80211/vht.c
index 171344d4eb7c..97c289414e32 100644
--- a/net/mac80211/vht.c
+++ b/net/mac80211/vht.c
@@ -396,7 +396,7 @@ void ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata,
396 new_bw = ieee80211_sta_cur_vht_bw(sta); 396 new_bw = ieee80211_sta_cur_vht_bw(sta);
397 if (new_bw != sta->sta.bandwidth) { 397 if (new_bw != sta->sta.bandwidth) {
398 sta->sta.bandwidth = new_bw; 398 sta->sta.bandwidth = new_bw;
399 changed |= IEEE80211_RC_NSS_CHANGED; 399 changed |= IEEE80211_RC_BW_CHANGED;
400 } 400 }
401 401
402 change: 402 change: