diff options
author | Gregory Greenman <gregory.greenman@intel.com> | 2014-06-25 08:08:50 -0400 |
---|---|---|
committer | Emmanuel Grumbach <emmanuel.grumbach@intel.com> | 2014-07-06 04:16:15 -0400 |
commit | d40fc489f308951f6361742e8b9689326c831f41 (patch) | |
tree | 8ae458d1fe70d8c2f40f2548a7ca22bc3dc3368c /drivers/net/wireless/iwlwifi/mvm | |
parent | 5bfe6f53283de44855ee45a102210abbfac995f9 (diff) |
iwlwifi: mvm: wait for d0i3 exit in add interface flow
This patch makes sure there're no target accesses in the add
interface flow before d0i3 exit completes.
Signed-off-by: Gregory Greenman <gregory.greenman@intel.com>
Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
Diffstat (limited to 'drivers/net/wireless/iwlwifi/mvm')
-rw-r--r-- | drivers/net/wireless/iwlwifi/mvm/mac80211.c | 40 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/mvm/mvm.h | 1 |
2 files changed, 32 insertions, 9 deletions
diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c index 5e425d3fddeb..7dde944a68fb 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c | |||
@@ -243,6 +243,21 @@ iwl_mvm_unref_all_except(struct iwl_mvm *mvm, enum iwl_mvm_ref_type ref) | |||
243 | } | 243 | } |
244 | } | 244 | } |
245 | 245 | ||
246 | static int iwl_mvm_ref_sync(struct iwl_mvm *mvm, enum iwl_mvm_ref_type ref_type) | ||
247 | { | ||
248 | iwl_mvm_ref(mvm, ref_type); | ||
249 | |||
250 | if (!wait_event_timeout(mvm->d0i3_exit_waitq, | ||
251 | !test_bit(IWL_MVM_STATUS_IN_D0I3, &mvm->status), | ||
252 | HZ)) { | ||
253 | WARN_ON_ONCE(1); | ||
254 | iwl_mvm_unref(mvm, ref_type); | ||
255 | return -EIO; | ||
256 | } | ||
257 | |||
258 | return 0; | ||
259 | } | ||
260 | |||
246 | static void iwl_mvm_reset_phy_ctxts(struct iwl_mvm *mvm) | 261 | static void iwl_mvm_reset_phy_ctxts(struct iwl_mvm *mvm) |
247 | { | 262 | { |
248 | int i; | 263 | int i; |
@@ -559,9 +574,6 @@ static int iwl_mvm_mac_ampdu_action(struct ieee80211_hw *hw, | |||
559 | case IEEE80211_AMPDU_TX_STOP_FLUSH: | 574 | case IEEE80211_AMPDU_TX_STOP_FLUSH: |
560 | case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT: | 575 | case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT: |
561 | case IEEE80211_AMPDU_TX_OPERATIONAL: | 576 | case IEEE80211_AMPDU_TX_OPERATIONAL: |
562 | iwl_mvm_ref(mvm, IWL_MVM_REF_TX_AGG); | ||
563 | tx_agg_ref = true; | ||
564 | |||
565 | /* | 577 | /* |
566 | * for tx start, wait synchronously until D0i3 exit to | 578 | * for tx start, wait synchronously until D0i3 exit to |
567 | * get the correct sequence number for the tid. | 579 | * get the correct sequence number for the tid. |
@@ -570,12 +582,11 @@ static int iwl_mvm_mac_ampdu_action(struct ieee80211_hw *hw, | |||
570 | * by the trans layer (unlike commands), so wait for | 582 | * by the trans layer (unlike commands), so wait for |
571 | * d0i3 exit in these cases as well. | 583 | * d0i3 exit in these cases as well. |
572 | */ | 584 | */ |
573 | if (!wait_event_timeout(mvm->d0i3_exit_waitq, | 585 | ret = iwl_mvm_ref_sync(mvm, IWL_MVM_REF_TX_AGG); |
574 | !test_bit(IWL_MVM_STATUS_IN_D0I3, &mvm->status), HZ)) { | 586 | if (ret) |
575 | WARN_ON_ONCE(1); | 587 | return ret; |
576 | iwl_mvm_unref(mvm, IWL_MVM_REF_TX_AGG); | 588 | |
577 | return -EIO; | 589 | tx_agg_ref = true; |
578 | } | ||
579 | break; | 590 | break; |
580 | default: | 591 | default: |
581 | break; | 592 | break; |
@@ -904,6 +915,15 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw, | |||
904 | int ret; | 915 | int ret; |
905 | 916 | ||
906 | /* | 917 | /* |
918 | * make sure D0i3 exit is completed, otherwise a target access | ||
919 | * during tx queue configuration could be done when still in | ||
920 | * D0i3 state. | ||
921 | */ | ||
922 | ret = iwl_mvm_ref_sync(mvm, IWL_MVM_REF_ADD_IF); | ||
923 | if (ret) | ||
924 | return ret; | ||
925 | |||
926 | /* | ||
907 | * Not much to do here. The stack will not allow interface | 927 | * Not much to do here. The stack will not allow interface |
908 | * types or combinations that we didn't advertise, so we | 928 | * types or combinations that we didn't advertise, so we |
909 | * don't really have to check the types. | 929 | * don't really have to check the types. |
@@ -1017,6 +1037,8 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw, | |||
1017 | out_unlock: | 1037 | out_unlock: |
1018 | mutex_unlock(&mvm->mutex); | 1038 | mutex_unlock(&mvm->mutex); |
1019 | 1039 | ||
1040 | iwl_mvm_unref(mvm, IWL_MVM_REF_ADD_IF); | ||
1041 | |||
1020 | return ret; | 1042 | return ret; |
1021 | } | 1043 | } |
1022 | 1044 | ||
diff --git a/drivers/net/wireless/iwlwifi/mvm/mvm.h b/drivers/net/wireless/iwlwifi/mvm/mvm.h index e067d9762603..6fe93a7335c1 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/iwlwifi/mvm/mvm.h | |||
@@ -230,6 +230,7 @@ enum iwl_mvm_ref_type { | |||
230 | IWL_MVM_REF_USER, | 230 | IWL_MVM_REF_USER, |
231 | IWL_MVM_REF_TX, | 231 | IWL_MVM_REF_TX, |
232 | IWL_MVM_REF_TX_AGG, | 232 | IWL_MVM_REF_TX_AGG, |
233 | IWL_MVM_REF_ADD_IF, | ||
233 | IWL_MVM_REF_EXIT_WORK, | 234 | IWL_MVM_REF_EXIT_WORK, |
234 | 235 | ||
235 | IWL_MVM_REF_COUNT, | 236 | IWL_MVM_REF_COUNT, |