Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+40 −0
Original line number Diff line number Diff line
@@ -1137,6 +1137,29 @@ static int __iwl_mvm_suspend(struct ieee80211_hw *hw,
	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)
{
	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)
	iwl_trans_suspend(mvm->trans);
	if (wowlan->any) {
		/* '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);
		__set_bit(D0I3_DEFER_WAKEUP, &mvm->d0i3_suspend_flags);
		mutex_unlock(&mvm->d0i3_suspend_mutex);
@@ -1879,6 +1909,16 @@ int iwl_mvm_resume(struct ieee80211_hw *hw)

	if (mvm->hw->wiphy->wowlan_config->any) {
		/* '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;
	}

+7 −0
Original line number Diff line number Diff line
@@ -1021,6 +1021,13 @@ static void iwl_mvm_resume_complete(struct iwl_mvm *mvm)
		IWL_DEBUG_RPM(mvm, "Run deferred d0i3 exit\n");
		_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
+2 −0
Original line number Diff line number Diff line
@@ -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);
bool iwl_mvm_ref_taken(struct iwl_mvm *mvm);
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);

/* BT Coex */
+3 −2
Original line number Diff line number Diff line
@@ -1030,7 +1030,8 @@ static void iwl_mvm_set_wowlan_data(struct iwl_mvm *mvm,
out:
	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);
	u32 flags = CMD_ASYNC | CMD_HIGH_PRIO | CMD_SEND_IN_IDLE;
@@ -1244,7 +1245,7 @@ int _iwl_mvm_exit_d0i3(struct iwl_mvm *mvm)
	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);

+1 −0
Original line number Diff line number Diff line
@@ -2453,6 +2453,7 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
	}

	trans_pcie->inta_mask = CSR_INI_SET_MASK;
	trans->d0i3_mode = IWL_D0I3_MODE_ON_SUSPEND;

	return trans;