summaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/intel/iwlwifi/mvm
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/intel/iwlwifi/mvm')
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/d3.c40
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c16
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/mvm.h13
3 files changed, 47 insertions, 22 deletions
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c
index 542de7401a8d..b1c99921c376 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c
@@ -1183,19 +1183,20 @@ remove_notif:
int iwl_mvm_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
{
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
+ struct iwl_trans *trans = mvm->trans;
int ret;
/* make sure the d0i3 exit work is not pending */
flush_work(&mvm->d0i3_exit_work);
- ret = iwl_trans_suspend(mvm->trans);
+ ret = iwl_trans_suspend(trans);
if (ret)
return ret;
- mvm->trans->wowlan_d0i3 = wowlan->any;
- if (mvm->trans->wowlan_d0i3) {
- /* 'any' trigger means d0i3 usage */
- if (mvm->trans->d0i3_mode == IWL_D0I3_MODE_ON_SUSPEND) {
+ if (wowlan->any) {
+ trans->system_pm_mode = IWL_PLAT_PM_MODE_D0I3;
+
+ if (iwl_mvm_enter_d0i3_on_suspend(mvm)) {
ret = iwl_mvm_enter_d0i3_sync(mvm);
if (ret)
@@ -1206,11 +1207,13 @@ int iwl_mvm_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
__set_bit(D0I3_DEFER_WAKEUP, &mvm->d0i3_suspend_flags);
mutex_unlock(&mvm->d0i3_suspend_mutex);
- iwl_trans_d3_suspend(mvm->trans, false);
+ iwl_trans_d3_suspend(trans, false);
return 0;
}
+ trans->system_pm_mode = IWL_PLAT_PM_MODE_D3;
+
return __iwl_mvm_suspend(hw, wowlan, false);
}
@@ -1973,8 +1976,9 @@ static int iwl_mvm_resume_d0i3(struct iwl_mvm *mvm)
{
bool exit_now;
enum iwl_d3_status d3_status;
+ struct iwl_trans *trans = mvm->trans;
- iwl_trans_d3_resume(mvm->trans, &d3_status, false);
+ iwl_trans_d3_resume(trans, &d3_status, false);
/*
* make sure to clear D0I3_DEFER_WAKEUP before
@@ -1991,9 +1995,9 @@ static int iwl_mvm_resume_d0i3(struct iwl_mvm *mvm)
_iwl_mvm_exit_d0i3(mvm);
}
- iwl_trans_resume(mvm->trans);
+ iwl_trans_resume(trans);
- if (mvm->trans->d0i3_mode == IWL_D0I3_MODE_ON_SUSPEND) {
+ if (iwl_mvm_enter_d0i3_on_suspend(mvm)) {
int ret = iwl_mvm_exit_d0i3(mvm->hw->priv);
if (ret)
@@ -2009,12 +2013,16 @@ static int iwl_mvm_resume_d0i3(struct iwl_mvm *mvm)
int iwl_mvm_resume(struct ieee80211_hw *hw)
{
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
+ int ret;
- /* 'any' trigger means d0i3 was used */
- if (hw->wiphy->wowlan_config->any)
- return iwl_mvm_resume_d0i3(mvm);
+ if (mvm->trans->system_pm_mode == IWL_PLAT_PM_MODE_D0I3)
+ ret = iwl_mvm_resume_d0i3(mvm);
else
- return iwl_mvm_resume_d3(mvm);
+ ret = iwl_mvm_resume_d3(mvm);
+
+ mvm->trans->system_pm_mode = IWL_PLAT_PM_MODE_DISABLED;
+
+ return ret;
}
void iwl_mvm_set_wakeup(struct ieee80211_hw *hw, bool enabled)
@@ -2038,6 +2046,8 @@ static int iwl_mvm_d3_test_open(struct inode *inode, struct file *file)
ieee80211_stop_queues(mvm->hw);
synchronize_net();
+ mvm->trans->system_pm_mode = IWL_PLAT_PM_MODE_D3;
+
/* start pseudo D3 */
rtnl_lock();
err = __iwl_mvm_suspend(mvm->hw, mvm->hw->wiphy->wowlan_config, true);
@@ -2092,9 +2102,13 @@ static int iwl_mvm_d3_test_release(struct inode *inode, struct file *file)
int remaining_time = 10;
mvm->d3_test_active = false;
+
rtnl_lock();
__iwl_mvm_resume(mvm, true);
rtnl_unlock();
+
+ mvm->trans->system_pm_mode = IWL_PLAT_PM_MODE_DISABLED;
+
iwl_abort_notification_waits(&mvm->notif_wait);
ieee80211_restart_hw(mvm->hw);
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
index 7487eb08d156..3a78a3f1610e 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
@@ -1087,15 +1087,13 @@ static void iwl_mvm_restart_complete(struct iwl_mvm *mvm)
static void iwl_mvm_resume_complete(struct iwl_mvm *mvm)
{
- if (!iwl_mvm_is_d0i3_supported(mvm))
- return;
-
- if (mvm->trans->d0i3_mode == IWL_D0I3_MODE_ON_SUSPEND)
- if (!wait_event_timeout(mvm->d0i3_exit_waitq,
- !test_bit(IWL_MVM_STATUS_IN_D0I3,
- &mvm->status),
- HZ))
- WARN_ONCE(1, "D0i3 exit on resume timed out\n");
+ if (iwl_mvm_is_d0i3_supported(mvm) &&
+ iwl_mvm_enter_d0i3_on_suspend(mvm))
+ WARN_ONCE(!wait_event_timeout(mvm->d0i3_exit_waitq,
+ !test_bit(IWL_MVM_STATUS_IN_D0I3,
+ &mvm->status),
+ HZ),
+ "D0i3 exit on resume timed out\n");
}
static void
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
index 3f0db29d5d56..3fc7199abc94 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
@@ -933,6 +933,19 @@ static inline bool iwl_mvm_is_dqa_supported(struct iwl_mvm *mvm)
IWL_UCODE_TLV_CAPA_DQA_SUPPORT);
}
+static inline bool iwl_mvm_enter_d0i3_on_suspend(struct iwl_mvm *mvm)
+{
+ /* For now we only use this mode to differentiate between
+ * slave transports, which handle D0i3 entry in suspend by
+ * themselves in conjunction with runtime PM D0i3. So, this
+ * function is used to check whether we need to do anything
+ * when entering suspend or if the transport layer has already
+ * done it.
+ */
+ return (mvm->trans->system_pm_mode == IWL_PLAT_PM_MODE_D0I3) &&
+ (mvm->trans->runtime_pm_mode != IWL_PLAT_PM_MODE_D0I3);
+}
+
static inline bool iwl_mvm_is_lar_supported(struct iwl_mvm *mvm)
{
bool nvm_lar = mvm->nvm_data->lar_enabled;
OpenPOWER on IntegriCloud