aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/mlme.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/mac80211/mlme.c')
-rw-r--r--net/mac80211/mlme.c88
1 files changed, 67 insertions, 21 deletions
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index b3a3ce316656..245dce969b31 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -222,6 +222,7 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata,
222 switch (vht_oper->chan_width) { 222 switch (vht_oper->chan_width) {
223 case IEEE80211_VHT_CHANWIDTH_USE_HT: 223 case IEEE80211_VHT_CHANWIDTH_USE_HT:
224 vht_chandef.width = chandef->width; 224 vht_chandef.width = chandef->width;
225 vht_chandef.center_freq1 = chandef->center_freq1;
225 break; 226 break;
226 case IEEE80211_VHT_CHANWIDTH_80MHZ: 227 case IEEE80211_VHT_CHANWIDTH_80MHZ:
227 vht_chandef.width = NL80211_CHAN_WIDTH_80; 228 vht_chandef.width = NL80211_CHAN_WIDTH_80;
@@ -271,6 +272,28 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata,
271 ret = 0; 272 ret = 0;
272 273
273out: 274out:
275 /*
276 * When tracking the current AP, don't do any further checks if the
277 * new chandef is identical to the one we're currently using for the
278 * connection. This keeps us from playing ping-pong with regulatory,
279 * without it the following can happen (for example):
280 * - connect to an AP with 80 MHz, world regdom allows 80 MHz
281 * - AP advertises regdom US
282 * - CRDA loads regdom US with 80 MHz prohibited (old database)
283 * - the code below detects an unsupported channel, downgrades, and
284 * we disconnect from the AP in the caller
285 * - disconnect causes CRDA to reload world regdomain and the game
286 * starts anew.
287 * (see https://bugzilla.kernel.org/show_bug.cgi?id=70881)
288 *
289 * It seems possible that there are still scenarios with CSA or real
290 * bandwidth changes where a this could happen, but those cases are
291 * less common and wouldn't completely prevent using the AP.
292 */
293 if (tracking &&
294 cfg80211_chandef_identical(chandef, &sdata->vif.bss_conf.chandef))
295 return ret;
296
274 /* don't print the message below for VHT mismatch if VHT is disabled */ 297 /* don't print the message below for VHT mismatch if VHT is disabled */
275 if (ret & IEEE80211_STA_DISABLE_VHT) 298 if (ret & IEEE80211_STA_DISABLE_VHT)
276 vht_chandef = *chandef; 299 vht_chandef = *chandef;
@@ -330,6 +353,16 @@ static int ieee80211_config_bw(struct ieee80211_sub_if_data *sdata,
330 if (WARN_ON_ONCE(!sta)) 353 if (WARN_ON_ONCE(!sta))
331 return -EINVAL; 354 return -EINVAL;
332 355
356 /*
357 * if bss configuration changed store the new one -
358 * this may be applicable even if channel is identical
359 */
360 ht_opmode = le16_to_cpu(ht_oper->operation_mode);
361 if (sdata->vif.bss_conf.ht_operation_mode != ht_opmode) {
362 *changed |= BSS_CHANGED_HT;
363 sdata->vif.bss_conf.ht_operation_mode = ht_opmode;
364 }
365
333 chan = sdata->vif.bss_conf.chandef.chan; 366 chan = sdata->vif.bss_conf.chandef.chan;
334 sband = local->hw.wiphy->bands[chan->band]; 367 sband = local->hw.wiphy->bands[chan->band];
335 368
@@ -416,14 +449,6 @@ static int ieee80211_config_bw(struct ieee80211_sub_if_data *sdata,
416 IEEE80211_RC_BW_CHANGED); 449 IEEE80211_RC_BW_CHANGED);
417 } 450 }
418 451
419 ht_opmode = le16_to_cpu(ht_oper->operation_mode);
420
421 /* if bss configuration changed store the new one */
422 if (sdata->vif.bss_conf.ht_operation_mode != ht_opmode) {
423 *changed |= BSS_CHANGED_HT;
424 sdata->vif.bss_conf.ht_operation_mode = ht_opmode;
425 }
426
427 return 0; 452 return 0;
428} 453}
429 454
@@ -714,7 +739,7 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata)
714 } 739 }
715 740
716 /* if present, add any custom IEs that go before HT */ 741 /* if present, add any custom IEs that go before HT */
717 if (assoc_data->ie_len && assoc_data->ie) { 742 if (assoc_data->ie_len) {
718 static const u8 before_ht[] = { 743 static const u8 before_ht[] = {
719 WLAN_EID_SSID, 744 WLAN_EID_SSID,
720 WLAN_EID_SUPP_RATES, 745 WLAN_EID_SUPP_RATES,
@@ -748,7 +773,7 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata)
748 &assoc_data->ap_vht_cap); 773 &assoc_data->ap_vht_cap);
749 774
750 /* if present, add any custom non-vendor IEs that go after HT */ 775 /* if present, add any custom non-vendor IEs that go after HT */
751 if (assoc_data->ie_len && assoc_data->ie) { 776 if (assoc_data->ie_len) {
752 noffset = ieee80211_ie_split_vendor(assoc_data->ie, 777 noffset = ieee80211_ie_split_vendor(assoc_data->ie,
753 assoc_data->ie_len, 778 assoc_data->ie_len,
754 offset); 779 offset);
@@ -779,7 +804,7 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata)
779 } 804 }
780 805
781 /* add any remaining custom (i.e. vendor specific here) IEs */ 806 /* add any remaining custom (i.e. vendor specific here) IEs */
782 if (assoc_data->ie_len && assoc_data->ie) { 807 if (assoc_data->ie_len) {
783 noffset = assoc_data->ie_len; 808 noffset = assoc_data->ie_len;
784 pos = skb_put(skb, noffset - offset); 809 pos = skb_put(skb, noffset - offset);
785 memcpy(pos, assoc_data->ie + offset, noffset - offset); 810 memcpy(pos, assoc_data->ie + offset, noffset - offset);
@@ -886,8 +911,9 @@ static void ieee80211_chswitch_work(struct work_struct *work)
886 if (!ifmgd->associated) 911 if (!ifmgd->associated)
887 goto out; 912 goto out;
888 913
889 ret = ieee80211_vif_change_channel(sdata, &local->csa_chandef, 914 mutex_lock(&local->mtx);
890 &changed); 915 ret = ieee80211_vif_change_channel(sdata, &changed);
916 mutex_unlock(&local->mtx);
891 if (ret) { 917 if (ret) {
892 sdata_info(sdata, 918 sdata_info(sdata,
893 "vif channel switch failed, disconnecting\n"); 919 "vif channel switch failed, disconnecting\n");
@@ -897,7 +923,7 @@ static void ieee80211_chswitch_work(struct work_struct *work)
897 } 923 }
898 924
899 if (!local->use_chanctx) { 925 if (!local->use_chanctx) {
900 local->_oper_chandef = local->csa_chandef; 926 local->_oper_chandef = sdata->csa_chandef;
901 /* Call "hw_config" only if doing sw channel switch. 927 /* Call "hw_config" only if doing sw channel switch.
902 * Otherwise update the channel directly 928 * Otherwise update the channel directly
903 */ 929 */
@@ -908,7 +934,7 @@ static void ieee80211_chswitch_work(struct work_struct *work)
908 } 934 }
909 935
910 /* XXX: shouldn't really modify cfg80211-owned data! */ 936 /* XXX: shouldn't really modify cfg80211-owned data! */
911 ifmgd->associated->channel = local->csa_chandef.chan; 937 ifmgd->associated->channel = sdata->csa_chandef.chan;
912 938
913 /* XXX: wait for a beacon first? */ 939 /* XXX: wait for a beacon first? */
914 ieee80211_wake_queues_by_reason(&local->hw, 940 ieee80211_wake_queues_by_reason(&local->hw,
@@ -1035,7 +1061,7 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
1035 } 1061 }
1036 mutex_unlock(&local->chanctx_mtx); 1062 mutex_unlock(&local->chanctx_mtx);
1037 1063
1038 local->csa_chandef = csa_ie.chandef; 1064 sdata->csa_chandef = csa_ie.chandef;
1039 1065
1040 if (csa_ie.mode) 1066 if (csa_ie.mode)
1041 ieee80211_stop_queues_by_reason(&local->hw, 1067 ieee80211_stop_queues_by_reason(&local->hw,
@@ -1398,10 +1424,16 @@ void ieee80211_dfs_cac_timer_work(struct work_struct *work)
1398 struct ieee80211_sub_if_data *sdata = 1424 struct ieee80211_sub_if_data *sdata =
1399 container_of(delayed_work, struct ieee80211_sub_if_data, 1425 container_of(delayed_work, struct ieee80211_sub_if_data,
1400 dfs_cac_timer_work); 1426 dfs_cac_timer_work);
1427 struct cfg80211_chan_def chandef = sdata->vif.bss_conf.chandef;
1401 1428
1402 ieee80211_vif_release_channel(sdata); 1429 mutex_lock(&sdata->local->mtx);
1403 1430 if (sdata->wdev.cac_started) {
1404 cfg80211_cac_event(sdata->dev, NL80211_RADAR_CAC_FINISHED, GFP_KERNEL); 1431 ieee80211_vif_release_channel(sdata);
1432 cfg80211_cac_event(sdata->dev, &chandef,
1433 NL80211_RADAR_CAC_FINISHED,
1434 GFP_KERNEL);
1435 }
1436 mutex_unlock(&sdata->local->mtx);
1405} 1437}
1406 1438
1407/* MLME */ 1439/* MLME */
@@ -1695,7 +1727,7 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
1695 memset(ifmgd->bssid, 0, ETH_ALEN); 1727 memset(ifmgd->bssid, 0, ETH_ALEN);
1696 1728
1697 /* remove AP and TDLS peers */ 1729 /* remove AP and TDLS peers */
1698 sta_info_flush_defer(sdata); 1730 sta_info_flush(sdata);
1699 1731
1700 /* finally reset all BSS / config parameters */ 1732 /* finally reset all BSS / config parameters */
1701 changed |= ieee80211_reset_erp_info(sdata); 1733 changed |= ieee80211_reset_erp_info(sdata);
@@ -1744,7 +1776,11 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
1744 ifmgd->have_beacon = false; 1776 ifmgd->have_beacon = false;
1745 1777
1746 ifmgd->flags = 0; 1778 ifmgd->flags = 0;
1779 mutex_lock(&local->mtx);
1747 ieee80211_vif_release_channel(sdata); 1780 ieee80211_vif_release_channel(sdata);
1781 mutex_unlock(&local->mtx);
1782
1783 sdata->encrypt_headroom = IEEE80211_ENCRYPT_HEADROOM;
1748} 1784}
1749 1785
1750void ieee80211_sta_rx_notify(struct ieee80211_sub_if_data *sdata, 1786void ieee80211_sta_rx_notify(struct ieee80211_sub_if_data *sdata,
@@ -2065,7 +2101,9 @@ static void ieee80211_destroy_auth_data(struct ieee80211_sub_if_data *sdata,
2065 memset(sdata->u.mgd.bssid, 0, ETH_ALEN); 2101 memset(sdata->u.mgd.bssid, 0, ETH_ALEN);
2066 ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BSSID); 2102 ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BSSID);
2067 sdata->u.mgd.flags = 0; 2103 sdata->u.mgd.flags = 0;
2104 mutex_lock(&sdata->local->mtx);
2068 ieee80211_vif_release_channel(sdata); 2105 ieee80211_vif_release_channel(sdata);
2106 mutex_unlock(&sdata->local->mtx);
2069 } 2107 }
2070 2108
2071 cfg80211_put_bss(sdata->local->hw.wiphy, auth_data->bss); 2109 cfg80211_put_bss(sdata->local->hw.wiphy, auth_data->bss);
@@ -2314,7 +2352,9 @@ static void ieee80211_destroy_assoc_data(struct ieee80211_sub_if_data *sdata,
2314 memset(sdata->u.mgd.bssid, 0, ETH_ALEN); 2352 memset(sdata->u.mgd.bssid, 0, ETH_ALEN);
2315 ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BSSID); 2353 ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BSSID);
2316 sdata->u.mgd.flags = 0; 2354 sdata->u.mgd.flags = 0;
2355 mutex_lock(&sdata->local->mtx);
2317 ieee80211_vif_release_channel(sdata); 2356 ieee80211_vif_release_channel(sdata);
2357 mutex_unlock(&sdata->local->mtx);
2318 } 2358 }
2319 2359
2320 kfree(assoc_data); 2360 kfree(assoc_data);
@@ -3665,6 +3705,7 @@ static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata,
3665 /* will change later if needed */ 3705 /* will change later if needed */
3666 sdata->smps_mode = IEEE80211_SMPS_OFF; 3706 sdata->smps_mode = IEEE80211_SMPS_OFF;
3667 3707
3708 mutex_lock(&local->mtx);
3668 /* 3709 /*
3669 * If this fails (possibly due to channel context sharing 3710 * If this fails (possibly due to channel context sharing
3670 * on incompatible channels, e.g. 80+80 and 160 sharing the 3711 * on incompatible channels, e.g. 80+80 and 160 sharing the
@@ -3676,13 +3717,15 @@ static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata,
3676 /* don't downgrade for 5 and 10 MHz channels, though. */ 3717 /* don't downgrade for 5 and 10 MHz channels, though. */
3677 if (chandef.width == NL80211_CHAN_WIDTH_5 || 3718 if (chandef.width == NL80211_CHAN_WIDTH_5 ||
3678 chandef.width == NL80211_CHAN_WIDTH_10) 3719 chandef.width == NL80211_CHAN_WIDTH_10)
3679 return ret; 3720 goto out;
3680 3721
3681 while (ret && chandef.width != NL80211_CHAN_WIDTH_20_NOHT) { 3722 while (ret && chandef.width != NL80211_CHAN_WIDTH_20_NOHT) {
3682 ifmgd->flags |= ieee80211_chandef_downgrade(&chandef); 3723 ifmgd->flags |= ieee80211_chandef_downgrade(&chandef);
3683 ret = ieee80211_vif_use_channel(sdata, &chandef, 3724 ret = ieee80211_vif_use_channel(sdata, &chandef,
3684 IEEE80211_CHANCTX_SHARED); 3725 IEEE80211_CHANCTX_SHARED);
3685 } 3726 }
3727 out:
3728 mutex_unlock(&local->mtx);
3686 return ret; 3729 return ret;
3687} 3730}
3688 3731
@@ -3733,6 +3776,7 @@ static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata,
3733 chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); 3776 chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
3734 if (WARN_ON(!chanctx_conf)) { 3777 if (WARN_ON(!chanctx_conf)) {
3735 rcu_read_unlock(); 3778 rcu_read_unlock();
3779 sta_info_free(local, new_sta);
3736 return -EINVAL; 3780 return -EINVAL;
3737 } 3781 }
3738 rate_flags = ieee80211_chandef_rate_flags(&chanctx_conf->def); 3782 rate_flags = ieee80211_chandef_rate_flags(&chanctx_conf->def);
@@ -4191,6 +4235,8 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
4191 4235
4192 sdata->control_port_protocol = req->crypto.control_port_ethertype; 4236 sdata->control_port_protocol = req->crypto.control_port_ethertype;
4193 sdata->control_port_no_encrypt = req->crypto.control_port_no_encrypt; 4237 sdata->control_port_no_encrypt = req->crypto.control_port_no_encrypt;
4238 sdata->encrypt_headroom = ieee80211_cs_headroom(local, &req->crypto,
4239 sdata->vif.type);
4194 4240
4195 /* kick off associate process */ 4241 /* kick off associate process */
4196 4242