diff options
-rw-r--r-- | drivers/net/wireless/iwlwifi/dvm/mac80211.c | 4 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-trans.h | 14 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/mvm/d3.c | 149 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/mvm/debugfs.c | 1 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/mvm/mvm.h | 3 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/mvm/phy-ctxt.c | 3 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/mvm/utils.c | 10 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/pcie/trans.c | 19 |
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 | ||
591 | static inline void iwl_trans_d3_suspend(struct iwl_trans *trans) | 592 | static 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 | ||
597 | static inline int iwl_trans_d3_resume(struct iwl_trans *trans, | 598 | static 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 | ||
604 | static inline int iwl_trans_send_cmd(struct iwl_trans *trans, | 606 | static 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 | ||
759 | int iwl_mvm_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) | 760 | static 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 | ||
1065 | int iwl_mvm_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) | ||
1066 | { | ||
1067 | return __iwl_mvm_suspend(hw, wowlan, false); | ||
1068 | } | ||
1069 | |||
1037 | static void iwl_mvm_query_wakeup_reasons(struct iwl_mvm *mvm, | 1070 | static 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 | ||
1241 | int iwl_mvm_resume(struct ieee80211_hw *hw) | 1274 | static 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 | ||
1320 | int 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 | |||
1288 | void iwl_mvm_set_wakeup(struct ieee80211_hw *hw, bool enabled) | 1327 | void 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 | ||
1335 | static 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 | |||
1362 | static 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 | |||
1380 | static 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 | |||
1387 | static 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 | |||
1416 | const 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); |
670 | void iwl_mvm_set_default_unicast_key(struct ieee80211_hw *hw, | 672 | void iwl_mvm_set_default_unicast_key(struct ieee80211_hw *hw, |
671 | struct ieee80211_vif *vif, int idx); | 673 | struct ieee80211_vif *vif, int idx); |
674 | extern const struct file_operations iwl_dbgfs_d3_test_ops; | ||
672 | 675 | ||
673 | /* BT Coex */ | 676 | /* BT Coex */ |
674 | int iwl_send_bt_prio_tbl(struct iwl_mvm *mvm); | 677 | int 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 | ||
581 | static void iwl_trans_pcie_d3_suspend(struct iwl_trans *trans) | 581 | static 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 | ||
601 | static int iwl_trans_pcie_d3_resume(struct iwl_trans *trans, | 609 | static 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); |