Commit 6735943f authored by Eliad Peller's avatar Eliad Peller Committed by Emmanuel Grumbach

iwlwifi: mvm: support IWL_D0I3_MODE_ON_SUSPEND d0i3 mode

Enter d0i3 on suspend, and exit d0i3. Wait for the
command responses in both cases.

Use this mode in case of pcie trans.
Signed-off-by: default avatarEliad Peller <eliadx.peller@intel.com>
Reviewed-by: default avatarJohannes Berg <johannes.berg@intel.com>
Signed-off-by: default avatarEmmanuel Grumbach <emmanuel.grumbach@intel.com>
parent 0f8f93d6
...@@ -1137,6 +1137,29 @@ static int __iwl_mvm_suspend(struct ieee80211_hw *hw, ...@@ -1137,6 +1137,29 @@ static int __iwl_mvm_suspend(struct ieee80211_hw *hw,
return ret; return ret;
} }
static int iwl_mvm_enter_d0i3_sync(struct iwl_mvm *mvm)
{
struct iwl_notification_wait wait_d3;
static const u8 d3_notif[] = { D3_CONFIG_CMD };
int ret;
iwl_init_notification_wait(&mvm->notif_wait, &wait_d3,
d3_notif, ARRAY_SIZE(d3_notif),
NULL, NULL);
ret = iwl_mvm_enter_d0i3(mvm->hw->priv);
if (ret)
goto remove_notif;
ret = iwl_wait_notification(&mvm->notif_wait, &wait_d3, HZ);
WARN_ON_ONCE(ret);
return ret;
remove_notif:
iwl_remove_notification(&mvm->notif_wait, &wait_d3);
return ret;
}
int iwl_mvm_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) int iwl_mvm_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
{ {
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
...@@ -1144,6 +1167,13 @@ int iwl_mvm_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) ...@@ -1144,6 +1167,13 @@ int iwl_mvm_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
iwl_trans_suspend(mvm->trans); iwl_trans_suspend(mvm->trans);
if (wowlan->any) { if (wowlan->any) {
/* 'any' trigger means d0i3 usage */ /* 'any' trigger means d0i3 usage */
if (mvm->trans->d0i3_mode == IWL_D0I3_MODE_ON_SUSPEND) {
int ret = iwl_mvm_enter_d0i3_sync(mvm);
if (ret)
return ret;
}
mutex_lock(&mvm->d0i3_suspend_mutex); mutex_lock(&mvm->d0i3_suspend_mutex);
__set_bit(D0I3_DEFER_WAKEUP, &mvm->d0i3_suspend_flags); __set_bit(D0I3_DEFER_WAKEUP, &mvm->d0i3_suspend_flags);
mutex_unlock(&mvm->d0i3_suspend_mutex); mutex_unlock(&mvm->d0i3_suspend_mutex);
...@@ -1879,6 +1909,16 @@ int iwl_mvm_resume(struct ieee80211_hw *hw) ...@@ -1879,6 +1909,16 @@ int iwl_mvm_resume(struct ieee80211_hw *hw)
if (mvm->hw->wiphy->wowlan_config->any) { if (mvm->hw->wiphy->wowlan_config->any) {
/* 'any' trigger means d0i3 usage */ /* 'any' trigger means d0i3 usage */
if (mvm->trans->d0i3_mode == IWL_D0I3_MODE_ON_SUSPEND) {
int ret = iwl_mvm_exit_d0i3(hw->priv);
if (ret)
return ret;
/*
* d0i3 exit will be deferred until reconfig_complete.
* make sure there we are out of d0i3.
*/
}
return 0; return 0;
} }
......
...@@ -1021,6 +1021,13 @@ static void iwl_mvm_resume_complete(struct iwl_mvm *mvm) ...@@ -1021,6 +1021,13 @@ static void iwl_mvm_resume_complete(struct iwl_mvm *mvm)
IWL_DEBUG_RPM(mvm, "Run deferred d0i3 exit\n"); IWL_DEBUG_RPM(mvm, "Run deferred d0i3 exit\n");
_iwl_mvm_exit_d0i3(mvm); _iwl_mvm_exit_d0i3(mvm);
} }
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");
} }
static void static void
......
...@@ -1187,6 +1187,8 @@ void iwl_mvm_unref(struct iwl_mvm *mvm, enum iwl_mvm_ref_type ref_type); ...@@ -1187,6 +1187,8 @@ void iwl_mvm_unref(struct iwl_mvm *mvm, enum iwl_mvm_ref_type ref_type);
int iwl_mvm_ref_sync(struct iwl_mvm *mvm, enum iwl_mvm_ref_type ref_type); int iwl_mvm_ref_sync(struct iwl_mvm *mvm, enum iwl_mvm_ref_type ref_type);
bool iwl_mvm_ref_taken(struct iwl_mvm *mvm); bool iwl_mvm_ref_taken(struct iwl_mvm *mvm);
void iwl_mvm_d0i3_enable_tx(struct iwl_mvm *mvm, __le16 *qos_seq); void iwl_mvm_d0i3_enable_tx(struct iwl_mvm *mvm, __le16 *qos_seq);
int iwl_mvm_enter_d0i3(struct iwl_op_mode *op_mode);
int iwl_mvm_exit_d0i3(struct iwl_op_mode *op_mode);
int _iwl_mvm_exit_d0i3(struct iwl_mvm *mvm); int _iwl_mvm_exit_d0i3(struct iwl_mvm *mvm);
/* BT Coex */ /* BT Coex */
......
...@@ -1030,7 +1030,8 @@ static void iwl_mvm_set_wowlan_data(struct iwl_mvm *mvm, ...@@ -1030,7 +1030,8 @@ static void iwl_mvm_set_wowlan_data(struct iwl_mvm *mvm,
out: out:
rcu_read_unlock(); rcu_read_unlock();
} }
static int iwl_mvm_enter_d0i3(struct iwl_op_mode *op_mode)
int iwl_mvm_enter_d0i3(struct iwl_op_mode *op_mode)
{ {
struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode); struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode);
u32 flags = CMD_ASYNC | CMD_HIGH_PRIO | CMD_SEND_IN_IDLE; u32 flags = CMD_ASYNC | CMD_HIGH_PRIO | CMD_SEND_IN_IDLE;
...@@ -1244,7 +1245,7 @@ int _iwl_mvm_exit_d0i3(struct iwl_mvm *mvm) ...@@ -1244,7 +1245,7 @@ int _iwl_mvm_exit_d0i3(struct iwl_mvm *mvm)
return ret; return ret;
} }
static int iwl_mvm_exit_d0i3(struct iwl_op_mode *op_mode) int iwl_mvm_exit_d0i3(struct iwl_op_mode *op_mode)
{ {
struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode); struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode);
......
...@@ -2453,6 +2453,7 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev, ...@@ -2453,6 +2453,7 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
} }
trans_pcie->inta_mask = CSR_INI_SET_MASK; trans_pcie->inta_mask = CSR_INI_SET_MASK;
trans->d0i3_mode = IWL_D0I3_MODE_ON_SUSPEND;
return trans; return trans;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment