hc
2023-12-09 b22da3d8526a935aa31e086e63f60ff3246cb61c
kernel/drivers/net/wireless/intel/iwlwifi/mvm/d3.c
....@@ -5,10 +5,9 @@
55 *
66 * GPL LICENSE SUMMARY
77 *
8
- * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
8
+ * Copyright(c) 2012 - 2014, 2018 - 2020 Intel Corporation. All rights reserved.
99 * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
1010 * Copyright(c) 2016 - 2017 Intel Deutschland GmbH
11
- * Copyright(c) 2018 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
....@@ -28,10 +27,9 @@
2827 *
2928 * BSD LICENSE
3029 *
31
- * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
30
+ * Copyright(c) 2012 - 2014, 2018 - 2020 Intel Corporation. All rights reserved.
3231 * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
3332 * Copyright(c) 2016 - 2017 Intel Deutschland GmbH
34
- * Copyright(c) 2018 Intel Corporation
3533 * All rights reserved.
3634 *
3735 * Redistribution and use in source and binary forms, with or without
....@@ -72,6 +70,7 @@
7270 #include "iwl-modparams.h"
7371 #include "fw-api.h"
7472 #include "mvm.h"
73
+#include "fw/img.h"
7574
7675 void iwl_mvm_set_rekey_data(struct ieee80211_hw *hw,
7776 struct ieee80211_vif *vif,
....@@ -80,13 +79,13 @@
8079 struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
8180 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
8281
83
- if (iwlwifi_mod_params.swcrypto)
84
- return;
85
-
8682 mutex_lock(&mvm->mutex);
8783
88
- memcpy(mvmvif->rekey_data.kek, data->kek, NL80211_KEK_LEN);
89
- memcpy(mvmvif->rekey_data.kck, data->kck, NL80211_KCK_LEN);
84
+ mvmvif->rekey_data.kek_len = data->kek_len;
85
+ mvmvif->rekey_data.kck_len = data->kck_len;
86
+ memcpy(mvmvif->rekey_data.kek, data->kek, data->kek_len);
87
+ memcpy(mvmvif->rekey_data.kck, data->kck, data->kck_len);
88
+ mvmvif->rekey_data.akm = data->akm & 0xFF;
9089 mvmvif->rekey_data.replay_ctr =
9190 cpu_to_le64(be64_to_cpup((__be64 *)data->replay_ctr));
9291 mvmvif->rekey_data.valid = true;
....@@ -161,6 +160,7 @@
161160 struct wowlan_key_data {
162161 struct iwl_wowlan_rsc_tsc_params_cmd *rsc_tsc;
163162 struct iwl_wowlan_tkip_params_cmd *tkip;
163
+ struct iwl_wowlan_kek_kck_material_cmd_v3 *kek_kck_cmd;
164164 bool error, use_rsc_tsc, use_tkip, configure_keys;
165165 int wep_key_idx;
166166 };
....@@ -237,7 +237,12 @@
237237 default:
238238 data->error = true;
239239 return;
240
+ case WLAN_CIPHER_SUITE_BIP_GMAC_256:
241
+ case WLAN_CIPHER_SUITE_BIP_GMAC_128:
242
+ data->kek_kck_cmd->igtk_cipher = cpu_to_le32(STA_KEY_FLG_GCMP);
243
+ return;
240244 case WLAN_CIPHER_SUITE_AES_CMAC:
245
+ data->kek_kck_cmd->igtk_cipher = cpu_to_le32(STA_KEY_FLG_CCM);
241246 /*
242247 * Ignore CMAC keys -- the WoWLAN firmware doesn't support them
243248 * but we also shouldn't abort suspend due to that. It does have
....@@ -250,8 +255,10 @@
250255 if (sta) {
251256 u64 pn64;
252257
253
- tkip_sc = data->rsc_tsc->all_tsc_rsc.tkip.unicast_rsc;
254
- tkip_tx_sc = &data->rsc_tsc->all_tsc_rsc.tkip.tsc;
258
+ tkip_sc =
259
+ data->rsc_tsc->params.all_tsc_rsc.tkip.unicast_rsc;
260
+ tkip_tx_sc =
261
+ &data->rsc_tsc->params.all_tsc_rsc.tkip.tsc;
255262
256263 rx_p1ks = data->tkip->rx_uni;
257264
....@@ -270,9 +277,11 @@
270277 rx_mic_key = data->tkip->mic_keys.rx_unicast;
271278 } else {
272279 tkip_sc =
273
- data->rsc_tsc->all_tsc_rsc.tkip.multicast_rsc;
280
+ data->rsc_tsc->params.all_tsc_rsc.tkip.multicast_rsc;
274281 rx_p1ks = data->tkip->rx_multi;
275282 rx_mic_key = data->tkip->mic_keys.rx_mcast;
283
+ data->kek_kck_cmd->gtk_cipher =
284
+ cpu_to_le32(STA_KEY_FLG_TKIP);
276285 }
277286
278287 /*
....@@ -304,16 +313,25 @@
304313 data->use_rsc_tsc = true;
305314 break;
306315 case WLAN_CIPHER_SUITE_CCMP:
316
+ case WLAN_CIPHER_SUITE_GCMP:
317
+ case WLAN_CIPHER_SUITE_GCMP_256:
307318 if (sta) {
308319 u64 pn64;
309320
310
- aes_sc = data->rsc_tsc->all_tsc_rsc.aes.unicast_rsc;
311
- aes_tx_sc = &data->rsc_tsc->all_tsc_rsc.aes.tsc;
321
+ aes_sc =
322
+ data->rsc_tsc->params.all_tsc_rsc.aes.unicast_rsc;
323
+ aes_tx_sc =
324
+ &data->rsc_tsc->params.all_tsc_rsc.aes.tsc;
312325
313326 pn64 = atomic64_read(&key->tx_pn);
314327 aes_tx_sc->pn = cpu_to_le64(pn64);
315328 } else {
316
- aes_sc = data->rsc_tsc->all_tsc_rsc.aes.multicast_rsc;
329
+ aes_sc =
330
+ data->rsc_tsc->params.all_tsc_rsc.aes.multicast_rsc;
331
+ data->kek_kck_cmd->gtk_cipher =
332
+ key->cipher == WLAN_CIPHER_SUITE_CCMP ?
333
+ cpu_to_le32(STA_KEY_FLG_CCM) :
334
+ cpu_to_le32(STA_KEY_FLG_GCMP);
317335 }
318336
319337 /*
....@@ -326,11 +344,12 @@
326344 const u8 *pn;
327345
328346 mvmsta = iwl_mvm_sta_from_mac80211(sta);
329
- ptk_pn = rcu_dereference_protected(
330
- mvmsta->ptk_pn[key->keyidx],
331
- lockdep_is_held(&mvm->mutex));
332
- if (WARN_ON(!ptk_pn))
347
+ rcu_read_lock();
348
+ ptk_pn = rcu_dereference(mvmsta->ptk_pn[key->keyidx]);
349
+ if (WARN_ON(!ptk_pn)) {
350
+ rcu_read_unlock();
333351 break;
352
+ }
334353
335354 for (i = 0; i < IWL_MAX_TID_COUNT; i++) {
336355 pn = iwl_mvm_find_max_pn(key, ptk_pn, &seq, i,
....@@ -342,6 +361,8 @@
342361 ((u64)pn[1] << 32) |
343362 ((u64)pn[0] << 40));
344363 }
364
+
365
+ rcu_read_unlock();
345366 } else {
346367 for (i = 0; i < IWL_NUM_RSC; i++) {
347368 u8 *pn = seq.ccmp.pn;
....@@ -358,6 +379,8 @@
358379 data->use_rsc_tsc = true;
359380 break;
360381 }
382
+
383
+ IWL_DEBUG_WOWLAN(mvm, "GTK cipher %d\n", data->kek_kck_cmd->gtk_cipher);
361384
362385 if (data->configure_keys) {
363386 mutex_lock(&mvm->mutex);
....@@ -385,10 +408,10 @@
385408 }
386409 }
387410
388
-static int iwl_mvm_send_patterns(struct iwl_mvm *mvm,
389
- struct cfg80211_wowlan *wowlan)
411
+static int iwl_mvm_send_patterns_v1(struct iwl_mvm *mvm,
412
+ struct cfg80211_wowlan *wowlan)
390413 {
391
- struct iwl_wowlan_patterns_cmd *pattern_cmd;
414
+ struct iwl_wowlan_patterns_cmd_v1 *pattern_cmd;
392415 struct iwl_host_cmd cmd = {
393416 .id = WOWLAN_PATTERNS,
394417 .dataflags[0] = IWL_HCMD_DFL_NOCOPY,
....@@ -398,8 +421,7 @@
398421 if (!wowlan->n_patterns)
399422 return 0;
400423
401
- cmd.len[0] = sizeof(*pattern_cmd) +
402
- wowlan->n_patterns * sizeof(struct iwl_wowlan_pattern);
424
+ cmd.len[0] = struct_size(pattern_cmd, patterns, wowlan->n_patterns);
403425
404426 pattern_cmd = kmalloc(cmd.len[0], GFP_KERNEL);
405427 if (!pattern_cmd)
....@@ -426,6 +448,50 @@
426448 return err;
427449 }
428450
451
+static int iwl_mvm_send_patterns(struct iwl_mvm *mvm,
452
+ struct cfg80211_wowlan *wowlan)
453
+{
454
+ struct iwl_wowlan_patterns_cmd *pattern_cmd;
455
+ struct iwl_host_cmd cmd = {
456
+ .id = WOWLAN_PATTERNS,
457
+ .dataflags[0] = IWL_HCMD_DFL_NOCOPY,
458
+ };
459
+ int i, err;
460
+
461
+ if (!wowlan->n_patterns)
462
+ return 0;
463
+
464
+ cmd.len[0] = sizeof(*pattern_cmd) +
465
+ wowlan->n_patterns * sizeof(struct iwl_wowlan_pattern_v2);
466
+
467
+ pattern_cmd = kmalloc(cmd.len[0], GFP_KERNEL);
468
+ if (!pattern_cmd)
469
+ return -ENOMEM;
470
+
471
+ pattern_cmd->n_patterns = cpu_to_le32(wowlan->n_patterns);
472
+
473
+ for (i = 0; i < wowlan->n_patterns; i++) {
474
+ int mask_len = DIV_ROUND_UP(wowlan->patterns[i].pattern_len, 8);
475
+
476
+ pattern_cmd->patterns[i].pattern_type =
477
+ WOWLAN_PATTERN_TYPE_BITMASK;
478
+
479
+ memcpy(&pattern_cmd->patterns[i].u.bitmask.mask,
480
+ wowlan->patterns[i].mask, mask_len);
481
+ memcpy(&pattern_cmd->patterns[i].u.bitmask.pattern,
482
+ wowlan->patterns[i].pattern,
483
+ wowlan->patterns[i].pattern_len);
484
+ pattern_cmd->patterns[i].u.bitmask.mask_size = mask_len;
485
+ pattern_cmd->patterns[i].u.bitmask.pattern_size =
486
+ wowlan->patterns[i].pattern_len;
487
+ }
488
+
489
+ cmd.data[0] = pattern_cmd;
490
+ err = iwl_mvm_send_cmd(mvm, &cmd);
491
+ kfree(pattern_cmd);
492
+ return err;
493
+}
494
+
429495 static int iwl_mvm_d3_reprogram(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
430496 struct ieee80211_sta *ap_sta)
431497 {
....@@ -434,23 +500,13 @@
434500 u8 chains_static, chains_dynamic;
435501 struct cfg80211_chan_def chandef;
436502 int ret, i;
437
- struct iwl_binding_cmd binding_cmd = {};
503
+ struct iwl_binding_cmd_v1 binding_cmd = {};
438504 struct iwl_time_quota_cmd quota_cmd = {};
439505 struct iwl_time_quota_data *quota;
440506 u32 status;
441
- int size;
442507
443
- if (fw_has_capa(&mvm->fw->ucode_capa,
444
- IWL_UCODE_TLV_CAPA_BINDING_CDB_SUPPORT)) {
445
- size = sizeof(binding_cmd);
446
- if (mvmvif->phy_ctxt->channel->band == NL80211_BAND_2GHZ ||
447
- !iwl_mvm_is_cdb_supported(mvm))
448
- binding_cmd.lmac_id = cpu_to_le32(IWL_LMAC_24G_INDEX);
449
- else
450
- binding_cmd.lmac_id = cpu_to_le32(IWL_LMAC_5G_INDEX);
451
- } else {
452
- size = IWL_BINDING_CMD_SIZE_V1;
453
- }
508
+ if (WARN_ON_ONCE(iwl_mvm_is_cdb_supported(mvm)))
509
+ return -EINVAL;
454510
455511 /* add back the PHY */
456512 if (WARN_ON(!mvmvif->phy_ctxt))
....@@ -497,7 +553,8 @@
497553
498554 status = 0;
499555 ret = iwl_mvm_send_cmd_pdu_status(mvm, BINDING_CONTEXT_CMD,
500
- size, &binding_cmd, &status);
556
+ IWL_BINDING_CMD_SIZE_V1, &binding_cmd,
557
+ &status);
501558 if (ret) {
502559 IWL_ERR(mvm, "Failed to add binding: %d\n", ret);
503560 return ret;
....@@ -701,46 +758,25 @@
701758 return 0;
702759 }
703760
704
-static void
705
-iwl_mvm_iter_d0i3_ap_keys(struct iwl_mvm *mvm,
706
- struct ieee80211_vif *vif,
707
- void (*iter)(struct ieee80211_hw *hw,
708
- struct ieee80211_vif *vif,
709
- struct ieee80211_sta *sta,
710
- struct ieee80211_key_conf *key,
711
- void *data),
712
- void *data)
761
+static int iwl_mvm_wowlan_config_key_params(struct iwl_mvm *mvm,
762
+ struct ieee80211_vif *vif,
763
+ u32 cmd_flags)
713764 {
714
- struct ieee80211_sta *ap_sta;
715
-
716
- rcu_read_lock();
717
-
718
- ap_sta = rcu_dereference(mvm->fw_id_to_mac_id[mvm->d0i3_ap_sta_id]);
719
- if (IS_ERR_OR_NULL(ap_sta))
720
- goto out;
721
-
722
- ieee80211_iter_keys_rcu(mvm->hw, vif, iter, data);
723
-out:
724
- rcu_read_unlock();
725
-}
726
-
727
-int iwl_mvm_wowlan_config_key_params(struct iwl_mvm *mvm,
728
- struct ieee80211_vif *vif,
729
- bool d0i3,
730
- u32 cmd_flags)
731
-{
732
- struct iwl_wowlan_kek_kck_material_cmd kek_kck_cmd = {};
765
+ struct iwl_wowlan_kek_kck_material_cmd_v3 kek_kck_cmd = {};
733766 struct iwl_wowlan_tkip_params_cmd tkip_cmd = {};
734767 bool unified = fw_has_capa(&mvm->fw->ucode_capa,
735768 IWL_UCODE_TLV_CAPA_CNSLDTD_D3_D0_IMG);
736769 struct wowlan_key_data key_data = {
737
- .configure_keys = !d0i3 && !unified,
770
+ .configure_keys = !unified,
738771 .use_rsc_tsc = false,
739772 .tkip = &tkip_cmd,
740773 .use_tkip = false,
774
+ .kek_kck_cmd = &kek_kck_cmd,
741775 };
742776 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
743777 int ret;
778
+ u8 cmd_ver;
779
+ size_t cmd_size;
744780
745781 key_data.rsc_tsc = kzalloc(sizeof(*key_data.rsc_tsc), GFP_KERNEL);
746782 if (!key_data.rsc_tsc)
....@@ -750,25 +786,16 @@
750786 * if we have to configure keys, call ieee80211_iter_keys(),
751787 * as we need non-atomic context in order to take the
752788 * required locks.
753
- * for the d0i3 we can't use ieee80211_iter_keys(), as
754
- * taking (almost) any mutex might result in deadlock.
755789 */
756
- if (!d0i3) {
757
- /*
758
- * Note that currently we don't propagate cmd_flags
759
- * to the iterator. In case of key_data.configure_keys,
760
- * all the configured commands are SYNC, and
761
- * iwl_mvm_wowlan_program_keys() will take care of
762
- * locking/unlocking mvm->mutex.
763
- */
764
- ieee80211_iter_keys(mvm->hw, vif,
765
- iwl_mvm_wowlan_program_keys,
766
- &key_data);
767
- } else {
768
- iwl_mvm_iter_d0i3_ap_keys(mvm, vif,
769
- iwl_mvm_wowlan_program_keys,
770
- &key_data);
771
- }
790
+ /*
791
+ * Note that currently we don't propagate cmd_flags
792
+ * to the iterator. In case of key_data.configure_keys,
793
+ * all the configured commands are SYNC, and
794
+ * iwl_mvm_wowlan_program_keys() will take care of
795
+ * locking/unlocking mvm->mutex.
796
+ */
797
+ ieee80211_iter_keys(mvm->hw, vif, iwl_mvm_wowlan_program_keys,
798
+ &key_data);
772799
773800 if (key_data.error) {
774801 ret = -EIO;
....@@ -776,10 +803,29 @@
776803 }
777804
778805 if (key_data.use_rsc_tsc) {
779
- ret = iwl_mvm_send_cmd_pdu(mvm,
780
- WOWLAN_TSC_RSC_PARAM, cmd_flags,
781
- sizeof(*key_data.rsc_tsc),
806
+ int ver = iwl_fw_lookup_cmd_ver(mvm->fw, LONG_GROUP,
807
+ WOWLAN_TSC_RSC_PARAM,
808
+ IWL_FW_CMD_VER_UNKNOWN);
809
+ int size;
810
+
811
+ if (ver == 4) {
812
+ size = sizeof(*key_data.rsc_tsc);
813
+ key_data.rsc_tsc->sta_id =
814
+ cpu_to_le32(mvmvif->ap_sta_id);
815
+
816
+ } else if (ver == 2 || ver == IWL_FW_CMD_VER_UNKNOWN) {
817
+ size = sizeof(key_data.rsc_tsc->params);
818
+ } else {
819
+ ret = 0;
820
+ WARN_ON_ONCE(1);
821
+ goto out;
822
+ }
823
+
824
+ ret = iwl_mvm_send_cmd_pdu(mvm, WOWLAN_TSC_RSC_PARAM,
825
+ cmd_flags,
826
+ size,
782827 key_data.rsc_tsc);
828
+
783829 if (ret)
784830 goto out;
785831 }
....@@ -787,28 +833,61 @@
787833 if (key_data.use_tkip &&
788834 !fw_has_api(&mvm->fw->ucode_capa,
789835 IWL_UCODE_TLV_API_TKIP_MIC_KEYS)) {
836
+ int ver = iwl_fw_lookup_cmd_ver(mvm->fw, LONG_GROUP,
837
+ WOWLAN_TKIP_PARAM,
838
+ IWL_FW_CMD_VER_UNKNOWN);
839
+ int size;
840
+
841
+ if (ver == 2) {
842
+ size = sizeof(tkip_cmd);
843
+ key_data.tkip->sta_id =
844
+ cpu_to_le32(mvmvif->ap_sta_id);
845
+ } else if (ver == 1 || ver == IWL_FW_CMD_VER_UNKNOWN) {
846
+ size = sizeof(struct iwl_wowlan_tkip_params_cmd_ver_1);
847
+ } else {
848
+ ret = -EINVAL;
849
+ WARN_ON_ONCE(1);
850
+ goto out;
851
+ }
852
+
853
+ /* send relevant data according to CMD version */
790854 ret = iwl_mvm_send_cmd_pdu(mvm,
791855 WOWLAN_TKIP_PARAM,
792
- cmd_flags, sizeof(tkip_cmd),
856
+ cmd_flags, size,
793857 &tkip_cmd);
794858 if (ret)
795859 goto out;
796860 }
797861
798862 /* configure rekey data only if offloaded rekey is supported (d3) */
799
- if (mvmvif->rekey_data.valid && !d0i3) {
800
- memset(&kek_kck_cmd, 0, sizeof(kek_kck_cmd));
863
+ if (mvmvif->rekey_data.valid) {
864
+ cmd_ver = iwl_fw_lookup_cmd_ver(mvm->fw,
865
+ IWL_ALWAYS_LONG_GROUP,
866
+ WOWLAN_KEK_KCK_MATERIAL,
867
+ IWL_FW_CMD_VER_UNKNOWN);
868
+ if (WARN_ON(cmd_ver != 2 && cmd_ver != 3 &&
869
+ cmd_ver != IWL_FW_CMD_VER_UNKNOWN))
870
+ return -EINVAL;
871
+ if (cmd_ver == 3)
872
+ cmd_size = sizeof(struct iwl_wowlan_kek_kck_material_cmd_v3);
873
+ else
874
+ cmd_size = sizeof(struct iwl_wowlan_kek_kck_material_cmd_v2);
875
+
801876 memcpy(kek_kck_cmd.kck, mvmvif->rekey_data.kck,
802
- NL80211_KCK_LEN);
803
- kek_kck_cmd.kck_len = cpu_to_le16(NL80211_KCK_LEN);
877
+ mvmvif->rekey_data.kck_len);
878
+ kek_kck_cmd.kck_len = cpu_to_le16(mvmvif->rekey_data.kck_len);
804879 memcpy(kek_kck_cmd.kek, mvmvif->rekey_data.kek,
805
- NL80211_KEK_LEN);
806
- kek_kck_cmd.kek_len = cpu_to_le16(NL80211_KEK_LEN);
880
+ mvmvif->rekey_data.kek_len);
881
+ kek_kck_cmd.kek_len = cpu_to_le16(mvmvif->rekey_data.kek_len);
807882 kek_kck_cmd.replay_ctr = mvmvif->rekey_data.replay_ctr;
883
+ kek_kck_cmd.akm = cpu_to_le32(mvmvif->rekey_data.akm);
884
+
885
+ IWL_DEBUG_WOWLAN(mvm, "setting akm %d\n",
886
+ mvmvif->rekey_data.akm);
808887
809888 ret = iwl_mvm_send_cmd_pdu(mvm,
810889 WOWLAN_KEK_KCK_MATERIAL, cmd_flags,
811
- sizeof(kek_kck_cmd),
890
+ cmd_size,
812891 &kek_kck_cmd);
813892 if (ret)
814893 goto out;
....@@ -830,6 +909,8 @@
830909 bool unified_image = fw_has_capa(&mvm->fw->ucode_capa,
831910 IWL_UCODE_TLV_CAPA_CNSLDTD_D3_D0_IMG);
832911
912
+ mvm->offload_tid = wowlan_config_cmd->offloading_tid;
913
+
833914 if (!unified_image) {
834915 ret = iwl_mvm_switch_to_d3(mvm);
835916 if (ret)
....@@ -840,19 +921,16 @@
840921 return ret;
841922 }
842923
843
- if (!iwlwifi_mod_params.swcrypto) {
844
- /*
845
- * This needs to be unlocked due to lock ordering
846
- * constraints. Since we're in the suspend path
847
- * that isn't really a problem though.
848
- */
849
- mutex_unlock(&mvm->mutex);
850
- ret = iwl_mvm_wowlan_config_key_params(mvm, vif, false,
851
- CMD_ASYNC);
852
- mutex_lock(&mvm->mutex);
853
- if (ret)
854
- return ret;
855
- }
924
+ /*
925
+ * This needs to be unlocked due to lock ordering
926
+ * constraints. Since we're in the suspend path
927
+ * that isn't really a problem though.
928
+ */
929
+ mutex_unlock(&mvm->mutex);
930
+ ret = iwl_mvm_wowlan_config_key_params(mvm, vif, CMD_ASYNC);
931
+ mutex_lock(&mvm->mutex);
932
+ if (ret)
933
+ return ret;
856934
857935 ret = iwl_mvm_send_cmd_pdu(mvm, WOWLAN_CONFIGURATION, 0,
858936 sizeof(*wowlan_config_cmd),
....@@ -860,7 +938,11 @@
860938 if (ret)
861939 return ret;
862940
863
- ret = iwl_mvm_send_patterns(mvm, wowlan);
941
+ if (fw_has_api(&mvm->fw->ucode_capa,
942
+ IWL_UCODE_TLV_API_WOWLAN_TCP_SYN_WAKE))
943
+ ret = iwl_mvm_send_patterns(mvm, wowlan);
944
+ else
945
+ ret = iwl_mvm_send_patterns_v1(mvm, wowlan);
864946 if (ret)
865947 return ret;
866948
....@@ -897,6 +979,8 @@
897979 if (wowlan->rfkill_release)
898980 wowlan_config_cmd.wakeup_filter |=
899981 cpu_to_le32(IWL_WOWLAN_WAKEUP_RF_KILL_DEASSERT);
982
+
983
+ wowlan_config_cmd.sta_id = mvm->aux_sta.sta_id;
900984
901985 ret = iwl_mvm_send_cmd_pdu(mvm, WOWLAN_CONFIGURATION, 0,
902986 sizeof(wowlan_config_cmd),
....@@ -981,6 +1065,8 @@
9811065
9821066 mutex_lock(&mvm->mutex);
9831067
1068
+ set_bit(IWL_MVM_STATUS_IN_D3, &mvm->status);
1069
+
9841070 vif = iwl_mvm_get_bss_vif(mvm);
9851071 if (IS_ERR_OR_NULL(vif)) {
9861072 ret = 1;
....@@ -1004,6 +1090,8 @@
10041090 mvm->net_detect = true;
10051091 } else {
10061092 struct iwl_wowlan_config_cmd wowlan_config_cmd = {};
1093
+
1094
+ wowlan_config_cmd.sta_id = mvmvif->ap_sta_id;
10071095
10081096 ap_sta = rcu_dereference_protected(
10091097 mvm->fw_id_to_mac_id[mvmvif->ap_sta_id],
....@@ -1040,11 +1128,12 @@
10401128 #endif
10411129
10421130 /*
1043
- * TODO: this is needed because the firmware is not stopping
1044
- * the recording automatically before entering D3. This can
1045
- * be removed once the FW starts doing that.
1131
+ * Prior to 9000 device family the driver needs to stop the dbg
1132
+ * recording before entering D3. In later devices the FW stops the
1133
+ * recording automatically.
10461134 */
1047
- iwl_fw_dbg_stop_recording(&mvm->fwrt);
1135
+ if (mvm->trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_9000)
1136
+ iwl_fw_dbg_stop_restart_recording(&mvm->fwrt, NULL, true);
10481137
10491138 /* must be last -- this switches firmware state */
10501139 ret = iwl_mvm_send_cmd(mvm, &d3_cfg_cmd);
....@@ -1061,45 +1150,23 @@
10611150
10621151 clear_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status);
10631152
1064
- iwl_trans_d3_suspend(mvm->trans, test, !unified_image);
1153
+ ret = iwl_trans_d3_suspend(mvm->trans, test, !unified_image);
10651154 out:
10661155 if (ret < 0) {
10671156 iwl_mvm_free_nd(mvm);
10681157
10691158 if (!unified_image) {
1070
- iwl_mvm_ref(mvm, IWL_MVM_REF_UCODE_DOWN);
10711159 if (mvm->fw_restart > 0) {
10721160 mvm->fw_restart--;
10731161 ieee80211_restart_hw(mvm->hw);
10741162 }
10751163 }
1164
+
1165
+ clear_bit(IWL_MVM_STATUS_IN_D3, &mvm->status);
10761166 }
10771167 out_noreset:
10781168 mutex_unlock(&mvm->mutex);
10791169
1080
- return ret;
1081
-}
1082
-
1083
-static int iwl_mvm_enter_d0i3_sync(struct iwl_mvm *mvm)
1084
-{
1085
- struct iwl_notification_wait wait_d3;
1086
- static const u16 d3_notif[] = { D3_CONFIG_CMD };
1087
- int ret;
1088
-
1089
- iwl_init_notification_wait(&mvm->notif_wait, &wait_d3,
1090
- d3_notif, ARRAY_SIZE(d3_notif),
1091
- NULL, NULL);
1092
-
1093
- ret = iwl_mvm_enter_d0i3(mvm->hw->priv);
1094
- if (ret)
1095
- goto remove_notif;
1096
-
1097
- ret = iwl_wait_notification(&mvm->notif_wait, &wait_d3, HZ);
1098
- WARN_ON_ONCE(ret);
1099
- return ret;
1100
-
1101
-remove_notif:
1102
- iwl_remove_notification(&mvm->notif_wait, &wait_d3);
11031170 return ret;
11041171 }
11051172
....@@ -1109,8 +1176,6 @@
11091176 struct iwl_trans *trans = mvm->trans;
11101177 int ret;
11111178
1112
- /* make sure the d0i3 exit work is not pending */
1113
- flush_work(&mvm->d0i3_exit_work);
11141179 iwl_mvm_pause_tcm(mvm, true);
11151180
11161181 iwl_fw_runtime_suspend(&mvm->fwrt);
....@@ -1118,25 +1183,6 @@
11181183 ret = iwl_trans_suspend(trans);
11191184 if (ret)
11201185 return ret;
1121
-
1122
- if (wowlan->any) {
1123
- trans->system_pm_mode = IWL_PLAT_PM_MODE_D0I3;
1124
-
1125
- if (iwl_mvm_enter_d0i3_on_suspend(mvm)) {
1126
- ret = iwl_mvm_enter_d0i3_sync(mvm);
1127
-
1128
- if (ret)
1129
- return ret;
1130
- }
1131
-
1132
- mutex_lock(&mvm->d0i3_suspend_mutex);
1133
- __set_bit(D0I3_DEFER_WAKEUP, &mvm->d0i3_suspend_flags);
1134
- mutex_unlock(&mvm->d0i3_suspend_mutex);
1135
-
1136
- iwl_trans_d3_suspend(trans, false, false);
1137
-
1138
- return 0;
1139
- }
11401186
11411187 trans->system_pm_mode = IWL_PLAT_PM_MODE_D3;
11421188
....@@ -1320,10 +1366,12 @@
13201366
13211367 mvmsta = iwl_mvm_sta_from_mac80211(sta);
13221368
1323
- ptk_pn = rcu_dereference_protected(mvmsta->ptk_pn[key->keyidx],
1324
- lockdep_is_held(&mvm->mutex));
1325
- if (WARN_ON(!ptk_pn))
1369
+ rcu_read_lock();
1370
+ ptk_pn = rcu_dereference(mvmsta->ptk_pn[key->keyidx]);
1371
+ if (WARN_ON(!ptk_pn)) {
1372
+ rcu_read_unlock();
13261373 return;
1374
+ }
13271375
13281376 for (tid = 0; tid < IWL_MAX_TID_COUNT; tid++) {
13291377 struct ieee80211_key_seq seq = {};
....@@ -1335,6 +1383,7 @@
13351383 memcpy(ptk_pn->q[i].pn[tid],
13361384 seq.ccmp.pn, IEEE80211_CCMP_PN_LEN);
13371385 }
1386
+ rcu_read_unlock();
13381387 } else {
13391388 for (tid = 0; tid < IWL_NUM_RSC; tid++) {
13401389 struct ieee80211_key_seq seq = {};
....@@ -1364,10 +1413,12 @@
13641413 struct ieee80211_key_conf *key,
13651414 struct iwl_wowlan_status *status)
13661415 {
1367
- union iwl_all_tsc_rsc *rsc = &status->gtk.rsc.all_tsc_rsc;
1416
+ union iwl_all_tsc_rsc *rsc = &status->gtk[0].rsc.all_tsc_rsc;
13681417
13691418 switch (key->cipher) {
13701419 case WLAN_CIPHER_SUITE_CCMP:
1420
+ case WLAN_CIPHER_SUITE_GCMP:
1421
+ case WLAN_CIPHER_SUITE_GCMP_256:
13711422 iwl_mvm_set_aes_rx_seq(mvm, rsc->aes.multicast_rsc, NULL, key);
13721423 break;
13731424 case WLAN_CIPHER_SUITE_TKIP:
....@@ -1404,6 +1455,8 @@
14041455 /* ignore WEP completely, nothing to do */
14051456 return;
14061457 case WLAN_CIPHER_SUITE_CCMP:
1458
+ case WLAN_CIPHER_SUITE_GCMP:
1459
+ case WLAN_CIPHER_SUITE_GCMP_256:
14071460 case WLAN_CIPHER_SUITE_TKIP:
14081461 /* we support these */
14091462 break;
....@@ -1421,13 +1474,16 @@
14211474 */
14221475 if (sta) {
14231476 struct ieee80211_key_seq seq = {};
1424
- union iwl_all_tsc_rsc *sc = &data->status->gtk.rsc.all_tsc_rsc;
1477
+ union iwl_all_tsc_rsc *sc =
1478
+ &data->status->gtk[0].rsc.all_tsc_rsc;
14251479
14261480 if (data->find_phase)
14271481 return;
14281482
14291483 switch (key->cipher) {
14301484 case WLAN_CIPHER_SUITE_CCMP:
1485
+ case WLAN_CIPHER_SUITE_GCMP:
1486
+ case WLAN_CIPHER_SUITE_GCMP_256:
14311487 iwl_mvm_set_aes_rx_seq(data->mvm, sc->aes.unicast_rsc,
14321488 sta, key);
14331489 atomic64_set(&key->tx_pn, le64_to_cpu(sc->aes.tsc.pn));
....@@ -1496,6 +1552,8 @@
14961552 ieee80211_iter_keys(mvm->hw, vif,
14971553 iwl_mvm_d3_update_keys, &gtkdata);
14981554
1555
+ IWL_DEBUG_WOWLAN(mvm, "num of GTK rekeying %d\n",
1556
+ le32_to_cpu(status->num_of_gtk_rekeys));
14991557 if (status->num_of_gtk_rekeys) {
15001558 struct ieee80211_key_conf *key;
15011559 struct {
....@@ -1503,22 +1561,37 @@
15031561 u8 key[32];
15041562 } conf = {
15051563 .conf.cipher = gtkdata.cipher,
1506
- .conf.keyidx = status->gtk.key_index,
1564
+ .conf.keyidx =
1565
+ iwlmvm_wowlan_gtk_idx(&status->gtk[0]),
15071566 };
1567
+ __be64 replay_ctr;
15081568
1569
+ IWL_DEBUG_WOWLAN(mvm,
1570
+ "Received from FW GTK cipher %d, key index %d\n",
1571
+ conf.conf.cipher, conf.conf.keyidx);
15091572 switch (gtkdata.cipher) {
15101573 case WLAN_CIPHER_SUITE_CCMP:
1574
+ case WLAN_CIPHER_SUITE_GCMP:
1575
+ BUILD_BUG_ON(WLAN_KEY_LEN_CCMP != WLAN_KEY_LEN_GCMP);
1576
+ BUILD_BUG_ON(sizeof(conf.key) < WLAN_KEY_LEN_CCMP);
15111577 conf.conf.keylen = WLAN_KEY_LEN_CCMP;
1512
- memcpy(conf.conf.key, status->gtk.decrypt_key,
1578
+ memcpy(conf.conf.key, status->gtk[0].key,
15131579 WLAN_KEY_LEN_CCMP);
15141580 break;
1581
+ case WLAN_CIPHER_SUITE_GCMP_256:
1582
+ BUILD_BUG_ON(sizeof(conf.key) < WLAN_KEY_LEN_GCMP_256);
1583
+ conf.conf.keylen = WLAN_KEY_LEN_GCMP_256;
1584
+ memcpy(conf.conf.key, status->gtk[0].key,
1585
+ WLAN_KEY_LEN_GCMP_256);
1586
+ break;
15151587 case WLAN_CIPHER_SUITE_TKIP:
1588
+ BUILD_BUG_ON(sizeof(conf.key) < WLAN_KEY_LEN_TKIP);
15161589 conf.conf.keylen = WLAN_KEY_LEN_TKIP;
1517
- memcpy(conf.conf.key, status->gtk.decrypt_key, 16);
1590
+ memcpy(conf.conf.key, status->gtk[0].key, 16);
15181591 /* leave TX MIC key zeroed, we don't use it anyway */
15191592 memcpy(conf.conf.key +
15201593 NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY,
1521
- status->gtk.tkip_mic_key, 8);
1594
+ status->gtk[0].tkip_mic_key, 8);
15221595 break;
15231596 }
15241597
....@@ -1526,11 +1599,10 @@
15261599 if (IS_ERR(key))
15271600 return false;
15281601 iwl_mvm_set_key_rx_seq(mvm, key, status);
1529
- }
15301602
1531
- if (status->num_of_gtk_rekeys) {
1532
- __be64 replay_ctr =
1603
+ replay_ctr =
15331604 cpu_to_be64(le64_to_cpu(status->replay_ctr));
1605
+
15341606 ieee80211_gtk_rekey_notify(vif, vif->bss_conf.bssid,
15351607 (void *)&replay_ctr, GFP_KERNEL);
15361608 }
....@@ -1543,71 +1615,155 @@
15431615 return true;
15441616 }
15451617
1546
-static struct iwl_wowlan_status *
1547
-iwl_mvm_get_wakeup_status(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
1618
+/* Occasionally, templates would be nice. This is one of those times ... */
1619
+#define iwl_mvm_parse_wowlan_status_common(_ver) \
1620
+static struct iwl_wowlan_status * \
1621
+iwl_mvm_parse_wowlan_status_common_ ## _ver(struct iwl_mvm *mvm, \
1622
+ void *_data, int len) \
1623
+{ \
1624
+ struct iwl_wowlan_status *status; \
1625
+ struct iwl_wowlan_status_ ##_ver *data = _data; \
1626
+ int data_size; \
1627
+ \
1628
+ if (len < sizeof(*data)) { \
1629
+ IWL_ERR(mvm, "Invalid WoWLAN status response!\n"); \
1630
+ return ERR_PTR(-EIO); \
1631
+ } \
1632
+ \
1633
+ data_size = ALIGN(le32_to_cpu(data->wake_packet_bufsize), 4); \
1634
+ if (len != sizeof(*data) + data_size) { \
1635
+ IWL_ERR(mvm, "Invalid WoWLAN status response!\n"); \
1636
+ return ERR_PTR(-EIO); \
1637
+ } \
1638
+ \
1639
+ status = kzalloc(sizeof(*status) + data_size, GFP_KERNEL); \
1640
+ if (!status) \
1641
+ return ERR_PTR(-ENOMEM); \
1642
+ \
1643
+ /* copy all the common fields */ \
1644
+ status->replay_ctr = data->replay_ctr; \
1645
+ status->pattern_number = data->pattern_number; \
1646
+ status->non_qos_seq_ctr = data->non_qos_seq_ctr; \
1647
+ memcpy(status->qos_seq_ctr, data->qos_seq_ctr, \
1648
+ sizeof(status->qos_seq_ctr)); \
1649
+ status->wakeup_reasons = data->wakeup_reasons; \
1650
+ status->num_of_gtk_rekeys = data->num_of_gtk_rekeys; \
1651
+ status->received_beacons = data->received_beacons; \
1652
+ status->wake_packet_length = data->wake_packet_length; \
1653
+ status->wake_packet_bufsize = data->wake_packet_bufsize; \
1654
+ memcpy(status->wake_packet, data->wake_packet, \
1655
+ le32_to_cpu(status->wake_packet_bufsize)); \
1656
+ \
1657
+ return status; \
1658
+}
1659
+
1660
+iwl_mvm_parse_wowlan_status_common(v6)
1661
+iwl_mvm_parse_wowlan_status_common(v7)
1662
+iwl_mvm_parse_wowlan_status_common(v9)
1663
+
1664
+struct iwl_wowlan_status *iwl_mvm_send_wowlan_get_status(struct iwl_mvm *mvm)
15481665 {
1549
- u32 base = mvm->error_event_table[0];
1550
- struct error_table_start {
1551
- /* cf. struct iwl_error_event_table */
1552
- u32 valid;
1553
- u32 error_id;
1554
- } err_info;
1666
+ struct iwl_wowlan_status *status;
15551667 struct iwl_host_cmd cmd = {
15561668 .id = WOWLAN_GET_STATUSES,
15571669 .flags = CMD_WANT_SKB,
15581670 };
1559
- struct iwl_wowlan_status *status, *fw_status;
1560
- int ret, len, status_size;
1671
+ int ret, len;
1672
+ u8 notif_ver;
15611673
1562
- iwl_trans_read_mem_bytes(mvm->trans, base,
1563
- &err_info, sizeof(err_info));
1674
+ lockdep_assert_held(&mvm->mutex);
15641675
1565
- if (err_info.valid) {
1566
- IWL_INFO(mvm, "error table is valid (%d) with error (%d)\n",
1567
- err_info.valid, err_info.error_id);
1568
- if (err_info.error_id == RF_KILL_INDICATOR_FOR_WOWLAN) {
1569
- struct cfg80211_wowlan_wakeup wakeup = {
1570
- .rfkill_release = true,
1571
- };
1572
- ieee80211_report_wowlan_wakeup(vif, &wakeup,
1573
- GFP_KERNEL);
1574
- }
1575
- return ERR_PTR(-EIO);
1676
+ ret = iwl_mvm_send_cmd(mvm, &cmd);
1677
+ if (ret) {
1678
+ IWL_ERR(mvm, "failed to query wakeup status (%d)\n", ret);
1679
+ return ERR_PTR(ret);
15761680 }
1681
+
1682
+ len = iwl_rx_packet_payload_len(cmd.resp_pkt);
1683
+
1684
+ /* default to 7 (when we have IWL_UCODE_TLV_API_WOWLAN_KEY_MATERIAL) */
1685
+ notif_ver = iwl_fw_lookup_notif_ver(mvm->fw, LEGACY_GROUP,
1686
+ WOWLAN_GET_STATUSES, 7);
1687
+
1688
+ if (!fw_has_api(&mvm->fw->ucode_capa,
1689
+ IWL_UCODE_TLV_API_WOWLAN_KEY_MATERIAL)) {
1690
+ struct iwl_wowlan_status_v6 *v6 = (void *)cmd.resp_pkt->data;
1691
+
1692
+ status = iwl_mvm_parse_wowlan_status_common_v6(mvm,
1693
+ cmd.resp_pkt->data,
1694
+ len);
1695
+ if (IS_ERR(status))
1696
+ goto out_free_resp;
1697
+
1698
+ BUILD_BUG_ON(sizeof(v6->gtk.decrypt_key) >
1699
+ sizeof(status->gtk[0].key));
1700
+ BUILD_BUG_ON(sizeof(v6->gtk.tkip_mic_key) >
1701
+ sizeof(status->gtk[0].tkip_mic_key));
1702
+
1703
+ /* copy GTK info to the right place */
1704
+ memcpy(status->gtk[0].key, v6->gtk.decrypt_key,
1705
+ sizeof(v6->gtk.decrypt_key));
1706
+ memcpy(status->gtk[0].tkip_mic_key, v6->gtk.tkip_mic_key,
1707
+ sizeof(v6->gtk.tkip_mic_key));
1708
+ memcpy(&status->gtk[0].rsc, &v6->gtk.rsc,
1709
+ sizeof(status->gtk[0].rsc));
1710
+
1711
+ /* hardcode the key length to 16 since v6 only supports 16 */
1712
+ status->gtk[0].key_len = 16;
1713
+
1714
+ /*
1715
+ * The key index only uses 2 bits (values 0 to 3) and
1716
+ * we always set bit 7 which means this is the
1717
+ * currently used key.
1718
+ */
1719
+ status->gtk[0].key_flags = v6->gtk.key_index | BIT(7);
1720
+ } else if (notif_ver == 7) {
1721
+ struct iwl_wowlan_status_v7 *v7 = (void *)cmd.resp_pkt->data;
1722
+
1723
+ status = iwl_mvm_parse_wowlan_status_common_v7(mvm,
1724
+ cmd.resp_pkt->data,
1725
+ len);
1726
+ if (IS_ERR(status))
1727
+ goto out_free_resp;
1728
+
1729
+ status->gtk[0] = v7->gtk[0];
1730
+ status->igtk[0] = v7->igtk[0];
1731
+ } else if (notif_ver == 9) {
1732
+ struct iwl_wowlan_status_v9 *v9 = (void *)cmd.resp_pkt->data;
1733
+
1734
+ status = iwl_mvm_parse_wowlan_status_common_v9(mvm,
1735
+ cmd.resp_pkt->data,
1736
+ len);
1737
+ if (IS_ERR(status))
1738
+ goto out_free_resp;
1739
+
1740
+ status->gtk[0] = v9->gtk[0];
1741
+ status->igtk[0] = v9->igtk[0];
1742
+
1743
+ status->tid_tear_down = v9->tid_tear_down;
1744
+ } else {
1745
+ IWL_ERR(mvm,
1746
+ "Firmware advertises unknown WoWLAN status response %d!\n",
1747
+ notif_ver);
1748
+ status = ERR_PTR(-EIO);
1749
+ }
1750
+
1751
+out_free_resp:
1752
+ iwl_free_resp(&cmd);
1753
+ return status;
1754
+}
1755
+
1756
+static struct iwl_wowlan_status *
1757
+iwl_mvm_get_wakeup_status(struct iwl_mvm *mvm)
1758
+{
1759
+ int ret;
15771760
15781761 /* only for tracing for now */
15791762 ret = iwl_mvm_send_cmd_pdu(mvm, OFFLOADS_QUERY_CMD, 0, 0, NULL);
15801763 if (ret)
15811764 IWL_ERR(mvm, "failed to query offload statistics (%d)\n", ret);
15821765
1583
- ret = iwl_mvm_send_cmd(mvm, &cmd);
1584
- if (ret) {
1585
- IWL_ERR(mvm, "failed to query status (%d)\n", ret);
1586
- return ERR_PTR(ret);
1587
- }
1588
-
1589
- status_size = sizeof(*fw_status);
1590
-
1591
- len = iwl_rx_packet_payload_len(cmd.resp_pkt);
1592
- if (len < status_size) {
1593
- IWL_ERR(mvm, "Invalid WoWLAN status response!\n");
1594
- fw_status = ERR_PTR(-EIO);
1595
- goto out_free_resp;
1596
- }
1597
-
1598
- status = (void *)cmd.resp_pkt->data;
1599
- if (len != (status_size +
1600
- ALIGN(le32_to_cpu(status->wake_packet_bufsize), 4))) {
1601
- IWL_ERR(mvm, "Invalid WoWLAN status response!\n");
1602
- fw_status = ERR_PTR(-EIO);
1603
- goto out_free_resp;
1604
- }
1605
-
1606
- fw_status = kmemdup(status, len, GFP_KERNEL);
1607
-
1608
-out_free_resp:
1609
- iwl_free_resp(&cmd);
1610
- return fw_status;
1766
+ return iwl_mvm_send_wowlan_get_status(mvm);
16111767 }
16121768
16131769 /* releases the MVM mutex */
....@@ -1620,9 +1776,12 @@
16201776 bool keep;
16211777 struct iwl_mvm_sta *mvm_ap_sta;
16221778
1623
- fw_status = iwl_mvm_get_wakeup_status(mvm, vif);
1779
+ fw_status = iwl_mvm_get_wakeup_status(mvm);
16241780 if (IS_ERR_OR_NULL(fw_status))
16251781 goto out_unlock;
1782
+
1783
+ IWL_DEBUG_WOWLAN(mvm, "wakeup reason 0x%x\n",
1784
+ le32_to_cpu(fw_status->wakeup_reasons));
16261785
16271786 status.pattern_number = le16_to_cpu(fw_status->pattern_number);
16281787 for (i = 0; i < 8; i++)
....@@ -1647,6 +1806,13 @@
16471806 mvm_ap_sta->tid_data[i].seq_number = seq;
16481807 }
16491808
1809
+ if (mvm->trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_22000) {
1810
+ i = mvm->offload_tid;
1811
+ iwl_trans_set_q_ptrs(mvm->trans,
1812
+ mvm_ap_sta->tid_data[i].txq_id,
1813
+ mvm_ap_sta->tid_data[i].seq_number >> 4);
1814
+ }
1815
+
16501816 /* now we have all the data we need, unlock to avoid mac80211 issues */
16511817 mutex_unlock(&mvm->mutex);
16521818
....@@ -1664,33 +1830,12 @@
16641830 return false;
16651831 }
16661832
1667
-void iwl_mvm_d0i3_update_keys(struct iwl_mvm *mvm,
1668
- struct ieee80211_vif *vif,
1669
- struct iwl_wowlan_status *status)
1670
-{
1671
- struct iwl_mvm_d3_gtk_iter_data gtkdata = {
1672
- .mvm = mvm,
1673
- .status = status,
1674
- };
1675
-
1676
- /*
1677
- * rekey handling requires taking locks that can't be taken now.
1678
- * however, d0i3 doesn't offload rekey, so we're fine.
1679
- */
1680
- if (WARN_ON_ONCE(status->num_of_gtk_rekeys))
1681
- return;
1682
-
1683
- /* find last GTK that we used initially, if any */
1684
- gtkdata.find_phase = true;
1685
- iwl_mvm_iter_d0i3_ap_keys(mvm, vif, iwl_mvm_d3_update_keys, &gtkdata);
1686
-
1687
- gtkdata.find_phase = false;
1688
- iwl_mvm_iter_d0i3_ap_keys(mvm, vif, iwl_mvm_d3_update_keys, &gtkdata);
1689
-}
1833
+#define ND_QUERY_BUF_LEN (sizeof(struct iwl_scan_offload_profile_match) * \
1834
+ IWL_SCAN_MAX_PROFILES)
16901835
16911836 struct iwl_mvm_nd_query_results {
16921837 u32 matched_profiles;
1693
- struct iwl_scan_offload_profile_match matches[IWL_SCAN_MAX_PROFILES];
1838
+ u8 matches[ND_QUERY_BUF_LEN];
16941839 };
16951840
16961841 static int
....@@ -1703,6 +1848,8 @@
17031848 .flags = CMD_WANT_SKB,
17041849 };
17051850 int ret, len;
1851
+ size_t query_len, matches_len;
1852
+ int max_profiles = iwl_umac_scan_get_max_profiles(mvm->fw);
17061853
17071854 ret = iwl_mvm_send_cmd(mvm, &cmd);
17081855 if (ret) {
....@@ -1710,8 +1857,19 @@
17101857 return ret;
17111858 }
17121859
1860
+ if (fw_has_api(&mvm->fw->ucode_capa,
1861
+ IWL_UCODE_TLV_API_SCAN_OFFLOAD_CHANS)) {
1862
+ query_len = sizeof(struct iwl_scan_offload_profiles_query);
1863
+ matches_len = sizeof(struct iwl_scan_offload_profile_match) *
1864
+ max_profiles;
1865
+ } else {
1866
+ query_len = sizeof(struct iwl_scan_offload_profiles_query_v1);
1867
+ matches_len = sizeof(struct iwl_scan_offload_profile_match_v1) *
1868
+ max_profiles;
1869
+ }
1870
+
17131871 len = iwl_rx_packet_payload_len(cmd.resp_pkt);
1714
- if (len < sizeof(*query)) {
1872
+ if (len < query_len) {
17151873 IWL_ERR(mvm, "Invalid scan offload profiles query response!\n");
17161874 ret = -EIO;
17171875 goto out_free_resp;
....@@ -1720,7 +1878,7 @@
17201878 query = (void *)cmd.resp_pkt->data;
17211879
17221880 results->matched_profiles = le32_to_cpu(query->matched_profiles);
1723
- memcpy(results->matches, query->matches, sizeof(results->matches));
1881
+ memcpy(results->matches, query->matches, matches_len);
17241882
17251883 #ifdef CONFIG_IWLWIFI_DEBUGFS
17261884 mvm->last_netdetect_scans = le32_to_cpu(query->n_scans_done);
....@@ -1729,6 +1887,57 @@
17291887 out_free_resp:
17301888 iwl_free_resp(&cmd);
17311889 return ret;
1890
+}
1891
+
1892
+static int iwl_mvm_query_num_match_chans(struct iwl_mvm *mvm,
1893
+ struct iwl_mvm_nd_query_results *query,
1894
+ int idx)
1895
+{
1896
+ int n_chans = 0, i;
1897
+
1898
+ if (fw_has_api(&mvm->fw->ucode_capa,
1899
+ IWL_UCODE_TLV_API_SCAN_OFFLOAD_CHANS)) {
1900
+ struct iwl_scan_offload_profile_match *matches =
1901
+ (struct iwl_scan_offload_profile_match *)query->matches;
1902
+
1903
+ for (i = 0; i < SCAN_OFFLOAD_MATCHING_CHANNELS_LEN; i++)
1904
+ n_chans += hweight8(matches[idx].matching_channels[i]);
1905
+ } else {
1906
+ struct iwl_scan_offload_profile_match_v1 *matches =
1907
+ (struct iwl_scan_offload_profile_match_v1 *)query->matches;
1908
+
1909
+ for (i = 0; i < SCAN_OFFLOAD_MATCHING_CHANNELS_LEN_V1; i++)
1910
+ n_chans += hweight8(matches[idx].matching_channels[i]);
1911
+ }
1912
+
1913
+ return n_chans;
1914
+}
1915
+
1916
+static void iwl_mvm_query_set_freqs(struct iwl_mvm *mvm,
1917
+ struct iwl_mvm_nd_query_results *query,
1918
+ struct cfg80211_wowlan_nd_match *match,
1919
+ int idx)
1920
+{
1921
+ int i;
1922
+
1923
+ if (fw_has_api(&mvm->fw->ucode_capa,
1924
+ IWL_UCODE_TLV_API_SCAN_OFFLOAD_CHANS)) {
1925
+ struct iwl_scan_offload_profile_match *matches =
1926
+ (struct iwl_scan_offload_profile_match *)query->matches;
1927
+
1928
+ for (i = 0; i < SCAN_OFFLOAD_MATCHING_CHANNELS_LEN * 8; i++)
1929
+ if (matches[idx].matching_channels[i / 8] & (BIT(i % 8)))
1930
+ match->channels[match->n_channels++] =
1931
+ mvm->nd_channels[i]->center_freq;
1932
+ } else {
1933
+ struct iwl_scan_offload_profile_match_v1 *matches =
1934
+ (struct iwl_scan_offload_profile_match_v1 *)query->matches;
1935
+
1936
+ for (i = 0; i < SCAN_OFFLOAD_MATCHING_CHANNELS_LEN_V1 * 8; i++)
1937
+ if (matches[idx].matching_channels[i / 8] & (BIT(i % 8)))
1938
+ match->channels[match->n_channels++] =
1939
+ mvm->nd_channels[i]->center_freq;
1940
+ }
17321941 }
17331942
17341943 static void iwl_mvm_query_netdetect_reasons(struct iwl_mvm *mvm,
....@@ -1743,9 +1952,9 @@
17431952 struct iwl_wowlan_status *fw_status;
17441953 unsigned long matched_profiles;
17451954 u32 reasons = 0;
1746
- int i, j, n_matches, ret;
1955
+ int i, n_matches, ret;
17471956
1748
- fw_status = iwl_mvm_get_wakeup_status(mvm, vif);
1957
+ fw_status = iwl_mvm_get_wakeup_status(mvm);
17491958 if (!IS_ERR_OR_NULL(fw_status)) {
17501959 reasons = le32_to_cpu(fw_status->wakeup_reasons);
17511960 kfree(fw_status);
....@@ -1771,24 +1980,18 @@
17711980 n_matches = 0;
17721981 }
17731982
1774
- net_detect = kzalloc(sizeof(*net_detect) +
1775
- (n_matches * sizeof(net_detect->matches[0])),
1983
+ net_detect = kzalloc(struct_size(net_detect, matches, n_matches),
17761984 GFP_KERNEL);
17771985 if (!net_detect || !n_matches)
17781986 goto out_report_nd;
17791987
17801988 for_each_set_bit(i, &matched_profiles, mvm->n_nd_match_sets) {
1781
- struct iwl_scan_offload_profile_match *fw_match;
17821989 struct cfg80211_wowlan_nd_match *match;
17831990 int idx, n_channels = 0;
17841991
1785
- fw_match = &query.matches[i];
1992
+ n_channels = iwl_mvm_query_num_match_chans(mvm, &query, i);
17861993
1787
- for (j = 0; j < SCAN_OFFLOAD_MATCHING_CHANNELS_LEN; j++)
1788
- n_channels += hweight8(fw_match->matching_channels[j]);
1789
-
1790
- match = kzalloc(sizeof(*match) +
1791
- (n_channels * sizeof(*match->channels)),
1994
+ match = kzalloc(struct_size(match, channels, n_channels),
17921995 GFP_KERNEL);
17931996 if (!match)
17941997 goto out_report_nd;
....@@ -1806,10 +2009,7 @@
18062009 if (mvm->n_nd_channels < n_channels)
18072010 continue;
18082011
1809
- for (j = 0; j < SCAN_OFFLOAD_MATCHING_CHANNELS_LEN * 8; j++)
1810
- if (fw_match->matching_channels[j / 8] & (BIT(j % 8)))
1811
- match->channels[match->n_channels++] =
1812
- mvm->nd_channels[j]->center_freq;
2012
+ iwl_mvm_query_set_freqs(mvm, &query, match, i);
18132013 }
18142014
18152015 out_report_nd:
....@@ -1827,26 +2027,6 @@
18272027 }
18282028 }
18292029
1830
-static void iwl_mvm_read_d3_sram(struct iwl_mvm *mvm)
1831
-{
1832
-#ifdef CONFIG_IWLWIFI_DEBUGFS
1833
- const struct fw_img *img = &mvm->fw->img[IWL_UCODE_WOWLAN];
1834
- u32 len = img->sec[IWL_UCODE_SECTION_DATA].len;
1835
- u32 offs = img->sec[IWL_UCODE_SECTION_DATA].offset;
1836
-
1837
- if (!mvm->store_d3_resume_sram)
1838
- return;
1839
-
1840
- if (!mvm->d3_resume_sram) {
1841
- mvm->d3_resume_sram = kzalloc(len, GFP_KERNEL);
1842
- if (!mvm->d3_resume_sram)
1843
- return;
1844
- }
1845
-
1846
- iwl_trans_read_mem_bytes(mvm->trans, offs, mvm->d3_resume_sram, len);
1847
-#endif
1848
-}
1849
-
18502030 static void iwl_mvm_d3_disconnect_iter(void *data, u8 *mac,
18512031 struct ieee80211_vif *vif)
18522032 {
....@@ -1856,6 +2036,57 @@
18562036
18572037 if (vif->type == NL80211_IFTYPE_STATION)
18582038 ieee80211_resume_disconnect(vif);
2039
+}
2040
+
2041
+static bool iwl_mvm_rt_status(struct iwl_trans *trans, u32 base, u32 *err_id)
2042
+{
2043
+ struct error_table_start {
2044
+ /* cf. struct iwl_error_event_table */
2045
+ u32 valid;
2046
+ __le32 err_id;
2047
+ } err_info;
2048
+
2049
+ if (!base)
2050
+ return false;
2051
+
2052
+ iwl_trans_read_mem_bytes(trans, base,
2053
+ &err_info, sizeof(err_info));
2054
+ if (err_info.valid && err_id)
2055
+ *err_id = le32_to_cpu(err_info.err_id);
2056
+
2057
+ return !!err_info.valid;
2058
+}
2059
+
2060
+static bool iwl_mvm_check_rt_status(struct iwl_mvm *mvm,
2061
+ struct ieee80211_vif *vif)
2062
+{
2063
+ u32 err_id;
2064
+
2065
+ /* check for lmac1 error */
2066
+ if (iwl_mvm_rt_status(mvm->trans,
2067
+ mvm->trans->dbg.lmac_error_event_table[0],
2068
+ &err_id)) {
2069
+ if (err_id == RF_KILL_INDICATOR_FOR_WOWLAN) {
2070
+ struct cfg80211_wowlan_wakeup wakeup = {
2071
+ .rfkill_release = true,
2072
+ };
2073
+ ieee80211_report_wowlan_wakeup(vif, &wakeup,
2074
+ GFP_KERNEL);
2075
+ }
2076
+ return true;
2077
+ }
2078
+
2079
+ /* check if we have lmac2 set and check for error */
2080
+ if (iwl_mvm_rt_status(mvm->trans,
2081
+ mvm->trans->dbg.lmac_error_event_table[1], NULL))
2082
+ return true;
2083
+
2084
+ /* check for umac error */
2085
+ if (iwl_mvm_rt_status(mvm->trans,
2086
+ mvm->trans->dbg.umac_error_event_table, NULL))
2087
+ return true;
2088
+
2089
+ return false;
18592090 }
18602091
18612092 static int __iwl_mvm_resume(struct iwl_mvm *mvm, bool test)
....@@ -1871,10 +2102,28 @@
18712102
18722103 mutex_lock(&mvm->mutex);
18732104
2105
+ clear_bit(IWL_MVM_STATUS_IN_D3, &mvm->status);
2106
+
18742107 /* get the BSS vif pointer again */
18752108 vif = iwl_mvm_get_bss_vif(mvm);
18762109 if (IS_ERR_OR_NULL(vif))
18772110 goto err;
2111
+
2112
+ iwl_fw_dbg_read_d3_debug_data(&mvm->fwrt);
2113
+
2114
+ if (iwl_mvm_check_rt_status(mvm, vif)) {
2115
+ set_bit(STATUS_FW_ERROR, &mvm->trans->status);
2116
+ iwl_mvm_dump_nic_error_log(mvm);
2117
+ iwl_dbg_tlv_time_point(&mvm->fwrt,
2118
+ IWL_FW_INI_TIME_POINT_FW_ASSERT, NULL);
2119
+ iwl_fw_dbg_collect_desc(&mvm->fwrt, &iwl_dump_desc_assert,
2120
+ false, 0);
2121
+ ret = 1;
2122
+ goto err;
2123
+ }
2124
+
2125
+ iwl_dbg_tlv_time_point(&mvm->fwrt, IWL_FW_INI_TIME_POINT_HOST_D3_END,
2126
+ NULL);
18782127
18792128 ret = iwl_trans_d3_resume(mvm->trans, &d3_status, test, !unified_image);
18802129 if (ret)
....@@ -1885,15 +2134,39 @@
18852134 goto err;
18862135 }
18872136
1888
- /* query SRAM first in case we want event logging */
1889
- iwl_mvm_read_d3_sram(mvm);
1890
-
18912137 if (d0i3_first) {
1892
- ret = iwl_mvm_send_cmd_pdu(mvm, D0I3_END_CMD, 0, 0, NULL);
2138
+ struct iwl_host_cmd cmd = {
2139
+ .id = D0I3_END_CMD,
2140
+ .flags = CMD_WANT_SKB,
2141
+ };
2142
+ int len;
2143
+
2144
+ ret = iwl_mvm_send_cmd(mvm, &cmd);
18932145 if (ret < 0) {
18942146 IWL_ERR(mvm, "Failed to send D0I3_END_CMD first (%d)\n",
18952147 ret);
18962148 goto err;
2149
+ }
2150
+ switch (mvm->cmd_ver.d0i3_resp) {
2151
+ case 0:
2152
+ break;
2153
+ case 1:
2154
+ len = iwl_rx_packet_payload_len(cmd.resp_pkt);
2155
+ if (len != sizeof(u32)) {
2156
+ IWL_ERR(mvm,
2157
+ "Error with D0I3_END_CMD response size (%d)\n",
2158
+ len);
2159
+ goto err;
2160
+ }
2161
+ if (IWL_D0I3_RESET_REQUIRE &
2162
+ le32_to_cpu(*(__le32 *)cmd.resp_pkt->data)) {
2163
+ iwl_write32(mvm->trans, CSR_RESET,
2164
+ CSR_RESET_REG_FLAG_FORCE_NMI);
2165
+ iwl_free_resp(&cmd);
2166
+ }
2167
+ break;
2168
+ default:
2169
+ WARN_ON(1);
18972170 }
18982171 }
18992172
....@@ -1902,6 +2175,9 @@
19022175 * can play it back when we re-intiailize the D0 firmware
19032176 */
19042177 iwl_mvm_update_changed_regdom(mvm);
2178
+
2179
+ /* Re-configure PPAG settings */
2180
+ iwl_mvm_ppag_send_cmd(mvm);
19052181
19062182 if (!unified_image)
19072183 /* Re-configure default SAR profile */
....@@ -1959,15 +2235,6 @@
19592235 * 2. We are using a unified image but had an error while exiting D3
19602236 */
19612237 set_bit(IWL_MVM_STATUS_HW_RESTART_REQUESTED, &mvm->status);
1962
- set_bit(IWL_MVM_STATUS_D3_RECONFIG, &mvm->status);
1963
- /*
1964
- * When switching images we return 1, which causes mac80211
1965
- * to do a reconfig with IEEE80211_RECONFIG_TYPE_RESTART.
1966
- * This type of reconfig calls iwl_mvm_restart_complete(),
1967
- * where we unref the IWL_MVM_REF_UCODE_DOWN, so we need
1968
- * to take the reference here.
1969
- */
1970
- iwl_mvm_ref(mvm, IWL_MVM_REF_UCODE_DOWN);
19712238
19722239 return 1;
19732240 }
....@@ -1979,53 +2246,12 @@
19792246 return __iwl_mvm_resume(mvm, false);
19802247 }
19812248
1982
-static int iwl_mvm_resume_d0i3(struct iwl_mvm *mvm)
1983
-{
1984
- bool exit_now;
1985
- enum iwl_d3_status d3_status;
1986
- struct iwl_trans *trans = mvm->trans;
1987
-
1988
- iwl_trans_d3_resume(trans, &d3_status, false, false);
1989
-
1990
- /*
1991
- * make sure to clear D0I3_DEFER_WAKEUP before
1992
- * calling iwl_trans_resume(), which might wait
1993
- * for d0i3 exit completion.
1994
- */
1995
- mutex_lock(&mvm->d0i3_suspend_mutex);
1996
- __clear_bit(D0I3_DEFER_WAKEUP, &mvm->d0i3_suspend_flags);
1997
- exit_now = __test_and_clear_bit(D0I3_PENDING_WAKEUP,
1998
- &mvm->d0i3_suspend_flags);
1999
- mutex_unlock(&mvm->d0i3_suspend_mutex);
2000
- if (exit_now) {
2001
- IWL_DEBUG_RPM(mvm, "Run deferred d0i3 exit\n");
2002
- _iwl_mvm_exit_d0i3(mvm);
2003
- }
2004
-
2005
- iwl_trans_resume(trans);
2006
-
2007
- if (iwl_mvm_enter_d0i3_on_suspend(mvm)) {
2008
- int ret = iwl_mvm_exit_d0i3(mvm->hw->priv);
2009
-
2010
- if (ret)
2011
- return ret;
2012
- /*
2013
- * d0i3 exit will be deferred until reconfig_complete.
2014
- * make sure there we are out of d0i3.
2015
- */
2016
- }
2017
- return 0;
2018
-}
2019
-
20202249 int iwl_mvm_resume(struct ieee80211_hw *hw)
20212250 {
20222251 struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
20232252 int ret;
20242253
2025
- if (mvm->trans->system_pm_mode == IWL_PLAT_PM_MODE_D0I3)
2026
- ret = iwl_mvm_resume_d0i3(mvm);
2027
- else
2028
- ret = iwl_mvm_resume_d3(mvm);
2254
+ ret = iwl_mvm_resume_d3(mvm);
20292255
20302256 mvm->trans->system_pm_mode = IWL_PLAT_PM_MODE_DISABLED;
20312257
....@@ -2054,7 +2280,6 @@
20542280
20552281 file->private_data = inode->i_private;
20562282
2057
- ieee80211_stop_queues(mvm->hw);
20582283 synchronize_net();
20592284
20602285 mvm->trans->system_pm_mode = IWL_PLAT_PM_MODE_D3;
....@@ -2069,10 +2294,9 @@
20692294 rtnl_unlock();
20702295 if (err > 0)
20712296 err = -EINVAL;
2072
- if (err) {
2073
- ieee80211_wake_queues(mvm->hw);
2297
+ if (err)
20742298 return err;
2075
- }
2299
+
20762300 mvm->d3_test_active = true;
20772301 mvm->keep_vif = NULL;
20782302 return 0;
....@@ -2119,6 +2343,8 @@
21192343
21202344 mvm->d3_test_active = false;
21212345
2346
+ iwl_fw_dbg_read_d3_debug_data(&mvm->fwrt);
2347
+
21222348 rtnl_lock();
21232349 __iwl_mvm_resume(mvm, true);
21242350 rtnl_unlock();
....@@ -2149,8 +2375,6 @@
21492375 ieee80211_iterate_active_interfaces_atomic(
21502376 mvm->hw, IEEE80211_IFACE_ITER_NORMAL,
21512377 iwl_mvm_d3_test_disconn_work_iter, mvm->keep_vif);
2152
-
2153
- ieee80211_wake_queues(mvm->hw);
21542378
21552379 return 0;
21562380 }