summaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwlwifi/mvm/debugfs.c
diff options
context:
space:
mode:
authorEliad Peller <eliad@wizery.com>2014-07-01 18:38:38 +0300
committerEmmanuel Grumbach <emmanuel.grumbach@intel.com>2014-07-21 10:43:13 +0300
commit576eeee9d3ab395f47462c03067c8b9381281f1d (patch)
treed8511410c9fcdb97ad4b06790b63d77f0c08bfbf /drivers/net/wireless/iwlwifi/mvm/debugfs.c
parent51ea1c7dbd4c5151b7f5777cabc505d43d2c42cb (diff)
iwlwifi: mvm: add some missing iwl_mvm_ref_sync() calls
Add iwl_mvm_ref_sync() calls (with new ref types) to flows that might access the device directly. These calls make sure the device is out of d0i3, and the bus is available for direct access. Since some of these functions are reentrant, convert the refs_bitmap to a ref counter, so multiple refs of the same type could be taken concurrently. Signed-off-by: Eliad Peller <eliadx.peller@intel.com> Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
Diffstat (limited to 'drivers/net/wireless/iwlwifi/mvm/debugfs.c')
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/debugfs.c43
1 files changed, 34 insertions, 9 deletions
diff --git a/drivers/net/wireless/iwlwifi/mvm/debugfs.c b/drivers/net/wireless/iwlwifi/mvm/debugfs.c
index f131ef0ec5b..ac9787c0924 100644
--- a/drivers/net/wireless/iwlwifi/mvm/debugfs.c
+++ b/drivers/net/wireless/iwlwifi/mvm/debugfs.c
@@ -830,8 +830,14 @@ static ssize_t iwl_dbgfs_fw_restart_write(struct iwl_mvm *mvm, char *buf,
static ssize_t iwl_dbgfs_fw_nmi_write(struct iwl_mvm *mvm, char *buf,
size_t count, loff_t *ppos)
{
+ int ret = iwl_mvm_ref_sync(mvm, IWL_MVM_REF_NMI);
+ if (ret)
+ return ret;
+
iwl_force_nmi(mvm->trans);
+ iwl_mvm_unref(mvm, IWL_MVM_REF_NMI);
+
return count;
}
@@ -1115,11 +1121,11 @@ static ssize_t iwl_dbgfs_d3_sram_read(struct file *file, char __user *user_buf,
}
#endif
-#define PRINT_MVM_REF(ref) do { \
- if (test_bit(ref, mvm->ref_bitmap)) \
- pos += scnprintf(buf + pos, bufsz - pos, \
- "\t(0x%lx) %s\n", \
- BIT(ref), #ref); \
+#define PRINT_MVM_REF(ref) do { \
+ if (mvm->refs[ref]) \
+ pos += scnprintf(buf + pos, bufsz - pos, \
+ "\t(0x%lx): %d %s\n", \
+ BIT(ref), mvm->refs[ref], #ref); \
} while (0)
static ssize_t iwl_dbgfs_d0i3_refs_read(struct file *file,
@@ -1127,12 +1133,17 @@ static ssize_t iwl_dbgfs_d0i3_refs_read(struct file *file,
size_t count, loff_t *ppos)
{
struct iwl_mvm *mvm = file->private_data;
- int pos = 0;
+ int i, pos = 0;
char buf[256];
const size_t bufsz = sizeof(buf);
+ u32 refs = 0;
+
+ for (i = 0; i < IWL_MVM_REF_COUNT; i++)
+ if (mvm->refs[i])
+ refs |= BIT(i);
- pos += scnprintf(buf + pos, bufsz - pos, "taken mvm refs: 0x%lx\n",
- mvm->ref_bitmap[0]);
+ pos += scnprintf(buf + pos, bufsz - pos, "taken mvm refs: 0x%x\n",
+ refs);
PRINT_MVM_REF(IWL_MVM_REF_UCODE_DOWN);
PRINT_MVM_REF(IWL_MVM_REF_SCAN);
@@ -1158,7 +1169,7 @@ static ssize_t iwl_dbgfs_d0i3_refs_write(struct iwl_mvm *mvm, char *buf,
mutex_lock(&mvm->mutex);
- taken = test_bit(IWL_MVM_REF_USER, mvm->ref_bitmap);
+ taken = mvm->refs[IWL_MVM_REF_USER];
if (value == 1 && !taken)
iwl_mvm_ref(mvm, IWL_MVM_REF_USER);
else if (value == 0 && taken)
@@ -1194,14 +1205,21 @@ iwl_dbgfs_prph_reg_read(struct file *file,
int pos = 0;
char buf[32];
const size_t bufsz = sizeof(buf);
+ int ret;
if (!mvm->dbgfs_prph_reg_addr)
return -EINVAL;
+ ret = iwl_mvm_ref_sync(mvm, IWL_MVM_REF_PRPH_READ);
+ if (ret)
+ return ret;
+
pos += scnprintf(buf + pos, bufsz - pos, "Reg 0x%x: (0x%x)\n",
mvm->dbgfs_prph_reg_addr,
iwl_read_prph(mvm->trans, mvm->dbgfs_prph_reg_addr));
+ iwl_mvm_unref(mvm, IWL_MVM_REF_PRPH_READ);
+
return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
}
@@ -1211,6 +1229,7 @@ iwl_dbgfs_prph_reg_write(struct iwl_mvm *mvm, char *buf,
{
u8 args;
u32 value;
+ int ret;
args = sscanf(buf, "%i %i", &mvm->dbgfs_prph_reg_addr, &value);
/* if we only want to set the reg address - nothing more to do */
@@ -1221,7 +1240,13 @@ iwl_dbgfs_prph_reg_write(struct iwl_mvm *mvm, char *buf,
if (args != 2)
return -EINVAL;
+ ret = iwl_mvm_ref_sync(mvm, IWL_MVM_REF_PRPH_WRITE);
+ if (ret)
+ return ret;
+
iwl_write_prph(mvm->trans, mvm->dbgfs_prph_reg_addr, value);
+
+ iwl_mvm_unref(mvm, IWL_MVM_REF_PRPH_WRITE);
out:
return count;
}