diff options
-rw-r--r-- | drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c | 1 | ||||
-rw-r--r-- | drivers/net/wireless/intel/iwlwifi/mvm/mvm.h | 1 | ||||
-rw-r--r-- | drivers/net/wireless/intel/iwlwifi/mvm/utils.c | 8 | ||||
-rw-r--r-- | drivers/net/wireless/intel/iwlwifi/pcie/tx.c | 11 |
4 files changed, 20 insertions, 1 deletions
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c index 362a54601a80..513a85403924 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c @@ -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); } diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h index 72c04672143f..23d7539edf17 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h @@ -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 */ diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/utils.c b/drivers/net/wireless/intel/iwlwifi/mvm/utils.c index f0ffd62f02d3..eb41d3bd8059 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/utils.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/utils.c @@ -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 diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/tx.c b/drivers/net/wireless/intel/iwlwifi/pcie/tx.c index e2eb130dae98..d6beac9af029 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/tx.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/tx.c @@ -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; |