iwlwifi: wake from runtime suspend before sending sync commands
If a host command was queued while in runtime suspend, it would go out before the D0I3_END_CMD was sent. Sometimes it works, but sometimes it fails, and it is obviously the wrong thing to do. To fix this, have the opmode take a reference before sending a SYNC command and make the pcie trans wait for the runtime state to become active before actually queueing the command. Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
This commit is contained in:
parent
fa820d696c
commit
71b1230ca9
@ -1309,6 +1309,7 @@ static ssize_t iwl_dbgfs_d0i3_refs_read(struct file *file,
|
||||
PRINT_MVM_REF(IWL_MVM_REF_PROTECT_CSA);
|
||||
PRINT_MVM_REF(IWL_MVM_REF_FW_DBG_COLLECT);
|
||||
PRINT_MVM_REF(IWL_MVM_REF_INIT_UCODE);
|
||||
PRINT_MVM_REF(IWL_MVM_REF_SENDING_CMD);
|
||||
|
||||
return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
|
||||
}
|
||||
|
@ -301,6 +301,7 @@ enum iwl_mvm_ref_type {
|
||||
IWL_MVM_REF_PROTECT_CSA,
|
||||
IWL_MVM_REF_FW_DBG_COLLECT,
|
||||
IWL_MVM_REF_INIT_UCODE,
|
||||
IWL_MVM_REF_SENDING_CMD,
|
||||
|
||||
/* update debugfs.c when changing this */
|
||||
|
||||
|
@ -90,11 +90,17 @@ int iwl_mvm_send_cmd(struct iwl_mvm *mvm, struct iwl_host_cmd *cmd)
|
||||
* the mutex, this ensures we don't try to send two
|
||||
* (or more) synchronous commands at a time.
|
||||
*/
|
||||
if (!(cmd->flags & CMD_ASYNC))
|
||||
if (!(cmd->flags & CMD_ASYNC)) {
|
||||
lockdep_assert_held(&mvm->mutex);
|
||||
if (!(cmd->flags & CMD_SEND_IN_IDLE))
|
||||
iwl_mvm_ref(mvm, IWL_MVM_REF_SENDING_CMD);
|
||||
}
|
||||
|
||||
ret = iwl_trans_send_cmd(mvm->trans, cmd);
|
||||
|
||||
if (!(cmd->flags & (CMD_ASYNC | CMD_SEND_IN_IDLE)))
|
||||
iwl_mvm_unref(mvm, IWL_MVM_REF_SENDING_CMD);
|
||||
|
||||
/*
|
||||
* If the caller wants the SKB, then don't hide any problems, the
|
||||
* caller might access the response buffer which will be NULL if
|
||||
|
@ -32,6 +32,7 @@
|
||||
#include <linux/ieee80211.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <net/ip6_checksum.h>
|
||||
#include <net/tso.h>
|
||||
|
||||
@ -1799,6 +1800,16 @@ static int iwl_pcie_send_hcmd_sync(struct iwl_trans *trans,
|
||||
IWL_DEBUG_INFO(trans, "Setting HCMD_ACTIVE for command %s\n",
|
||||
iwl_get_cmd_string(trans, cmd->id));
|
||||
|
||||
if (pm_runtime_suspended(&trans_pcie->pci_dev->dev)) {
|
||||
ret = wait_event_timeout(trans_pcie->d0i3_waitq,
|
||||
pm_runtime_active(&trans_pcie->pci_dev->dev),
|
||||
msecs_to_jiffies(IWL_TRANS_IDLE_TIMEOUT));
|
||||
if (!ret) {
|
||||
IWL_ERR(trans, "Timeout exiting D0i3 before hcmd\n");
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
}
|
||||
|
||||
cmd_idx = iwl_pcie_enqueue_hcmd(trans, cmd);
|
||||
if (cmd_idx < 0) {
|
||||
ret = cmd_idx;
|
||||
|
Loading…
x
Reference in New Issue
Block a user