diff options
author | Haim Dreyfuss <haim.dreyfuss@intel.com> | 2021-01-17 16:52:26 +0200 |
---|---|---|
committer | Luca Coelho <luciano.coelho@intel.com> | 2021-02-05 11:55:15 +0200 |
commit | 708a39aaca2204dcacc96dec1401373063801213 (patch) | |
tree | 264a0f061245857c5b7ecd2ca050a98c90f23da4 /drivers/net/wireless/intel/iwlwifi/mvm/d3.c | |
parent | 00520b7a2a13db5c6b56cc1f49cea4e0e174479c (diff) |
iwlwifi: mvm: don't send commands during suspend\resume transition
D3_CONFIG_CMD and D0I3_END_CMD should be the last\first
command upon suspend\resume correspondingly, otherwise,
FW will raise an assert (0x342).
There are firmware notifications that cause the driver to
send a command back to the firmware. If such a notification
is sent to the driver while the the driver prepares the
firmware for D3, operation, what is likely to happen is that
the handling of the notification will try to get the mutex
and will wait unil the driver finished configuring the
firmware for D3. Then the handling notification will get
the mutex and handle the notification which will lead to
the aforementioned ASSERT 342.
To avoid this, we need to prevent any command to be sent to
the firmware between the D3_CONFIG_CMD and the D0I3_END_CMD.
Check this in the utility layer that sends the host commands
and in the transport layer as well.
Flag the D3_CONFIG_CMD and the D0I3_END_CMD commands as
commands that must be sent even if the firmware has already
been configured for D3 operation.
Signed-off-by: Haim Dreyfuss <haim.dreyfuss@intel.com>
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
Link: https://lore.kernel.org/r/iwlwifi.20210117164916.1935a993b471.I3192c93c030576ca16773c01b009c4d93610d6ea@changeid
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
Diffstat (limited to 'drivers/net/wireless/intel/iwlwifi/mvm/d3.c')
-rw-r--r-- | drivers/net/wireless/intel/iwlwifi/mvm/d3.c | 19 |
1 files changed, 6 insertions, 13 deletions
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c index cc523fb26f39..f98eb7b71068 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c @@ -975,7 +975,7 @@ static int __iwl_mvm_suspend(struct ieee80211_hw *hw, }; struct iwl_host_cmd d3_cfg_cmd = { .id = D3_CONFIG_CMD, - .flags = CMD_WANT_SKB, + .flags = CMD_WANT_SKB | CMD_SEND_IN_D3, .data[0] = &d3_cfg_cmd_data, .len[0] = sizeof(d3_cfg_cmd_data), }; @@ -1067,6 +1067,8 @@ static int __iwl_mvm_suspend(struct ieee80211_hw *hw, if (mvm->trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_9000) iwl_fw_dbg_stop_restart_recording(&mvm->fwrt, NULL, true); + mvm->trans->system_pm_mode = IWL_PLAT_PM_MODE_D3; + /* must be last -- this switches firmware state */ ret = iwl_mvm_send_cmd(mvm, &d3_cfg_cmd); if (ret) @@ -1105,14 +1107,11 @@ static int __iwl_mvm_suspend(struct ieee80211_hw *hw, int iwl_mvm_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) { struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); - struct iwl_trans *trans = mvm->trans; iwl_mvm_pause_tcm(mvm, true); iwl_fw_runtime_suspend(&mvm->fwrt); - trans->system_pm_mode = IWL_PLAT_PM_MODE_D3; - return __iwl_mvm_suspend(hw, wowlan, false); } @@ -2064,7 +2063,7 @@ static int __iwl_mvm_resume(struct iwl_mvm *mvm, bool test) if (d0i3_first) { struct iwl_host_cmd cmd = { .id = D0I3_END_CMD, - .flags = CMD_WANT_SKB, + .flags = CMD_WANT_SKB | CMD_SEND_IN_D3, }; int len; @@ -2097,6 +2096,8 @@ static int __iwl_mvm_resume(struct iwl_mvm *mvm, bool test) } } + mvm->trans->system_pm_mode = IWL_PLAT_PM_MODE_DISABLED; + /* * Query the current location and source from the D3 firmware so we * can play it back when we re-intiailize the D0 firmware @@ -2178,8 +2179,6 @@ int iwl_mvm_resume(struct ieee80211_hw *hw) ret = iwl_mvm_resume_d3(mvm); - mvm->trans->system_pm_mode = IWL_PLAT_PM_MODE_DISABLED; - iwl_mvm_resume_tcm(mvm); iwl_fw_runtime_resume(&mvm->fwrt); @@ -2205,10 +2204,6 @@ static int iwl_mvm_d3_test_open(struct inode *inode, struct file *file) file->private_data = inode->i_private; - synchronize_net(); - - mvm->trans->system_pm_mode = IWL_PLAT_PM_MODE_D3; - iwl_mvm_pause_tcm(mvm, true); iwl_fw_runtime_suspend(&mvm->fwrt); @@ -2278,8 +2273,6 @@ static int iwl_mvm_d3_test_release(struct inode *inode, struct file *file) iwl_fw_runtime_resume(&mvm->fwrt); - mvm->trans->system_pm_mode = IWL_PLAT_PM_MODE_DISABLED; - iwl_abort_notification_waits(&mvm->notif_wait); if (!unified_image) { int remaining_time = 10; |