diff options
author | Eliad Peller <eliad@wizery.com> | 2014-11-04 16:57:06 +0200 |
---|---|---|
committer | Emmanuel Grumbach <emmanuel.grumbach@intel.com> | 2014-11-11 17:15:04 +0200 |
commit | f4cf8680dfa42c80476a9cc5b90f933b12cf6d29 (patch) | |
tree | 7e9301164e06fd69d7e3d1c6de74d8472d661155 /drivers/net/wireless/iwlwifi/mvm/ops.c | |
parent | 1507fb757a0a706a9aae002d45ea7c12b076a482 (diff) | |
download | op-kernel-dev-f4cf8680dfa42c80476a9cc5b90f933b12cf6d29.zip op-kernel-dev-f4cf8680dfa42c80476a9cc5b90f933b12cf6d29.tar.gz |
iwlwifi: mvm/trans: abort d0i3_enter in case of held ref
Other contexts might call iwl_mvm_ref_sync() right before
we set IWL_MVM_STATUS_IN_D0I3, and then assume the fw/bus
is not in d0i3 state.
However, since we currently don't check for held references
in the d0i3_enter flow, we might enter d0i3 although there
is an active reference.
Solve it by aborting the d0i3 enter flow if there is an
active reference. Since users are assumed to use
iwl_mvm_ref_sync, which takes a ref before checking the
flag, we don't need further locking.
Signed-off-by: Eliad Peller <eliadx.peller@intel.com>
Reviewed-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
Diffstat (limited to 'drivers/net/wireless/iwlwifi/mvm/ops.c')
-rw-r--r-- | drivers/net/wireless/iwlwifi/mvm/ops.c | 12 |
1 files changed, 12 insertions, 0 deletions
diff --git a/drivers/net/wireless/iwlwifi/mvm/ops.c b/drivers/net/wireless/iwlwifi/mvm/ops.c index 8c5bdf9..be3dd4f 100644 --- a/drivers/net/wireless/iwlwifi/mvm/ops.c +++ b/drivers/net/wireless/iwlwifi/mvm/ops.c @@ -1041,6 +1041,18 @@ static int iwl_mvm_enter_d0i3(struct iwl_op_mode *op_mode) set_bit(IWL_MVM_STATUS_IN_D0I3, &mvm->status); synchronize_net(); + /* + * iwl_mvm_ref_sync takes a reference before checking the flag. + * so by checking there is no held reference we prevent a state + * in which iwl_mvm_ref_sync continues successfully while we + * configure the firmware to enter d0i3 + */ + if (iwl_mvm_ref_taken(mvm)) { + IWL_DEBUG_RPM(mvm->trans, "abort d0i3 due to taken ref\n"); + clear_bit(IWL_MVM_STATUS_IN_D0I3, &mvm->status); + return 1; + } + ieee80211_iterate_active_interfaces_atomic(mvm->hw, IEEE80211_IFACE_ITER_NORMAL, iwl_mvm_enter_d0i3_iterator, |