aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/wireless/iwlwifi/dvm/mac80211.c4
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-trans.h14
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/d3.c149
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/debugfs.c1
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/mvm.h3
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/phy-ctxt.c3
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/utils.c10
-rw-r--r--drivers/net/wireless/iwlwifi/pcie/trans.c19
8 files changed, 182 insertions, 21 deletions
diff --git a/drivers/net/wireless/iwlwifi/dvm/mac80211.c b/drivers/net/wireless/iwlwifi/dvm/mac80211.c
index ac7ed3f809a0..c0039a992909 100644
--- a/drivers/net/wireless/iwlwifi/dvm/mac80211.c
+++ b/drivers/net/wireless/iwlwifi/dvm/mac80211.c
@@ -430,7 +430,7 @@ static int iwlagn_mac_suspend(struct ieee80211_hw *hw,
430 iwl_write32(priv->trans, CSR_UCODE_DRV_GP1_SET, 430 iwl_write32(priv->trans, CSR_UCODE_DRV_GP1_SET,
431 CSR_UCODE_DRV_GP1_BIT_D3_CFG_COMPLETE); 431 CSR_UCODE_DRV_GP1_BIT_D3_CFG_COMPLETE);
432 432
433 iwl_trans_d3_suspend(priv->trans); 433 iwl_trans_d3_suspend(priv->trans, false);
434 434
435 goto out; 435 goto out;
436 436
@@ -504,7 +504,7 @@ static int iwlagn_mac_resume(struct ieee80211_hw *hw)
504 /* we'll clear ctx->vif during iwlagn_prepare_restart() */ 504 /* we'll clear ctx->vif during iwlagn_prepare_restart() */
505 vif = ctx->vif; 505 vif = ctx->vif;
506 506
507 ret = iwl_trans_d3_resume(priv->trans, &d3_status); 507 ret = iwl_trans_d3_resume(priv->trans, &d3_status, false);
508 if (ret) 508 if (ret)
509 goto out_unlock; 509 goto out_unlock;
510 510
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h
index 84f1c8dc9741..be4b2ac3dbbf 100644
--- a/drivers/net/wireless/iwlwifi/iwl-trans.h
+++ b/drivers/net/wireless/iwlwifi/iwl-trans.h
@@ -428,8 +428,9 @@ struct iwl_trans_ops {
428 void (*fw_alive)(struct iwl_trans *trans, u32 scd_addr); 428 void (*fw_alive)(struct iwl_trans *trans, u32 scd_addr);
429 void (*stop_device)(struct iwl_trans *trans); 429 void (*stop_device)(struct iwl_trans *trans);
430 430
431 void (*d3_suspend)(struct iwl_trans *trans); 431 void (*d3_suspend)(struct iwl_trans *trans, bool test);
432 int (*d3_resume)(struct iwl_trans *trans, enum iwl_d3_status *status); 432 int (*d3_resume)(struct iwl_trans *trans, enum iwl_d3_status *status,
433 bool test);
433 434
434 int (*send_cmd)(struct iwl_trans *trans, struct iwl_host_cmd *cmd); 435 int (*send_cmd)(struct iwl_trans *trans, struct iwl_host_cmd *cmd);
435 436
@@ -588,17 +589,18 @@ static inline void iwl_trans_stop_device(struct iwl_trans *trans)
588 trans->state = IWL_TRANS_NO_FW; 589 trans->state = IWL_TRANS_NO_FW;
589} 590}
590 591
591static inline void iwl_trans_d3_suspend(struct iwl_trans *trans) 592static inline void iwl_trans_d3_suspend(struct iwl_trans *trans, bool test)
592{ 593{
593 might_sleep(); 594 might_sleep();
594 trans->ops->d3_suspend(trans); 595 trans->ops->d3_suspend(trans, test);
595} 596}
596 597
597static inline int iwl_trans_d3_resume(struct iwl_trans *trans, 598static inline int iwl_trans_d3_resume(struct iwl_trans *trans,
598 enum iwl_d3_status *status) 599 enum iwl_d3_status *status,
600 bool test)
599{ 601{
600 might_sleep(); 602 might_sleep();
601 return trans->ops->d3_resume(trans, status); 603 return trans->ops->d3_resume(trans, status, test);
602} 604}
603 605
604static inline int iwl_trans_send_cmd(struct iwl_trans *trans, 606static inline int iwl_trans_send_cmd(struct iwl_trans *trans,
diff --git a/drivers/net/wireless/iwlwifi/mvm/d3.c b/drivers/net/wireless/iwlwifi/mvm/d3.c
index 4d3c978b5c76..7a2ef3f013fd 100644
--- a/drivers/net/wireless/iwlwifi/mvm/d3.c
+++ b/drivers/net/wireless/iwlwifi/mvm/d3.c
@@ -63,6 +63,7 @@
63 63
64#include <linux/etherdevice.h> 64#include <linux/etherdevice.h>
65#include <linux/ip.h> 65#include <linux/ip.h>
66#include <linux/fs.h>
66#include <net/cfg80211.h> 67#include <net/cfg80211.h>
67#include <net/ipv6.h> 68#include <net/ipv6.h>
68#include <net/tcp.h> 69#include <net/tcp.h>
@@ -756,7 +757,9 @@ static int iwl_mvm_d3_reprogram(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
756 return 0; 757 return 0;
757} 758}
758 759
759int iwl_mvm_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) 760static int __iwl_mvm_suspend(struct ieee80211_hw *hw,
761 struct cfg80211_wowlan *wowlan,
762 bool test)
760{ 763{
761 struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); 764 struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
762 struct iwl_d3_iter_data suspend_iter_data = { 765 struct iwl_d3_iter_data suspend_iter_data = {
@@ -769,7 +772,7 @@ int iwl_mvm_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
769 struct iwl_wowlan_config_cmd wowlan_config_cmd = {}; 772 struct iwl_wowlan_config_cmd wowlan_config_cmd = {};
770 struct iwl_wowlan_kek_kck_material_cmd kek_kck_cmd = {}; 773 struct iwl_wowlan_kek_kck_material_cmd kek_kck_cmd = {};
771 struct iwl_wowlan_tkip_params_cmd tkip_cmd = {}; 774 struct iwl_wowlan_tkip_params_cmd tkip_cmd = {};
772 struct iwl_d3_manager_config d3_cfg_cmd = { 775 struct iwl_d3_manager_config d3_cfg_cmd_data = {
773 /* 776 /*
774 * Program the minimum sleep time to 10 seconds, as many 777 * Program the minimum sleep time to 10 seconds, as many
775 * platforms have issues processing a wakeup signal while 778 * platforms have issues processing a wakeup signal while
@@ -777,17 +780,30 @@ int iwl_mvm_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
777 */ 780 */
778 .min_sleep_time = cpu_to_le32(10 * 1000 * 1000), 781 .min_sleep_time = cpu_to_le32(10 * 1000 * 1000),
779 }; 782 };
783 struct iwl_host_cmd d3_cfg_cmd = {
784 .id = D3_CONFIG_CMD,
785 .flags = CMD_SYNC | CMD_WANT_SKB,
786 .data[0] = &d3_cfg_cmd_data,
787 .len[0] = sizeof(d3_cfg_cmd_data),
788 };
780 struct wowlan_key_data key_data = { 789 struct wowlan_key_data key_data = {
781 .use_rsc_tsc = false, 790 .use_rsc_tsc = false,
782 .tkip = &tkip_cmd, 791 .tkip = &tkip_cmd,
783 .use_tkip = false, 792 .use_tkip = false,
784 }; 793 };
785 int ret, i; 794 int ret, i;
795 int len __maybe_unused;
786 u16 seq; 796 u16 seq;
787 u8 old_aux_sta_id, old_ap_sta_id = IWL_MVM_STATION_COUNT; 797 u8 old_aux_sta_id, old_ap_sta_id = IWL_MVM_STATION_COUNT;
788 798
789 if (WARN_ON(!wowlan)) 799 if (!wowlan) {
800 /*
801 * mac80211 shouldn't get here, but for D3 test
802 * it doesn't warrant a warning
803 */
804 WARN_ON(!test);
790 return -EINVAL; 805 return -EINVAL;
806 }
791 807
792 key_data.rsc_tsc = kzalloc(sizeof(*key_data.rsc_tsc), GFP_KERNEL); 808 key_data.rsc_tsc = kzalloc(sizeof(*key_data.rsc_tsc), GFP_KERNEL);
793 if (!key_data.rsc_tsc) 809 if (!key_data.rsc_tsc)
@@ -1012,14 +1028,26 @@ int iwl_mvm_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
1012 goto out; 1028 goto out;
1013 1029
1014 /* must be last -- this switches firmware state */ 1030 /* must be last -- this switches firmware state */
1015 ret = iwl_mvm_send_cmd_pdu(mvm, D3_CONFIG_CMD, CMD_SYNC, 1031 ret = iwl_mvm_send_cmd(mvm, &d3_cfg_cmd);
1016 sizeof(d3_cfg_cmd), &d3_cfg_cmd);
1017 if (ret) 1032 if (ret)
1018 goto out; 1033 goto out;
1034#ifdef CONFIG_IWLWIFI_DEBUGFS
1035 len = le32_to_cpu(d3_cfg_cmd.resp_pkt->len_n_flags) &
1036 FH_RSCSR_FRAME_SIZE_MSK;
1037 if (len >= sizeof(u32) * 2) {
1038 mvm->d3_test_pme_ptr =
1039 le32_to_cpup((__le32 *)d3_cfg_cmd.resp_pkt->data);
1040 } else if (test) {
1041 /* in test mode we require the pointer */
1042 ret = -EIO;
1043 goto out;
1044 }
1045#endif
1046 iwl_free_resp(&d3_cfg_cmd);
1019 1047
1020 clear_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status); 1048 clear_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status);
1021 1049
1022 iwl_trans_d3_suspend(mvm->trans); 1050 iwl_trans_d3_suspend(mvm->trans, test);
1023 out: 1051 out:
1024 mvm->aux_sta.sta_id = old_aux_sta_id; 1052 mvm->aux_sta.sta_id = old_aux_sta_id;
1025 mvm_ap_sta->sta_id = old_ap_sta_id; 1053 mvm_ap_sta->sta_id = old_ap_sta_id;
@@ -1034,6 +1062,11 @@ int iwl_mvm_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
1034 return ret; 1062 return ret;
1035} 1063}
1036 1064
1065int iwl_mvm_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
1066{
1067 return __iwl_mvm_suspend(hw, wowlan, false);
1068}
1069
1037static void iwl_mvm_query_wakeup_reasons(struct iwl_mvm *mvm, 1070static void iwl_mvm_query_wakeup_reasons(struct iwl_mvm *mvm,
1038 struct ieee80211_vif *vif) 1071 struct ieee80211_vif *vif)
1039{ 1072{
@@ -1238,9 +1271,8 @@ static void iwl_mvm_read_d3_sram(struct iwl_mvm *mvm)
1238#endif 1271#endif
1239} 1272}
1240 1273
1241int iwl_mvm_resume(struct ieee80211_hw *hw) 1274static int __iwl_mvm_resume(struct iwl_mvm *mvm, bool test)
1242{ 1275{
1243 struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
1244 struct iwl_d3_iter_data resume_iter_data = { 1276 struct iwl_d3_iter_data resume_iter_data = {
1245 .mvm = mvm, 1277 .mvm = mvm,
1246 }; 1278 };
@@ -1260,7 +1292,7 @@ int iwl_mvm_resume(struct ieee80211_hw *hw)
1260 1292
1261 vif = resume_iter_data.vif; 1293 vif = resume_iter_data.vif;
1262 1294
1263 ret = iwl_trans_d3_resume(mvm->trans, &d3_status); 1295 ret = iwl_trans_d3_resume(mvm->trans, &d3_status, test);
1264 if (ret) 1296 if (ret)
1265 goto out_unlock; 1297 goto out_unlock;
1266 1298
@@ -1277,7 +1309,7 @@ int iwl_mvm_resume(struct ieee80211_hw *hw)
1277 out_unlock: 1309 out_unlock:
1278 mutex_unlock(&mvm->mutex); 1310 mutex_unlock(&mvm->mutex);
1279 1311
1280 if (vif) 1312 if (!test && vif)
1281 ieee80211_resume_disconnect(vif); 1313 ieee80211_resume_disconnect(vif);
1282 1314
1283 /* return 1 to reconfigure the device */ 1315 /* return 1 to reconfigure the device */
@@ -1285,9 +1317,106 @@ int iwl_mvm_resume(struct ieee80211_hw *hw)
1285 return 1; 1317 return 1;
1286} 1318}
1287 1319
1320int iwl_mvm_resume(struct ieee80211_hw *hw)
1321{
1322 struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
1323
1324 return __iwl_mvm_resume(mvm, false);
1325}
1326
1288void iwl_mvm_set_wakeup(struct ieee80211_hw *hw, bool enabled) 1327void iwl_mvm_set_wakeup(struct ieee80211_hw *hw, bool enabled)
1289{ 1328{
1290 struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); 1329 struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
1291 1330
1292 device_set_wakeup_enable(mvm->trans->dev, enabled); 1331 device_set_wakeup_enable(mvm->trans->dev, enabled);
1293} 1332}
1333
1334#ifdef CONFIG_IWLWIFI_DEBUGFS
1335static int iwl_mvm_d3_test_open(struct inode *inode, struct file *file)
1336{
1337 struct iwl_mvm *mvm = inode->i_private;
1338 int err;
1339
1340 if (mvm->d3_test_active)
1341 return -EBUSY;
1342
1343 file->private_data = inode->i_private;
1344
1345 ieee80211_stop_queues(mvm->hw);
1346 synchronize_net();
1347
1348 /* start pseudo D3 */
1349 rtnl_lock();
1350 err = __iwl_mvm_suspend(mvm->hw, mvm->hw->wiphy->wowlan_config, true);
1351 rtnl_unlock();
1352 if (err > 0)
1353 err = -EINVAL;
1354 if (err) {
1355 ieee80211_wake_queues(mvm->hw);
1356 return err;
1357 }
1358 mvm->d3_test_active = true;
1359 return 0;
1360}
1361
1362static ssize_t iwl_mvm_d3_test_read(struct file *file, char __user *user_buf,
1363 size_t count, loff_t *ppos)
1364{
1365 struct iwl_mvm *mvm = file->private_data;
1366 u32 pme_asserted;
1367
1368 while (true) {
1369 pme_asserted = iwl_trans_read_mem32(mvm->trans,
1370 mvm->d3_test_pme_ptr);
1371 if (pme_asserted)
1372 break;
1373 if (msleep_interruptible(100))
1374 break;
1375 }
1376
1377 return 0;
1378}
1379
1380static void iwl_mvm_d3_test_disconn_work_iter(void *_data, u8 *mac,
1381 struct ieee80211_vif *vif)
1382{
1383 if (vif->type == NL80211_IFTYPE_STATION)
1384 ieee80211_connection_loss(vif);
1385}
1386
1387static int iwl_mvm_d3_test_release(struct inode *inode, struct file *file)
1388{
1389 struct iwl_mvm *mvm = inode->i_private;
1390 int remaining_time = 10;
1391
1392 mvm->d3_test_active = false;
1393 __iwl_mvm_resume(mvm, true);
1394 iwl_abort_notification_waits(&mvm->notif_wait);
1395 ieee80211_restart_hw(mvm->hw);
1396
1397 /* wait for restart and disconnect all interfaces */
1398 while (test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status) &&
1399 remaining_time > 0) {
1400 remaining_time--;
1401 msleep(1000);
1402 }
1403
1404 if (remaining_time == 0)
1405 IWL_ERR(mvm, "Timed out waiting for HW restart to finish!\n");
1406
1407 ieee80211_iterate_active_interfaces_atomic(
1408 mvm->hw, IEEE80211_IFACE_ITER_NORMAL,
1409 iwl_mvm_d3_test_disconn_work_iter, NULL);
1410
1411 ieee80211_wake_queues(mvm->hw);
1412
1413 return 0;
1414}
1415
1416const struct file_operations iwl_dbgfs_d3_test_ops = {
1417 .llseek = no_llseek,
1418 .open = iwl_mvm_d3_test_open,
1419 .read = iwl_mvm_d3_test_read,
1420 .release = iwl_mvm_d3_test_release,
1421};
1422#endif
diff --git a/drivers/net/wireless/iwlwifi/mvm/debugfs.c b/drivers/net/wireless/iwlwifi/mvm/debugfs.c
index 69e0806075a2..b7643c16201f 100644
--- a/drivers/net/wireless/iwlwifi/mvm/debugfs.c
+++ b/drivers/net/wireless/iwlwifi/mvm/debugfs.c
@@ -938,6 +938,7 @@ int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir)
938 MVM_DEBUGFS_ADD_FILE(fw_restart, mvm->debugfs_dir, S_IWUSR); 938 MVM_DEBUGFS_ADD_FILE(fw_restart, mvm->debugfs_dir, S_IWUSR);
939#ifdef CONFIG_PM_SLEEP 939#ifdef CONFIG_PM_SLEEP
940 MVM_DEBUGFS_ADD_FILE(d3_sram, mvm->debugfs_dir, S_IRUSR | S_IWUSR); 940 MVM_DEBUGFS_ADD_FILE(d3_sram, mvm->debugfs_dir, S_IRUSR | S_IWUSR);
941 MVM_DEBUGFS_ADD_FILE(d3_test, mvm->debugfs_dir, S_IRUSR);
941#endif 942#endif
942 943
943 /* 944 /*
diff --git a/drivers/net/wireless/iwlwifi/mvm/mvm.h b/drivers/net/wireless/iwlwifi/mvm/mvm.h
index 6a3220b6273e..384259baf525 100644
--- a/drivers/net/wireless/iwlwifi/mvm/mvm.h
+++ b/drivers/net/wireless/iwlwifi/mvm/mvm.h
@@ -459,8 +459,10 @@ struct iwl_mvm {
459#ifdef CONFIG_PM_SLEEP 459#ifdef CONFIG_PM_SLEEP
460 int gtk_ivlen, gtk_icvlen, ptk_ivlen, ptk_icvlen; 460 int gtk_ivlen, gtk_icvlen, ptk_ivlen, ptk_icvlen;
461#ifdef CONFIG_IWLWIFI_DEBUGFS 461#ifdef CONFIG_IWLWIFI_DEBUGFS
462 bool d3_test_active;
462 bool store_d3_resume_sram; 463 bool store_d3_resume_sram;
463 void *d3_resume_sram; 464 void *d3_resume_sram;
465 u32 d3_test_pme_ptr;
464#endif 466#endif
465#endif 467#endif
466 468
@@ -669,6 +671,7 @@ void iwl_mvm_ipv6_addr_change(struct ieee80211_hw *hw,
669 struct inet6_dev *idev); 671 struct inet6_dev *idev);
670void iwl_mvm_set_default_unicast_key(struct ieee80211_hw *hw, 672void iwl_mvm_set_default_unicast_key(struct ieee80211_hw *hw,
671 struct ieee80211_vif *vif, int idx); 673 struct ieee80211_vif *vif, int idx);
674extern const struct file_operations iwl_dbgfs_d3_test_ops;
672 675
673/* BT Coex */ 676/* BT Coex */
674int iwl_send_bt_prio_tbl(struct iwl_mvm *mvm); 677int iwl_send_bt_prio_tbl(struct iwl_mvm *mvm);
diff --git a/drivers/net/wireless/iwlwifi/mvm/phy-ctxt.c b/drivers/net/wireless/iwlwifi/mvm/phy-ctxt.c
index 1b4db25d53fb..a8652ddd6bed 100644
--- a/drivers/net/wireless/iwlwifi/mvm/phy-ctxt.c
+++ b/drivers/net/wireless/iwlwifi/mvm/phy-ctxt.c
@@ -204,7 +204,8 @@ int iwl_mvm_phy_ctxt_add(struct iwl_mvm *mvm, struct iwl_mvm_phy_ctxt *ctxt,
204{ 204{
205 int ret; 205 int ret;
206 206
207 WARN_ON(ctxt->ref); 207 WARN_ON(!test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status) &&
208 ctxt->ref);
208 lockdep_assert_held(&mvm->mutex); 209 lockdep_assert_held(&mvm->mutex);
209 210
210 ctxt->channel = chandef->chan; 211 ctxt->channel = chandef->chan;
diff --git a/drivers/net/wireless/iwlwifi/mvm/utils.c b/drivers/net/wireless/iwlwifi/mvm/utils.c
index c9b44ab4af07..1e1332839e4a 100644
--- a/drivers/net/wireless/iwlwifi/mvm/utils.c
+++ b/drivers/net/wireless/iwlwifi/mvm/utils.c
@@ -76,6 +76,11 @@ int iwl_mvm_send_cmd(struct iwl_mvm *mvm, struct iwl_host_cmd *cmd)
76{ 76{
77 int ret; 77 int ret;
78 78
79#if defined(CONFIG_IWLWIFI_DEBUGFS) && defined(CONFIG_PM_SLEEP)
80 if (WARN_ON(mvm->d3_test_active))
81 return -EIO;
82#endif
83
79 /* 84 /*
80 * Synchronous commands from this op-mode must hold 85 * Synchronous commands from this op-mode must hold
81 * the mutex, this ensures we don't try to send two 86 * the mutex, this ensures we don't try to send two
@@ -125,6 +130,11 @@ int iwl_mvm_send_cmd_status(struct iwl_mvm *mvm, struct iwl_host_cmd *cmd,
125 130
126 lockdep_assert_held(&mvm->mutex); 131 lockdep_assert_held(&mvm->mutex);
127 132
133#if defined(CONFIG_IWLWIFI_DEBUGFS) && defined(CONFIG_PM_SLEEP)
134 if (WARN_ON(mvm->d3_test_active))
135 return -EIO;
136#endif
137
128 /* 138 /*
129 * Only synchronous commands can wait for status, 139 * Only synchronous commands can wait for status,
130 * we use WANT_SKB so the caller can't. 140 * we use WANT_SKB so the caller can't.
diff --git a/drivers/net/wireless/iwlwifi/pcie/trans.c b/drivers/net/wireless/iwlwifi/pcie/trans.c
index 0b021305eedf..197dbe0a868c 100644
--- a/drivers/net/wireless/iwlwifi/pcie/trans.c
+++ b/drivers/net/wireless/iwlwifi/pcie/trans.c
@@ -578,9 +578,17 @@ static void iwl_trans_pcie_stop_device(struct iwl_trans *trans)
578 clear_bit(STATUS_RFKILL, &trans_pcie->status); 578 clear_bit(STATUS_RFKILL, &trans_pcie->status);
579} 579}
580 580
581static void iwl_trans_pcie_d3_suspend(struct iwl_trans *trans) 581static void iwl_trans_pcie_d3_suspend(struct iwl_trans *trans, bool test)
582{ 582{
583 iwl_disable_interrupts(trans); 583 iwl_disable_interrupts(trans);
584
585 /*
586 * in testing mode, the host stays awake and the
587 * hardware won't be reset (not even partially)
588 */
589 if (test)
590 return;
591
584 iwl_pcie_disable_ict(trans); 592 iwl_pcie_disable_ict(trans);
585 593
586 iwl_clear_bit(trans, CSR_GP_CNTRL, 594 iwl_clear_bit(trans, CSR_GP_CNTRL,
@@ -599,11 +607,18 @@ static void iwl_trans_pcie_d3_suspend(struct iwl_trans *trans)
599} 607}
600 608
601static int iwl_trans_pcie_d3_resume(struct iwl_trans *trans, 609static int iwl_trans_pcie_d3_resume(struct iwl_trans *trans,
602 enum iwl_d3_status *status) 610 enum iwl_d3_status *status,
611 bool test)
603{ 612{
604 u32 val; 613 u32 val;
605 int ret; 614 int ret;
606 615
616 if (test) {
617 iwl_enable_interrupts(trans);
618 *status = IWL_D3_STATUS_ALIVE;
619 return 0;
620 }
621
607 iwl_pcie_set_pwr(trans, false); 622 iwl_pcie_set_pwr(trans, false);
608 623
609 val = iwl_read32(trans, CSR_RESET); 624 val = iwl_read32(trans, CSR_RESET);