diff options
author | John W. Linville <linville@tuxdriver.com> | 2013-06-28 13:18:21 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2013-06-28 13:18:21 -0400 |
commit | 57ed5cd695d7373b8ae0ae9f10fe945e774d58f0 (patch) | |
tree | 7ee6244ea7c0be81a541d4e57783f83c4dfd7d66 /net/mac80211 | |
parent | 5e6700b3bf98fe98d630bf9c939ad4c85ce95592 (diff) | |
parent | 0f817ed52d07873cd39c9d3f6d87fae962dc742f (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.c | 14 | ||||
-rw-r--r-- | net/mac80211/ht.c | 4 | ||||
-rw-r--r-- | net/mac80211/ibss.c | 65 | ||||
-rw-r--r-- | net/mac80211/ieee80211_i.h | 6 | ||||
-rw-r--r-- | net/mac80211/mesh.c | 57 | ||||
-rw-r--r-- | net/mac80211/mesh.h | 2 | ||||
-rw-r--r-- | net/mac80211/mesh_plink.c | 8 | ||||
-rw-r--r-- | net/mac80211/mlme.c | 35 | ||||
-rw-r--r-- | net/mac80211/rate.c | 8 | ||||
-rw-r--r-- | net/mac80211/scan.c | 9 | ||||
-rw-r--r-- | net/mac80211/sta_info.c | 2 | ||||
-rw-r--r-- | net/mac80211/sta_info.h | 1 | ||||
-rw-r--r-- | net/mac80211/vht.c | 2 |
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 | ||
301 | static struct sta_info *ieee80211_ibss_finish_sta(struct sta_info *sta, | 303 | static 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 | ||
334 | static struct sta_info * | 328 | static struct sta_info * |
335 | ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata, | 329 | ieee80211_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 | ||
391 | static void ieee80211_rx_mgmt_deauth_ibss(struct ieee80211_sub_if_data *sdata, | 384 | static 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(¶ms->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 | ||
171 | int mesh_rmc_init(struct ieee80211_sub_if_data *sdata) | 168 | int 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) | |||
719 | void ieee80211_mbss_info_change_notify(struct ieee80211_sub_if_data *sdata, | 718 | void 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 | ||
732 | int ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata) | 735 | int 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 | ||
975 | static 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 | |||
968 | void ieee80211_mesh_work(struct ieee80211_sub_if_data *sdata) | 997 | void 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); | ||
998 | out: | 1029 | out: |
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 | */ |
62 | enum mesh_deferred_task_flags { | 63 | enum 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 | */ |
207 | struct sta_ampdu_mlme { | 208 | struct 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: |