aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/intel/iwlwifi/mvm/d3.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/intel/iwlwifi/mvm/d3.c')
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/d3.c70
1 files changed, 49 insertions, 21 deletions
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c
index d3e21d95cece..78572ef89b26 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c
@@ -7,6 +7,7 @@
7 * 7 *
8 * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. 8 * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
9 * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH 9 * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
10 * Copyright(c) 2016 Intel Deutschland GmbH
10 * 11 *
11 * This program is free software; you can redistribute it and/or modify 12 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of version 2 of the GNU General Public License as 13 * it under the terms of version 2 of the GNU General Public License as
@@ -33,6 +34,7 @@
33 * 34 *
34 * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. 35 * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
35 * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH 36 * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
37 * Copyright(c) 2016 Intel Deutschland GmbH
36 * All rights reserved. 38 * All rights reserved.
37 * 39 *
38 * Redistribution and use in source and binary forms, with or without 40 * Redistribution and use in source and binary forms, with or without
@@ -1023,14 +1025,18 @@ iwl_mvm_wowlan_config(struct iwl_mvm *mvm,
1023 struct ieee80211_sta *ap_sta) 1025 struct ieee80211_sta *ap_sta)
1024{ 1026{
1025 int ret; 1027 int ret;
1028 bool unified_image = fw_has_capa(&mvm->fw->ucode_capa,
1029 IWL_UCODE_TLV_CAPA_CNSLDTD_D3_D0_IMG);
1026 1030
1027 ret = iwl_mvm_switch_to_d3(mvm); 1031 if (!unified_image) {
1028 if (ret) 1032 ret = iwl_mvm_switch_to_d3(mvm);
1029 return ret; 1033 if (ret)
1034 return ret;
1030 1035
1031 ret = iwl_mvm_d3_reprogram(mvm, vif, ap_sta); 1036 ret = iwl_mvm_d3_reprogram(mvm, vif, ap_sta);
1032 if (ret) 1037 if (ret)
1033 return ret; 1038 return ret;
1039 }
1034 1040
1035 if (!iwlwifi_mod_params.sw_crypto) { 1041 if (!iwlwifi_mod_params.sw_crypto) {
1036 /* 1042 /*
@@ -1072,10 +1078,14 @@ iwl_mvm_netdetect_config(struct iwl_mvm *mvm,
1072{ 1078{
1073 struct iwl_wowlan_config_cmd wowlan_config_cmd = {}; 1079 struct iwl_wowlan_config_cmd wowlan_config_cmd = {};
1074 int ret; 1080 int ret;
1081 bool unified_image = fw_has_capa(&mvm->fw->ucode_capa,
1082 IWL_UCODE_TLV_CAPA_CNSLDTD_D3_D0_IMG);
1075 1083
1076 ret = iwl_mvm_switch_to_d3(mvm); 1084 if (!unified_image) {
1077 if (ret) 1085 ret = iwl_mvm_switch_to_d3(mvm);
1078 return ret; 1086 if (ret)
1087 return ret;
1088 }
1079 1089
1080 /* rfkill release can be either for wowlan or netdetect */ 1090 /* rfkill release can be either for wowlan or netdetect */
1081 if (wowlan->rfkill_release) 1091 if (wowlan->rfkill_release)
@@ -1151,6 +1161,8 @@ static int __iwl_mvm_suspend(struct ieee80211_hw *hw,
1151 }; 1161 };
1152 int ret; 1162 int ret;
1153 int len __maybe_unused; 1163 int len __maybe_unused;
1164 bool unified_image = fw_has_capa(&mvm->fw->ucode_capa,
1165 IWL_UCODE_TLV_CAPA_CNSLDTD_D3_D0_IMG);
1154 1166
1155 if (!wowlan) { 1167 if (!wowlan) {
1156 /* 1168 /*
@@ -1236,7 +1248,7 @@ static int __iwl_mvm_suspend(struct ieee80211_hw *hw,
1236 1248
1237 clear_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status); 1249 clear_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status);
1238 1250
1239 iwl_trans_d3_suspend(mvm->trans, test); 1251 iwl_trans_d3_suspend(mvm->trans, test, !unified_image);
1240 out: 1252 out:
1241 if (ret < 0) { 1253 if (ret < 0) {
1242 iwl_mvm_ref(mvm, IWL_MVM_REF_UCODE_DOWN); 1254 iwl_mvm_ref(mvm, IWL_MVM_REF_UCODE_DOWN);
@@ -1299,7 +1311,7 @@ int iwl_mvm_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
1299 __set_bit(D0I3_DEFER_WAKEUP, &mvm->d0i3_suspend_flags); 1311 __set_bit(D0I3_DEFER_WAKEUP, &mvm->d0i3_suspend_flags);
1300 mutex_unlock(&mvm->d0i3_suspend_mutex); 1312 mutex_unlock(&mvm->d0i3_suspend_mutex);
1301 1313
1302 iwl_trans_d3_suspend(trans, false); 1314 iwl_trans_d3_suspend(trans, false, false);
1303 1315
1304 return 0; 1316 return 0;
1305 } 1317 }
@@ -2041,9 +2053,14 @@ static void iwl_mvm_d3_disconnect_iter(void *data, u8 *mac,
2041static int __iwl_mvm_resume(struct iwl_mvm *mvm, bool test) 2053static int __iwl_mvm_resume(struct iwl_mvm *mvm, bool test)
2042{ 2054{
2043 struct ieee80211_vif *vif = NULL; 2055 struct ieee80211_vif *vif = NULL;
2044 int ret; 2056 int ret = 1;
2045 enum iwl_d3_status d3_status; 2057 enum iwl_d3_status d3_status;
2046 bool keep = false; 2058 bool keep = false;
2059 bool unified_image = fw_has_capa(&mvm->fw->ucode_capa,
2060 IWL_UCODE_TLV_CAPA_CNSLDTD_D3_D0_IMG);
2061
2062 u32 flags = CMD_ASYNC | CMD_HIGH_PRIO | CMD_SEND_IN_IDLE |
2063 CMD_WAKE_UP_TRANS;
2047 2064
2048 mutex_lock(&mvm->mutex); 2065 mutex_lock(&mvm->mutex);
2049 2066
@@ -2052,7 +2069,7 @@ static int __iwl_mvm_resume(struct iwl_mvm *mvm, bool test)
2052 if (IS_ERR_OR_NULL(vif)) 2069 if (IS_ERR_OR_NULL(vif))
2053 goto err; 2070 goto err;
2054 2071
2055 ret = iwl_trans_d3_resume(mvm->trans, &d3_status, test); 2072 ret = iwl_trans_d3_resume(mvm->trans, &d3_status, test, !unified_image);
2056 if (ret) 2073 if (ret)
2057 goto err; 2074 goto err;
2058 2075
@@ -2095,17 +2112,28 @@ out_iterate:
2095 iwl_mvm_d3_disconnect_iter, keep ? vif : NULL); 2112 iwl_mvm_d3_disconnect_iter, keep ? vif : NULL);
2096 2113
2097out: 2114out:
2098 /* return 1 to reconfigure the device */ 2115 if (unified_image && !ret) {
2116 ret = iwl_mvm_send_cmd_pdu(mvm, D0I3_END_CMD, flags, 0, NULL);
2117 if (!ret) /* D3 ended successfully - no need to reset device */
2118 return 0;
2119 }
2120
2121 /*
2122 * Reconfigure the device in one of the following cases:
2123 * 1. We are not using a unified image
2124 * 2. We are using a unified image but had an error while exiting D3
2125 */
2099 set_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status); 2126 set_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status);
2100 set_bit(IWL_MVM_STATUS_D3_RECONFIG, &mvm->status); 2127 set_bit(IWL_MVM_STATUS_D3_RECONFIG, &mvm->status);
2101 2128 /*
2102 /* We always return 1, which causes mac80211 to do a reconfig 2129 * When switching images we return 1, which causes mac80211
2103 * with IEEE80211_RECONFIG_TYPE_RESTART. This type of 2130 * to do a reconfig with IEEE80211_RECONFIG_TYPE_RESTART.
2104 * reconfig calls iwl_mvm_restart_complete(), where we unref 2131 * This type of reconfig calls iwl_mvm_restart_complete(),
2105 * the IWL_MVM_REF_UCODE_DOWN, so we need to take the 2132 * where we unref the IWL_MVM_REF_UCODE_DOWN, so we need
2106 * reference here. 2133 * to take the reference here.
2107 */ 2134 */
2108 iwl_mvm_ref(mvm, IWL_MVM_REF_UCODE_DOWN); 2135 iwl_mvm_ref(mvm, IWL_MVM_REF_UCODE_DOWN);
2136
2109 return 1; 2137 return 1;
2110} 2138}
2111 2139
@@ -2122,7 +2150,7 @@ static int iwl_mvm_resume_d0i3(struct iwl_mvm *mvm)
2122 enum iwl_d3_status d3_status; 2150 enum iwl_d3_status d3_status;
2123 struct iwl_trans *trans = mvm->trans; 2151 struct iwl_trans *trans = mvm->trans;
2124 2152
2125 iwl_trans_d3_resume(trans, &d3_status, false); 2153 iwl_trans_d3_resume(trans, &d3_status, false, false);
2126 2154
2127 /* 2155 /*
2128 * make sure to clear D0I3_DEFER_WAKEUP before 2156 * make sure to clear D0I3_DEFER_WAKEUP before