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.c735
1 files changed, 565 insertions, 170 deletions
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 1b7eed252fe9..7753a9ca98a6 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -178,20 +178,32 @@ static u32 ieee80211_config_ht_tx(struct ieee80211_sub_if_data *sdata,
178{ 178{
179 struct ieee80211_local *local = sdata->local; 179 struct ieee80211_local *local = sdata->local;
180 struct ieee80211_supported_band *sband; 180 struct ieee80211_supported_band *sband;
181 struct ieee80211_chanctx_conf *chanctx_conf;
182 struct ieee80211_channel *chan;
181 struct sta_info *sta; 183 struct sta_info *sta;
182 u32 changed = 0; 184 u32 changed = 0;
183 u16 ht_opmode; 185 u16 ht_opmode;
184 bool disable_40 = false; 186 bool disable_40 = false;
185 187
186 sband = local->hw.wiphy->bands[local->oper_channel->band]; 188 rcu_read_lock();
189 chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
190 if (WARN_ON(!chanctx_conf)) {
191 rcu_read_unlock();
192 return 0;
193 }
194 chan = chanctx_conf->def.chan;
195 rcu_read_unlock();
196 sband = local->hw.wiphy->bands[chan->band];
187 197
188 switch (sdata->vif.bss_conf.channel_type) { 198 switch (sdata->vif.bss_conf.chandef.width) {
189 case NL80211_CHAN_HT40PLUS: 199 case NL80211_CHAN_WIDTH_40:
190 if (local->oper_channel->flags & IEEE80211_CHAN_NO_HT40PLUS) 200 if (sdata->vif.bss_conf.chandef.chan->center_freq >
201 sdata->vif.bss_conf.chandef.center_freq1 &&
202 chan->flags & IEEE80211_CHAN_NO_HT40PLUS)
191 disable_40 = true; 203 disable_40 = true;
192 break; 204 if (sdata->vif.bss_conf.chandef.chan->center_freq <
193 case NL80211_CHAN_HT40MINUS: 205 sdata->vif.bss_conf.chandef.center_freq1 &&
194 if (local->oper_channel->flags & IEEE80211_CHAN_NO_HT40MINUS) 206 chan->flags & IEEE80211_CHAN_NO_HT40MINUS)
195 disable_40 = true; 207 disable_40 = true;
196 break; 208 break;
197 default: 209 default:
@@ -342,8 +354,18 @@ static void ieee80211_add_vht_ie(struct ieee80211_sub_if_data *sdata,
342 /* determine capability flags */ 354 /* determine capability flags */
343 cap = vht_cap.cap; 355 cap = vht_cap.cap;
344 356
357 if (sdata->u.mgd.flags & IEEE80211_STA_DISABLE_80P80MHZ) {
358 cap &= ~IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ;
359 cap |= IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
360 }
361
362 if (sdata->u.mgd.flags & IEEE80211_STA_DISABLE_160MHZ) {
363 cap &= ~IEEE80211_VHT_CAP_SHORT_GI_160;
364 cap &= ~IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
365 }
366
345 /* reserve and fill IE */ 367 /* reserve and fill IE */
346 pos = skb_put(skb, sizeof(struct ieee80211_vht_capabilities) + 2); 368 pos = skb_put(skb, sizeof(struct ieee80211_vht_cap) + 2);
347 ieee80211_ie_build_vht_cap(pos, &vht_cap, cap); 369 ieee80211_ie_build_vht_cap(pos, &vht_cap, cap);
348} 370}
349 371
@@ -359,11 +381,21 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata)
359 int i, count, rates_len, supp_rates_len; 381 int i, count, rates_len, supp_rates_len;
360 u16 capab; 382 u16 capab;
361 struct ieee80211_supported_band *sband; 383 struct ieee80211_supported_band *sband;
384 struct ieee80211_chanctx_conf *chanctx_conf;
385 struct ieee80211_channel *chan;
362 u32 rates = 0; 386 u32 rates = 0;
363 387
364 lockdep_assert_held(&ifmgd->mtx); 388 lockdep_assert_held(&ifmgd->mtx);
365 389
366 sband = local->hw.wiphy->bands[local->oper_channel->band]; 390 rcu_read_lock();
391 chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
392 if (WARN_ON(!chanctx_conf)) {
393 rcu_read_unlock();
394 return;
395 }
396 chan = chanctx_conf->def.chan;
397 rcu_read_unlock();
398 sband = local->hw.wiphy->bands[chan->band];
367 399
368 if (assoc_data->supp_rates_len) { 400 if (assoc_data->supp_rates_len) {
369 /* 401 /*
@@ -392,7 +424,7 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata)
392 4 + /* power capability */ 424 4 + /* power capability */
393 2 + 2 * sband->n_channels + /* supported channels */ 425 2 + 2 * sband->n_channels + /* supported channels */
394 2 + sizeof(struct ieee80211_ht_cap) + /* HT */ 426 2 + sizeof(struct ieee80211_ht_cap) + /* HT */
395 2 + sizeof(struct ieee80211_vht_capabilities) + /* VHT */ 427 2 + sizeof(struct ieee80211_vht_cap) + /* VHT */
396 assoc_data->ie_len + /* extra IEs */ 428 assoc_data->ie_len + /* extra IEs */
397 9, /* WMM */ 429 9, /* WMM */
398 GFP_KERNEL); 430 GFP_KERNEL);
@@ -485,7 +517,7 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata)
485 *pos++ = WLAN_EID_PWR_CAPABILITY; 517 *pos++ = WLAN_EID_PWR_CAPABILITY;
486 *pos++ = 2; 518 *pos++ = 2;
487 *pos++ = 0; /* min tx power */ 519 *pos++ = 0; /* min tx power */
488 *pos++ = local->oper_channel->max_power; /* max tx power */ 520 *pos++ = chan->max_power; /* max tx power */
489 521
490 /* 2. supported channels */ 522 /* 2. supported channels */
491 /* TODO: get this in reg domain format */ 523 /* TODO: get this in reg domain format */
@@ -521,9 +553,13 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata)
521 offset = noffset; 553 offset = noffset;
522 } 554 }
523 555
524 if (!(ifmgd->flags & IEEE80211_STA_DISABLE_11N)) 556 if (WARN_ON_ONCE((ifmgd->flags & IEEE80211_STA_DISABLE_HT) &&
557 !(ifmgd->flags & IEEE80211_STA_DISABLE_VHT)))
558 ifmgd->flags |= IEEE80211_STA_DISABLE_VHT;
559
560 if (!(ifmgd->flags & IEEE80211_STA_DISABLE_HT))
525 ieee80211_add_ht_ie(sdata, skb, assoc_data->ap_ht_param, 561 ieee80211_add_ht_ie(sdata, skb, assoc_data->ap_ht_param,
526 sband, local->oper_channel, ifmgd->ap_smps); 562 sband, chan, sdata->smps_mode);
527 563
528 if (!(ifmgd->flags & IEEE80211_STA_DISABLE_VHT)) 564 if (!(ifmgd->flags & IEEE80211_STA_DISABLE_VHT))
529 ieee80211_add_vht_ie(sdata, skb, sband); 565 ieee80211_add_vht_ie(sdata, skb, sband);
@@ -657,18 +693,18 @@ static void ieee80211_chswitch_work(struct work_struct *work)
657 if (!ifmgd->associated) 693 if (!ifmgd->associated)
658 goto out; 694 goto out;
659 695
660 sdata->local->oper_channel = sdata->local->csa_channel; 696 sdata->local->_oper_channel = sdata->local->csa_channel;
661 if (!sdata->local->ops->channel_switch) { 697 if (!sdata->local->ops->channel_switch) {
662 /* call "hw_config" only if doing sw channel switch */ 698 /* call "hw_config" only if doing sw channel switch */
663 ieee80211_hw_config(sdata->local, 699 ieee80211_hw_config(sdata->local,
664 IEEE80211_CONF_CHANGE_CHANNEL); 700 IEEE80211_CONF_CHANGE_CHANNEL);
665 } else { 701 } else {
666 /* update the device channel directly */ 702 /* update the device channel directly */
667 sdata->local->hw.conf.channel = sdata->local->oper_channel; 703 sdata->local->hw.conf.channel = sdata->local->_oper_channel;
668 } 704 }
669 705
670 /* XXX: shouldn't really modify cfg80211-owned data! */ 706 /* XXX: shouldn't really modify cfg80211-owned data! */
671 ifmgd->associated->channel = sdata->local->oper_channel; 707 ifmgd->associated->channel = sdata->local->_oper_channel;
672 708
673 /* XXX: wait for a beacon first? */ 709 /* XXX: wait for a beacon first? */
674 ieee80211_wake_queues_by_reason(&sdata->local->hw, 710 ieee80211_wake_queues_by_reason(&sdata->local->hw,
@@ -680,11 +716,8 @@ static void ieee80211_chswitch_work(struct work_struct *work)
680 716
681void ieee80211_chswitch_done(struct ieee80211_vif *vif, bool success) 717void ieee80211_chswitch_done(struct ieee80211_vif *vif, bool success)
682{ 718{
683 struct ieee80211_sub_if_data *sdata; 719 struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
684 struct ieee80211_if_managed *ifmgd; 720 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
685
686 sdata = vif_to_sdata(vif);
687 ifmgd = &sdata->u.mgd;
688 721
689 trace_api_chswitch_done(sdata, success); 722 trace_api_chswitch_done(sdata, success);
690 if (!success) { 723 if (!success) {
@@ -723,6 +756,7 @@ void ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
723 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; 756 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
724 int new_freq = ieee80211_channel_to_frequency(sw_elem->new_ch_num, 757 int new_freq = ieee80211_channel_to_frequency(sw_elem->new_ch_num,
725 cbss->channel->band); 758 cbss->channel->band);
759 struct ieee80211_chanctx *chanctx;
726 760
727 ASSERT_MGD_MTX(ifmgd); 761 ASSERT_MGD_MTX(ifmgd);
728 762
@@ -748,10 +782,35 @@ void ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
748 return; 782 return;
749 } 783 }
750 784
751 sdata->local->csa_channel = new_ch;
752
753 ifmgd->flags |= IEEE80211_STA_CSA_RECEIVED; 785 ifmgd->flags |= IEEE80211_STA_CSA_RECEIVED;
754 786
787 if (sdata->local->use_chanctx) {
788 sdata_info(sdata,
789 "not handling channel switch with channel contexts\n");
790 ieee80211_queue_work(&sdata->local->hw,
791 &ifmgd->csa_connection_drop_work);
792 return;
793 }
794
795 mutex_lock(&sdata->local->chanctx_mtx);
796 if (WARN_ON(!rcu_access_pointer(sdata->vif.chanctx_conf))) {
797 mutex_unlock(&sdata->local->chanctx_mtx);
798 return;
799 }
800 chanctx = container_of(rcu_access_pointer(sdata->vif.chanctx_conf),
801 struct ieee80211_chanctx, conf);
802 if (chanctx->refcount > 1) {
803 sdata_info(sdata,
804 "channel switch with multiple interfaces on the same channel, disconnecting\n");
805 ieee80211_queue_work(&sdata->local->hw,
806 &ifmgd->csa_connection_drop_work);
807 mutex_unlock(&sdata->local->chanctx_mtx);
808 return;
809 }
810 mutex_unlock(&sdata->local->chanctx_mtx);
811
812 sdata->local->csa_channel = new_ch;
813
755 if (sw_elem->mode) 814 if (sw_elem->mode)
756 ieee80211_stop_queues_by_reason(&sdata->local->hw, 815 ieee80211_stop_queues_by_reason(&sdata->local->hw,
757 IEEE80211_QUEUE_STOP_REASON_CSA); 816 IEEE80211_QUEUE_STOP_REASON_CSA);
@@ -778,10 +837,10 @@ void ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
778 cbss->beacon_interval)); 837 cbss->beacon_interval));
779} 838}
780 839
781static void ieee80211_handle_pwr_constr(struct ieee80211_sub_if_data *sdata, 840static u32 ieee80211_handle_pwr_constr(struct ieee80211_sub_if_data *sdata,
782 struct ieee80211_channel *channel, 841 struct ieee80211_channel *channel,
783 const u8 *country_ie, u8 country_ie_len, 842 const u8 *country_ie, u8 country_ie_len,
784 const u8 *pwr_constr_elem) 843 const u8 *pwr_constr_elem)
785{ 844{
786 struct ieee80211_country_ie_triplet *triplet; 845 struct ieee80211_country_ie_triplet *triplet;
787 int chan = ieee80211_frequency_to_channel(channel->center_freq); 846 int chan = ieee80211_frequency_to_channel(channel->center_freq);
@@ -790,7 +849,7 @@ static void ieee80211_handle_pwr_constr(struct ieee80211_sub_if_data *sdata,
790 849
791 /* Invalid IE */ 850 /* Invalid IE */
792 if (country_ie_len % 2 || country_ie_len < IEEE80211_COUNTRY_IE_MIN_LEN) 851 if (country_ie_len % 2 || country_ie_len < IEEE80211_COUNTRY_IE_MIN_LEN)
793 return; 852 return 0;
794 853
795 triplet = (void *)(country_ie + 3); 854 triplet = (void *)(country_ie + 3);
796 country_ie_len -= 3; 855 country_ie_len -= 3;
@@ -831,19 +890,21 @@ static void ieee80211_handle_pwr_constr(struct ieee80211_sub_if_data *sdata,
831 } 890 }
832 891
833 if (!have_chan_pwr) 892 if (!have_chan_pwr)
834 return; 893 return 0;
835 894
836 new_ap_level = max_t(int, 0, chan_pwr - *pwr_constr_elem); 895 new_ap_level = max_t(int, 0, chan_pwr - *pwr_constr_elem);
837 896
838 if (sdata->local->ap_power_level == new_ap_level) 897 if (sdata->ap_power_level == new_ap_level)
839 return; 898 return 0;
840 899
841 sdata_info(sdata, 900 sdata_info(sdata,
842 "Limiting TX power to %d (%d - %d) dBm as advertised by %pM\n", 901 "Limiting TX power to %d (%d - %d) dBm as advertised by %pM\n",
843 new_ap_level, chan_pwr, *pwr_constr_elem, 902 new_ap_level, chan_pwr, *pwr_constr_elem,
844 sdata->u.mgd.bssid); 903 sdata->u.mgd.bssid);
845 sdata->local->ap_power_level = new_ap_level; 904 sdata->ap_power_level = new_ap_level;
846 ieee80211_hw_config(sdata->local, 0); 905 if (__ieee80211_recalc_txpower(sdata))
906 return BSS_CHANGED_TXPOWER;
907 return 0;
847} 908}
848 909
849void ieee80211_enable_dyn_ps(struct ieee80211_vif *vif) 910void ieee80211_enable_dyn_ps(struct ieee80211_vif *vif)
@@ -1280,7 +1341,7 @@ static u32 ieee80211_handle_bss_capability(struct ieee80211_sub_if_data *sdata,
1280 } 1341 }
1281 1342
1282 use_short_slot = !!(capab & WLAN_CAPABILITY_SHORT_SLOT_TIME); 1343 use_short_slot = !!(capab & WLAN_CAPABILITY_SHORT_SLOT_TIME);
1283 if (sdata->local->oper_channel->band == IEEE80211_BAND_5GHZ) 1344 if (ieee80211_get_sdata_band(sdata) == IEEE80211_BAND_5GHZ)
1284 use_short_slot = true; 1345 use_short_slot = true;
1285 1346
1286 if (use_protection != bss_conf->use_cts_prot) { 1347 if (use_protection != bss_conf->use_cts_prot) {
@@ -1321,6 +1382,29 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata,
1321 1382
1322 sdata->u.mgd.flags |= IEEE80211_STA_RESET_SIGNAL_AVE; 1383 sdata->u.mgd.flags |= IEEE80211_STA_RESET_SIGNAL_AVE;
1323 1384
1385 if (sdata->vif.p2p) {
1386 const struct cfg80211_bss_ies *ies;
1387
1388 rcu_read_lock();
1389 ies = rcu_dereference(cbss->ies);
1390 if (ies) {
1391 u8 noa[2];
1392 int ret;
1393
1394 ret = cfg80211_get_p2p_attr(
1395 ies->data, ies->len,
1396 IEEE80211_P2P_ATTR_ABSENCE_NOTICE,
1397 noa, sizeof(noa));
1398 if (ret >= 2) {
1399 bss_conf->p2p_oppps = noa[1] & 0x80;
1400 bss_conf->p2p_ctwindow = noa[1] & 0x7f;
1401 bss_info_changed |= BSS_CHANGED_P2P_PS;
1402 sdata->u.mgd.p2p_noa_index = noa[0];
1403 }
1404 }
1405 rcu_read_unlock();
1406 }
1407
1324 /* just to be sure */ 1408 /* just to be sure */
1325 ieee80211_stop_poll(sdata); 1409 ieee80211_stop_poll(sdata);
1326 1410
@@ -1350,7 +1434,7 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata,
1350 ieee80211_recalc_ps(local, -1); 1434 ieee80211_recalc_ps(local, -1);
1351 mutex_unlock(&local->iflist_mtx); 1435 mutex_unlock(&local->iflist_mtx);
1352 1436
1353 ieee80211_recalc_smps(local); 1437 ieee80211_recalc_smps(sdata);
1354 ieee80211_recalc_ps_vif(sdata); 1438 ieee80211_recalc_ps_vif(sdata);
1355 1439
1356 netif_tx_start_all_queues(sdata->dev); 1440 netif_tx_start_all_queues(sdata->dev);
@@ -1443,11 +1527,14 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
1443 changed |= BSS_CHANGED_ASSOC; 1527 changed |= BSS_CHANGED_ASSOC;
1444 sdata->vif.bss_conf.assoc = false; 1528 sdata->vif.bss_conf.assoc = false;
1445 1529
1530 sdata->vif.bss_conf.p2p_ctwindow = 0;
1531 sdata->vif.bss_conf.p2p_oppps = false;
1532
1446 /* on the next assoc, re-program HT parameters */ 1533 /* on the next assoc, re-program HT parameters */
1447 memset(&ifmgd->ht_capa, 0, sizeof(ifmgd->ht_capa)); 1534 memset(&ifmgd->ht_capa, 0, sizeof(ifmgd->ht_capa));
1448 memset(&ifmgd->ht_capa_mask, 0, sizeof(ifmgd->ht_capa_mask)); 1535 memset(&ifmgd->ht_capa_mask, 0, sizeof(ifmgd->ht_capa_mask));
1449 1536
1450 local->ap_power_level = 0; 1537 sdata->ap_power_level = IEEE80211_UNSET_POWER_LEVEL;
1451 1538
1452 del_timer_sync(&local->dynamic_ps_timer); 1539 del_timer_sync(&local->dynamic_ps_timer);
1453 cancel_work_sync(&local->dynamic_ps_enable_work); 1540 cancel_work_sync(&local->dynamic_ps_enable_work);
@@ -1465,10 +1552,6 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
1465 changed |= BSS_CHANGED_BSSID | BSS_CHANGED_HT; 1552 changed |= BSS_CHANGED_BSSID | BSS_CHANGED_HT;
1466 ieee80211_bss_info_change_notify(sdata, changed); 1553 ieee80211_bss_info_change_notify(sdata, changed);
1467 1554
1468 /* channel(_type) changes are handled by ieee80211_hw_config */
1469 WARN_ON(!ieee80211_set_channel_type(local, sdata, NL80211_CHAN_NO_HT));
1470 ieee80211_hw_config(local, 0);
1471
1472 /* disassociated - set to defaults now */ 1555 /* disassociated - set to defaults now */
1473 ieee80211_set_wmm_default(sdata, false); 1556 ieee80211_set_wmm_default(sdata, false);
1474 1557
@@ -1478,6 +1561,9 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
1478 del_timer_sync(&sdata->u.mgd.chswitch_timer); 1561 del_timer_sync(&sdata->u.mgd.chswitch_timer);
1479 1562
1480 sdata->u.mgd.timers_running = 0; 1563 sdata->u.mgd.timers_running = 0;
1564
1565 ifmgd->flags = 0;
1566 ieee80211_vif_release_channel(sdata);
1481} 1567}
1482 1568
1483void ieee80211_sta_rx_notify(struct ieee80211_sub_if_data *sdata, 1569void ieee80211_sta_rx_notify(struct ieee80211_sub_if_data *sdata,
@@ -1581,6 +1667,7 @@ static void ieee80211_mgd_probe_ap_send(struct ieee80211_sub_if_data *sdata)
1581 } else { 1667 } else {
1582 int ssid_len; 1668 int ssid_len;
1583 1669
1670 rcu_read_lock();
1584 ssid = ieee80211_bss_get_ie(ifmgd->associated, WLAN_EID_SSID); 1671 ssid = ieee80211_bss_get_ie(ifmgd->associated, WLAN_EID_SSID);
1585 if (WARN_ON_ONCE(ssid == NULL)) 1672 if (WARN_ON_ONCE(ssid == NULL))
1586 ssid_len = 0; 1673 ssid_len = 0;
@@ -1589,7 +1676,8 @@ static void ieee80211_mgd_probe_ap_send(struct ieee80211_sub_if_data *sdata)
1589 1676
1590 ieee80211_send_probe_req(sdata, dst, ssid + 2, ssid_len, NULL, 1677 ieee80211_send_probe_req(sdata, dst, ssid + 2, ssid_len, NULL,
1591 0, (u32) -1, true, false, 1678 0, (u32) -1, true, false,
1592 ifmgd->associated->channel); 1679 ifmgd->associated->channel, false);
1680 rcu_read_unlock();
1593 } 1681 }
1594 1682
1595 ifmgd->probe_timeout = jiffies + msecs_to_jiffies(probe_wait_ms); 1683 ifmgd->probe_timeout = jiffies + msecs_to_jiffies(probe_wait_ms);
@@ -1685,6 +1773,7 @@ struct sk_buff *ieee80211_ap_probereq_get(struct ieee80211_hw *hw,
1685 else 1773 else
1686 return NULL; 1774 return NULL;
1687 1775
1776 rcu_read_lock();
1688 ssid = ieee80211_bss_get_ie(cbss, WLAN_EID_SSID); 1777 ssid = ieee80211_bss_get_ie(cbss, WLAN_EID_SSID);
1689 if (WARN_ON_ONCE(ssid == NULL)) 1778 if (WARN_ON_ONCE(ssid == NULL))
1690 ssid_len = 0; 1779 ssid_len = 0;
@@ -1692,10 +1781,10 @@ struct sk_buff *ieee80211_ap_probereq_get(struct ieee80211_hw *hw,
1692 ssid_len = ssid[1]; 1781 ssid_len = ssid[1];
1693 1782
1694 skb = ieee80211_build_probe_req(sdata, cbss->bssid, 1783 skb = ieee80211_build_probe_req(sdata, cbss->bssid,
1695 (u32) -1, 1784 (u32) -1, cbss->channel,
1696 sdata->local->oper_channel,
1697 ssid + 2, ssid_len, 1785 ssid + 2, ssid_len,
1698 NULL, 0, true); 1786 NULL, 0, true);
1787 rcu_read_unlock();
1699 1788
1700 return skb; 1789 return skb;
1701} 1790}
@@ -1804,6 +1893,8 @@ static void ieee80211_destroy_auth_data(struct ieee80211_sub_if_data *sdata,
1804 1893
1805 memset(sdata->u.mgd.bssid, 0, ETH_ALEN); 1894 memset(sdata->u.mgd.bssid, 0, ETH_ALEN);
1806 ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BSSID); 1895 ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BSSID);
1896 sdata->u.mgd.flags = 0;
1897 ieee80211_vif_release_channel(sdata);
1807 } 1898 }
1808 1899
1809 cfg80211_put_bss(auth_data->bss); 1900 cfg80211_put_bss(auth_data->bss);
@@ -1824,7 +1915,7 @@ static void ieee80211_auth_challenge(struct ieee80211_sub_if_data *sdata,
1824 return; 1915 return;
1825 auth_data->expected_transaction = 4; 1916 auth_data->expected_transaction = 4;
1826 drv_mgd_prepare_tx(sdata->local, sdata); 1917 drv_mgd_prepare_tx(sdata->local, sdata);
1827 ieee80211_send_auth(sdata, 3, auth_data->algorithm, 1918 ieee80211_send_auth(sdata, 3, auth_data->algorithm, 0,
1828 elems.challenge - 2, elems.challenge_len + 2, 1919 elems.challenge - 2, elems.challenge_len + 2,
1829 auth_data->bss->bssid, auth_data->bss->bssid, 1920 auth_data->bss->bssid, auth_data->bss->bssid,
1830 auth_data->key, auth_data->key_len, 1921 auth_data->key, auth_data->key_len,
@@ -1858,8 +1949,13 @@ ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata,
1858 status_code = le16_to_cpu(mgmt->u.auth.status_code); 1949 status_code = le16_to_cpu(mgmt->u.auth.status_code);
1859 1950
1860 if (auth_alg != ifmgd->auth_data->algorithm || 1951 if (auth_alg != ifmgd->auth_data->algorithm ||
1861 auth_transaction != ifmgd->auth_data->expected_transaction) 1952 auth_transaction != ifmgd->auth_data->expected_transaction) {
1953 sdata_info(sdata, "%pM unexpected authentication state: alg %d (expected %d) transact %d (expected %d)\n",
1954 mgmt->sa, auth_alg, ifmgd->auth_data->algorithm,
1955 auth_transaction,
1956 ifmgd->auth_data->expected_transaction);
1862 return RX_MGMT_NONE; 1957 return RX_MGMT_NONE;
1958 }
1863 1959
1864 if (status_code != WLAN_STATUS_SUCCESS) { 1960 if (status_code != WLAN_STATUS_SUCCESS) {
1865 sdata_info(sdata, "%pM denied authentication (status %d)\n", 1961 sdata_info(sdata, "%pM denied authentication (status %d)\n",
@@ -1872,6 +1968,7 @@ ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata,
1872 case WLAN_AUTH_OPEN: 1968 case WLAN_AUTH_OPEN:
1873 case WLAN_AUTH_LEAP: 1969 case WLAN_AUTH_LEAP:
1874 case WLAN_AUTH_FT: 1970 case WLAN_AUTH_FT:
1971 case WLAN_AUTH_SAE:
1875 break; 1972 break;
1876 case WLAN_AUTH_SHARED_KEY: 1973 case WLAN_AUTH_SHARED_KEY:
1877 if (ifmgd->auth_data->expected_transaction != 4) { 1974 if (ifmgd->auth_data->expected_transaction != 4) {
@@ -1891,6 +1988,15 @@ ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata,
1891 ifmgd->auth_data->timeout = jiffies + IEEE80211_AUTH_WAIT_ASSOC; 1988 ifmgd->auth_data->timeout = jiffies + IEEE80211_AUTH_WAIT_ASSOC;
1892 run_again(ifmgd, ifmgd->auth_data->timeout); 1989 run_again(ifmgd, ifmgd->auth_data->timeout);
1893 1990
1991 if (ifmgd->auth_data->algorithm == WLAN_AUTH_SAE &&
1992 ifmgd->auth_data->expected_transaction != 2) {
1993 /*
1994 * Report auth frame to user space for processing since another
1995 * round of Authentication frames is still needed.
1996 */
1997 return RX_MGMT_CFG80211_RX_AUTH;
1998 }
1999
1894 /* move station state to auth */ 2000 /* move station state to auth */
1895 mutex_lock(&sdata->local->sta_mtx); 2001 mutex_lock(&sdata->local->sta_mtx);
1896 sta = sta_info_get(sdata, bssid); 2002 sta = sta_info_get(sdata, bssid);
@@ -2030,6 +2136,8 @@ static void ieee80211_destroy_assoc_data(struct ieee80211_sub_if_data *sdata,
2030 2136
2031 memset(sdata->u.mgd.bssid, 0, ETH_ALEN); 2137 memset(sdata->u.mgd.bssid, 0, ETH_ALEN);
2032 ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BSSID); 2138 ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BSSID);
2139 sdata->u.mgd.flags = 0;
2140 ieee80211_vif_release_channel(sdata);
2033 } 2141 }
2034 2142
2035 kfree(assoc_data); 2143 kfree(assoc_data);
@@ -2091,15 +2199,20 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata,
2091 return false; 2199 return false;
2092 } 2200 }
2093 2201
2094 sband = local->hw.wiphy->bands[local->oper_channel->band]; 2202 sband = local->hw.wiphy->bands[ieee80211_get_sdata_band(sdata)];
2095 2203
2096 if (elems.ht_cap_elem && !(ifmgd->flags & IEEE80211_STA_DISABLE_11N)) 2204 if (elems.ht_cap_elem && !(ifmgd->flags & IEEE80211_STA_DISABLE_HT))
2097 ieee80211_ht_cap_ie_to_sta_ht_cap(sdata, sband, 2205 ieee80211_ht_cap_ie_to_sta_ht_cap(sdata, sband,
2098 elems.ht_cap_elem, &sta->sta.ht_cap); 2206 elems.ht_cap_elem, &sta->sta.ht_cap);
2099 2207
2100 sta->supports_40mhz = 2208 sta->supports_40mhz =
2101 sta->sta.ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40; 2209 sta->sta.ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40;
2102 2210
2211 if (elems.vht_cap_elem && !(ifmgd->flags & IEEE80211_STA_DISABLE_VHT))
2212 ieee80211_vht_cap_ie_to_sta_vht_cap(sdata, sband,
2213 elems.vht_cap_elem,
2214 &sta->sta.vht_cap);
2215
2103 rate_control_rate_init(sta); 2216 rate_control_rate_init(sta);
2104 2217
2105 if (ifmgd->flags & IEEE80211_STA_MFP_ENABLED) 2218 if (ifmgd->flags & IEEE80211_STA_MFP_ENABLED)
@@ -2140,7 +2253,7 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata,
2140 changed |= BSS_CHANGED_QOS; 2253 changed |= BSS_CHANGED_QOS;
2141 2254
2142 if (elems.ht_operation && elems.wmm_param && 2255 if (elems.ht_operation && elems.wmm_param &&
2143 !(ifmgd->flags & IEEE80211_STA_DISABLE_11N)) 2256 !(ifmgd->flags & IEEE80211_STA_DISABLE_HT))
2144 changed |= ieee80211_config_ht_tx(sdata, elems.ht_operation, 2257 changed |= ieee80211_config_ht_tx(sdata, elems.ht_operation,
2145 cbss->bssid, false); 2258 cbss->bssid, false);
2146 2259
@@ -2247,9 +2360,9 @@ ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
2247 2360
2248 return RX_MGMT_CFG80211_RX_ASSOC; 2361 return RX_MGMT_CFG80211_RX_ASSOC;
2249} 2362}
2363
2250static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, 2364static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
2251 struct ieee80211_mgmt *mgmt, 2365 struct ieee80211_mgmt *mgmt, size_t len,
2252 size_t len,
2253 struct ieee80211_rx_status *rx_status, 2366 struct ieee80211_rx_status *rx_status,
2254 struct ieee802_11_elems *elems, 2367 struct ieee802_11_elems *elems,
2255 bool beacon) 2368 bool beacon)
@@ -2369,8 +2482,10 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
2369 size_t baselen; 2482 size_t baselen;
2370 struct ieee802_11_elems elems; 2483 struct ieee802_11_elems elems;
2371 struct ieee80211_local *local = sdata->local; 2484 struct ieee80211_local *local = sdata->local;
2485 struct ieee80211_chanctx_conf *chanctx_conf;
2486 struct ieee80211_channel *chan;
2372 u32 changed = 0; 2487 u32 changed = 0;
2373 bool erp_valid, directed_tim = false; 2488 bool erp_valid;
2374 u8 erp_value = 0; 2489 u8 erp_value = 0;
2375 u32 ncrc; 2490 u32 ncrc;
2376 u8 *bssid; 2491 u8 *bssid;
@@ -2382,8 +2497,19 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
2382 if (baselen > len) 2497 if (baselen > len)
2383 return; 2498 return;
2384 2499
2385 if (rx_status->freq != local->oper_channel->center_freq) 2500 rcu_read_lock();
2501 chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
2502 if (!chanctx_conf) {
2503 rcu_read_unlock();
2504 return;
2505 }
2506
2507 if (rx_status->freq != chanctx_conf->def.chan->center_freq) {
2508 rcu_read_unlock();
2386 return; 2509 return;
2510 }
2511 chan = chanctx_conf->def.chan;
2512 rcu_read_unlock();
2387 2513
2388 if (ifmgd->assoc_data && !ifmgd->assoc_data->have_beacon && 2514 if (ifmgd->assoc_data && !ifmgd->assoc_data->have_beacon &&
2389 ether_addr_equal(mgmt->bssid, ifmgd->assoc_data->bss->bssid)) { 2515 ether_addr_equal(mgmt->bssid, ifmgd->assoc_data->bss->bssid)) {
@@ -2490,11 +2616,10 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
2490 len - baselen, &elems, 2616 len - baselen, &elems,
2491 care_about_ies, ncrc); 2617 care_about_ies, ncrc);
2492 2618
2493 if (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK)
2494 directed_tim = ieee80211_check_tim(elems.tim, elems.tim_len,
2495 ifmgd->aid);
2496
2497 if (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK) { 2619 if (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK) {
2620 bool directed_tim = ieee80211_check_tim(elems.tim,
2621 elems.tim_len,
2622 ifmgd->aid);
2498 if (directed_tim) { 2623 if (directed_tim) {
2499 if (local->hw.conf.dynamic_ps_timeout > 0) { 2624 if (local->hw.conf.dynamic_ps_timeout > 0) {
2500 if (local->hw.conf.flags & IEEE80211_CONF_PS) { 2625 if (local->hw.conf.flags & IEEE80211_CONF_PS) {
@@ -2519,6 +2644,27 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
2519 } 2644 }
2520 } 2645 }
2521 2646
2647 if (sdata->vif.p2p) {
2648 u8 noa[2];
2649 int ret;
2650
2651 ret = cfg80211_get_p2p_attr(mgmt->u.beacon.variable,
2652 len - baselen,
2653 IEEE80211_P2P_ATTR_ABSENCE_NOTICE,
2654 noa, sizeof(noa));
2655 if (ret >= 2 && sdata->u.mgd.p2p_noa_index != noa[0]) {
2656 bss_conf->p2p_oppps = noa[1] & 0x80;
2657 bss_conf->p2p_ctwindow = noa[1] & 0x7f;
2658 changed |= BSS_CHANGED_P2P_PS;
2659 sdata->u.mgd.p2p_noa_index = noa[0];
2660 /*
2661 * make sure we update all information, the CRC
2662 * mechanism doesn't look at P2P attributes.
2663 */
2664 ifmgd->beacon_crc_valid = false;
2665 }
2666 }
2667
2522 if (ncrc == ifmgd->beacon_crc && ifmgd->beacon_crc_valid) 2668 if (ncrc == ifmgd->beacon_crc && ifmgd->beacon_crc_valid)
2523 return; 2669 return;
2524 ifmgd->beacon_crc = ncrc; 2670 ifmgd->beacon_crc = ncrc;
@@ -2543,22 +2689,17 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
2543 2689
2544 2690
2545 if (elems.ht_cap_elem && elems.ht_operation && elems.wmm_param && 2691 if (elems.ht_cap_elem && elems.ht_operation && elems.wmm_param &&
2546 !(ifmgd->flags & IEEE80211_STA_DISABLE_11N)) { 2692 !(ifmgd->flags & IEEE80211_STA_DISABLE_HT))
2547 struct ieee80211_supported_band *sband;
2548
2549 sband = local->hw.wiphy->bands[local->oper_channel->band];
2550
2551 changed |= ieee80211_config_ht_tx(sdata, elems.ht_operation, 2693 changed |= ieee80211_config_ht_tx(sdata, elems.ht_operation,
2552 bssid, true); 2694 bssid, true);
2553 }
2554 2695
2555 if (elems.country_elem && elems.pwr_constr_elem && 2696 if (elems.country_elem && elems.pwr_constr_elem &&
2556 mgmt->u.probe_resp.capab_info & 2697 mgmt->u.probe_resp.capab_info &
2557 cpu_to_le16(WLAN_CAPABILITY_SPECTRUM_MGMT)) 2698 cpu_to_le16(WLAN_CAPABILITY_SPECTRUM_MGMT))
2558 ieee80211_handle_pwr_constr(sdata, local->oper_channel, 2699 changed |= ieee80211_handle_pwr_constr(sdata, chan,
2559 elems.country_elem, 2700 elems.country_elem,
2560 elems.country_elem_len, 2701 elems.country_elem_len,
2561 elems.pwr_constr_elem); 2702 elems.pwr_constr_elem);
2562 2703
2563 ieee80211_bss_info_change_notify(sdata, changed); 2704 ieee80211_bss_info_change_notify(sdata, changed);
2564} 2705}
@@ -2703,13 +2844,23 @@ static int ieee80211_probe_auth(struct ieee80211_sub_if_data *sdata)
2703 drv_mgd_prepare_tx(local, sdata); 2844 drv_mgd_prepare_tx(local, sdata);
2704 2845
2705 if (auth_data->bss->proberesp_ies) { 2846 if (auth_data->bss->proberesp_ies) {
2847 u16 trans = 1;
2848 u16 status = 0;
2849
2706 sdata_info(sdata, "send auth to %pM (try %d/%d)\n", 2850 sdata_info(sdata, "send auth to %pM (try %d/%d)\n",
2707 auth_data->bss->bssid, auth_data->tries, 2851 auth_data->bss->bssid, auth_data->tries,
2708 IEEE80211_AUTH_MAX_TRIES); 2852 IEEE80211_AUTH_MAX_TRIES);
2709 2853
2710 auth_data->expected_transaction = 2; 2854 auth_data->expected_transaction = 2;
2711 ieee80211_send_auth(sdata, 1, auth_data->algorithm, 2855
2712 auth_data->ie, auth_data->ie_len, 2856 if (auth_data->algorithm == WLAN_AUTH_SAE) {
2857 trans = auth_data->sae_trans;
2858 status = auth_data->sae_status;
2859 auth_data->expected_transaction = trans;
2860 }
2861
2862 ieee80211_send_auth(sdata, trans, auth_data->algorithm, status,
2863 auth_data->data, auth_data->data_len,
2713 auth_data->bss->bssid, 2864 auth_data->bss->bssid,
2714 auth_data->bss->bssid, NULL, 0, 0); 2865 auth_data->bss->bssid, NULL, 0, 0);
2715 } else { 2866 } else {
@@ -2719,16 +2870,20 @@ static int ieee80211_probe_auth(struct ieee80211_sub_if_data *sdata)
2719 auth_data->bss->bssid, auth_data->tries, 2870 auth_data->bss->bssid, auth_data->tries,
2720 IEEE80211_AUTH_MAX_TRIES); 2871 IEEE80211_AUTH_MAX_TRIES);
2721 2872
2873 rcu_read_lock();
2722 ssidie = ieee80211_bss_get_ie(auth_data->bss, WLAN_EID_SSID); 2874 ssidie = ieee80211_bss_get_ie(auth_data->bss, WLAN_EID_SSID);
2723 if (!ssidie) 2875 if (!ssidie) {
2876 rcu_read_unlock();
2724 return -EINVAL; 2877 return -EINVAL;
2878 }
2725 /* 2879 /*
2726 * Direct probe is sent to broadcast address as some APs 2880 * Direct probe is sent to broadcast address as some APs
2727 * will not answer to direct packet in unassociated state. 2881 * will not answer to direct packet in unassociated state.
2728 */ 2882 */
2729 ieee80211_send_probe_req(sdata, NULL, ssidie + 2, ssidie[1], 2883 ieee80211_send_probe_req(sdata, NULL, ssidie + 2, ssidie[1],
2730 NULL, 0, (u32) -1, true, false, 2884 NULL, 0, (u32) -1, true, false,
2731 auth_data->bss->channel); 2885 auth_data->bss->channel, false);
2886 rcu_read_unlock();
2732 } 2887 }
2733 2888
2734 auth_data->timeout = jiffies + IEEE80211_AUTH_TIMEOUT; 2889 auth_data->timeout = jiffies + IEEE80211_AUTH_TIMEOUT;
@@ -3058,90 +3213,313 @@ int ieee80211_max_network_latency(struct notifier_block *nb,
3058 return 0; 3213 return 0;
3059} 3214}
3060 3215
3216static u32 chandef_downgrade(struct cfg80211_chan_def *c)
3217{
3218 u32 ret;
3219 int tmp;
3220
3221 switch (c->width) {
3222 case NL80211_CHAN_WIDTH_20:
3223 c->width = NL80211_CHAN_WIDTH_20_NOHT;
3224 ret = IEEE80211_STA_DISABLE_HT | IEEE80211_STA_DISABLE_VHT;
3225 break;
3226 case NL80211_CHAN_WIDTH_40:
3227 c->width = NL80211_CHAN_WIDTH_20;
3228 c->center_freq1 = c->chan->center_freq;
3229 ret = IEEE80211_STA_DISABLE_40MHZ |
3230 IEEE80211_STA_DISABLE_VHT;
3231 break;
3232 case NL80211_CHAN_WIDTH_80:
3233 tmp = (30 + c->chan->center_freq - c->center_freq1)/20;
3234 /* n_P40 */
3235 tmp /= 2;
3236 /* freq_P40 */
3237 c->center_freq1 = c->center_freq1 - 20 + 40 * tmp;
3238 c->width = NL80211_CHAN_WIDTH_40;
3239 ret = IEEE80211_STA_DISABLE_VHT;
3240 break;
3241 case NL80211_CHAN_WIDTH_80P80:
3242 c->center_freq2 = 0;
3243 c->width = NL80211_CHAN_WIDTH_80;
3244 ret = IEEE80211_STA_DISABLE_80P80MHZ |
3245 IEEE80211_STA_DISABLE_160MHZ;
3246 break;
3247 case NL80211_CHAN_WIDTH_160:
3248 /* n_P20 */
3249 tmp = (70 + c->chan->center_freq - c->center_freq1)/20;
3250 /* n_P80 */
3251 tmp /= 4;
3252 c->center_freq1 = c->center_freq1 - 40 + 80 * tmp;
3253 c->width = NL80211_CHAN_WIDTH_80;
3254 ret = IEEE80211_STA_DISABLE_80P80MHZ |
3255 IEEE80211_STA_DISABLE_160MHZ;
3256 break;
3257 default:
3258 case NL80211_CHAN_WIDTH_20_NOHT:
3259 WARN_ON_ONCE(1);
3260 c->width = NL80211_CHAN_WIDTH_20_NOHT;
3261 ret = IEEE80211_STA_DISABLE_HT | IEEE80211_STA_DISABLE_VHT;
3262 break;
3263 }
3264
3265 WARN_ON_ONCE(!cfg80211_chandef_valid(c));
3266
3267 return ret;
3268}
3269
3270static u32
3271ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata,
3272 struct ieee80211_supported_band *sband,
3273 struct ieee80211_channel *channel,
3274 const struct ieee80211_ht_operation *ht_oper,
3275 const struct ieee80211_vht_operation *vht_oper,
3276 struct cfg80211_chan_def *chandef)
3277{
3278 struct cfg80211_chan_def vht_chandef;
3279 u32 ht_cfreq, ret;
3280
3281 chandef->chan = channel;
3282 chandef->width = NL80211_CHAN_WIDTH_20_NOHT;
3283 chandef->center_freq1 = channel->center_freq;
3284 chandef->center_freq2 = 0;
3285
3286 if (!ht_oper || !sband->ht_cap.ht_supported) {
3287 ret = IEEE80211_STA_DISABLE_HT | IEEE80211_STA_DISABLE_VHT;
3288 goto out;
3289 }
3290
3291 chandef->width = NL80211_CHAN_WIDTH_20;
3292
3293 ht_cfreq = ieee80211_channel_to_frequency(ht_oper->primary_chan,
3294 channel->band);
3295 /* check that channel matches the right operating channel */
3296 if (channel->center_freq != ht_cfreq) {
3297 /*
3298 * It's possible that some APs are confused here;
3299 * Netgear WNDR3700 sometimes reports 4 higher than
3300 * the actual channel in association responses, but
3301 * since we look at probe response/beacon data here
3302 * it should be OK.
3303 */
3304 sdata_info(sdata,
3305 "Wrong control channel: center-freq: %d ht-cfreq: %d ht->primary_chan: %d band: %d - Disabling HT\n",
3306 channel->center_freq, ht_cfreq,
3307 ht_oper->primary_chan, channel->band);
3308 ret = IEEE80211_STA_DISABLE_HT | IEEE80211_STA_DISABLE_VHT;
3309 goto out;
3310 }
3311
3312 /* check 40 MHz support, if we have it */
3313 if (sband->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) {
3314 switch (ht_oper->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) {
3315 case IEEE80211_HT_PARAM_CHA_SEC_ABOVE:
3316 chandef->width = NL80211_CHAN_WIDTH_40;
3317 chandef->center_freq1 += 10;
3318 break;
3319 case IEEE80211_HT_PARAM_CHA_SEC_BELOW:
3320 chandef->width = NL80211_CHAN_WIDTH_40;
3321 chandef->center_freq1 -= 10;
3322 break;
3323 }
3324 } else {
3325 /* 40 MHz (and 80 MHz) must be supported for VHT */
3326 ret = IEEE80211_STA_DISABLE_VHT;
3327 goto out;
3328 }
3329
3330 if (!vht_oper || !sband->vht_cap.vht_supported) {
3331 ret = IEEE80211_STA_DISABLE_VHT;
3332 goto out;
3333 }
3334
3335 vht_chandef.chan = channel;
3336 vht_chandef.center_freq1 =
3337 ieee80211_channel_to_frequency(vht_oper->center_freq_seg1_idx,
3338 channel->band);
3339 vht_chandef.center_freq2 = 0;
3340
3341 if (vht_oper->center_freq_seg2_idx)
3342 vht_chandef.center_freq2 =
3343 ieee80211_channel_to_frequency(
3344 vht_oper->center_freq_seg2_idx,
3345 channel->band);
3346
3347 switch (vht_oper->chan_width) {
3348 case IEEE80211_VHT_CHANWIDTH_USE_HT:
3349 vht_chandef.width = chandef->width;
3350 break;
3351 case IEEE80211_VHT_CHANWIDTH_80MHZ:
3352 vht_chandef.width = NL80211_CHAN_WIDTH_80;
3353 break;
3354 case IEEE80211_VHT_CHANWIDTH_160MHZ:
3355 vht_chandef.width = NL80211_CHAN_WIDTH_160;
3356 break;
3357 case IEEE80211_VHT_CHANWIDTH_80P80MHZ:
3358 vht_chandef.width = NL80211_CHAN_WIDTH_80P80;
3359 break;
3360 default:
3361 sdata_info(sdata,
3362 "AP VHT operation IE has invalid channel width (%d), disable VHT\n",
3363 vht_oper->chan_width);
3364 ret = IEEE80211_STA_DISABLE_VHT;
3365 goto out;
3366 }
3367
3368 if (!cfg80211_chandef_valid(&vht_chandef)) {
3369 sdata_info(sdata,
3370 "AP VHT information is invalid, disable VHT\n");
3371 ret = IEEE80211_STA_DISABLE_VHT;
3372 goto out;
3373 }
3374
3375 if (cfg80211_chandef_identical(chandef, &vht_chandef)) {
3376 ret = 0;
3377 goto out;
3378 }
3379
3380 if (!cfg80211_chandef_compatible(chandef, &vht_chandef)) {
3381 sdata_info(sdata,
3382 "AP VHT information doesn't match HT, disable VHT\n");
3383 ret = IEEE80211_STA_DISABLE_VHT;
3384 goto out;
3385 }
3386
3387 *chandef = vht_chandef;
3388
3389 ret = 0;
3390
3391 while (!cfg80211_chandef_usable(sdata->local->hw.wiphy, chandef,
3392 IEEE80211_CHAN_DISABLED)) {
3393 if (WARN_ON(chandef->width == NL80211_CHAN_WIDTH_20_NOHT)) {
3394 ret = IEEE80211_STA_DISABLE_HT |
3395 IEEE80211_STA_DISABLE_VHT;
3396 goto out;
3397 }
3398
3399 ret = chandef_downgrade(chandef);
3400 }
3401
3402 if (chandef->width != vht_chandef.width)
3403 sdata_info(sdata,
3404 "local regulatory prevented using AP HT/VHT configuration, downgraded\n");
3405
3406out:
3407 WARN_ON_ONCE(!cfg80211_chandef_valid(chandef));
3408 return ret;
3409}
3410
3411static u8 ieee80211_ht_vht_rx_chains(struct ieee80211_sub_if_data *sdata,
3412 struct cfg80211_bss *cbss)
3413{
3414 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
3415 const u8 *ht_cap_ie, *vht_cap_ie;
3416 const struct ieee80211_ht_cap *ht_cap;
3417 const struct ieee80211_vht_cap *vht_cap;
3418 u8 chains = 1;
3419
3420 if (ifmgd->flags & IEEE80211_STA_DISABLE_HT)
3421 return chains;
3422
3423 ht_cap_ie = ieee80211_bss_get_ie(cbss, WLAN_EID_HT_CAPABILITY);
3424 if (ht_cap_ie && ht_cap_ie[1] >= sizeof(*ht_cap)) {
3425 ht_cap = (void *)(ht_cap_ie + 2);
3426 chains = ieee80211_mcs_to_chains(&ht_cap->mcs);
3427 /*
3428 * TODO: use "Tx Maximum Number Spatial Streams Supported" and
3429 * "Tx Unequal Modulation Supported" fields.
3430 */
3431 }
3432
3433 if (ifmgd->flags & IEEE80211_STA_DISABLE_VHT)
3434 return chains;
3435
3436 vht_cap_ie = ieee80211_bss_get_ie(cbss, WLAN_EID_VHT_CAPABILITY);
3437 if (vht_cap_ie && vht_cap_ie[1] >= sizeof(*vht_cap)) {
3438 u8 nss;
3439 u16 tx_mcs_map;
3440
3441 vht_cap = (void *)(vht_cap_ie + 2);
3442 tx_mcs_map = le16_to_cpu(vht_cap->supp_mcs.tx_mcs_map);
3443 for (nss = 8; nss > 0; nss--) {
3444 if (((tx_mcs_map >> (2 * (nss - 1))) & 3) !=
3445 IEEE80211_VHT_MCS_NOT_SUPPORTED)
3446 break;
3447 }
3448 /* TODO: use "Tx Highest Supported Long GI Data Rate" field? */
3449 chains = max(chains, nss);
3450 }
3451
3452 return chains;
3453}
3454
3061static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata, 3455static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata,
3062 struct cfg80211_bss *cbss) 3456 struct cfg80211_bss *cbss)
3063{ 3457{
3064 struct ieee80211_local *local = sdata->local; 3458 struct ieee80211_local *local = sdata->local;
3065 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; 3459 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
3066 int ht_cfreq;
3067 enum nl80211_channel_type channel_type = NL80211_CHAN_NO_HT;
3068 const u8 *ht_oper_ie;
3069 const struct ieee80211_ht_operation *ht_oper = NULL; 3460 const struct ieee80211_ht_operation *ht_oper = NULL;
3461 const struct ieee80211_vht_operation *vht_oper = NULL;
3070 struct ieee80211_supported_band *sband; 3462 struct ieee80211_supported_band *sband;
3463 struct cfg80211_chan_def chandef;
3464 int ret;
3071 3465
3072 sband = local->hw.wiphy->bands[cbss->channel->band]; 3466 sband = local->hw.wiphy->bands[cbss->channel->band];
3073 3467
3074 ifmgd->flags &= ~IEEE80211_STA_DISABLE_40MHZ; 3468 ifmgd->flags &= ~(IEEE80211_STA_DISABLE_40MHZ |
3469 IEEE80211_STA_DISABLE_80P80MHZ |
3470 IEEE80211_STA_DISABLE_160MHZ);
3471
3472 rcu_read_lock();
3473
3474 if (!(ifmgd->flags & IEEE80211_STA_DISABLE_HT) &&
3475 sband->ht_cap.ht_supported) {
3476 const u8 *ht_oper_ie;
3075 3477
3076 if (sband->ht_cap.ht_supported) { 3478 ht_oper_ie = ieee80211_bss_get_ie(cbss, WLAN_EID_HT_OPERATION);
3077 ht_oper_ie = cfg80211_find_ie(WLAN_EID_HT_OPERATION,
3078 cbss->information_elements,
3079 cbss->len_information_elements);
3080 if (ht_oper_ie && ht_oper_ie[1] >= sizeof(*ht_oper)) 3479 if (ht_oper_ie && ht_oper_ie[1] >= sizeof(*ht_oper))
3081 ht_oper = (void *)(ht_oper_ie + 2); 3480 ht_oper = (void *)(ht_oper_ie + 2);
3082 } 3481 }
3083 3482
3084 if (ht_oper) { 3483 if (!(ifmgd->flags & IEEE80211_STA_DISABLE_VHT) &&
3085 ht_cfreq = ieee80211_channel_to_frequency(ht_oper->primary_chan, 3484 sband->vht_cap.vht_supported) {
3086 cbss->channel->band); 3485 const u8 *vht_oper_ie;
3087 /* check that channel matches the right operating channel */ 3486
3088 if (cbss->channel->center_freq != ht_cfreq) { 3487 vht_oper_ie = ieee80211_bss_get_ie(cbss,
3089 /* 3488 WLAN_EID_VHT_OPERATION);
3090 * It's possible that some APs are confused here; 3489 if (vht_oper_ie && vht_oper_ie[1] >= sizeof(*vht_oper))
3091 * Netgear WNDR3700 sometimes reports 4 higher than 3490 vht_oper = (void *)(vht_oper_ie + 2);
3092 * the actual channel in association responses, but 3491 if (vht_oper && !ht_oper) {
3093 * since we look at probe response/beacon data here 3492 vht_oper = NULL;
3094 * it should be OK.
3095 */
3096 sdata_info(sdata, 3493 sdata_info(sdata,
3097 "Wrong control channel: center-freq: %d ht-cfreq: %d ht->primary_chan: %d band: %d - Disabling HT\n", 3494 "AP advertised VHT without HT, disabling both\n");
3098 cbss->channel->center_freq, 3495 sdata->flags |= IEEE80211_STA_DISABLE_HT;
3099 ht_cfreq, ht_oper->primary_chan, 3496 sdata->flags |= IEEE80211_STA_DISABLE_VHT;
3100 cbss->channel->band);
3101 ht_oper = NULL;
3102 } else {
3103 channel_type = NL80211_CHAN_HT20;
3104 } 3497 }
3105 } 3498 }
3106 3499
3107 if (ht_oper && sband->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) { 3500 ifmgd->flags |= ieee80211_determine_chantype(sdata, sband,
3108 /* 3501 cbss->channel,
3109 * cfg80211 already verified that the channel itself can 3502 ht_oper, vht_oper,
3110 * be used, but it didn't check that we can do the right 3503 &chandef);
3111 * HT type, so do that here as well. If HT40 isn't allowed
3112 * on this channel, disable 40 MHz operation.
3113 */
3114 3504
3115 switch (ht_oper->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) { 3505 sdata->needed_rx_chains = min(ieee80211_ht_vht_rx_chains(sdata, cbss),
3116 case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: 3506 local->rx_chains);
3117 if (cbss->channel->flags & IEEE80211_CHAN_NO_HT40PLUS)
3118 ifmgd->flags |= IEEE80211_STA_DISABLE_40MHZ;
3119 else
3120 channel_type = NL80211_CHAN_HT40PLUS;
3121 break;
3122 case IEEE80211_HT_PARAM_CHA_SEC_BELOW:
3123 if (cbss->channel->flags & IEEE80211_CHAN_NO_HT40MINUS)
3124 ifmgd->flags |= IEEE80211_STA_DISABLE_40MHZ;
3125 else
3126 channel_type = NL80211_CHAN_HT40MINUS;
3127 break;
3128 }
3129 }
3130 3507
3131 if (!ieee80211_set_channel_type(local, sdata, channel_type)) { 3508 rcu_read_unlock();
3132 /* can only fail due to HT40+/- mismatch */
3133 channel_type = NL80211_CHAN_HT20;
3134 sdata_info(sdata,
3135 "disabling 40 MHz due to multi-vif mismatch\n");
3136 ifmgd->flags |= IEEE80211_STA_DISABLE_40MHZ;
3137 WARN_ON(!ieee80211_set_channel_type(local, sdata,
3138 channel_type));
3139 }
3140 3509
3141 local->oper_channel = cbss->channel; 3510 /* will change later if needed */
3142 ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); 3511 sdata->smps_mode = IEEE80211_SMPS_OFF;
3143 3512
3144 return 0; 3513 /*
3514 * If this fails (possibly due to channel context sharing
3515 * on incompatible channels, e.g. 80+80 and 160 sharing the
3516 * same control channel) try to use a smaller bandwidth.
3517 */
3518 ret = ieee80211_vif_use_channel(sdata, &chandef,
3519 IEEE80211_CHANCTX_SHARED);
3520 while (ret && chandef.width != NL80211_CHAN_WIDTH_20_NOHT)
3521 ifmgd->flags |= chandef_downgrade(&chandef);
3522 return ret;
3145} 3523}
3146 3524
3147static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata, 3525static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata,
@@ -3211,7 +3589,7 @@ static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata,
3211 sdata->vif.bss_conf.basic_rates = basic_rates; 3589 sdata->vif.bss_conf.basic_rates = basic_rates;
3212 3590
3213 /* cf. IEEE 802.11 9.2.12 */ 3591 /* cf. IEEE 802.11 9.2.12 */
3214 if (local->oper_channel->band == IEEE80211_BAND_2GHZ && 3592 if (cbss->channel->band == IEEE80211_BAND_2GHZ &&
3215 have_higher_than_11mbit) 3593 have_higher_than_11mbit)
3216 sdata->flags |= IEEE80211_SDATA_OPERATING_GMODE; 3594 sdata->flags |= IEEE80211_SDATA_OPERATING_GMODE;
3217 else 3595 else
@@ -3273,19 +3651,33 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata,
3273 case NL80211_AUTHTYPE_NETWORK_EAP: 3651 case NL80211_AUTHTYPE_NETWORK_EAP:
3274 auth_alg = WLAN_AUTH_LEAP; 3652 auth_alg = WLAN_AUTH_LEAP;
3275 break; 3653 break;
3654 case NL80211_AUTHTYPE_SAE:
3655 auth_alg = WLAN_AUTH_SAE;
3656 break;
3276 default: 3657 default:
3277 return -EOPNOTSUPP; 3658 return -EOPNOTSUPP;
3278 } 3659 }
3279 3660
3280 auth_data = kzalloc(sizeof(*auth_data) + req->ie_len, GFP_KERNEL); 3661 auth_data = kzalloc(sizeof(*auth_data) + req->sae_data_len +
3662 req->ie_len, GFP_KERNEL);
3281 if (!auth_data) 3663 if (!auth_data)
3282 return -ENOMEM; 3664 return -ENOMEM;
3283 3665
3284 auth_data->bss = req->bss; 3666 auth_data->bss = req->bss;
3285 3667
3668 if (req->sae_data_len >= 4) {
3669 __le16 *pos = (__le16 *) req->sae_data;
3670 auth_data->sae_trans = le16_to_cpu(pos[0]);
3671 auth_data->sae_status = le16_to_cpu(pos[1]);
3672 memcpy(auth_data->data, req->sae_data + 4,
3673 req->sae_data_len - 4);
3674 auth_data->data_len += req->sae_data_len - 4;
3675 }
3676
3286 if (req->ie && req->ie_len) { 3677 if (req->ie && req->ie_len) {
3287 memcpy(auth_data->ie, req->ie, req->ie_len); 3678 memcpy(&auth_data->data[auth_data->data_len],
3288 auth_data->ie_len = req->ie_len; 3679 req->ie, req->ie_len);
3680 auth_data->data_len += req->ie_len;
3289 } 3681 }
3290 3682
3291 if (req->key && req->key_len) { 3683 if (req->key && req->key_len) {
@@ -3355,14 +3747,21 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
3355 const u8 *ssidie, *ht_ie; 3747 const u8 *ssidie, *ht_ie;
3356 int i, err; 3748 int i, err;
3357 3749
3358 ssidie = ieee80211_bss_get_ie(req->bss, WLAN_EID_SSID);
3359 if (!ssidie)
3360 return -EINVAL;
3361
3362 assoc_data = kzalloc(sizeof(*assoc_data) + req->ie_len, GFP_KERNEL); 3750 assoc_data = kzalloc(sizeof(*assoc_data) + req->ie_len, GFP_KERNEL);
3363 if (!assoc_data) 3751 if (!assoc_data)
3364 return -ENOMEM; 3752 return -ENOMEM;
3365 3753
3754 rcu_read_lock();
3755 ssidie = ieee80211_bss_get_ie(req->bss, WLAN_EID_SSID);
3756 if (!ssidie) {
3757 rcu_read_unlock();
3758 kfree(assoc_data);
3759 return -EINVAL;
3760 }
3761 memcpy(assoc_data->ssid, ssidie + 2, ssidie[1]);
3762 assoc_data->ssid_len = ssidie[1];
3763 rcu_read_unlock();
3764
3366 mutex_lock(&ifmgd->mtx); 3765 mutex_lock(&ifmgd->mtx);
3367 3766
3368 if (ifmgd->associated) 3767 if (ifmgd->associated)
@@ -3388,13 +3787,6 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
3388 3787
3389 /* prepare assoc data */ 3788 /* prepare assoc data */
3390 3789
3391 /*
3392 * keep only the 40 MHz disable bit set as it might have
3393 * been set during authentication already, all other bits
3394 * should be reset for a new connection
3395 */
3396 ifmgd->flags &= IEEE80211_STA_DISABLE_40MHZ;
3397
3398 ifmgd->beacon_crc_valid = false; 3790 ifmgd->beacon_crc_valid = false;
3399 3791
3400 /* 3792 /*
@@ -3408,7 +3800,7 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
3408 if (req->crypto.ciphers_pairwise[i] == WLAN_CIPHER_SUITE_WEP40 || 3800 if (req->crypto.ciphers_pairwise[i] == WLAN_CIPHER_SUITE_WEP40 ||
3409 req->crypto.ciphers_pairwise[i] == WLAN_CIPHER_SUITE_TKIP || 3801 req->crypto.ciphers_pairwise[i] == WLAN_CIPHER_SUITE_TKIP ||
3410 req->crypto.ciphers_pairwise[i] == WLAN_CIPHER_SUITE_WEP104) { 3802 req->crypto.ciphers_pairwise[i] == WLAN_CIPHER_SUITE_WEP104) {
3411 ifmgd->flags |= IEEE80211_STA_DISABLE_11N; 3803 ifmgd->flags |= IEEE80211_STA_DISABLE_HT;
3412 ifmgd->flags |= IEEE80211_STA_DISABLE_VHT; 3804 ifmgd->flags |= IEEE80211_STA_DISABLE_VHT;
3413 netdev_info(sdata->dev, 3805 netdev_info(sdata->dev,
3414 "disabling HT/VHT due to WEP/TKIP use\n"); 3806 "disabling HT/VHT due to WEP/TKIP use\n");
@@ -3416,7 +3808,7 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
3416 } 3808 }
3417 3809
3418 if (req->flags & ASSOC_REQ_DISABLE_HT) { 3810 if (req->flags & ASSOC_REQ_DISABLE_HT) {
3419 ifmgd->flags |= IEEE80211_STA_DISABLE_11N; 3811 ifmgd->flags |= IEEE80211_STA_DISABLE_HT;
3420 ifmgd->flags |= IEEE80211_STA_DISABLE_VHT; 3812 ifmgd->flags |= IEEE80211_STA_DISABLE_VHT;
3421 } 3813 }
3422 3814
@@ -3424,7 +3816,7 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
3424 sband = local->hw.wiphy->bands[req->bss->channel->band]; 3816 sband = local->hw.wiphy->bands[req->bss->channel->band];
3425 if (!sband->ht_cap.ht_supported || 3817 if (!sband->ht_cap.ht_supported ||
3426 local->hw.queues < IEEE80211_NUM_ACS || !bss->wmm_used) { 3818 local->hw.queues < IEEE80211_NUM_ACS || !bss->wmm_used) {
3427 ifmgd->flags |= IEEE80211_STA_DISABLE_11N; 3819 ifmgd->flags |= IEEE80211_STA_DISABLE_HT;
3428 if (!bss->wmm_used) 3820 if (!bss->wmm_used)
3429 netdev_info(sdata->dev, 3821 netdev_info(sdata->dev,
3430 "disabling HT as WMM/QoS is not supported by the AP\n"); 3822 "disabling HT as WMM/QoS is not supported by the AP\n");
@@ -3452,11 +3844,11 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
3452 3844
3453 if (ifmgd->req_smps == IEEE80211_SMPS_AUTOMATIC) { 3845 if (ifmgd->req_smps == IEEE80211_SMPS_AUTOMATIC) {
3454 if (ifmgd->powersave) 3846 if (ifmgd->powersave)
3455 ifmgd->ap_smps = IEEE80211_SMPS_DYNAMIC; 3847 sdata->smps_mode = IEEE80211_SMPS_DYNAMIC;
3456 else 3848 else
3457 ifmgd->ap_smps = IEEE80211_SMPS_OFF; 3849 sdata->smps_mode = IEEE80211_SMPS_OFF;
3458 } else 3850 } else
3459 ifmgd->ap_smps = ifmgd->req_smps; 3851 sdata->smps_mode = ifmgd->req_smps;
3460 3852
3461 assoc_data->capability = req->bss->capability; 3853 assoc_data->capability = req->bss->capability;
3462 assoc_data->wmm = bss->wmm_used && 3854 assoc_data->wmm = bss->wmm_used &&
@@ -3464,12 +3856,14 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
3464 assoc_data->supp_rates = bss->supp_rates; 3856 assoc_data->supp_rates = bss->supp_rates;
3465 assoc_data->supp_rates_len = bss->supp_rates_len; 3857 assoc_data->supp_rates_len = bss->supp_rates_len;
3466 3858
3859 rcu_read_lock();
3467 ht_ie = ieee80211_bss_get_ie(req->bss, WLAN_EID_HT_OPERATION); 3860 ht_ie = ieee80211_bss_get_ie(req->bss, WLAN_EID_HT_OPERATION);
3468 if (ht_ie && ht_ie[1] >= sizeof(struct ieee80211_ht_operation)) 3861 if (ht_ie && ht_ie[1] >= sizeof(struct ieee80211_ht_operation))
3469 assoc_data->ap_ht_param = 3862 assoc_data->ap_ht_param =
3470 ((struct ieee80211_ht_operation *)(ht_ie + 2))->ht_param; 3863 ((struct ieee80211_ht_operation *)(ht_ie + 2))->ht_param;
3471 else 3864 else
3472 ifmgd->flags |= IEEE80211_STA_DISABLE_11N; 3865 ifmgd->flags |= IEEE80211_STA_DISABLE_HT;
3866 rcu_read_unlock();
3473 3867
3474 if (bss->wmm_used && bss->uapsd_supported && 3868 if (bss->wmm_used && bss->uapsd_supported &&
3475 (sdata->local->hw.flags & IEEE80211_HW_SUPPORTS_UAPSD)) { 3869 (sdata->local->hw.flags & IEEE80211_HW_SUPPORTS_UAPSD)) {
@@ -3480,9 +3874,6 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
3480 ifmgd->flags &= ~IEEE80211_STA_UAPSD_ENABLED; 3874 ifmgd->flags &= ~IEEE80211_STA_UAPSD_ENABLED;
3481 } 3875 }
3482 3876
3483 memcpy(assoc_data->ssid, ssidie + 2, ssidie[1]);
3484 assoc_data->ssid_len = ssidie[1];
3485
3486 if (req->prev_bssid) 3877 if (req->prev_bssid)
3487 memcpy(assoc_data->prev_bssid, req->prev_bssid, ETH_ALEN); 3878 memcpy(assoc_data->prev_bssid, req->prev_bssid, ETH_ALEN);
3488 3879
@@ -3560,40 +3951,44 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata,
3560 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; 3951 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
3561 u8 frame_buf[IEEE80211_DEAUTH_FRAME_LEN]; 3952 u8 frame_buf[IEEE80211_DEAUTH_FRAME_LEN];
3562 bool tx = !req->local_state_change; 3953 bool tx = !req->local_state_change;
3954 bool sent_frame = false;
3563 3955
3564 mutex_lock(&ifmgd->mtx); 3956 mutex_lock(&ifmgd->mtx);
3565 3957
3566 if (ifmgd->auth_data) {
3567 ieee80211_destroy_auth_data(sdata, false);
3568 mutex_unlock(&ifmgd->mtx);
3569 return 0;
3570 }
3571
3572 sdata_info(sdata, 3958 sdata_info(sdata,
3573 "deauthenticating from %pM by local choice (reason=%d)\n", 3959 "deauthenticating from %pM by local choice (reason=%d)\n",
3574 req->bssid, req->reason_code); 3960 req->bssid, req->reason_code);
3575 3961
3576 if (ifmgd->associated && 3962 if (ifmgd->auth_data) {
3577 ether_addr_equal(ifmgd->associated->bssid, req->bssid)) {
3578 ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH,
3579 req->reason_code, tx, frame_buf);
3580 } else {
3581 drv_mgd_prepare_tx(sdata->local, sdata); 3963 drv_mgd_prepare_tx(sdata->local, sdata);
3582 ieee80211_send_deauth_disassoc(sdata, req->bssid, 3964 ieee80211_send_deauth_disassoc(sdata, req->bssid,
3583 IEEE80211_STYPE_DEAUTH, 3965 IEEE80211_STYPE_DEAUTH,
3584 req->reason_code, tx, 3966 req->reason_code, tx,
3585 frame_buf); 3967 frame_buf);
3968 ieee80211_destroy_auth_data(sdata, false);
3969 mutex_unlock(&ifmgd->mtx);
3970
3971 sent_frame = tx;
3972 goto out;
3586 } 3973 }
3587 3974
3975 if (ifmgd->associated &&
3976 ether_addr_equal(ifmgd->associated->bssid, req->bssid)) {
3977 ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH,
3978 req->reason_code, tx, frame_buf);
3979 sent_frame = tx;
3980 }
3588 mutex_unlock(&ifmgd->mtx); 3981 mutex_unlock(&ifmgd->mtx);
3589 3982
3590 __cfg80211_send_deauth(sdata->dev, frame_buf, 3983 out:
3591 IEEE80211_DEAUTH_FRAME_LEN);
3592
3593 mutex_lock(&sdata->local->mtx); 3984 mutex_lock(&sdata->local->mtx);
3594 ieee80211_recalc_idle(sdata->local); 3985 ieee80211_recalc_idle(sdata->local);
3595 mutex_unlock(&sdata->local->mtx); 3986 mutex_unlock(&sdata->local->mtx);
3596 3987
3988 if (sent_frame)
3989 __cfg80211_send_deauth(sdata->dev, frame_buf,
3990 IEEE80211_DEAUTH_FRAME_LEN);
3991
3597 return 0; 3992 return 0;
3598} 3993}
3599 3994