hc
2024-01-05 071106ecf68c401173c58808b1cf5f68cc50d390
kernel/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
....@@ -5,10 +5,9 @@
55 *
66 * GPL LICENSE SUMMARY
77 *
8
- * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
98 * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
109 * Copyright(c) 2016 - 2017 Intel Deutschland GmbH
11
- * Copyright(c) 2018 Intel Corporation
10
+ * Copyright(c) 2012 - 2014, 2018 - 2020 Intel Corporation
1211 *
1312 * This program is free software; you can redistribute it and/or modify
1413 * it under the terms of version 2 of the GNU General Public License as
....@@ -19,11 +18,6 @@
1918 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
2019 * General Public License for more details.
2120 *
22
- * You should have received a copy of the GNU General Public License
23
- * along with this program; if not, write to the Free Software
24
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
25
- * USA
26
- *
2721 * The full GNU General Public License is included in this distribution
2822 * in the file called COPYING.
2923 *
....@@ -33,10 +27,9 @@
3327 *
3428 * BSD LICENSE
3529 *
36
- * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
3730 * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
3831 * Copyright(c) 2016 - 2017 Intel Deutschland GmbH
39
- * Copyright(c) 2018 Intel Corporation
32
+ * Copyright(c) 2012 - 2014, 2018 - 2020 Intel Corporation
4033 * All rights reserved.
4134 *
4235 * Redistribution and use in source and binary forms, with or without
....@@ -78,6 +71,7 @@
7871 #include <net/ieee80211_radiotap.h>
7972 #include <net/tcp.h>
8073
74
+#include "iwl-drv.h"
8175 #include "iwl-op-mode.h"
8276 #include "iwl-io.h"
8377 #include "mvm.h"
....@@ -189,90 +183,37 @@
189183 };
190184 #endif
191185
192
-void iwl_mvm_ref(struct iwl_mvm *mvm, enum iwl_mvm_ref_type ref_type)
193
-{
194
- if (!iwl_mvm_is_d0i3_supported(mvm))
195
- return;
186
+static const struct cfg80211_pmsr_capabilities iwl_mvm_pmsr_capa = {
187
+ .max_peers = IWL_MVM_TOF_MAX_APS,
188
+ .report_ap_tsf = 1,
189
+ .randomize_mac_addr = 1,
196190
197
- IWL_DEBUG_RPM(mvm, "Take mvm reference - type %d\n", ref_type);
198
- spin_lock_bh(&mvm->refs_lock);
199
- mvm->refs[ref_type]++;
200
- spin_unlock_bh(&mvm->refs_lock);
201
- iwl_trans_ref(mvm->trans);
202
-}
191
+ .ftm = {
192
+ .supported = 1,
193
+ .asap = 1,
194
+ .non_asap = 1,
195
+ .request_lci = 1,
196
+ .request_civicloc = 1,
197
+ .trigger_based = 1,
198
+ .non_trigger_based = 1,
199
+ .max_bursts_exponent = -1, /* all supported */
200
+ .max_ftms_per_burst = 0, /* no limits */
201
+ .bandwidths = BIT(NL80211_CHAN_WIDTH_20_NOHT) |
202
+ BIT(NL80211_CHAN_WIDTH_20) |
203
+ BIT(NL80211_CHAN_WIDTH_40) |
204
+ BIT(NL80211_CHAN_WIDTH_80),
205
+ .preambles = BIT(NL80211_PREAMBLE_LEGACY) |
206
+ BIT(NL80211_PREAMBLE_HT) |
207
+ BIT(NL80211_PREAMBLE_VHT) |
208
+ BIT(NL80211_PREAMBLE_HE),
209
+ },
210
+};
203211
204
-void iwl_mvm_unref(struct iwl_mvm *mvm, enum iwl_mvm_ref_type ref_type)
205
-{
206
- if (!iwl_mvm_is_d0i3_supported(mvm))
207
- return;
208
-
209
- IWL_DEBUG_RPM(mvm, "Leave mvm reference - type %d\n", ref_type);
210
- spin_lock_bh(&mvm->refs_lock);
211
- if (WARN_ON(!mvm->refs[ref_type])) {
212
- spin_unlock_bh(&mvm->refs_lock);
213
- return;
214
- }
215
- mvm->refs[ref_type]--;
216
- spin_unlock_bh(&mvm->refs_lock);
217
- iwl_trans_unref(mvm->trans);
218
-}
219
-
220
-static void iwl_mvm_unref_all_except(struct iwl_mvm *mvm,
221
- enum iwl_mvm_ref_type except_ref)
222
-{
223
- int i, j;
224
-
225
- if (!iwl_mvm_is_d0i3_supported(mvm))
226
- return;
227
-
228
- spin_lock_bh(&mvm->refs_lock);
229
- for (i = 0; i < IWL_MVM_REF_COUNT; i++) {
230
- if (except_ref == i || !mvm->refs[i])
231
- continue;
232
-
233
- IWL_DEBUG_RPM(mvm, "Cleanup: remove mvm ref type %d (%d)\n",
234
- i, mvm->refs[i]);
235
- for (j = 0; j < mvm->refs[i]; j++)
236
- iwl_trans_unref(mvm->trans);
237
- mvm->refs[i] = 0;
238
- }
239
- spin_unlock_bh(&mvm->refs_lock);
240
-}
241
-
242
-bool iwl_mvm_ref_taken(struct iwl_mvm *mvm)
243
-{
244
- int i;
245
- bool taken = false;
246
-
247
- if (!iwl_mvm_is_d0i3_supported(mvm))
248
- return true;
249
-
250
- spin_lock_bh(&mvm->refs_lock);
251
- for (i = 0; i < IWL_MVM_REF_COUNT; i++) {
252
- if (mvm->refs[i]) {
253
- taken = true;
254
- break;
255
- }
256
- }
257
- spin_unlock_bh(&mvm->refs_lock);
258
-
259
- return taken;
260
-}
261
-
262
-int iwl_mvm_ref_sync(struct iwl_mvm *mvm, enum iwl_mvm_ref_type ref_type)
263
-{
264
- iwl_mvm_ref(mvm, ref_type);
265
-
266
- if (!wait_event_timeout(mvm->d0i3_exit_waitq,
267
- !test_bit(IWL_MVM_STATUS_IN_D0I3, &mvm->status),
268
- HZ)) {
269
- WARN_ON_ONCE(1);
270
- iwl_mvm_unref(mvm, ref_type);
271
- return -EIO;
272
- }
273
-
274
- return 0;
275
-}
212
+static int __iwl_mvm_mac_set_key(struct ieee80211_hw *hw,
213
+ enum set_key_cmd cmd,
214
+ struct ieee80211_vif *vif,
215
+ struct ieee80211_sta *sta,
216
+ struct ieee80211_key_conf *key);
276217
277218 static void iwl_mvm_reset_phy_ctxts(struct iwl_mvm *mvm)
278219 {
....@@ -294,6 +235,7 @@
294235 struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
295236 struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
296237 struct iwl_mcc_update_resp *resp;
238
+ u8 resp_ver;
297239
298240 IWL_DEBUG_LAR(mvm, "Getting regdomain data for %s from FW\n", alpha2);
299241
....@@ -312,13 +254,16 @@
312254 *changed = (status == MCC_RESP_NEW_CHAN_PROFILE ||
313255 status == MCC_RESP_ILLEGAL);
314256 }
257
+ resp_ver = iwl_fw_lookup_notif_ver(mvm->fw, IWL_ALWAYS_LONG_GROUP,
258
+ MCC_UPDATE_CMD, 0);
259
+ IWL_DEBUG_LAR(mvm, "MCC update response version: %d\n", resp_ver);
315260
316261 regd = iwl_parse_nvm_mcc_info(mvm->trans->dev, mvm->cfg,
317262 __le32_to_cpu(resp->n_channels),
318263 resp->channels,
319264 __le16_to_cpu(resp->mcc),
320265 __le16_to_cpu(resp->geo_info),
321
- __le16_to_cpu(resp->cap));
266
+ __le16_to_cpu(resp->cap), resp_ver);
322267 /* Store the return source id */
323268 src_id = resp->source_id;
324269 kfree(resp);
....@@ -401,6 +346,30 @@
401346 return ret;
402347 }
403348
349
+static const u8 he_if_types_ext_capa_sta[] = {
350
+ [0] = WLAN_EXT_CAPA1_EXT_CHANNEL_SWITCHING,
351
+ [2] = WLAN_EXT_CAPA3_MULTI_BSSID_SUPPORT,
352
+ [7] = WLAN_EXT_CAPA8_OPMODE_NOTIF,
353
+};
354
+
355
+static const struct wiphy_iftype_ext_capab he_iftypes_ext_capa[] = {
356
+ {
357
+ .iftype = NL80211_IFTYPE_STATION,
358
+ .extended_capabilities = he_if_types_ext_capa_sta,
359
+ .extended_capabilities_mask = he_if_types_ext_capa_sta,
360
+ .extended_capabilities_len = sizeof(he_if_types_ext_capa_sta),
361
+ },
362
+};
363
+
364
+static int
365
+iwl_mvm_op_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant)
366
+{
367
+ struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
368
+ *tx_ant = iwl_mvm_get_valid_tx_ant(mvm);
369
+ *rx_ant = iwl_mvm_get_valid_rx_ant(mvm);
370
+ return 0;
371
+}
372
+
404373 int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
405374 {
406375 struct ieee80211_hw *hw = mvm->hw;
....@@ -411,12 +380,15 @@
411380 WLAN_CIPHER_SUITE_TKIP,
412381 WLAN_CIPHER_SUITE_CCMP,
413382 };
383
+#ifdef CONFIG_PM_SLEEP
384
+ bool unified = fw_has_capa(&mvm->fw->ucode_capa,
385
+ IWL_UCODE_TLV_CAPA_CNSLDTD_D3_D0_IMG);
386
+#endif
414387
415388 /* Tell mac80211 our characteristics */
416389 ieee80211_hw_set(hw, SIGNAL_DBM);
417390 ieee80211_hw_set(hw, SPECTRUM_MGMT);
418391 ieee80211_hw_set(hw, REPORTS_TX_ACK_STATUS);
419
- ieee80211_hw_set(hw, QUEUE_CONTROL);
420392 ieee80211_hw_set(hw, WANT_MONITOR_VIF);
421393 ieee80211_hw_set(hw, SUPPORTS_PS);
422394 ieee80211_hw_set(hw, SUPPORTS_DYNAMIC_PS);
....@@ -429,6 +401,23 @@
429401 ieee80211_hw_set(hw, SUPPORTS_AMSDU_IN_AMPDU);
430402 ieee80211_hw_set(hw, NEEDS_UNIQUE_STA_ADDR);
431403 ieee80211_hw_set(hw, DEAUTH_NEED_MGD_TX_PREP);
404
+ ieee80211_hw_set(hw, SUPPORTS_VHT_EXT_NSS_BW);
405
+ ieee80211_hw_set(hw, BUFF_MMPDU_TXQ);
406
+ ieee80211_hw_set(hw, STA_MMPDU_TXQ);
407
+ /*
408
+ * On older devices, enabling TX A-MSDU occasionally leads to
409
+ * something getting messed up, the command read from the FIFO
410
+ * gets out of sync and isn't a TX command, so that we have an
411
+ * assert EDC.
412
+ *
413
+ * It's not clear where the bug is, but since we didn't used to
414
+ * support A-MSDU until moving the mac80211 iTXQs, just leave it
415
+ * for older devices. We also don't see this issue on any newer
416
+ * devices.
417
+ */
418
+ if (mvm->trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_9000)
419
+ ieee80211_hw_set(hw, TX_AMSDU);
420
+ ieee80211_hw_set(hw, TX_FRAG_LIST);
432421
433422 if (iwl_mvm_has_tlc_offload(mvm)) {
434423 ieee80211_hw_set(hw, TX_AMPDU_SETUP_IN_HW);
....@@ -474,6 +463,7 @@
474463
475464 hw->uapsd_queues = IWL_MVM_UAPSD_QUEUES;
476465 hw->uapsd_max_sp_len = IWL_UAPSD_MAX_SP;
466
+ hw->max_tx_fragments = mvm->trans->max_skb_frags;
477467
478468 BUILD_BUG_ON(ARRAY_SIZE(mvm->ciphers) < ARRAY_SIZE(mvm_ciphers) + 6);
479469 memcpy(mvm->ciphers, mvm_ciphers, sizeof(mvm_ciphers));
....@@ -489,23 +479,23 @@
489479 hw->wiphy->n_cipher_suites++;
490480 }
491481
492
- /* Enable 11w if software crypto is not enabled (as the
493
- * firmware will interpret some mgmt packets, so enabling it
494
- * with software crypto isn't safe).
495
- */
496
- if (!iwlwifi_mod_params.swcrypto) {
497
- ieee80211_hw_set(hw, MFP_CAPABLE);
482
+ if (iwlwifi_mod_params.swcrypto)
483
+ IWL_ERR(mvm,
484
+ "iwlmvm doesn't allow to disable HW crypto, check swcrypto module parameter\n");
485
+ if (!iwlwifi_mod_params.bt_coex_active)
486
+ IWL_ERR(mvm,
487
+ "iwlmvm doesn't allow to disable BT Coex, check bt_coex_active module parameter\n");
488
+
489
+ ieee80211_hw_set(hw, MFP_CAPABLE);
490
+ mvm->ciphers[hw->wiphy->n_cipher_suites] = WLAN_CIPHER_SUITE_AES_CMAC;
491
+ hw->wiphy->n_cipher_suites++;
492
+ if (iwl_mvm_has_new_rx_api(mvm)) {
498493 mvm->ciphers[hw->wiphy->n_cipher_suites] =
499
- WLAN_CIPHER_SUITE_AES_CMAC;
494
+ WLAN_CIPHER_SUITE_BIP_GMAC_128;
500495 hw->wiphy->n_cipher_suites++;
501
- if (iwl_mvm_has_new_rx_api(mvm)) {
502
- mvm->ciphers[hw->wiphy->n_cipher_suites] =
503
- WLAN_CIPHER_SUITE_BIP_GMAC_128;
504
- hw->wiphy->n_cipher_suites++;
505
- mvm->ciphers[hw->wiphy->n_cipher_suites] =
506
- WLAN_CIPHER_SUITE_BIP_GMAC_256;
507
- hw->wiphy->n_cipher_suites++;
508
- }
496
+ mvm->ciphers[hw->wiphy->n_cipher_suites] =
497
+ WLAN_CIPHER_SUITE_BIP_GMAC_256;
498
+ hw->wiphy->n_cipher_suites++;
509499 }
510500
511501 /* currently FW API supports only one optional cipher scheme */
....@@ -530,6 +520,13 @@
530520 hw->wiphy->n_cipher_suites++;
531521 }
532522
523
+ if (fw_has_capa(&mvm->fw->ucode_capa,
524
+ IWL_UCODE_TLV_CAPA_FTM_CALIBRATED)) {
525
+ wiphy_ext_feature_set(hw->wiphy,
526
+ NL80211_EXT_FEATURE_ENABLE_FTM_RESPONDER);
527
+ hw->wiphy->pmsr_capa = &iwl_mvm_pmsr_capa;
528
+ }
529
+
533530 ieee80211_hw_set(hw, SINGLE_SCAN_ON_ALL_BANDS);
534531 hw->wiphy->features |=
535532 NL80211_FEATURE_SCHED_SCAN_RANDOM_MAC_ADDR |
....@@ -539,6 +536,7 @@
539536 hw->sta_data_size = sizeof(struct iwl_mvm_sta);
540537 hw->vif_data_size = sizeof(struct iwl_mvm_vif);
541538 hw->chanctx_data_size = sizeof(u16);
539
+ hw->txq_data_size = sizeof(struct iwl_mvm_txq);
542540
543541 hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
544542 BIT(NL80211_IFTYPE_P2P_CLIENT) |
....@@ -548,6 +546,17 @@
548546 BIT(NL80211_IFTYPE_ADHOC);
549547
550548 hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN;
549
+ wiphy_ext_feature_set(hw->wiphy, NL80211_EXT_FEATURE_VHT_IBSS);
550
+
551
+ /* The new Tx API does not allow to pass the key or keyid of a MPDU to
552
+ * the hw, preventing us to control which key(id) to use per MPDU.
553
+ * Till that's fixed we can't use Extended Key ID for the newer cards.
554
+ */
555
+ if (!iwl_mvm_has_new_tx_api(mvm))
556
+ wiphy_ext_feature_set(hw->wiphy,
557
+ NL80211_EXT_FEATURE_EXT_KEY_ID);
558
+ hw->wiphy->features |= NL80211_FEATURE_HT_IBSS;
559
+
551560 hw->wiphy->regulatory_flags |= REGULATORY_ENABLE_RELAX_NO_IR;
552561 if (iwl_mvm_is_lar_supported(mvm))
553562 hw->wiphy->regulatory_flags |= REGULATORY_WIPHY_SELF_MANAGED;
....@@ -564,8 +573,6 @@
564573
565574 hw->wiphy->max_remain_on_channel_duration = 10000;
566575 hw->max_listen_interval = IWL_CONN_MAX_LISTEN_INTERVAL;
567
- /* we can compensate an offset of up to 3 channels = 15 MHz */
568
- hw->wiphy->max_adj_channel_rssi_comp = 3 * 5;
569576
570577 /* Extract MAC address */
571578 memcpy(mvm->addresses[0].addr, mvm->nvm_data->hw_addr, ETH_ALEN);
....@@ -622,7 +629,7 @@
622629
623630 hw->wiphy->max_sched_scan_reqs = 1;
624631 hw->wiphy->max_sched_scan_ssids = PROBE_OPTION_MAX;
625
- hw->wiphy->max_match_sets = IWL_SCAN_MAX_PROFILES;
632
+ hw->wiphy->max_match_sets = iwl_umac_scan_get_max_profiles(mvm->fw);
626633 /* we create the 802.11 header and zero length SSID IE. */
627634 hw->wiphy->max_sched_scan_ie_len =
628635 SCAN_OFFLOAD_PROBE_REQ_SIZE - 24 - 2;
....@@ -659,14 +666,17 @@
659666 IWL_UCODE_TLV_CAPA_WFA_TPC_REP_IE_SUPPORT))
660667 hw->wiphy->features |= NL80211_FEATURE_WFA_TPC_IE_IN_PROBES;
661668
669
+ if (iwl_fw_lookup_cmd_ver(mvm->fw, IWL_ALWAYS_LONG_GROUP,
670
+ WOWLAN_KEK_KCK_MATERIAL,
671
+ IWL_FW_CMD_VER_UNKNOWN) == 3)
672
+ hw->wiphy->flags |= WIPHY_FLAG_SUPPORTS_EXT_KEK_KCK;
673
+
662674 if (fw_has_api(&mvm->fw->ucode_capa,
663675 IWL_UCODE_TLV_API_SCAN_TSF_REPORT)) {
664676 wiphy_ext_feature_set(hw->wiphy,
665677 NL80211_EXT_FEATURE_SCAN_START_TIME);
666678 wiphy_ext_feature_set(hw->wiphy,
667679 NL80211_EXT_FEATURE_BSS_PARENT_TSF);
668
- wiphy_ext_feature_set(hw->wiphy,
669
- NL80211_EXT_FEATURE_SET_SCAN_DWELL);
670680 }
671681
672682 if (iwl_mvm_is_oce_supported(mvm)) {
....@@ -680,16 +690,20 @@
680690 NL80211_EXT_FEATURE_OCE_PROBE_REQ_HIGH_TX_RATE);
681691 }
682692
693
+ if (mvm->nvm_data->sku_cap_11ax_enable &&
694
+ !iwlwifi_mod_params.disable_11ax) {
695
+ hw->wiphy->iftype_ext_capab = he_iftypes_ext_capa;
696
+ hw->wiphy->num_iftype_ext_capab =
697
+ ARRAY_SIZE(he_iftypes_ext_capa);
698
+
699
+ ieee80211_hw_set(hw, SUPPORTS_MULTI_BSSID);
700
+ ieee80211_hw_set(hw, SUPPORTS_ONLY_HE_MULTI_BSSID);
701
+ }
702
+
683703 mvm->rts_threshold = IEEE80211_MAX_RTS_THRESHOLD;
684704
685705 #ifdef CONFIG_PM_SLEEP
686
- if (iwl_mvm_is_d0i3_supported(mvm) &&
687
- device_can_wakeup(mvm->trans->dev)) {
688
- mvm->wowlan.flags = WIPHY_WOWLAN_ANY;
689
- hw->wiphy->wowlan = &mvm->wowlan;
690
- }
691
-
692
- if (mvm->fw->img[IWL_UCODE_WOWLAN].num_sec &&
706
+ if ((unified || mvm->fw->img[IWL_UCODE_WOWLAN].num_sec) &&
693707 mvm->trans->ops->d3_suspend &&
694708 mvm->trans->ops->d3_resume &&
695709 device_can_wakeup(mvm->trans->dev)) {
....@@ -698,15 +712,15 @@
698712 WIPHY_WOWLAN_EAP_IDENTITY_REQ |
699713 WIPHY_WOWLAN_RFKILL_RELEASE |
700714 WIPHY_WOWLAN_NET_DETECT;
701
- if (!iwlwifi_mod_params.swcrypto)
702
- mvm->wowlan.flags |= WIPHY_WOWLAN_SUPPORTS_GTK_REKEY |
703
- WIPHY_WOWLAN_GTK_REKEY_FAILURE |
704
- WIPHY_WOWLAN_4WAY_HANDSHAKE;
715
+ mvm->wowlan.flags |= WIPHY_WOWLAN_SUPPORTS_GTK_REKEY |
716
+ WIPHY_WOWLAN_GTK_REKEY_FAILURE |
717
+ WIPHY_WOWLAN_4WAY_HANDSHAKE;
705718
706719 mvm->wowlan.n_patterns = IWL_WOWLAN_MAX_PATTERNS;
707720 mvm->wowlan.pattern_min_len = IWL_WOWLAN_MIN_PATTERN_LEN;
708721 mvm->wowlan.pattern_max_len = IWL_WOWLAN_MAX_PATTERN_LEN;
709
- mvm->wowlan.max_nd_match_sets = IWL_SCAN_MAX_PROFILES;
722
+ mvm->wowlan.max_nd_match_sets =
723
+ iwl_umac_scan_get_max_profiles(mvm->fw);
710724 hw->wiphy->wowlan = &mvm->wowlan;
711725 }
712726 #endif
....@@ -742,57 +756,37 @@
742756 hw->netdev_features |= IWL_TX_CSUM_NETIF_FLAGS;
743757 }
744758
745
- ret = ieee80211_register_hw(mvm->hw);
746
- if (ret)
747
- iwl_mvm_leds_exit(mvm);
748
- mvm->init_status |= IWL_MVM_INIT_STATUS_REG_HW_INIT_COMPLETE;
749
-
750759 if (mvm->cfg->vht_mu_mimo_supported)
751760 wiphy_ext_feature_set(hw->wiphy,
752761 NL80211_EXT_FEATURE_MU_MIMO_AIR_SNIFFER);
753762
763
+ if (fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_PROTECTED_TWT))
764
+ wiphy_ext_feature_set(hw->wiphy,
765
+ NL80211_EXT_FEATURE_PROTECTED_TWT);
766
+
767
+ hw->wiphy->available_antennas_tx = iwl_mvm_get_valid_tx_ant(mvm);
768
+ hw->wiphy->available_antennas_rx = iwl_mvm_get_valid_rx_ant(mvm);
769
+
770
+ ret = ieee80211_register_hw(mvm->hw);
771
+ if (ret) {
772
+ iwl_mvm_leds_exit(mvm);
773
+ }
774
+
754775 return ret;
755776 }
756777
757
-static bool iwl_mvm_defer_tx(struct iwl_mvm *mvm,
758
- struct ieee80211_sta *sta,
759
- struct sk_buff *skb)
778
+static void iwl_mvm_tx_skb(struct iwl_mvm *mvm, struct sk_buff *skb,
779
+ struct ieee80211_sta *sta)
760780 {
761
- struct iwl_mvm_sta *mvmsta;
762
- bool defer = false;
781
+ if (likely(sta)) {
782
+ if (likely(iwl_mvm_tx_skb_sta(mvm, skb, sta) == 0))
783
+ return;
784
+ } else {
785
+ if (likely(iwl_mvm_tx_skb_non_sta(mvm, skb) == 0))
786
+ return;
787
+ }
763788
764
- /*
765
- * double check the IN_D0I3 flag both before and after
766
- * taking the spinlock, in order to prevent taking
767
- * the spinlock when not needed.
768
- */
769
- if (likely(!test_bit(IWL_MVM_STATUS_IN_D0I3, &mvm->status)))
770
- return false;
771
-
772
- spin_lock(&mvm->d0i3_tx_lock);
773
- /*
774
- * testing the flag again ensures the skb dequeue
775
- * loop (on d0i3 exit) hasn't run yet.
776
- */
777
- if (!test_bit(IWL_MVM_STATUS_IN_D0I3, &mvm->status))
778
- goto out;
779
-
780
- mvmsta = iwl_mvm_sta_from_mac80211(sta);
781
- if (mvmsta->sta_id == IWL_MVM_INVALID_STA ||
782
- mvmsta->sta_id != mvm->d0i3_ap_sta_id)
783
- goto out;
784
-
785
- __skb_queue_tail(&mvm->d0i3_tx, skb);
786
- ieee80211_stop_queues(mvm->hw);
787
-
788
- /* trigger wakeup */
789
- iwl_mvm_ref(mvm, IWL_MVM_REF_TX);
790
- iwl_mvm_unref(mvm, IWL_MVM_REF_TX);
791
-
792
- defer = true;
793
-out:
794
- spin_unlock(&mvm->d0i3_tx_lock);
795
- return defer;
789
+ ieee80211_free_txskb(mvm->hw, skb);
796790 }
797791
798792 static void iwl_mvm_mac_tx(struct ieee80211_hw *hw,
....@@ -803,13 +797,15 @@
803797 struct ieee80211_sta *sta = control->sta;
804798 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
805799 struct ieee80211_hdr *hdr = (void *)skb->data;
800
+ bool offchannel = IEEE80211_SKB_CB(skb)->flags &
801
+ IEEE80211_TX_CTL_TX_OFFCHAN;
806802
807803 if (iwl_mvm_is_radio_killed(mvm)) {
808804 IWL_DEBUG_DROP(mvm, "Dropping - RF/CT KILL\n");
809805 goto drop;
810806 }
811807
812
- if (info->hw_queue == IWL_MVM_OFFCHANNEL_QUEUE &&
808
+ if (offchannel &&
813809 !test_bit(IWL_MVM_STATUS_ROC_RUNNING, &mvm->status) &&
814810 !test_bit(IWL_MVM_STATUS_ROC_AUX_RUNNING, &mvm->status))
815811 goto drop;
....@@ -822,13 +818,13 @@
822818 sta = NULL;
823819
824820 /* If there is no sta, and it's not offchannel - send through AP */
825
- if (info->control.vif->type == NL80211_IFTYPE_STATION &&
826
- info->hw_queue != IWL_MVM_OFFCHANNEL_QUEUE && !sta) {
821
+ if (!sta && info->control.vif->type == NL80211_IFTYPE_STATION &&
822
+ !offchannel) {
827823 struct iwl_mvm_vif *mvmvif =
828824 iwl_mvm_vif_from_mac80211(info->control.vif);
829825 u8 ap_sta_id = READ_ONCE(mvmvif->ap_sta_id);
830826
831
- if (ap_sta_id < IWL_MVM_STATION_COUNT) {
827
+ if (ap_sta_id < mvm->fw->ucode_capa.num_stations) {
832828 /* mac80211 holds rcu read lock */
833829 sta = rcu_dereference(mvm->fw_id_to_mac_id[ap_sta_id]);
834830 if (IS_ERR_OR_NULL(sta))
....@@ -836,37 +832,104 @@
836832 }
837833 }
838834
839
- if (sta) {
840
- if (iwl_mvm_defer_tx(mvm, sta, skb))
841
- return;
842
- if (iwl_mvm_tx_skb(mvm, skb, sta))
843
- goto drop;
844
- return;
845
- }
846
-
847
- if (iwl_mvm_tx_skb_non_sta(mvm, skb))
848
- goto drop;
835
+ iwl_mvm_tx_skb(mvm, skb, sta);
849836 return;
850837 drop:
851838 ieee80211_free_txskb(hw, skb);
852839 }
853840
854
-static inline bool iwl_enable_rx_ampdu(const struct iwl_cfg *cfg)
841
+void iwl_mvm_mac_itxq_xmit(struct ieee80211_hw *hw, struct ieee80211_txq *txq)
855842 {
856
- if (iwlwifi_mod_params.disable_11n & IWL_DISABLE_HT_RXAGG)
857
- return false;
858
- return true;
843
+ struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
844
+ struct iwl_mvm_txq *mvmtxq = iwl_mvm_txq_from_mac80211(txq);
845
+ struct sk_buff *skb = NULL;
846
+
847
+ /*
848
+ * No need for threads to be pending here, they can leave the first
849
+ * taker all the work.
850
+ *
851
+ * mvmtxq->tx_request logic:
852
+ *
853
+ * If 0, no one is currently TXing, set to 1 to indicate current thread
854
+ * will now start TX and other threads should quit.
855
+ *
856
+ * If 1, another thread is currently TXing, set to 2 to indicate to
857
+ * that thread that there was another request. Since that request may
858
+ * have raced with the check whether the queue is empty, the TXing
859
+ * thread should check the queue's status one more time before leaving.
860
+ * This check is done in order to not leave any TX hanging in the queue
861
+ * until the next TX invocation (which may not even happen).
862
+ *
863
+ * If 2, another thread is currently TXing, and it will already double
864
+ * check the queue, so do nothing.
865
+ */
866
+ if (atomic_fetch_add_unless(&mvmtxq->tx_request, 1, 2))
867
+ return;
868
+
869
+ rcu_read_lock();
870
+ do {
871
+ while (likely(!mvmtxq->stopped &&
872
+ (mvm->trans->system_pm_mode ==
873
+ IWL_PLAT_PM_MODE_DISABLED))) {
874
+ skb = ieee80211_tx_dequeue(hw, txq);
875
+
876
+ if (!skb) {
877
+ if (txq->sta)
878
+ IWL_DEBUG_TX(mvm,
879
+ "TXQ of sta %pM tid %d is now empty\n",
880
+ txq->sta->addr,
881
+ txq->tid);
882
+ break;
883
+ }
884
+
885
+ iwl_mvm_tx_skb(mvm, skb, txq->sta);
886
+ }
887
+ } while (atomic_dec_return(&mvmtxq->tx_request));
888
+ rcu_read_unlock();
859889 }
860890
861
-static inline bool iwl_enable_tx_ampdu(const struct iwl_cfg *cfg)
891
+static void iwl_mvm_mac_wake_tx_queue(struct ieee80211_hw *hw,
892
+ struct ieee80211_txq *txq)
862893 {
863
- if (iwlwifi_mod_params.disable_11n & IWL_DISABLE_HT_TXAGG)
864
- return false;
865
- if (iwlwifi_mod_params.disable_11n & IWL_ENABLE_HT_TXAGG)
866
- return true;
894
+ struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
895
+ struct iwl_mvm_txq *mvmtxq = iwl_mvm_txq_from_mac80211(txq);
867896
868
- /* enabled by default */
869
- return true;
897
+ /*
898
+ * Please note that racing is handled very carefully here:
899
+ * mvmtxq->txq_id is updated during allocation, and mvmtxq->list is
900
+ * deleted afterwards.
901
+ * This means that if:
902
+ * mvmtxq->txq_id != INVALID_QUEUE && list_empty(&mvmtxq->list):
903
+ * queue is allocated and we can TX.
904
+ * mvmtxq->txq_id != INVALID_QUEUE && !list_empty(&mvmtxq->list):
905
+ * a race, should defer the frame.
906
+ * mvmtxq->txq_id == INVALID_QUEUE && list_empty(&mvmtxq->list):
907
+ * need to allocate the queue and defer the frame.
908
+ * mvmtxq->txq_id == INVALID_QUEUE && !list_empty(&mvmtxq->list):
909
+ * queue is already scheduled for allocation, no need to allocate,
910
+ * should defer the frame.
911
+ */
912
+
913
+ /* If the queue is allocated TX and return. */
914
+ if (!txq->sta || mvmtxq->txq_id != IWL_MVM_INVALID_QUEUE) {
915
+ /*
916
+ * Check that list is empty to avoid a race where txq_id is
917
+ * already updated, but the queue allocation work wasn't
918
+ * finished
919
+ */
920
+ if (unlikely(txq->sta && !list_empty(&mvmtxq->list)))
921
+ return;
922
+
923
+ iwl_mvm_mac_itxq_xmit(hw, txq);
924
+ return;
925
+ }
926
+
927
+ /* The list is being deleted only after the queue is fully allocated. */
928
+ if (!list_empty(&mvmtxq->list))
929
+ return;
930
+
931
+ list_add_tail(&mvmtxq->list, &mvm->add_stream_txqs);
932
+ schedule_work(&mvm->add_stream_wk);
870933 }
871934
872935 #define CHECK_BA_TRIGGER(_mvm, _trig, _tid_bm, _tid, _fmt...) \
....@@ -884,15 +947,12 @@
884947 struct iwl_fw_dbg_trigger_tlv *trig;
885948 struct iwl_fw_dbg_trigger_ba *ba_trig;
886949
887
- if (!iwl_fw_dbg_trigger_enabled(mvm->fw, FW_DBG_TRIGGER_BA))
950
+ trig = iwl_fw_dbg_trigger_on(&mvm->fwrt, ieee80211_vif_to_wdev(vif),
951
+ FW_DBG_TRIGGER_BA);
952
+ if (!trig)
888953 return;
889954
890
- trig = iwl_fw_dbg_get_trigger(mvm->fw, FW_DBG_TRIGGER_BA);
891955 ba_trig = (void *)trig->data;
892
-
893
- if (!iwl_fw_dbg_trigger_check_stop(&mvm->fwrt,
894
- ieee80211_vif_to_wdev(vif), trig))
895
- return;
896956
897957 switch (action) {
898958 case IEEE80211_AMPDU_TX_OPERATIONAL: {
....@@ -930,7 +990,6 @@
930990 {
931991 struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
932992 int ret;
933
- bool tx_agg_ref = false;
934993 struct ieee80211_sta *sta = params->sta;
935994 enum ieee80211_ampdu_mlme_action action = params->action;
936995 u16 tid = params->tid;
....@@ -944,31 +1003,6 @@
9441003
9451004 if (!(mvm->nvm_data->sku_cap_11n_enable))
9461005 return -EACCES;
947
-
948
- /* return from D0i3 before starting a new Tx aggregation */
949
- switch (action) {
950
- case IEEE80211_AMPDU_TX_START:
951
- case IEEE80211_AMPDU_TX_STOP_CONT:
952
- case IEEE80211_AMPDU_TX_STOP_FLUSH:
953
- case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT:
954
- case IEEE80211_AMPDU_TX_OPERATIONAL:
955
- /*
956
- * for tx start, wait synchronously until D0i3 exit to
957
- * get the correct sequence number for the tid.
958
- * additionally, some other ampdu actions use direct
959
- * target access, which is not handled automatically
960
- * by the trans layer (unlike commands), so wait for
961
- * d0i3 exit in these cases as well.
962
- */
963
- ret = iwl_mvm_ref_sync(mvm, IWL_MVM_REF_TX_AGG);
964
- if (ret)
965
- return ret;
966
-
967
- tx_agg_ref = true;
968
- break;
969
- default:
970
- break;
971
- }
9721006
9731007 mutex_lock(&mvm->mutex);
9741008
....@@ -984,7 +1018,7 @@
9841018 mvmvif = iwl_mvm_vif_from_mac80211(vif);
9851019 cancel_delayed_work(&mvmvif->uapsd_nonagg_detected_wk);
9861020 }
987
- if (!iwl_enable_rx_ampdu(mvm->cfg)) {
1021
+ if (!iwl_enable_rx_ampdu()) {
9881022 ret = -EINVAL;
9891023 break;
9901024 }
....@@ -996,7 +1030,7 @@
9961030 timeout);
9971031 break;
9981032 case IEEE80211_AMPDU_TX_START:
999
- if (!iwl_enable_tx_ampdu(mvm->cfg)) {
1033
+ if (!iwl_enable_tx_ampdu()) {
10001034 ret = -EINVAL;
10011035 break;
10021036 }
....@@ -1030,13 +1064,6 @@
10301064 }
10311065 mutex_unlock(&mvm->mutex);
10321066
1033
- /*
1034
- * If the tid is marked as started, we won't use it for offloaded
1035
- * traffic on the next D0i3 entry. It's safe to unref.
1036
- */
1037
- if (tx_agg_ref)
1038
- iwl_mvm_unref(mvm, IWL_MVM_REF_TX_AGG);
1039
-
10401067 return ret;
10411068 }
10421069
....@@ -1055,33 +1082,24 @@
10551082
10561083 mvmvif->phy_ctxt = NULL;
10571084 memset(&mvmvif->bf_data, 0, sizeof(mvmvif->bf_data));
1085
+ memset(&mvmvif->probe_resp_data, 0, sizeof(mvmvif->probe_resp_data));
10581086 }
10591087
10601088 static void iwl_mvm_restart_cleanup(struct iwl_mvm *mvm)
10611089 {
1062
- /* clear the D3 reconfig, we only need it to avoid dumping a
1063
- * firmware coredump on reconfiguration, we shouldn't do that
1064
- * on D3->D0 transition
1065
- */
1066
- if (!test_and_clear_bit(IWL_MVM_STATUS_D3_RECONFIG, &mvm->status)) {
1067
- mvm->fwrt.dump.desc = &iwl_dump_desc_assert;
1068
- iwl_fw_error_dump(&mvm->fwrt);
1069
- }
1070
-
1071
- /* cleanup all stale references (scan, roc), but keep the
1072
- * ucode_down ref until reconfig is complete
1073
- */
1074
- iwl_mvm_unref_all_except(mvm, IWL_MVM_REF_UCODE_DOWN);
1075
-
10761090 iwl_mvm_stop_device(mvm);
1091
+
1092
+ mvm->cur_aid = 0;
10771093
10781094 mvm->scan_status = 0;
10791095 mvm->ps_disabled = false;
1080
- mvm->calibrating = false;
1096
+ mvm->rfkill_safe_init_done = false;
10811097
10821098 /* just in case one was running */
10831099 iwl_mvm_cleanup_roc_te(mvm);
10841100 ieee80211_remain_on_channel_expired(mvm->hw);
1101
+
1102
+ iwl_mvm_ftm_restart(mvm);
10851103
10861104 /*
10871105 * cleanup all interfaces, even inactive ones, as some might have
....@@ -1090,18 +1108,13 @@
10901108 ieee80211_iterate_interfaces(mvm->hw, 0, iwl_mvm_cleanup_iterator, mvm);
10911109
10921110 mvm->p2p_device_vif = NULL;
1093
- mvm->d0i3_ap_sta_id = IWL_MVM_INVALID_STA;
10941111
10951112 iwl_mvm_reset_phy_ctxts(mvm);
10961113 memset(mvm->fw_key_table, 0, sizeof(mvm->fw_key_table));
1097
- memset(mvm->sta_deferred_frames, 0, sizeof(mvm->sta_deferred_frames));
10981114 memset(&mvm->last_bt_notif, 0, sizeof(mvm->last_bt_notif));
10991115 memset(&mvm->last_bt_ci_cmd, 0, sizeof(mvm->last_bt_ci_cmd));
11001116
11011117 ieee80211_wake_queues(mvm->hw);
1102
-
1103
- /* clear any stale d0i3 state */
1104
- clear_bit(IWL_MVM_STATUS_IN_D0I3, &mvm->status);
11051118
11061119 mvm->vif_count = 0;
11071120 mvm->rx_ba_sessions = 0;
....@@ -1127,16 +1140,13 @@
11271140 clear_bit(IWL_MVM_STATUS_HW_RESTART_REQUESTED, &mvm->status);
11281141 /* Clean up some internal and mac80211 state on restart */
11291142 iwl_mvm_restart_cleanup(mvm);
1130
- } else {
1131
- /* Hold the reference to prevent runtime suspend while
1132
- * the start procedure runs. It's a bit confusing
1133
- * that the UCODE_DOWN reference is taken, but it just
1134
- * means "UCODE is not UP yet". ( TODO: rename this
1135
- * reference).
1136
- */
1137
- iwl_mvm_ref(mvm, IWL_MVM_REF_UCODE_DOWN);
11381143 }
11391144 ret = iwl_mvm_up(mvm);
1145
+
1146
+ iwl_dbg_tlv_time_point(&mvm->fwrt, IWL_FW_INI_TIME_POINT_POST_INIT,
1147
+ NULL);
1148
+ iwl_dbg_tlv_time_point(&mvm->fwrt, IWL_FW_INI_TIME_POINT_PERIODIC,
1149
+ NULL);
11401150
11411151 if (ret && test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)) {
11421152 /* Something went wrong - we need to finish some cleanup
....@@ -1144,7 +1154,6 @@
11441154 * would do.
11451155 */
11461156 clear_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status);
1147
- iwl_mvm_d0i3_enable_tx(mvm, NULL);
11481157 }
11491158
11501159 return ret;
....@@ -1154,22 +1163,30 @@
11541163 {
11551164 struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
11561165 int ret;
1157
-
1158
- /* Some hw restart cleanups must not hold the mutex */
1159
- if (test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)) {
1160
- /*
1161
- * Make sure we are out of d0i3. This is needed
1162
- * to make sure the reference accounting is correct
1163
- * (and there is no stale d0i3_exit_work).
1164
- */
1165
- wait_event_timeout(mvm->d0i3_exit_waitq,
1166
- !test_bit(IWL_MVM_STATUS_IN_D0I3,
1167
- &mvm->status),
1168
- HZ);
1169
- }
1166
+ int retry, max_retry = 0;
11701167
11711168 mutex_lock(&mvm->mutex);
1172
- ret = __iwl_mvm_mac_start(mvm);
1169
+
1170
+ /* we are starting the mac not in error flow, and restart is enabled */
1171
+ if (!test_bit(IWL_MVM_STATUS_HW_RESTART_REQUESTED, &mvm->status) &&
1172
+ iwlwifi_mod_params.fw_restart) {
1173
+ max_retry = IWL_MAX_INIT_RETRY;
1174
+ /*
1175
+ * This will prevent mac80211 recovery flows to trigger during
1176
+ * init failures
1177
+ */
1178
+ set_bit(IWL_MVM_STATUS_STARTING, &mvm->status);
1179
+ }
1180
+
1181
+ for (retry = 0; retry <= max_retry; retry++) {
1182
+ ret = __iwl_mvm_mac_start(mvm);
1183
+ if (!ret)
1184
+ break;
1185
+
1186
+ IWL_ERR(mvm, "mac start retry %d\n", retry);
1187
+ }
1188
+ clear_bit(IWL_MVM_STATUS_STARTING, &mvm->status);
1189
+
11731190 mutex_unlock(&mvm->mutex);
11741191
11751192 return ret;
....@@ -1182,14 +1199,13 @@
11821199 mutex_lock(&mvm->mutex);
11831200
11841201 clear_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status);
1185
- iwl_mvm_d0i3_enable_tx(mvm, NULL);
1202
+
11861203 ret = iwl_mvm_update_quotas(mvm, true, NULL);
11871204 if (ret)
11881205 IWL_ERR(mvm, "Failed to update quotas after restart (%d)\n",
11891206 ret);
11901207
1191
- /* allow transport/FW low power modes */
1192
- iwl_mvm_unref(mvm, IWL_MVM_REF_UCODE_DOWN);
1208
+ iwl_mvm_send_recovery_cmd(mvm, ERROR_RECOVERY_END_OF_RECOVERY);
11931209
11941210 /*
11951211 * If we have TDLS peers, remove them. We don't know the last seqno/PN
....@@ -1198,17 +1214,6 @@
11981214 iwl_mvm_teardown_tdls_peers(mvm);
11991215
12001216 mutex_unlock(&mvm->mutex);
1201
-}
1202
-
1203
-static void iwl_mvm_resume_complete(struct iwl_mvm *mvm)
1204
-{
1205
- if (iwl_mvm_is_d0i3_supported(mvm) &&
1206
- iwl_mvm_enter_d0i3_on_suspend(mvm))
1207
- WARN_ONCE(!wait_event_timeout(mvm->d0i3_exit_waitq,
1208
- !test_bit(IWL_MVM_STATUS_IN_D0I3,
1209
- &mvm->status),
1210
- HZ),
1211
- "D0i3 exit on resume timed out\n");
12121217 }
12131218
12141219 static void
....@@ -1222,7 +1227,6 @@
12221227 iwl_mvm_restart_complete(mvm);
12231228 break;
12241229 case IEEE80211_RECONFIG_TYPE_SUSPEND:
1225
- iwl_mvm_resume_complete(mvm);
12261230 break;
12271231 }
12281232 }
....@@ -1231,6 +1235,8 @@
12311235 {
12321236 lockdep_assert_held(&mvm->mutex);
12331237
1238
+ iwl_mvm_ftm_initiator_smooth_stop(mvm);
1239
+
12341240 /* firmware counters are obviously reset now, but we shouldn't
12351241 * partially track so also clear the fw_reset_accu counters.
12361242 */
....@@ -1238,19 +1244,13 @@
12381244
12391245 /* async_handlers_wk is now blocked */
12401246
1241
- /*
1242
- * The work item could be running or queued if the
1243
- * ROC time event stops just as we get here.
1244
- */
1245
- flush_work(&mvm->roc_done_wk);
1247
+ if (iwl_fw_lookup_cmd_ver(mvm->fw, LONG_GROUP, ADD_STA, 0) < 12)
1248
+ iwl_mvm_rm_aux_sta(mvm);
12461249
12471250 iwl_mvm_stop_device(mvm);
12481251
12491252 iwl_mvm_async_handlers_purge(mvm);
12501253 /* async_handlers_list is empty and will stay empty: HW is stopped */
1251
-
1252
- /* the fw is stopped, the aux sta is dead: clean up driver state */
1253
- iwl_mvm_del_aux_sta(mvm);
12541254
12551255 /*
12561256 * Clear IN_HW_RESTART and HW_RESTART_REQUESTED flag when stopping the
....@@ -1284,7 +1284,6 @@
12841284 {
12851285 struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
12861286
1287
- flush_work(&mvm->d0i3_exit_work);
12881287 flush_work(&mvm->async_handlers_wk);
12891288 flush_work(&mvm->add_stream_wk);
12901289
....@@ -1298,10 +1297,14 @@
12981297 */
12991298 clear_bit(IWL_MVM_STATUS_FIRMWARE_RUNNING, &mvm->status);
13001299
1301
- iwl_fw_cancel_dump(&mvm->fwrt);
13021300 cancel_delayed_work_sync(&mvm->cs_tx_unblock_dwork);
13031301 cancel_delayed_work_sync(&mvm->scan_timeout_dwork);
1304
- iwl_fw_free_dump_desc(&mvm->fwrt);
1302
+
1303
+ /*
1304
+ * The work item could be running or queued if the
1305
+ * ROC time event stops just as we get here.
1306
+ */
1307
+ flush_work(&mvm->roc_done_wk);
13051308
13061309 mutex_lock(&mvm->mutex);
13071310 __iwl_mvm_mac_stop(mvm);
....@@ -1331,21 +1334,127 @@
13311334 static int iwl_mvm_set_tx_power(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
13321335 s16 tx_power)
13331336 {
1337
+ int len;
13341338 struct iwl_dev_tx_power_cmd cmd = {
1335
- .v3.set_mode = cpu_to_le32(IWL_TX_POWER_MODE_SET_MAC),
1336
- .v3.mac_context_id =
1339
+ .common.set_mode = cpu_to_le32(IWL_TX_POWER_MODE_SET_MAC),
1340
+ .common.mac_context_id =
13371341 cpu_to_le32(iwl_mvm_vif_from_mac80211(vif)->id),
1338
- .v3.pwr_restriction = cpu_to_le16(8 * tx_power),
1342
+ .common.pwr_restriction = cpu_to_le16(8 * tx_power),
13391343 };
1340
- int len = sizeof(cmd);
1344
+ u8 cmd_ver = iwl_fw_lookup_cmd_ver(mvm->fw, LONG_GROUP,
1345
+ REDUCE_TX_POWER_CMD,
1346
+ IWL_FW_CMD_VER_UNKNOWN);
13411347
13421348 if (tx_power == IWL_DEFAULT_MAX_TX_POWER)
1343
- cmd.v3.pwr_restriction = cpu_to_le16(IWL_DEV_MAX_TX_POWER);
1349
+ cmd.common.pwr_restriction = cpu_to_le16(IWL_DEV_MAX_TX_POWER);
13441350
1345
- if (!fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_TX_POWER_ACK))
1351
+ if (cmd_ver == 6)
1352
+ len = sizeof(cmd.v6);
1353
+ else if (fw_has_api(&mvm->fw->ucode_capa,
1354
+ IWL_UCODE_TLV_API_REDUCE_TX_POWER))
1355
+ len = sizeof(cmd.v5);
1356
+ else if (fw_has_capa(&mvm->fw->ucode_capa,
1357
+ IWL_UCODE_TLV_CAPA_TX_POWER_ACK))
1358
+ len = sizeof(cmd.v4);
1359
+ else
13461360 len = sizeof(cmd.v3);
13471361
1362
+ /* all structs have the same common part, add it */
1363
+ len += sizeof(cmd.common);
1364
+
13481365 return iwl_mvm_send_cmd_pdu(mvm, REDUCE_TX_POWER_CMD, 0, len, &cmd);
1366
+}
1367
+
1368
+static int iwl_mvm_post_channel_switch(struct ieee80211_hw *hw,
1369
+ struct ieee80211_vif *vif)
1370
+{
1371
+ struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
1372
+ struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
1373
+ int ret;
1374
+
1375
+ mutex_lock(&mvm->mutex);
1376
+
1377
+ if (mvmvif->csa_failed) {
1378
+ mvmvif->csa_failed = false;
1379
+ ret = -EIO;
1380
+ goto out_unlock;
1381
+ }
1382
+
1383
+ if (vif->type == NL80211_IFTYPE_STATION) {
1384
+ struct iwl_mvm_sta *mvmsta;
1385
+
1386
+ mvmvif->csa_bcn_pending = false;
1387
+ mvmsta = iwl_mvm_sta_from_staid_protected(mvm,
1388
+ mvmvif->ap_sta_id);
1389
+
1390
+ if (WARN_ON(!mvmsta)) {
1391
+ ret = -EIO;
1392
+ goto out_unlock;
1393
+ }
1394
+
1395
+ iwl_mvm_sta_modify_disable_tx(mvm, mvmsta, false);
1396
+
1397
+ iwl_mvm_mac_ctxt_changed(mvm, vif, false, NULL);
1398
+
1399
+ if (!fw_has_capa(&mvm->fw->ucode_capa,
1400
+ IWL_UCODE_TLV_CAPA_CHANNEL_SWITCH_CMD)) {
1401
+ ret = iwl_mvm_enable_beacon_filter(mvm, vif, 0);
1402
+ if (ret)
1403
+ goto out_unlock;
1404
+
1405
+ iwl_mvm_stop_session_protection(mvm, vif);
1406
+ }
1407
+ }
1408
+
1409
+ mvmvif->ps_disabled = false;
1410
+
1411
+ ret = iwl_mvm_power_update_ps(mvm);
1412
+
1413
+out_unlock:
1414
+ mutex_unlock(&mvm->mutex);
1415
+
1416
+ return ret;
1417
+}
1418
+
1419
+static void iwl_mvm_abort_channel_switch(struct ieee80211_hw *hw,
1420
+ struct ieee80211_vif *vif)
1421
+{
1422
+ struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
1423
+ struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
1424
+ struct iwl_chan_switch_te_cmd cmd = {
1425
+ .mac_id = cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id,
1426
+ mvmvif->color)),
1427
+ .action = cpu_to_le32(FW_CTXT_ACTION_REMOVE),
1428
+ };
1429
+
1430
+ IWL_DEBUG_MAC80211(mvm, "Abort CSA on mac %d\n", mvmvif->id);
1431
+
1432
+ mutex_lock(&mvm->mutex);
1433
+ if (!fw_has_capa(&mvm->fw->ucode_capa,
1434
+ IWL_UCODE_TLV_CAPA_CHANNEL_SWITCH_CMD))
1435
+ iwl_mvm_remove_csa_period(mvm, vif);
1436
+ else
1437
+ WARN_ON(iwl_mvm_send_cmd_pdu(mvm,
1438
+ WIDE_ID(MAC_CONF_GROUP,
1439
+ CHANNEL_SWITCH_TIME_EVENT_CMD),
1440
+ 0, sizeof(cmd), &cmd));
1441
+ mutex_unlock(&mvm->mutex);
1442
+
1443
+ WARN_ON(iwl_mvm_post_channel_switch(hw, vif));
1444
+}
1445
+
1446
+static void iwl_mvm_channel_switch_disconnect_wk(struct work_struct *wk)
1447
+{
1448
+ struct iwl_mvm *mvm;
1449
+ struct iwl_mvm_vif *mvmvif;
1450
+ struct ieee80211_vif *vif;
1451
+
1452
+ mvmvif = container_of(wk, struct iwl_mvm_vif, csa_work.work);
1453
+ vif = container_of((void *)mvmvif, struct ieee80211_vif, drv_priv);
1454
+ mvm = mvmvif->mvm;
1455
+
1456
+ iwl_mvm_abort_channel_switch(mvm->hw, vif);
1457
+ ieee80211_chswitch_done(vif, false);
13491458 }
13501459
13511460 static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw,
....@@ -1356,15 +1465,7 @@
13561465 int ret;
13571466
13581467 mvmvif->mvm = mvm;
1359
-
1360
- /*
1361
- * make sure D0i3 exit is completed, otherwise a target access
1362
- * during tx queue configuration could be done when still in
1363
- * D0i3 state.
1364
- */
1365
- ret = iwl_mvm_ref_sync(mvm, IWL_MVM_REF_ADD_IF);
1366
- if (ret)
1367
- return ret;
1468
+ RCU_INIT_POINTER(mvmvif->probe_resp_data, NULL);
13681469
13691470 /*
13701471 * Not much to do here. The stack will not allow interface
....@@ -1383,6 +1484,8 @@
13831484 ret = iwl_mvm_mac_ctxt_init(mvm, vif);
13841485 if (ret)
13851486 goto out_unlock;
1487
+
1488
+ rcu_assign_pointer(mvm->vif_id_to_mac[mvmvif->id], vif);
13861489
13871490 /* Counting number of interfaces is needed for legacy PM */
13881491 if (vif->type != NL80211_IFTYPE_P2P_DEVICE)
....@@ -1471,6 +1574,8 @@
14711574 }
14721575
14731576 iwl_mvm_tcm_add_vif(mvm, vif);
1577
+ INIT_DELAYED_WORK(&mvmvif->csa_work,
1578
+ iwl_mvm_channel_switch_disconnect_wk);
14741579
14751580 if (vif->type == NL80211_IFTYPE_MONITOR)
14761581 mvm->monitor_on = true;
....@@ -1497,8 +1602,6 @@
14971602 out_unlock:
14981603 mutex_unlock(&mvm->mutex);
14991604
1500
- iwl_mvm_unref(mvm, IWL_MVM_REF_ADD_IF);
1501
-
15021605 return ret;
15031606 }
15041607
....@@ -1520,6 +1623,7 @@
15201623 {
15211624 struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
15221625 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
1626
+ struct iwl_probe_resp_data *probe_data;
15231627
15241628 iwl_mvm_prepare_mac_removal(mvm, vif);
15251629
....@@ -1529,11 +1633,20 @@
15291633
15301634 mutex_lock(&mvm->mutex);
15311635
1636
+ probe_data = rcu_dereference_protected(mvmvif->probe_resp_data,
1637
+ lockdep_is_held(&mvm->mutex));
1638
+ RCU_INIT_POINTER(mvmvif->probe_resp_data, NULL);
1639
+ if (probe_data)
1640
+ kfree_rcu(probe_data, rcu_head);
1641
+
15321642 if (mvm->bf_allowed_vif == mvmvif) {
15331643 mvm->bf_allowed_vif = NULL;
15341644 vif->driver_flags &= ~(IEEE80211_VIF_BEACON_FILTER |
15351645 IEEE80211_VIF_SUPPORTS_CQM_RSSI);
15361646 }
1647
+
1648
+ if (vif->bss_conf.ftm_responder)
1649
+ memset(&mvm->ftm_resp_stats, 0, sizeof(mvm->ftm_resp_stats));
15371650
15381651 iwl_mvm_vif_dbgfs_clean(mvm, vif);
15391652
....@@ -1567,6 +1680,8 @@
15671680
15681681 iwl_mvm_power_update_mac(mvm);
15691682 iwl_mvm_mac_ctxt_remove(mvm, vif);
1683
+
1684
+ RCU_INIT_POINTER(mvm->vif_id_to_mac[mvmvif->id], NULL);
15701685
15711686 if (vif->type == NL80211_IFTYPE_MONITOR)
15721687 mvm->monitor_on = false;
....@@ -1972,11 +2087,15 @@
19722087 struct iwl_he_sta_context_cmd sta_ctxt_cmd = {
19732088 .sta_id = sta_id,
19742089 .tid_limit = IWL_MAX_TID_COUNT,
1975
- .bss_color = vif->bss_conf.bss_color,
2090
+ .bss_color = vif->bss_conf.he_bss_color.color,
19762091 .htc_trig_based_pkt_ext = vif->bss_conf.htc_trig_based_pkt_ext,
19772092 .frame_time_rts_th =
19782093 cpu_to_le16(vif->bss_conf.frame_time_rts_th),
19792094 };
2095
+ int size = fw_has_api(&mvm->fw->ucode_capa,
2096
+ IWL_UCODE_TLV_API_MBSSID_HE) ?
2097
+ sizeof(sta_ctxt_cmd) :
2098
+ sizeof(struct iwl_he_sta_context_cmd_v1);
19802099 struct ieee80211_sta *sta;
19812100 u32 flags;
19822101 int i;
....@@ -1984,7 +2103,7 @@
19842103 rcu_read_lock();
19852104
19862105 sta = rcu_dereference(mvm->fw_id_to_mac_id[sta_ctxt_cmd.sta_id]);
1987
- if (IS_ERR(sta)) {
2106
+ if (IS_ERR_OR_NULL(sta)) {
19882107 rcu_read_unlock();
19892108 WARN(1, "Can't find STA to configure HE\n");
19902109 return;
....@@ -1996,6 +2115,10 @@
19962115 }
19972116
19982117 flags = 0;
2118
+
2119
+ /* Block 26-tone RU OFDMA transmissions */
2120
+ if (mvmvif->he_ru_2mhz_block)
2121
+ flags |= STA_CTXT_HE_RU_2MHZ_BLOCK;
19992122
20002123 /* HTC flags */
20012124 if (sta->he_cap.he_cap_elem.mac_cap_info[0] &
....@@ -2018,10 +2141,6 @@
20182141 sta_ctxt_cmd.htc_flags |=
20192142 cpu_to_le32(IWL_HE_HTC_LINK_ADAP_BOTH);
20202143 }
2021
- if (sta->he_cap.he_cap_elem.mac_cap_info[2] &
2022
- IEEE80211_HE_MAC_CAP2_UL_MU_RESP_SCHED)
2023
- sta_ctxt_cmd.htc_flags |=
2024
- cpu_to_le32(IWL_HE_HTC_UL_MU_RESP_SCHED);
20252144 if (sta->he_cap.he_cap_elem.mac_cap_info[2] & IEEE80211_HE_MAC_CAP2_BSR)
20262145 sta_ctxt_cmd.htc_flags |= cpu_to_le32(IWL_HE_HTC_BSR_SUPP);
20272146 if (sta->he_cap.he_cap_elem.mac_cap_info[3] &
....@@ -2083,35 +2202,82 @@
20832202 }
20842203
20852204 flags |= STA_CTXT_HE_PACKET_EXT;
2205
+ } else if ((sta->he_cap.he_cap_elem.phy_cap_info[9] &
2206
+ IEEE80211_HE_PHY_CAP9_NOMIMAL_PKT_PADDING_MASK) !=
2207
+ IEEE80211_HE_PHY_CAP9_NOMIMAL_PKT_PADDING_RESERVED) {
2208
+ int low_th = -1;
2209
+ int high_th = -1;
2210
+
2211
+ /* Take the PPE thresholds from the nominal padding info */
2212
+ switch (sta->he_cap.he_cap_elem.phy_cap_info[9] &
2213
+ IEEE80211_HE_PHY_CAP9_NOMIMAL_PKT_PADDING_MASK) {
2214
+ case IEEE80211_HE_PHY_CAP9_NOMIMAL_PKT_PADDING_0US:
2215
+ low_th = IWL_HE_PKT_EXT_NONE;
2216
+ high_th = IWL_HE_PKT_EXT_NONE;
2217
+ break;
2218
+ case IEEE80211_HE_PHY_CAP9_NOMIMAL_PKT_PADDING_8US:
2219
+ low_th = IWL_HE_PKT_EXT_BPSK;
2220
+ high_th = IWL_HE_PKT_EXT_NONE;
2221
+ break;
2222
+ case IEEE80211_HE_PHY_CAP9_NOMIMAL_PKT_PADDING_16US:
2223
+ low_th = IWL_HE_PKT_EXT_NONE;
2224
+ high_th = IWL_HE_PKT_EXT_BPSK;
2225
+ break;
2226
+ }
2227
+
2228
+ /* Set the PPE thresholds accordingly */
2229
+ if (low_th >= 0 && high_th >= 0) {
2230
+ struct iwl_he_pkt_ext *pkt_ext =
2231
+ (struct iwl_he_pkt_ext *)&sta_ctxt_cmd.pkt_ext;
2232
+
2233
+ for (i = 0; i < MAX_HE_SUPP_NSS; i++) {
2234
+ u8 bw;
2235
+
2236
+ for (bw = 0; bw < MAX_HE_CHANNEL_BW_INDX;
2237
+ bw++) {
2238
+ pkt_ext->pkt_ext_qam_th[i][bw][0] =
2239
+ low_th;
2240
+ pkt_ext->pkt_ext_qam_th[i][bw][1] =
2241
+ high_th;
2242
+ }
2243
+ }
2244
+
2245
+ flags |= STA_CTXT_HE_PACKET_EXT;
2246
+ }
20862247 }
2248
+
2249
+ if (sta->he_cap.he_cap_elem.mac_cap_info[2] &
2250
+ IEEE80211_HE_MAC_CAP2_32BIT_BA_BITMAP)
2251
+ flags |= STA_CTXT_HE_32BIT_BA_BITMAP;
2252
+
2253
+ if (sta->he_cap.he_cap_elem.mac_cap_info[2] &
2254
+ IEEE80211_HE_MAC_CAP2_ACK_EN)
2255
+ flags |= STA_CTXT_HE_ACK_ENABLED;
2256
+
20872257 rcu_read_unlock();
20882258
20892259 /* Mark MU EDCA as enabled, unless none detected on some AC */
20902260 flags |= STA_CTXT_HE_MU_EDCA_CW;
2091
- for (i = 0; i < AC_NUM; i++) {
2261
+ for (i = 0; i < IEEE80211_NUM_ACS; i++) {
20922262 struct ieee80211_he_mu_edca_param_ac_rec *mu_edca =
20932263 &mvmvif->queue_params[i].mu_edca_param_rec;
2264
+ u8 ac = iwl_mvm_mac80211_ac_to_ucode_ac(i);
20942265
20952266 if (!mvmvif->queue_params[i].mu_edca) {
20962267 flags &= ~STA_CTXT_HE_MU_EDCA_CW;
20972268 break;
20982269 }
20992270
2100
- sta_ctxt_cmd.trig_based_txf[i].cwmin =
2271
+ sta_ctxt_cmd.trig_based_txf[ac].cwmin =
21012272 cpu_to_le16(mu_edca->ecw_min_max & 0xf);
2102
- sta_ctxt_cmd.trig_based_txf[i].cwmax =
2273
+ sta_ctxt_cmd.trig_based_txf[ac].cwmax =
21032274 cpu_to_le16((mu_edca->ecw_min_max & 0xf0) >> 4);
2104
- sta_ctxt_cmd.trig_based_txf[i].aifsn =
2275
+ sta_ctxt_cmd.trig_based_txf[ac].aifsn =
21052276 cpu_to_le16(mu_edca->aifsn);
2106
- sta_ctxt_cmd.trig_based_txf[i].mu_time =
2277
+ sta_ctxt_cmd.trig_based_txf[ac].mu_time =
21072278 cpu_to_le16(mu_edca->mu_edca_timer);
21082279 }
21092280
2110
- if (vif->bss_conf.multi_sta_back_32bit)
2111
- flags |= STA_CTXT_HE_32BIT_BA_BITMAP;
2112
-
2113
- if (vif->bss_conf.ack_enabled)
2114
- flags |= STA_CTXT_HE_ACK_ENABLED;
21152281
21162282 if (vif->bss_conf.uora_exists) {
21172283 flags |= STA_CTXT_HE_TRIG_RND_ALLOC;
....@@ -2122,13 +2288,23 @@
21222288 (vif->bss_conf.uora_ocw_range >> 3) & 0x7;
21232289 }
21242290
2125
- /* TODO: support Multi BSSID IE */
2291
+ if (vif->bss_conf.nontransmitted) {
2292
+ flags |= STA_CTXT_HE_REF_BSSID_VALID;
2293
+ ether_addr_copy(sta_ctxt_cmd.ref_bssid_addr,
2294
+ vif->bss_conf.transmitter_bssid);
2295
+ sta_ctxt_cmd.max_bssid_indicator =
2296
+ vif->bss_conf.bssid_indicator;
2297
+ sta_ctxt_cmd.bssid_index = vif->bss_conf.bssid_index;
2298
+ sta_ctxt_cmd.ema_ap = vif->bss_conf.ema_ap;
2299
+ sta_ctxt_cmd.profile_periodicity =
2300
+ vif->bss_conf.profile_periodicity;
2301
+ }
21262302
21272303 sta_ctxt_cmd.flags = cpu_to_le32(flags);
21282304
21292305 if (iwl_mvm_send_cmd_pdu(mvm, iwl_cmd_id(STA_HE_CTXT_CMD,
21302306 DATA_PATH_GROUP, 0),
2131
- 0, sizeof(sta_ctxt_cmd), &sta_ctxt_cmd))
2307
+ 0, size, &sta_ctxt_cmd))
21322308 IWL_ERR(mvm, "Failed to config FW to work HE!\n");
21332309 }
21342310
....@@ -2141,9 +2317,9 @@
21412317 int ret;
21422318
21432319 /*
2144
- * Re-calculate the tsf id, as the master-slave relations depend on the
2145
- * beacon interval, which was not known when the station interface was
2146
- * added.
2320
+ * Re-calculate the tsf id, as the leader-follower relations depend
2321
+ * on the beacon interval, which was not known when the station
2322
+ * interface was added.
21472323 */
21482324 if (changes & BSS_CHANGED_ASSOC && bss_conf->assoc) {
21492325 if (vif->bss_conf.he_support &&
....@@ -2152,6 +2328,12 @@
21522328
21532329 iwl_mvm_mac_ctxt_recalc_tsf_id(mvm, vif);
21542330 }
2331
+
2332
+ /* Update MU EDCA params */
2333
+ if (changes & BSS_CHANGED_QOS && mvmvif->associated &&
2334
+ bss_conf->assoc && vif->bss_conf.he_support &&
2335
+ !iwlwifi_mod_params.disable_11ax)
2336
+ iwl_mvm_cfg_he_sta(mvm, vif, mvmvif->ap_sta_id);
21552337
21562338 /*
21572339 * If we're not associated yet, take the (new) BSSID before associating
....@@ -2185,7 +2367,9 @@
21852367 }
21862368
21872369 if (test_bit(IWL_MVM_STATUS_IN_HW_RESTART,
2188
- &mvm->status)) {
2370
+ &mvm->status) &&
2371
+ !fw_has_capa(&mvm->fw->ucode_capa,
2372
+ IWL_UCODE_TLV_CAPA_SESSION_PROT_CMD)) {
21892373 /*
21902374 * If we're restarting then the firmware will
21912375 * obviously have lost synchronisation with
....@@ -2199,6 +2383,10 @@
21992383 *
22002384 * Set a large maximum delay to allow for more
22012385 * than a single interface.
2386
+ *
2387
+ * For new firmware versions, rely on the
2388
+ * firmware. This is relevant for DCM scenarios
2389
+ * only anyway.
22022390 */
22032391 u32 dur = (11 * vif->bss_conf.beacon_int) / 10;
22042392 iwl_mvm_protect_session(mvm, vif, dur, dur,
....@@ -2208,7 +2396,6 @@
22082396 iwl_mvm_sf_update(mvm, vif, false);
22092397 iwl_mvm_power_vif_assoc(mvm, vif);
22102398 if (vif->p2p) {
2211
- iwl_mvm_ref(mvm, IWL_MVM_REF_P2P_CLIENT);
22122399 iwl_mvm_update_smps(mvm, vif,
22132400 IWL_MVM_SMPS_REQ_PROT,
22142401 IEEE80211_SMPS_DYNAMIC);
....@@ -2218,7 +2405,10 @@
22182405 * If update fails - SF might be running in associated
22192406 * mode while disassociated - which is forbidden.
22202407 */
2221
- WARN_ONCE(iwl_mvm_sf_update(mvm, vif, false),
2408
+ ret = iwl_mvm_sf_update(mvm, vif, false);
2409
+ WARN_ONCE(ret &&
2410
+ !test_bit(IWL_MVM_STATUS_HW_RESTART_REQUESTED,
2411
+ &mvm->status),
22222412 "Failed to update SF upon disassociation\n");
22232413
22242414 /*
....@@ -2241,9 +2431,6 @@
22412431 IWL_ERR(mvm,
22422432 "failed to remove AP station\n");
22432433
2244
- if (mvm->d0i3_ap_sta_id == mvmvif->ap_sta_id)
2245
- mvm->d0i3_ap_sta_id =
2246
- IWL_MVM_INVALID_STA;
22472434 mvmvif->ap_sta_id = IWL_MVM_INVALID_STA;
22482435 }
22492436
....@@ -2251,9 +2438,6 @@
22512438 ret = iwl_mvm_update_quotas(mvm, false, NULL);
22522439 if (ret)
22532440 IWL_ERR(mvm, "failed to update quotas\n");
2254
-
2255
- if (vif->p2p)
2256
- iwl_mvm_unref(mvm, IWL_MVM_REF_P2P_CLIENT);
22572441
22582442 /* this will take the cleared BSSID from bss_conf */
22592443 ret = iwl_mvm_mac_ctxt_changed(mvm, vif, false, NULL);
....@@ -2293,8 +2477,11 @@
22932477 /*
22942478 * We received a beacon from the associated AP so
22952479 * remove the session protection.
2480
+ * A firmware with the new API will remove it automatically.
22962481 */
2297
- iwl_mvm_stop_session_protection(mvm, vif);
2482
+ if (!fw_has_capa(&mvm->fw->ucode_capa,
2483
+ IWL_UCODE_TLV_CAPA_SESSION_PROT_CMD))
2484
+ iwl_mvm_stop_session_protection(mvm, vif);
22982485
22992486 iwl_mvm_sf_update(mvm, vif, false);
23002487 WARN_ON(iwl_mvm_enable_beacon_filter(mvm, vif, 0));
....@@ -2340,15 +2527,7 @@
23402527 {
23412528 struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
23422529 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
2343
- int ret;
2344
-
2345
- /*
2346
- * iwl_mvm_mac_ctxt_add() might read directly from the device
2347
- * (the system time), so make sure it is available.
2348
- */
2349
- ret = iwl_mvm_ref_sync(mvm, IWL_MVM_REF_START_AP);
2350
- if (ret)
2351
- return ret;
2530
+ int ret, i;
23522531
23532532 mutex_lock(&mvm->mutex);
23542533
....@@ -2358,8 +2537,9 @@
23582537 goto out_unlock;
23592538
23602539 /*
2361
- * Re-calculate the tsf id, as the master-slave relations depend on the
2362
- * beacon interval, which was not known when the AP interface was added.
2540
+ * Re-calculate the tsf id, as the leader-follower relations depend on
2541
+ * the beacon interval, which was not known when the AP interface
2542
+ * was added.
23632543 */
23642544 if (vif->type == NL80211_IFTYPE_AP)
23652545 iwl_mvm_mac_ctxt_recalc_tsf_id(mvm, vif);
....@@ -2414,6 +2594,26 @@
24142594 /* must be set before quota calculations */
24152595 mvmvif->ap_ibss_active = true;
24162596
2597
+ /* send all the early keys to the device now */
2598
+ for (i = 0; i < ARRAY_SIZE(mvmvif->ap_early_keys); i++) {
2599
+ struct ieee80211_key_conf *key = mvmvif->ap_early_keys[i];
2600
+
2601
+ if (!key)
2602
+ continue;
2603
+
2604
+ mvmvif->ap_early_keys[i] = NULL;
2605
+
2606
+ ret = __iwl_mvm_mac_set_key(hw, SET_KEY, vif, NULL, key);
2607
+ if (ret)
2608
+ goto out_quota_failed;
2609
+ }
2610
+
2611
+ if (vif->type == NL80211_IFTYPE_AP && !vif->p2p) {
2612
+ iwl_mvm_vif_set_low_latency(mvmvif, true,
2613
+ LOW_LATENCY_VIF_TYPE);
2614
+ iwl_mvm_send_low_latency_cmd(mvm, true, mvmvif->id);
2615
+ }
2616
+
24172617 /* power updated needs to be done before quotas */
24182618 iwl_mvm_power_update_mac(mvm);
24192619
....@@ -2425,13 +2625,13 @@
24252625 if (vif->p2p && mvm->p2p_device_vif)
24262626 iwl_mvm_mac_ctxt_changed(mvm, mvm->p2p_device_vif, false, NULL);
24272627
2428
- iwl_mvm_ref(mvm, IWL_MVM_REF_AP_IBSS);
2429
-
24302628 iwl_mvm_bt_coex_vif_change(mvm);
24312629
24322630 /* we don't support TDLS during DCM */
24332631 if (iwl_mvm_phy_ctx_count(mvm) > 1)
24342632 iwl_mvm_teardown_tdls_peers(mvm);
2633
+
2634
+ iwl_mvm_ftm_restart_responder(mvm, vif);
24352635
24362636 goto out_unlock;
24372637
....@@ -2446,7 +2646,6 @@
24462646 iwl_mvm_mac_ctxt_remove(mvm, vif);
24472647 out_unlock:
24482648 mutex_unlock(&mvm->mutex);
2449
- iwl_mvm_unref(mvm, IWL_MVM_REF_START_AP);
24502649 return ret;
24512650 }
24522651
....@@ -2476,15 +2675,21 @@
24762675 mvmvif->ap_ibss_active = false;
24772676 mvm->ap_last_beacon_gp2 = 0;
24782677
2479
- iwl_mvm_bt_coex_vif_change(mvm);
2678
+ if (vif->type == NL80211_IFTYPE_AP && !vif->p2p) {
2679
+ iwl_mvm_vif_set_low_latency(mvmvif, false,
2680
+ LOW_LATENCY_VIF_TYPE);
2681
+ iwl_mvm_send_low_latency_cmd(mvm, false, mvmvif->id);
2682
+ }
24802683
2481
- iwl_mvm_unref(mvm, IWL_MVM_REF_AP_IBSS);
2684
+ iwl_mvm_bt_coex_vif_change(mvm);
24822685
24832686 /* Need to update the P2P Device MAC (only GO, IBSS is single vif) */
24842687 if (vif->p2p && mvm->p2p_device_vif)
24852688 iwl_mvm_mac_ctxt_changed(mvm, mvm->p2p_device_vif, false, NULL);
24862689
24872690 iwl_mvm_update_quotas(mvm, false, NULL);
2691
+
2692
+ iwl_mvm_ftm_responder_clear(mvm, vif);
24882693
24892694 /*
24902695 * This is not very nice, but the simplest:
....@@ -2535,6 +2740,15 @@
25352740 bss_conf->txpower);
25362741 iwl_mvm_set_tx_power(mvm, vif, bss_conf->txpower);
25372742 }
2743
+
2744
+ if (changes & BSS_CHANGED_FTM_RESPONDER) {
2745
+ int ret = iwl_mvm_ftm_start_responder(mvm, vif);
2746
+
2747
+ if (ret)
2748
+ IWL_WARN(mvm, "Failed to enable FTM responder (%d)\n",
2749
+ ret);
2750
+ }
2751
+
25382752 }
25392753
25402754 static void iwl_mvm_bss_info_changed(struct ieee80211_hw *hw,
....@@ -2543,14 +2757,6 @@
25432757 u32 changes)
25442758 {
25452759 struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
2546
-
2547
- /*
2548
- * iwl_mvm_bss_info_changed_station() might call
2549
- * iwl_mvm_protect_session(), which reads directly from
2550
- * the device (the system time), so make sure it is available.
2551
- */
2552
- if (iwl_mvm_ref_sync(mvm, IWL_MVM_REF_BSS_CHANGED))
2553
- return;
25542760
25552761 mutex_lock(&mvm->mutex);
25562762
....@@ -2575,7 +2781,6 @@
25752781 }
25762782
25772783 mutex_unlock(&mvm->mutex);
2578
- iwl_mvm_unref(mvm, IWL_MVM_REF_BSS_CHANGED);
25792784 }
25802785
25812786 static int iwl_mvm_mac_hw_scan(struct ieee80211_hw *hw,
....@@ -2664,7 +2869,7 @@
26642869 return;
26652870
26662871 spin_lock_bh(&mvmsta->lock);
2667
- for (tid = 0; tid < IWL_MAX_TID_COUNT; tid++) {
2872
+ for (tid = 0; tid < ARRAY_SIZE(mvmsta->tid_data); tid++) {
26682873 struct iwl_mvm_tid_data *tid_data = &mvmsta->tid_data[tid];
26692874
26702875 if (tid_data->txq_id == IWL_MVM_INVALID_QUEUE)
....@@ -2721,7 +2926,7 @@
27212926 struct iwl_mvm_sta *mvmsta;
27222927 bool sleeping = (notif->type != IWL_MVM_PM_EVENT_AWAKE);
27232928
2724
- if (WARN_ON(notif->sta_id >= ARRAY_SIZE(mvm->fw_id_to_mac_id)))
2929
+ if (WARN_ON(notif->sta_id >= mvm->fw->ucode_capa.num_stations))
27252930 return;
27262931
27272932 rcu_read_lock();
....@@ -2834,14 +3039,12 @@
28343039 struct iwl_fw_dbg_trigger_tlv *trig;
28353040 struct iwl_fw_dbg_trigger_tdls *tdls_trig;
28363041
2837
- if (!iwl_fw_dbg_trigger_enabled(mvm->fw, FW_DBG_TRIGGER_TDLS))
3042
+ trig = iwl_fw_dbg_trigger_on(&mvm->fwrt, ieee80211_vif_to_wdev(vif),
3043
+ FW_DBG_TRIGGER_TDLS);
3044
+ if (!trig)
28383045 return;
28393046
2840
- trig = iwl_fw_dbg_get_trigger(mvm->fw, FW_DBG_TRIGGER_TDLS);
28413047 tdls_trig = (void *)trig->data;
2842
- if (!iwl_fw_dbg_trigger_check_stop(&mvm->fwrt,
2843
- ieee80211_vif_to_wdev(vif), trig))
2844
- return;
28453048
28463049 if (!(tdls_trig->action_bitmap & BIT(action)))
28473050 return;
....@@ -2855,30 +3058,53 @@
28553058 peer_addr, action);
28563059 }
28573060
2858
-static void iwl_mvm_purge_deferred_tx_frames(struct iwl_mvm *mvm,
2859
- struct iwl_mvm_sta *mvm_sta)
3061
+struct iwl_mvm_he_obss_narrow_bw_ru_data {
3062
+ bool tolerated;
3063
+};
3064
+
3065
+static void iwl_mvm_check_he_obss_narrow_bw_ru_iter(struct wiphy *wiphy,
3066
+ struct cfg80211_bss *bss,
3067
+ void *_data)
28603068 {
2861
- struct iwl_mvm_tid_data *tid_data;
2862
- struct sk_buff *skb;
2863
- int i;
3069
+ struct iwl_mvm_he_obss_narrow_bw_ru_data *data = _data;
3070
+ const struct cfg80211_bss_ies *ies;
3071
+ const struct element *elem;
28643072
2865
- spin_lock_bh(&mvm_sta->lock);
2866
- for (i = 0; i <= IWL_MAX_TID_COUNT; i++) {
2867
- tid_data = &mvm_sta->tid_data[i];
3073
+ rcu_read_lock();
3074
+ ies = rcu_dereference(bss->ies);
3075
+ elem = cfg80211_find_elem(WLAN_EID_EXT_CAPABILITY, ies->data,
3076
+ ies->len);
28683077
2869
- while ((skb = __skb_dequeue(&tid_data->deferred_tx_frames))) {
2870
- struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
2871
-
2872
- /*
2873
- * The first deferred frame should've stopped the MAC
2874
- * queues, so we should never get a second deferred
2875
- * frame for the RA/TID.
2876
- */
2877
- iwl_mvm_start_mac_queues(mvm, BIT(info->hw_queue));
2878
- ieee80211_free_txskb(mvm->hw, skb);
2879
- }
3078
+ if (!elem || elem->datalen < 10 ||
3079
+ !(elem->data[10] &
3080
+ WLAN_EXT_CAPA10_OBSS_NARROW_BW_RU_TOLERANCE_SUPPORT)) {
3081
+ data->tolerated = false;
28803082 }
2881
- spin_unlock_bh(&mvm_sta->lock);
3083
+ rcu_read_unlock();
3084
+}
3085
+
3086
+static void iwl_mvm_check_he_obss_narrow_bw_ru(struct ieee80211_hw *hw,
3087
+ struct ieee80211_vif *vif)
3088
+{
3089
+ struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
3090
+ struct iwl_mvm_he_obss_narrow_bw_ru_data iter_data = {
3091
+ .tolerated = true,
3092
+ };
3093
+
3094
+ if (!(vif->bss_conf.chandef.chan->flags & IEEE80211_CHAN_RADAR)) {
3095
+ mvmvif->he_ru_2mhz_block = false;
3096
+ return;
3097
+ }
3098
+
3099
+ cfg80211_bss_iter(hw->wiphy, &vif->bss_conf.chandef,
3100
+ iwl_mvm_check_he_obss_narrow_bw_ru_iter,
3101
+ &iter_data);
3102
+
3103
+ /*
3104
+ * If there is at least one AP on radar channel that cannot
3105
+ * tolerate 26-tone RU UL OFDMA transmissions using HE TB PPDU.
3106
+ */
3107
+ mvmvif->he_ru_2mhz_block = !iter_data.tolerated;
28823108 }
28833109
28843110 static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw,
....@@ -2914,7 +3140,6 @@
29143140 */
29153141 if (old_state == IEEE80211_STA_NONE &&
29163142 new_state == IEEE80211_STA_NOTEXIST) {
2917
- iwl_mvm_purge_deferred_tx_frames(mvm, mvm_sta);
29183143 flush_work(&mvm->add_stream_wk);
29193144
29203145 /*
....@@ -2934,7 +3159,7 @@
29343159 * than 16. We can't avoid connecting at all, so refuse the
29353160 * station state change, this will cause mac80211 to abandon
29363161 * attempts to connect to this AP, and eventually wpa_s will
2937
- * blacklist the AP...
3162
+ * blocklist the AP...
29383163 */
29393164 if (vif->type == NL80211_IFTYPE_STATION &&
29403165 vif->bss_conf.beacon_int < 16) {
....@@ -2944,6 +3169,9 @@
29443169 ret = -EINVAL;
29453170 goto out_unlock;
29463171 }
3172
+
3173
+ if (vif->type == NL80211_IFTYPE_STATION)
3174
+ vif->bss_conf.he_support = sta->he_cap.has_he;
29473175
29483176 if (sta->tdls &&
29493177 (vif->p2p ||
....@@ -2961,6 +3189,8 @@
29613189 iwl_mvm_tdls_check_trigger(mvm, vif, sta->addr,
29623190 NL80211_TDLS_SETUP);
29633191 }
3192
+
3193
+ sta->max_rc_amsdu_len = 1;
29643194 } else if (old_state == IEEE80211_STA_NONE &&
29653195 new_state == IEEE80211_STA_AUTH) {
29663196 /*
....@@ -2973,7 +3203,19 @@
29733203 } else if (old_state == IEEE80211_STA_AUTH &&
29743204 new_state == IEEE80211_STA_ASSOC) {
29753205 if (vif->type == NL80211_IFTYPE_AP) {
3206
+ vif->bss_conf.he_support = sta->he_cap.has_he;
29763207 mvmvif->ap_assoc_sta_count++;
3208
+ iwl_mvm_mac_ctxt_changed(mvm, vif, false, NULL);
3209
+ if (vif->bss_conf.he_support &&
3210
+ !iwlwifi_mod_params.disable_11ax)
3211
+ iwl_mvm_cfg_he_sta(mvm, vif, mvm_sta->sta_id);
3212
+ } else if (vif->type == NL80211_IFTYPE_STATION) {
3213
+ vif->bss_conf.he_support = sta->he_cap.has_he;
3214
+
3215
+ mvmvif->he_ru_2mhz_block = false;
3216
+ if (sta->he_cap.has_he)
3217
+ iwl_mvm_check_he_obss_narrow_bw_ru(hw, vif);
3218
+
29773219 iwl_mvm_mac_ctxt_changed(mvm, vif, false, NULL);
29783220 }
29793221
....@@ -2982,6 +3224,7 @@
29823224 ret = iwl_mvm_update_sta(mvm, vif, sta);
29833225 } else if (old_state == IEEE80211_STA_ASSOC &&
29843226 new_state == IEEE80211_STA_AUTHORIZED) {
3227
+ ret = 0;
29853228
29863229 /* we don't support TDLS during DCM */
29873230 if (iwl_mvm_phy_ctx_count(mvm) > 1)
....@@ -2994,14 +3237,25 @@
29943237 /* enable beacon filtering */
29953238 WARN_ON(iwl_mvm_enable_beacon_filter(mvm, vif, 0));
29963239
3240
+ /*
3241
+ * Now that the station is authorized, i.e., keys were already
3242
+ * installed, need to indicate to the FW that
3243
+ * multicast data frames can be forwarded to the driver
3244
+ */
3245
+ iwl_mvm_mac_ctxt_changed(mvm, vif, false, NULL);
3246
+
29973247 iwl_mvm_rs_rate_init(mvm, sta, mvmvif->phy_ctxt->channel->band,
29983248 true);
2999
-
3000
- ret = 0;
30013249 } else if (old_state == IEEE80211_STA_AUTHORIZED &&
30023250 new_state == IEEE80211_STA_ASSOC) {
3251
+ /* Multicast data frames are no longer allowed */
3252
+ iwl_mvm_mac_ctxt_changed(mvm, vif, false, NULL);
3253
+
30033254 /* disable beacon filtering */
3004
- WARN_ON(iwl_mvm_disable_beacon_filter(mvm, vif, 0));
3255
+ ret = iwl_mvm_disable_beacon_filter(mvm, vif, 0);
3256
+ WARN_ON(ret &&
3257
+ !test_bit(IWL_MVM_STATUS_HW_RESTART_REQUESTED,
3258
+ &mvm->status));
30053259 ret = 0;
30063260 } else if (old_state == IEEE80211_STA_ASSOC &&
30073261 new_state == IEEE80211_STA_AUTH) {
....@@ -3021,6 +3275,11 @@
30213275 iwl_mvm_tdls_check_trigger(mvm, vif, sta->addr,
30223276 NL80211_TDLS_DISABLE_LINK);
30233277 }
3278
+
3279
+ if (unlikely(ret &&
3280
+ test_bit(IWL_MVM_STATUS_HW_RESTART_REQUESTED,
3281
+ &mvm->status)))
3282
+ ret = 0;
30243283 } else {
30253284 ret = -EIO;
30263285 }
....@@ -3053,6 +3312,13 @@
30533312 struct ieee80211_sta *sta, u32 changed)
30543313 {
30553314 struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
3315
+ struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
3316
+
3317
+ if (changed & (IEEE80211_RC_BW_CHANGED |
3318
+ IEEE80211_RC_SUPP_RATES_CHANGED |
3319
+ IEEE80211_RC_NSS_CHANGED))
3320
+ iwl_mvm_rs_rate_init(mvm, sta, mvmvif->phy_ctxt->channel->band,
3321
+ true);
30563322
30573323 if (vif->type == NL80211_IFTYPE_STATION &&
30583324 changed & IEEE80211_RC_NSS_CHANGED)
....@@ -3091,22 +3357,27 @@
30913357 u32 duration = IWL_MVM_TE_SESSION_PROTECTION_MAX_TIME_MS;
30923358 u32 min_duration = IWL_MVM_TE_SESSION_PROTECTION_MIN_TIME_MS;
30933359
3094
- /*
3095
- * iwl_mvm_protect_session() reads directly from the device
3096
- * (the system time), so make sure it is available.
3097
- */
3098
- if (iwl_mvm_ref_sync(mvm, IWL_MVM_REF_PREPARE_TX))
3099
- return;
3100
-
31013360 if (req_duration > duration)
31023361 duration = req_duration;
31033362
31043363 mutex_lock(&mvm->mutex);
3105
- /* Try really hard to protect the session and hear a beacon */
3106
- iwl_mvm_protect_session(mvm, vif, duration, min_duration, 500, false);
3364
+ /* Try really hard to protect the session and hear a beacon
3365
+ * The new session protection command allows us to protect the
3366
+ * session for a much longer time since the firmware will internally
3367
+ * create two events: a 300TU one with a very high priority that
3368
+ * won't be fragmented which should be enough for 99% of the cases,
3369
+ * and another one (which we configure here to be 900TU long) which
3370
+ * will have a slightly lower priority, but more importantly, can be
3371
+ * fragmented so that it'll allow other activities to run.
3372
+ */
3373
+ if (fw_has_capa(&mvm->fw->ucode_capa,
3374
+ IWL_UCODE_TLV_CAPA_SESSION_PROT_CMD))
3375
+ iwl_mvm_schedule_session_protection(mvm, vif, 900,
3376
+ min_duration, false);
3377
+ else
3378
+ iwl_mvm_protect_session(mvm, vif, duration,
3379
+ min_duration, 500, false);
31073380 mutex_unlock(&mvm->mutex);
3108
-
3109
- iwl_mvm_unref(mvm, IWL_MVM_REF_PREPARE_TX);
31103381 }
31113382
31123383 static int iwl_mvm_mac_sched_scan_start(struct ieee80211_hw *hw,
....@@ -3160,28 +3431,31 @@
31603431 return ret;
31613432 }
31623433
3163
-static int iwl_mvm_mac_set_key(struct ieee80211_hw *hw,
3164
- enum set_key_cmd cmd,
3165
- struct ieee80211_vif *vif,
3166
- struct ieee80211_sta *sta,
3167
- struct ieee80211_key_conf *key)
3434
+static int __iwl_mvm_mac_set_key(struct ieee80211_hw *hw,
3435
+ enum set_key_cmd cmd,
3436
+ struct ieee80211_vif *vif,
3437
+ struct ieee80211_sta *sta,
3438
+ struct ieee80211_key_conf *key)
31683439 {
3440
+ struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
31693441 struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
31703442 struct iwl_mvm_sta *mvmsta;
31713443 struct iwl_mvm_key_pn *ptk_pn;
31723444 int keyidx = key->keyidx;
3173
- int ret;
3445
+ int ret, i;
31743446 u8 key_offset;
3175
-
3176
- if (iwlwifi_mod_params.swcrypto) {
3177
- IWL_DEBUG_MAC80211(mvm, "leave - hwcrypto disabled\n");
3178
- return -EOPNOTSUPP;
3179
- }
31803447
31813448 switch (key->cipher) {
31823449 case WLAN_CIPHER_SUITE_TKIP:
3183
- key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC;
3184
- key->flags |= IEEE80211_KEY_FLAG_PUT_IV_SPACE;
3450
+ if (!mvm->trans->trans_cfg->gen2) {
3451
+ key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC;
3452
+ key->flags |= IEEE80211_KEY_FLAG_PUT_IV_SPACE;
3453
+ } else if (vif->type == NL80211_IFTYPE_STATION) {
3454
+ key->flags |= IEEE80211_KEY_FLAG_PUT_MIC_SPACE;
3455
+ } else {
3456
+ IWL_DEBUG_MAC80211(mvm, "Use SW encryption for TKIP\n");
3457
+ return -EOPNOTSUPP;
3458
+ }
31853459 break;
31863460 case WLAN_CIPHER_SUITE_CCMP:
31873461 case WLAN_CIPHER_SUITE_GCMP:
....@@ -3196,16 +3470,12 @@
31963470 break;
31973471 case WLAN_CIPHER_SUITE_WEP40:
31983472 case WLAN_CIPHER_SUITE_WEP104:
3199
- /* For non-client mode, only use WEP keys for TX as we probably
3200
- * don't have a station yet anyway and would then have to keep
3201
- * track of the keys, linking them to each of the clients/peers
3202
- * as they appear. For now, don't do that, for performance WEP
3203
- * offload doesn't really matter much, but we need it for some
3204
- * other offload features in client mode.
3205
- */
3206
- if (vif->type != NL80211_IFTYPE_STATION)
3207
- return 0;
3208
- break;
3473
+ if (vif->type == NL80211_IFTYPE_STATION)
3474
+ break;
3475
+ if (iwl_mvm_has_new_tx_api(mvm))
3476
+ return -EOPNOTSUPP;
3477
+ /* support HW crypto on TX */
3478
+ return 0;
32093479 default:
32103480 /* currently FW supports only one optional cipher scheme */
32113481 if (hw->n_cipher_schemes &&
....@@ -3214,8 +3484,6 @@
32143484 else
32153485 return -EOPNOTSUPP;
32163486 }
3217
-
3218
- mutex_lock(&mvm->mutex);
32193487
32203488 switch (cmd) {
32213489 case SET_KEY:
....@@ -3229,15 +3497,34 @@
32293497 */
32303498 if (key->cipher == WLAN_CIPHER_SUITE_AES_CMAC ||
32313499 key->cipher == WLAN_CIPHER_SUITE_BIP_GMAC_128 ||
3232
- key->cipher == WLAN_CIPHER_SUITE_BIP_GMAC_256)
3500
+ key->cipher == WLAN_CIPHER_SUITE_BIP_GMAC_256) {
32333501 ret = -EOPNOTSUPP;
3234
- else
3235
- ret = 0;
3502
+ break;
3503
+ }
32363504
32373505 if (key->cipher != WLAN_CIPHER_SUITE_GCMP &&
32383506 key->cipher != WLAN_CIPHER_SUITE_GCMP_256 &&
32393507 !iwl_mvm_has_new_tx_api(mvm)) {
32403508 key->hw_key_idx = STA_KEY_IDX_INVALID;
3509
+ ret = 0;
3510
+ break;
3511
+ }
3512
+
3513
+ if (!mvmvif->ap_ibss_active) {
3514
+ for (i = 0;
3515
+ i < ARRAY_SIZE(mvmvif->ap_early_keys);
3516
+ i++) {
3517
+ if (!mvmvif->ap_early_keys[i]) {
3518
+ mvmvif->ap_early_keys[i] = key;
3519
+ break;
3520
+ }
3521
+ }
3522
+
3523
+ if (i >= ARRAY_SIZE(mvmvif->ap_early_keys))
3524
+ ret = -ENOSPC;
3525
+ else
3526
+ ret = 0;
3527
+
32413528 break;
32423529 }
32433530 }
....@@ -3293,16 +3580,33 @@
32933580 ret = iwl_mvm_set_sta_key(mvm, vif, sta, key, key_offset);
32943581 if (ret) {
32953582 IWL_WARN(mvm, "set key failed\n");
3583
+ key->hw_key_idx = STA_KEY_IDX_INVALID;
32963584 /*
32973585 * can't add key for RX, but we don't need it
3298
- * in the device for TX so still return 0
3586
+ * in the device for TX so still return 0,
3587
+ * unless we have new TX API where we cannot
3588
+ * put key material into the TX_CMD
32993589 */
3300
- key->hw_key_idx = STA_KEY_IDX_INVALID;
3301
- ret = 0;
3590
+ if (iwl_mvm_has_new_tx_api(mvm))
3591
+ ret = -EOPNOTSUPP;
3592
+ else
3593
+ ret = 0;
33023594 }
33033595
33043596 break;
33053597 case DISABLE_KEY:
3598
+ ret = -ENOENT;
3599
+ for (i = 0; i < ARRAY_SIZE(mvmvif->ap_early_keys); i++) {
3600
+ if (mvmvif->ap_early_keys[i] == key) {
3601
+ mvmvif->ap_early_keys[i] = NULL;
3602
+ ret = 0;
3603
+ }
3604
+ }
3605
+
3606
+ /* found in pending list - don't do anything else */
3607
+ if (ret == 0)
3608
+ break;
3609
+
33063610 if (key->hw_key_idx == STA_KEY_IDX_INVALID) {
33073611 ret = 0;
33083612 break;
....@@ -3329,7 +3633,22 @@
33293633 ret = -EINVAL;
33303634 }
33313635
3636
+ return ret;
3637
+}
3638
+
3639
+static int iwl_mvm_mac_set_key(struct ieee80211_hw *hw,
3640
+ enum set_key_cmd cmd,
3641
+ struct ieee80211_vif *vif,
3642
+ struct ieee80211_sta *sta,
3643
+ struct ieee80211_key_conf *key)
3644
+{
3645
+ struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
3646
+ int ret;
3647
+
3648
+ mutex_lock(&mvm->mutex);
3649
+ ret = __iwl_mvm_mac_set_key(hw, cmd, vif, sta, key);
33323650 mutex_unlock(&mvm->mutex);
3651
+
33333652 return ret;
33343653 }
33353654
....@@ -3368,7 +3687,7 @@
33683687 resp = (void *)pkt->data;
33693688
33703689 IWL_DEBUG_TE(mvm,
3371
- "Aux ROC: Recieved response from ucode: status=%d uid=%d\n",
3690
+ "Aux ROC: Received response from ucode: status=%d uid=%d\n",
33723691 resp->status, resp->event_unique_id);
33733692
33743693 te_data->uid = le32_to_cpu(resp->event_unique_id);
....@@ -3392,7 +3711,7 @@
33923711 struct ieee80211_vif *vif,
33933712 int duration)
33943713 {
3395
- int res, time_reg = DEVICE_SYSTEM_TIME_REG;
3714
+ int res;
33963715 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
33973716 struct iwl_mvm_time_event_data *te_data = &mvmvif->hs_time_event_data;
33983717 static const u16 time_event_response[] = { HOT_SPOT_CMD };
....@@ -3405,14 +3724,19 @@
34053724 .id_and_color =
34063725 cpu_to_le32(FW_CMD_ID_AND_COLOR(MAC_INDEX_AUX, 0)),
34073726 .sta_id_and_color = cpu_to_le32(mvm->aux_sta.sta_id),
3408
- /* Set the channel info data */
3409
- .channel_info.band = (channel->band == NL80211_BAND_2GHZ) ?
3410
- PHY_BAND_24 : PHY_BAND_5,
3411
- .channel_info.channel = channel->hw_value,
3412
- .channel_info.width = PHY_VHT_CHANNEL_MODE20,
3413
- /* Set the time and duration */
3414
- .apply_time = cpu_to_le32(iwl_read_prph(mvm->trans, time_reg)),
3415
- };
3727
+ };
3728
+ struct iwl_hs20_roc_req_tail *tail = iwl_mvm_chan_info_cmd_tail(mvm,
3729
+ &aux_roc_req.channel_info);
3730
+ u16 len = sizeof(aux_roc_req) - iwl_mvm_chan_info_padding(mvm);
3731
+
3732
+ /* Set the channel info data */
3733
+ iwl_mvm_set_chan_info(mvm, &aux_roc_req.channel_info, channel->hw_value,
3734
+ iwl_mvm_phy_band_from_nl80211(channel->band),
3735
+ PHY_VHT_CHANNEL_MODE20,
3736
+ 0);
3737
+
3738
+ /* Set the time and duration */
3739
+ tail->apply_time = cpu_to_le32(iwl_mvm_get_systime(mvm));
34163740
34173741 delay = AUX_ROC_MIN_DELAY;
34183742 req_dur = MSEC_TO_TU(duration);
....@@ -3437,8 +3761,8 @@
34373761 }
34383762 }
34393763
3440
- aux_roc_req.duration = cpu_to_le32(req_dur);
3441
- aux_roc_req.apply_time_max_delay = cpu_to_le32(delay);
3764
+ tail->duration = cpu_to_le32(req_dur);
3765
+ tail->apply_time_max_delay = cpu_to_le32(delay);
34423766
34433767 IWL_DEBUG_TE(mvm,
34443768 "ROC: Requesting to remain on channel %u for %ums\n",
....@@ -3448,7 +3772,7 @@
34483772 duration, delay, dtim_interval);
34493773
34503774 /* Set the node address */
3451
- memcpy(aux_roc_req.node_addr, vif->addr, ETH_ALEN);
3775
+ memcpy(tail->node_addr, vif->addr, ETH_ALEN);
34523776
34533777 lockdep_assert_held(&mvm->mutex);
34543778
....@@ -3479,7 +3803,7 @@
34793803 ARRAY_SIZE(time_event_response),
34803804 iwl_mvm_rx_aux_roc, te_data);
34813805
3482
- res = iwl_mvm_send_cmd_pdu(mvm, HOT_SPOT_CMD, 0, sizeof(aux_roc_req),
3806
+ res = iwl_mvm_send_cmd_pdu(mvm, HOT_SPOT_CMD, 0, len,
34833807 &aux_roc_req);
34843808
34853809 if (res) {
....@@ -3532,6 +3856,17 @@
35323856 if (fw_has_capa(&mvm->fw->ucode_capa,
35333857 IWL_UCODE_TLV_CAPA_HOTSPOT_SUPPORT)) {
35343858 /* Use aux roc framework (HS20) */
3859
+ if (iwl_fw_lookup_cmd_ver(mvm->fw, LONG_GROUP,
3860
+ ADD_STA, 0) >= 12) {
3861
+ u32 lmac_id;
3862
+
3863
+ lmac_id = iwl_mvm_get_lmac_id(mvm->fw,
3864
+ channel->band);
3865
+ ret = iwl_mvm_add_aux_sta(mvm, lmac_id);
3866
+ if (WARN(ret,
3867
+ "Failed to allocate aux station"))
3868
+ goto out_unlock;
3869
+ }
35353870 ret = iwl_mvm_send_aux_roc_cmd(mvm, channel,
35363871 vif, duration);
35373872 goto out_unlock;
....@@ -3648,18 +3983,49 @@
36483983 return ret;
36493984 }
36503985
3651
-static int iwl_mvm_cancel_roc(struct ieee80211_hw *hw)
3986
+static int iwl_mvm_cancel_roc(struct ieee80211_hw *hw,
3987
+ struct ieee80211_vif *vif)
36523988 {
36533989 struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
36543990
36553991 IWL_DEBUG_MAC80211(mvm, "enter\n");
36563992
36573993 mutex_lock(&mvm->mutex);
3658
- iwl_mvm_stop_roc(mvm);
3994
+ iwl_mvm_stop_roc(mvm, vif);
36593995 mutex_unlock(&mvm->mutex);
36603996
36613997 IWL_DEBUG_MAC80211(mvm, "leave\n");
36623998 return 0;
3999
+}
4000
+
4001
+struct iwl_mvm_ftm_responder_iter_data {
4002
+ bool responder;
4003
+ struct ieee80211_chanctx_conf *ctx;
4004
+};
4005
+
4006
+static void iwl_mvm_ftm_responder_chanctx_iter(void *_data, u8 *mac,
4007
+ struct ieee80211_vif *vif)
4008
+{
4009
+ struct iwl_mvm_ftm_responder_iter_data *data = _data;
4010
+
4011
+ if (rcu_access_pointer(vif->chanctx_conf) == data->ctx &&
4012
+ vif->type == NL80211_IFTYPE_AP && vif->bss_conf.ftmr_params)
4013
+ data->responder = true;
4014
+}
4015
+
4016
+static bool iwl_mvm_is_ftm_responder_chanctx(struct iwl_mvm *mvm,
4017
+ struct ieee80211_chanctx_conf *ctx)
4018
+{
4019
+ struct iwl_mvm_ftm_responder_iter_data data = {
4020
+ .responder = false,
4021
+ .ctx = ctx,
4022
+ };
4023
+
4024
+ ieee80211_iterate_active_interfaces_atomic(mvm->hw,
4025
+ IEEE80211_IFACE_ITER_NORMAL,
4026
+ iwl_mvm_ftm_responder_chanctx_iter,
4027
+ &data);
4028
+ return data.responder;
36634029 }
36644030
36654031 static int __iwl_mvm_add_chanctx(struct iwl_mvm *mvm,
....@@ -3667,6 +4033,8 @@
36674033 {
36684034 u16 *phy_ctxt_id = (u16 *)ctx->drv_priv;
36694035 struct iwl_mvm_phy_ctxt *phy_ctxt;
4036
+ bool responder = iwl_mvm_is_ftm_responder_chanctx(mvm, ctx);
4037
+ struct cfg80211_chan_def *def = responder ? &ctx->def : &ctx->min_def;
36704038 int ret;
36714039
36724040 lockdep_assert_held(&mvm->mutex);
....@@ -3679,7 +4047,7 @@
36794047 goto out;
36804048 }
36814049
3682
- ret = iwl_mvm_phy_ctxt_changed(mvm, phy_ctxt, &ctx->min_def,
4050
+ ret = iwl_mvm_phy_ctxt_changed(mvm, phy_ctxt, def,
36834051 ctx->rx_chains_static,
36844052 ctx->rx_chains_dynamic);
36854053 if (ret) {
....@@ -3734,6 +4102,8 @@
37344102 struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
37354103 u16 *phy_ctxt_id = (u16 *)ctx->drv_priv;
37364104 struct iwl_mvm_phy_ctxt *phy_ctxt = &mvm->phy_ctxts[*phy_ctxt_id];
4105
+ bool responder = iwl_mvm_is_ftm_responder_chanctx(mvm, ctx);
4106
+ struct cfg80211_chan_def *def = responder ? &ctx->def : &ctx->min_def;
37374107
37384108 if (WARN_ONCE((phy_ctxt->ref > 1) &&
37394109 (changed & ~(IEEE80211_CHANCTX_CHANGE_WIDTH |
....@@ -3748,17 +4118,17 @@
37484118
37494119 /* we are only changing the min_width, may be a noop */
37504120 if (changed == IEEE80211_CHANCTX_CHANGE_MIN_WIDTH) {
3751
- if (phy_ctxt->width == ctx->min_def.width)
4121
+ if (phy_ctxt->width == def->width)
37524122 goto out_unlock;
37534123
37544124 /* we are just toggling between 20_NOHT and 20 */
37554125 if (phy_ctxt->width <= NL80211_CHAN_WIDTH_20 &&
3756
- ctx->min_def.width <= NL80211_CHAN_WIDTH_20)
4126
+ def->width <= NL80211_CHAN_WIDTH_20)
37574127 goto out_unlock;
37584128 }
37594129
37604130 iwl_mvm_bt_coex_vif_change(mvm);
3761
- iwl_mvm_phy_ctxt_changed(mvm, phy_ctxt, &ctx->min_def,
4131
+ iwl_mvm_phy_ctxt_changed(mvm, phy_ctxt, def,
37624132 ctx->rx_chains_static,
37634133 ctx->rx_chains_dynamic);
37644134
....@@ -3787,6 +4157,7 @@
37874157 mvmvif->ap_ibss_active = true;
37884158 break;
37894159 }
4160
+ /* fall through */
37904161 case NL80211_IFTYPE_ADHOC:
37914162 /*
37924163 * The AP binding flow is handled as part of the start_ap flow
....@@ -3839,25 +4210,19 @@
38394210 }
38404211
38414212 if (switching_chanctx && vif->type == NL80211_IFTYPE_STATION) {
3842
- u32 duration = 3 * vif->bss_conf.beacon_int;
3843
-
3844
- /* iwl_mvm_protect_session() reads directly from the
3845
- * device (the system time), so make sure it is
3846
- * available.
3847
- */
3848
- ret = iwl_mvm_ref_sync(mvm, IWL_MVM_REF_PROTECT_CSA);
3849
- if (ret)
3850
- goto out_remove_binding;
3851
-
3852
- /* Protect the session to make sure we hear the first
3853
- * beacon on the new channel.
3854
- */
38554213 mvmvif->csa_bcn_pending = true;
3856
- iwl_mvm_protect_session(mvm, vif, duration, duration,
3857
- vif->bss_conf.beacon_int / 2,
3858
- true);
38594214
3860
- iwl_mvm_unref(mvm, IWL_MVM_REF_PROTECT_CSA);
4215
+ if (!fw_has_capa(&mvm->fw->ucode_capa,
4216
+ IWL_UCODE_TLV_CAPA_CHANNEL_SWITCH_CMD)) {
4217
+ u32 duration = 3 * vif->bss_conf.beacon_int;
4218
+
4219
+ /* Protect the session to make sure we hear the first
4220
+ * beacon on the new channel.
4221
+ */
4222
+ iwl_mvm_protect_session(mvm, vif, duration, duration,
4223
+ vif->bss_conf.beacon_int / 2,
4224
+ true);
4225
+ }
38614226
38624227 iwl_mvm_update_quotas(mvm, false, NULL);
38634228 }
....@@ -3927,7 +4292,9 @@
39274292
39284293 disabled_vif = vif;
39294294
3930
- iwl_mvm_mac_ctxt_changed(mvm, vif, true, NULL);
4295
+ if (!fw_has_capa(&mvm->fw->ucode_capa,
4296
+ IWL_UCODE_TLV_CAPA_CHANNEL_SWITCH_CMD))
4297
+ iwl_mvm_mac_ctxt_changed(mvm, vif, true, NULL);
39314298 break;
39324299 default:
39334300 break;
....@@ -3937,6 +4304,9 @@
39374304 iwl_mvm_binding_remove_vif(mvm, vif);
39384305
39394306 out:
4307
+ if (fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_CHANNEL_SWITCH_CMD) &&
4308
+ switching_chanctx)
4309
+ return;
39404310 mvmvif->phy_ctxt = NULL;
39414311 iwl_mvm_power_update_mac(mvm);
39424312 }
....@@ -4111,8 +4481,8 @@
41114481 int err;
41124482 u32 noa_duration;
41134483
4114
- err = nla_parse(tb, IWL_MVM_TM_ATTR_MAX, data, len, iwl_mvm_tm_policy,
4115
- NULL);
4484
+ err = nla_parse_deprecated(tb, IWL_MVM_TM_ATTR_MAX, data, len,
4485
+ iwl_mvm_tm_policy, NULL);
41164486 if (err)
41174487 return err;
41184488
....@@ -4178,6 +4548,69 @@
41784548 "dummy channel switch op\n");
41794549 }
41804550
4551
+static int iwl_mvm_schedule_client_csa(struct iwl_mvm *mvm,
4552
+ struct ieee80211_vif *vif,
4553
+ struct ieee80211_channel_switch *chsw)
4554
+{
4555
+ struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
4556
+ struct iwl_chan_switch_te_cmd cmd = {
4557
+ .mac_id = cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id,
4558
+ mvmvif->color)),
4559
+ .action = cpu_to_le32(FW_CTXT_ACTION_ADD),
4560
+ .tsf = cpu_to_le32(chsw->timestamp),
4561
+ .cs_count = chsw->count,
4562
+ .cs_mode = chsw->block_tx,
4563
+ };
4564
+
4565
+ lockdep_assert_held(&mvm->mutex);
4566
+
4567
+ if (chsw->delay)
4568
+ cmd.cs_delayed_bcn_count =
4569
+ DIV_ROUND_UP(chsw->delay, vif->bss_conf.beacon_int);
4570
+
4571
+ return iwl_mvm_send_cmd_pdu(mvm,
4572
+ WIDE_ID(MAC_CONF_GROUP,
4573
+ CHANNEL_SWITCH_TIME_EVENT_CMD),
4574
+ 0, sizeof(cmd), &cmd);
4575
+}
4576
+
4577
+static int iwl_mvm_old_pre_chan_sw_sta(struct iwl_mvm *mvm,
4578
+ struct ieee80211_vif *vif,
4579
+ struct ieee80211_channel_switch *chsw)
4580
+{
4581
+ struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
4582
+ u32 apply_time;
4583
+
4584
+ /* Schedule the time event to a bit before beacon 1,
4585
+ * to make sure we're in the new channel when the
4586
+ * GO/AP arrives. In case count <= 1 immediately schedule the
4587
+ * TE (this might result with some packet loss or connection
4588
+ * loss).
4589
+ */
4590
+ if (chsw->count <= 1)
4591
+ apply_time = 0;
4592
+ else
4593
+ apply_time = chsw->device_timestamp +
4594
+ ((vif->bss_conf.beacon_int * (chsw->count - 1) -
4595
+ IWL_MVM_CHANNEL_SWITCH_TIME_CLIENT) * 1024);
4596
+
4597
+ if (chsw->block_tx)
4598
+ iwl_mvm_csa_client_absent(mvm, vif);
4599
+
4600
+ if (mvmvif->bf_data.bf_enabled) {
4601
+ int ret = iwl_mvm_disable_beacon_filter(mvm, vif, 0);
4602
+
4603
+ if (ret)
4604
+ return ret;
4605
+ }
4606
+
4607
+ iwl_mvm_schedule_csa_period(mvm, vif, vif->bss_conf.beacon_int,
4608
+ apply_time);
4609
+
4610
+ return 0;
4611
+}
4612
+
4613
+#define IWL_MAX_CSA_BLOCK_TX 1500
41814614 static int iwl_mvm_pre_channel_switch(struct ieee80211_hw *hw,
41824615 struct ieee80211_vif *vif,
41834616 struct ieee80211_channel_switch *chsw)
....@@ -4185,7 +4618,6 @@
41854618 struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
41864619 struct ieee80211_vif *csa_vif;
41874620 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
4188
- u32 apply_time;
41894621 int ret;
41904622
41914623 mutex_lock(&mvm->mutex);
....@@ -4229,30 +4661,29 @@
42294661
42304662 break;
42314663 case NL80211_IFTYPE_STATION:
4232
- /* Schedule the time event to a bit before beacon 1,
4233
- * to make sure we're in the new channel when the
4234
- * GO/AP arrives. In case count <= 1 immediately schedule the
4235
- * TE (this might result with some packet loss or connection
4236
- * loss).
4237
- */
4238
- if (chsw->count <= 1)
4239
- apply_time = 0;
4240
- else
4241
- apply_time = chsw->device_timestamp +
4242
- ((vif->bss_conf.beacon_int * (chsw->count - 1) -
4243
- IWL_MVM_CHANNEL_SWITCH_TIME_CLIENT) * 1024);
4244
-
4245
- if (chsw->block_tx)
4246
- iwl_mvm_csa_client_absent(mvm, vif);
4247
-
4248
- iwl_mvm_schedule_csa_period(mvm, vif, vif->bss_conf.beacon_int,
4249
- apply_time);
4250
- if (mvmvif->bf_data.bf_enabled) {
4251
- ret = iwl_mvm_disable_beacon_filter(mvm, vif, 0);
4252
- if (ret)
4253
- goto out_unlock;
4664
+ if (chsw->block_tx) {
4665
+ /*
4666
+ * In case of undetermined / long time with immediate
4667
+ * quiet monitor status to gracefully disconnect
4668
+ */
4669
+ if (!chsw->count ||
4670
+ chsw->count * vif->bss_conf.beacon_int >
4671
+ IWL_MAX_CSA_BLOCK_TX)
4672
+ schedule_delayed_work(&mvmvif->csa_work,
4673
+ msecs_to_jiffies(IWL_MAX_CSA_BLOCK_TX));
42544674 }
42554675
4676
+ if (!fw_has_capa(&mvm->fw->ucode_capa,
4677
+ IWL_UCODE_TLV_CAPA_CHANNEL_SWITCH_CMD)) {
4678
+ ret = iwl_mvm_old_pre_chan_sw_sta(mvm, vif, chsw);
4679
+ if (ret)
4680
+ goto out_unlock;
4681
+ } else {
4682
+ iwl_mvm_schedule_client_csa(mvm, vif, chsw);
4683
+ }
4684
+
4685
+ mvmvif->csa_count = chsw->count;
4686
+ mvmvif->csa_misbehave = false;
42564687 break;
42574688 default:
42584689 break;
....@@ -4273,52 +4704,42 @@
42734704 return ret;
42744705 }
42754706
4276
-static int iwl_mvm_post_channel_switch(struct ieee80211_hw *hw,
4277
- struct ieee80211_vif *vif)
4707
+static void iwl_mvm_channel_switch_rx_beacon(struct ieee80211_hw *hw,
4708
+ struct ieee80211_vif *vif,
4709
+ struct ieee80211_channel_switch *chsw)
42784710 {
4279
- struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
42804711 struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
4281
- int ret;
4712
+ struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
4713
+ struct iwl_chan_switch_te_cmd cmd = {
4714
+ .mac_id = cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id,
4715
+ mvmvif->color)),
4716
+ .action = cpu_to_le32(FW_CTXT_ACTION_MODIFY),
4717
+ .tsf = cpu_to_le32(chsw->timestamp),
4718
+ .cs_count = chsw->count,
4719
+ .cs_mode = chsw->block_tx,
4720
+ };
42824721
4283
- mutex_lock(&mvm->mutex);
4722
+ if (!fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_CS_MODIFY))
4723
+ return;
42844724
4285
- if (mvmvif->csa_failed) {
4286
- mvmvif->csa_failed = false;
4287
- ret = -EIO;
4288
- goto out_unlock;
4289
- }
4290
-
4291
- if (vif->type == NL80211_IFTYPE_STATION) {
4292
- struct iwl_mvm_sta *mvmsta;
4293
-
4294
- mvmvif->csa_bcn_pending = false;
4295
- mvmsta = iwl_mvm_sta_from_staid_protected(mvm,
4296
- mvmvif->ap_sta_id);
4297
-
4298
- if (WARN_ON(!mvmsta)) {
4299
- ret = -EIO;
4300
- goto out_unlock;
4725
+ if (chsw->count >= mvmvif->csa_count && chsw->block_tx) {
4726
+ if (mvmvif->csa_misbehave) {
4727
+ /* Second time, give up on this AP*/
4728
+ iwl_mvm_abort_channel_switch(hw, vif);
4729
+ ieee80211_chswitch_done(vif, false);
4730
+ mvmvif->csa_misbehave = false;
4731
+ return;
43014732 }
4302
-
4303
- iwl_mvm_sta_modify_disable_tx(mvm, mvmsta, false);
4304
-
4305
- iwl_mvm_mac_ctxt_changed(mvm, vif, false, NULL);
4306
-
4307
- ret = iwl_mvm_enable_beacon_filter(mvm, vif, 0);
4308
- if (ret)
4309
- goto out_unlock;
4310
-
4311
- iwl_mvm_stop_session_protection(mvm, vif);
4733
+ mvmvif->csa_misbehave = true;
43124734 }
4735
+ mvmvif->csa_count = chsw->count;
43134736
4314
- mvmvif->ps_disabled = false;
4737
+ IWL_DEBUG_MAC80211(mvm, "Modify CSA on mac %d\n", mvmvif->id);
43154738
4316
- ret = iwl_mvm_power_update_ps(mvm);
4317
-
4318
-out_unlock:
4319
- mutex_unlock(&mvm->mutex);
4320
-
4321
- return ret;
4739
+ WARN_ON(iwl_mvm_send_cmd_pdu(mvm,
4740
+ WIDE_ID(MAC_CONF_GROUP,
4741
+ CHANNEL_SWITCH_TIME_EVENT_CMD),
4742
+ CMD_ASYNC, sizeof(cmd), &cmd));
43224743 }
43234744
43244745 static void iwl_mvm_flush_no_vif(struct iwl_mvm *mvm, u32 queues, bool drop)
....@@ -4338,7 +4759,7 @@
43384759 }
43394760
43404761 mutex_lock(&mvm->mutex);
4341
- for (i = 0; i < ARRAY_SIZE(mvm->fw_id_to_mac_id); i++) {
4762
+ for (i = 0; i < mvm->fw->ucode_capa.num_stations; i++) {
43424763 struct ieee80211_sta *sta;
43434764
43444765 sta = rcu_dereference_protected(mvm->fw_id_to_mac_id[i],
....@@ -4347,7 +4768,7 @@
43474768 continue;
43484769
43494770 if (drop)
4350
- iwl_mvm_flush_sta_tids(mvm, i, 0xFF, 0);
4771
+ iwl_mvm_flush_sta_tids(mvm, i, 0xFFFF, 0);
43514772 else
43524773 iwl_mvm_wait_sta_queues_empty(mvm,
43534774 iwl_mvm_sta_from_mac80211(sta));
....@@ -4380,7 +4801,7 @@
43804801 mvmvif = iwl_mvm_vif_from_mac80211(vif);
43814802
43824803 /* flush the AP-station and all TDLS peers */
4383
- for (i = 0; i < ARRAY_SIZE(mvm->fw_id_to_mac_id); i++) {
4804
+ for (i = 0; i < mvm->fw->ucode_capa.num_stations; i++) {
43844805 sta = rcu_dereference_protected(mvm->fw_id_to_mac_id[i],
43854806 lockdep_is_held(&mvm->mutex));
43864807 if (IS_ERR_OR_NULL(sta))
....@@ -4394,7 +4815,7 @@
43944815 WARN_ON(i != mvmvif->ap_sta_id && !sta->tdls);
43954816
43964817 if (drop) {
4397
- if (iwl_mvm_flush_sta(mvm, mvmsta, false, 0))
4818
+ if (iwl_mvm_flush_sta(mvm, mvmsta, false))
43984819 IWL_ERR(mvm, "flush request fail\n");
43994820 } else {
44004821 msk |= mvmsta->tfd_queue_msk;
....@@ -4462,6 +4883,125 @@
44624883 return ret;
44634884 }
44644885
4886
+static void iwl_mvm_set_sta_rate(u32 rate_n_flags, struct rate_info *rinfo)
4887
+{
4888
+ switch (rate_n_flags & RATE_MCS_CHAN_WIDTH_MSK) {
4889
+ case RATE_MCS_CHAN_WIDTH_20:
4890
+ rinfo->bw = RATE_INFO_BW_20;
4891
+ break;
4892
+ case RATE_MCS_CHAN_WIDTH_40:
4893
+ rinfo->bw = RATE_INFO_BW_40;
4894
+ break;
4895
+ case RATE_MCS_CHAN_WIDTH_80:
4896
+ rinfo->bw = RATE_INFO_BW_80;
4897
+ break;
4898
+ case RATE_MCS_CHAN_WIDTH_160:
4899
+ rinfo->bw = RATE_INFO_BW_160;
4900
+ break;
4901
+ }
4902
+
4903
+ if (rate_n_flags & RATE_MCS_HT_MSK) {
4904
+ rinfo->flags |= RATE_INFO_FLAGS_MCS;
4905
+ rinfo->mcs = u32_get_bits(rate_n_flags, RATE_HT_MCS_INDEX_MSK);
4906
+ rinfo->nss = u32_get_bits(rate_n_flags,
4907
+ RATE_HT_MCS_NSS_MSK) + 1;
4908
+ if (rate_n_flags & RATE_MCS_SGI_MSK)
4909
+ rinfo->flags |= RATE_INFO_FLAGS_SHORT_GI;
4910
+ } else if (rate_n_flags & RATE_MCS_VHT_MSK) {
4911
+ rinfo->flags |= RATE_INFO_FLAGS_VHT_MCS;
4912
+ rinfo->mcs = u32_get_bits(rate_n_flags,
4913
+ RATE_VHT_MCS_RATE_CODE_MSK);
4914
+ rinfo->nss = u32_get_bits(rate_n_flags,
4915
+ RATE_VHT_MCS_NSS_MSK) + 1;
4916
+ if (rate_n_flags & RATE_MCS_SGI_MSK)
4917
+ rinfo->flags |= RATE_INFO_FLAGS_SHORT_GI;
4918
+ } else if (rate_n_flags & RATE_MCS_HE_MSK) {
4919
+ u32 gi_ltf = u32_get_bits(rate_n_flags,
4920
+ RATE_MCS_HE_GI_LTF_MSK);
4921
+
4922
+ rinfo->flags |= RATE_INFO_FLAGS_HE_MCS;
4923
+ rinfo->mcs = u32_get_bits(rate_n_flags,
4924
+ RATE_VHT_MCS_RATE_CODE_MSK);
4925
+ rinfo->nss = u32_get_bits(rate_n_flags,
4926
+ RATE_VHT_MCS_NSS_MSK) + 1;
4927
+
4928
+ if (rate_n_flags & RATE_MCS_HE_106T_MSK) {
4929
+ rinfo->bw = RATE_INFO_BW_HE_RU;
4930
+ rinfo->he_ru_alloc = NL80211_RATE_INFO_HE_RU_ALLOC_106;
4931
+ }
4932
+
4933
+ switch (rate_n_flags & RATE_MCS_HE_TYPE_MSK) {
4934
+ case RATE_MCS_HE_TYPE_SU:
4935
+ case RATE_MCS_HE_TYPE_EXT_SU:
4936
+ if (gi_ltf == 0 || gi_ltf == 1)
4937
+ rinfo->he_gi = NL80211_RATE_INFO_HE_GI_0_8;
4938
+ else if (gi_ltf == 2)
4939
+ rinfo->he_gi = NL80211_RATE_INFO_HE_GI_1_6;
4940
+ else if (rate_n_flags & RATE_MCS_SGI_MSK)
4941
+ rinfo->he_gi = NL80211_RATE_INFO_HE_GI_0_8;
4942
+ else
4943
+ rinfo->he_gi = NL80211_RATE_INFO_HE_GI_3_2;
4944
+ break;
4945
+ case RATE_MCS_HE_TYPE_MU:
4946
+ if (gi_ltf == 0 || gi_ltf == 1)
4947
+ rinfo->he_gi = NL80211_RATE_INFO_HE_GI_0_8;
4948
+ else if (gi_ltf == 2)
4949
+ rinfo->he_gi = NL80211_RATE_INFO_HE_GI_1_6;
4950
+ else
4951
+ rinfo->he_gi = NL80211_RATE_INFO_HE_GI_3_2;
4952
+ break;
4953
+ case RATE_MCS_HE_TYPE_TRIG:
4954
+ if (gi_ltf == 0 || gi_ltf == 1)
4955
+ rinfo->he_gi = NL80211_RATE_INFO_HE_GI_1_6;
4956
+ else
4957
+ rinfo->he_gi = NL80211_RATE_INFO_HE_GI_3_2;
4958
+ break;
4959
+ }
4960
+
4961
+ if (rate_n_flags & RATE_HE_DUAL_CARRIER_MODE_MSK)
4962
+ rinfo->he_dcm = 1;
4963
+ } else {
4964
+ switch (u32_get_bits(rate_n_flags, RATE_LEGACY_RATE_MSK)) {
4965
+ case IWL_RATE_1M_PLCP:
4966
+ rinfo->legacy = 10;
4967
+ break;
4968
+ case IWL_RATE_2M_PLCP:
4969
+ rinfo->legacy = 20;
4970
+ break;
4971
+ case IWL_RATE_5M_PLCP:
4972
+ rinfo->legacy = 55;
4973
+ break;
4974
+ case IWL_RATE_11M_PLCP:
4975
+ rinfo->legacy = 110;
4976
+ break;
4977
+ case IWL_RATE_6M_PLCP:
4978
+ rinfo->legacy = 60;
4979
+ break;
4980
+ case IWL_RATE_9M_PLCP:
4981
+ rinfo->legacy = 90;
4982
+ break;
4983
+ case IWL_RATE_12M_PLCP:
4984
+ rinfo->legacy = 120;
4985
+ break;
4986
+ case IWL_RATE_18M_PLCP:
4987
+ rinfo->legacy = 180;
4988
+ break;
4989
+ case IWL_RATE_24M_PLCP:
4990
+ rinfo->legacy = 240;
4991
+ break;
4992
+ case IWL_RATE_36M_PLCP:
4993
+ rinfo->legacy = 360;
4994
+ break;
4995
+ case IWL_RATE_48M_PLCP:
4996
+ rinfo->legacy = 480;
4997
+ break;
4998
+ case IWL_RATE_54M_PLCP:
4999
+ rinfo->legacy = 540;
5000
+ break;
5001
+ }
5002
+ }
5003
+}
5004
+
44655005 static void iwl_mvm_mac_sta_statistics(struct ieee80211_hw *hw,
44665006 struct ieee80211_vif *vif,
44675007 struct ieee80211_sta *sta,
....@@ -4472,8 +5012,15 @@
44725012 struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
44735013
44745014 if (mvmsta->avg_energy) {
4475
- sinfo->signal_avg = mvmsta->avg_energy;
5015
+ sinfo->signal_avg = -(s8)mvmsta->avg_energy;
44765016 sinfo->filled |= BIT_ULL(NL80211_STA_INFO_SIGNAL_AVG);
5017
+ }
5018
+
5019
+ if (iwl_mvm_has_tlc_offload(mvm)) {
5020
+ struct iwl_lq_sta_rs_fw *lq_sta = &mvmsta->lq_sta.rs_fw;
5021
+
5022
+ iwl_mvm_set_sta_rate(lq_sta->last_rate_n_flags, &sinfo->txrate);
5023
+ sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BITRATE);
44775024 }
44785025
44795026 /* if beacon filtering isn't on mac80211 does it anyway */
....@@ -4517,14 +5064,12 @@
45175064 struct iwl_fw_dbg_trigger_tlv *trig;
45185065 struct iwl_fw_dbg_trigger_mlme *trig_mlme;
45195066
4520
- if (!iwl_fw_dbg_trigger_enabled(mvm->fw, FW_DBG_TRIGGER_MLME))
5067
+ trig = iwl_fw_dbg_trigger_on(&mvm->fwrt, ieee80211_vif_to_wdev(vif),
5068
+ FW_DBG_TRIGGER_MLME);
5069
+ if (!trig)
45215070 return;
45225071
4523
- trig = iwl_fw_dbg_get_trigger(mvm->fw, FW_DBG_TRIGGER_MLME);
45245072 trig_mlme = (void *)trig->data;
4525
- if (!iwl_fw_dbg_trigger_check_stop(&mvm->fwrt,
4526
- ieee80211_vif_to_wdev(vif), trig))
4527
- return;
45285073
45295074 if (event->u.mlme.data == ASSOC_EVENT) {
45305075 if (event->u.mlme.status == MLME_DENIED)
....@@ -4559,14 +5104,12 @@
45595104 struct iwl_fw_dbg_trigger_tlv *trig;
45605105 struct iwl_fw_dbg_trigger_ba *ba_trig;
45615106
4562
- if (!iwl_fw_dbg_trigger_enabled(mvm->fw, FW_DBG_TRIGGER_BA))
5107
+ trig = iwl_fw_dbg_trigger_on(&mvm->fwrt, ieee80211_vif_to_wdev(vif),
5108
+ FW_DBG_TRIGGER_BA);
5109
+ if (!trig)
45635110 return;
45645111
4565
- trig = iwl_fw_dbg_get_trigger(mvm->fw, FW_DBG_TRIGGER_BA);
45665112 ba_trig = (void *)trig->data;
4567
- if (!iwl_fw_dbg_trigger_check_stop(&mvm->fwrt,
4568
- ieee80211_vif_to_wdev(vif), trig))
4569
- return;
45705113
45715114 if (!(le16_to_cpu(ba_trig->rx_bar) & BIT(event->u.ba.tid)))
45725115 return;
....@@ -4606,24 +5149,25 @@
46065149 u32 qmask = BIT(mvm->trans->num_rx_queues) - 1;
46075150 int ret;
46085151
4609
- lockdep_assert_held(&mvm->mutex);
46105152
46115153 if (!iwl_mvm_has_new_rx_api(mvm))
46125154 return;
46135155
4614
- notif->cookie = mvm->queue_sync_cookie;
4615
-
4616
- if (notif->sync)
5156
+ if (notif->sync) {
5157
+ notif->cookie = mvm->queue_sync_cookie;
46175158 atomic_set(&mvm->queue_sync_counter,
46185159 mvm->trans->num_rx_queues);
5160
+ }
46195161
4620
- ret = iwl_mvm_notify_rx_queue(mvm, qmask, (u8 *)notif, size);
5162
+ ret = iwl_mvm_notify_rx_queue(mvm, qmask, (u8 *)notif,
5163
+ size, !notif->sync);
46215164 if (ret) {
46225165 IWL_ERR(mvm, "Failed to trigger RX queues sync (%d)\n", ret);
46235166 goto out;
46245167 }
46255168
46265169 if (notif->sync) {
5170
+ lockdep_assert_held(&mvm->mutex);
46275171 ret = wait_event_timeout(mvm->rx_sync_waitq,
46285172 atomic_read(&mvm->queue_sync_counter) == 0 ||
46295173 iwl_mvm_is_radio_killed(mvm),
....@@ -4633,7 +5177,8 @@
46335177
46345178 out:
46355179 atomic_set(&mvm->queue_sync_counter, 0);
4636
- mvm->queue_sync_cookie++;
5180
+ if (notif->sync)
5181
+ mvm->queue_sync_cookie++;
46375182 }
46385183
46395184 static void iwl_mvm_sync_rx_queues(struct ieee80211_hw *hw)
....@@ -4649,9 +5194,91 @@
46495194 mutex_unlock(&mvm->mutex);
46505195 }
46515196
5197
+static int
5198
+iwl_mvm_mac_get_ftm_responder_stats(struct ieee80211_hw *hw,
5199
+ struct ieee80211_vif *vif,
5200
+ struct cfg80211_ftm_responder_stats *stats)
5201
+{
5202
+ struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
5203
+ struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
5204
+
5205
+ if (vif->p2p || vif->type != NL80211_IFTYPE_AP ||
5206
+ !mvmvif->ap_ibss_active || !vif->bss_conf.ftm_responder)
5207
+ return -EINVAL;
5208
+
5209
+ mutex_lock(&mvm->mutex);
5210
+ *stats = mvm->ftm_resp_stats;
5211
+ mutex_unlock(&mvm->mutex);
5212
+
5213
+ stats->filled = BIT(NL80211_FTM_STATS_SUCCESS_NUM) |
5214
+ BIT(NL80211_FTM_STATS_PARTIAL_NUM) |
5215
+ BIT(NL80211_FTM_STATS_FAILED_NUM) |
5216
+ BIT(NL80211_FTM_STATS_ASAP_NUM) |
5217
+ BIT(NL80211_FTM_STATS_NON_ASAP_NUM) |
5218
+ BIT(NL80211_FTM_STATS_TOTAL_DURATION_MSEC) |
5219
+ BIT(NL80211_FTM_STATS_UNKNOWN_TRIGGERS_NUM) |
5220
+ BIT(NL80211_FTM_STATS_RESCHEDULE_REQUESTS_NUM) |
5221
+ BIT(NL80211_FTM_STATS_OUT_OF_WINDOW_TRIGGERS_NUM);
5222
+
5223
+ return 0;
5224
+}
5225
+
5226
+static int iwl_mvm_start_pmsr(struct ieee80211_hw *hw,
5227
+ struct ieee80211_vif *vif,
5228
+ struct cfg80211_pmsr_request *request)
5229
+{
5230
+ struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
5231
+ int ret;
5232
+
5233
+ mutex_lock(&mvm->mutex);
5234
+ ret = iwl_mvm_ftm_start(mvm, vif, request);
5235
+ mutex_unlock(&mvm->mutex);
5236
+
5237
+ return ret;
5238
+}
5239
+
5240
+static void iwl_mvm_abort_pmsr(struct ieee80211_hw *hw,
5241
+ struct ieee80211_vif *vif,
5242
+ struct cfg80211_pmsr_request *request)
5243
+{
5244
+ struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
5245
+
5246
+ mutex_lock(&mvm->mutex);
5247
+ iwl_mvm_ftm_abort(mvm, request);
5248
+ mutex_unlock(&mvm->mutex);
5249
+}
5250
+
5251
+static bool iwl_mvm_can_hw_csum(struct sk_buff *skb)
5252
+{
5253
+ u8 protocol = ip_hdr(skb)->protocol;
5254
+
5255
+ if (!IS_ENABLED(CONFIG_INET))
5256
+ return false;
5257
+
5258
+ return protocol == IPPROTO_TCP || protocol == IPPROTO_UDP;
5259
+}
5260
+
5261
+static bool iwl_mvm_mac_can_aggregate(struct ieee80211_hw *hw,
5262
+ struct sk_buff *head,
5263
+ struct sk_buff *skb)
5264
+{
5265
+ struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
5266
+
5267
+ /* For now don't aggregate IPv6 in AMSDU */
5268
+ if (skb->protocol != htons(ETH_P_IP))
5269
+ return false;
5270
+
5271
+ if (!iwl_mvm_is_csum_supported(mvm))
5272
+ return true;
5273
+
5274
+ return iwl_mvm_can_hw_csum(skb) == iwl_mvm_can_hw_csum(head);
5275
+}
5276
+
46525277 const struct ieee80211_ops iwl_mvm_hw_ops = {
46535278 .tx = iwl_mvm_mac_tx,
5279
+ .wake_tx_queue = iwl_mvm_mac_wake_tx_queue,
46545280 .ampdu_action = iwl_mvm_mac_ampdu_action,
5281
+ .get_antenna = iwl_mvm_op_get_antenna,
46555282 .start = iwl_mvm_mac_start,
46565283 .reconfig_complete = iwl_mvm_mac_reconfig_complete,
46575284 .stop = iwl_mvm_mac_stop,
....@@ -4700,6 +5327,8 @@
47005327 .channel_switch = iwl_mvm_channel_switch,
47015328 .pre_channel_switch = iwl_mvm_pre_channel_switch,
47025329 .post_channel_switch = iwl_mvm_post_channel_switch,
5330
+ .abort_channel_switch = iwl_mvm_abort_channel_switch,
5331
+ .channel_switch_rx_beacon = iwl_mvm_channel_switch_rx_beacon,
47035332
47045333 .tdls_channel_switch = iwl_mvm_tdls_channel_switch,
47055334 .tdls_cancel_channel_switch = iwl_mvm_tdls_cancel_channel_switch,
....@@ -4724,6 +5353,11 @@
47245353 #endif
47255354 .get_survey = iwl_mvm_mac_get_survey,
47265355 .sta_statistics = iwl_mvm_mac_sta_statistics,
5356
+ .get_ftm_responder_stats = iwl_mvm_mac_get_ftm_responder_stats,
5357
+ .start_pmsr = iwl_mvm_start_pmsr,
5358
+ .abort_pmsr = iwl_mvm_abort_pmsr,
5359
+
5360
+ .can_aggregate_in_amsdu = iwl_mvm_mac_can_aggregate,
47275361 #ifdef CONFIG_IWLWIFI_DEBUGFS
47285362 .sta_add_debugfs = iwl_mvm_sta_add_debugfs,
47295363 #endif