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

Commit 40abc2de authored by Raja Mani's avatar Raja Mani Committed by Kalle Valo
Browse files

ath6kl: Optimize target power in deep sleep suspend



Adding below steps helps to get good power numbers
in deep sleep suspend path,

    * Disable WOW mode.
    * Flush data packets and wait for all control packets.
      to be cleared in TX path before deep sleep suspend.
    * Set host sleep mode to SLEEP.

Below steps are added to perform the recovery action
while the system resume from deep sleep,

     * Set host sleep mode to AWAKE.
     * Reset scan parameters to default value.

In addition, Debug prints are added to track deep sleep
suspend/resume state.

Signed-off-by: default avatarRaja Mani <rmani@qca.qualcomm.com>
Signed-off-by: default avatarKalle Valo <kvalo@qca.qualcomm.com>
parent 055bde49
Loading
Loading
Loading
Loading
+81 −17
Original line number Diff line number Diff line
@@ -2130,6 +2130,77 @@ static int ath6kl_wow_resume(struct ath6kl *ar)
	return 0;
}

static int ath6kl_cfg80211_deepsleep_suspend(struct ath6kl *ar)
{
	struct ath6kl_vif *vif;
	int ret;

	vif = ath6kl_vif_first(ar);
	if (!vif)
		return -EIO;

	if (!ath6kl_cfg80211_ready(vif))
		return -EIO;

	ath6kl_cfg80211_stop_all(ar);

	/* Save the current power mode before enabling power save */
	ar->wmi->saved_pwr_mode = ar->wmi->pwr_mode;

	ret = ath6kl_wmi_powermode_cmd(ar->wmi, 0, REC_POWER);
	if (ret)
		return ret;

	/* Disable WOW mode */
	ret = ath6kl_wmi_set_wow_mode_cmd(ar->wmi, vif->fw_vif_idx,
					  ATH6KL_WOW_MODE_DISABLE,
					  0, 0);
	if (ret)
		return ret;

	/* Flush all non control pkts in TX path */
	ath6kl_tx_data_cleanup(ar);

	ret = ath6kl_cfg80211_host_sleep(ar, vif);
	if (ret)
		return ret;

	return 0;
}

static int ath6kl_cfg80211_deepsleep_resume(struct ath6kl *ar)
{
	struct ath6kl_vif *vif;
	int ret;

	vif = ath6kl_vif_first(ar);

	if (!vif)
		return -EIO;

	if (ar->wmi->pwr_mode != ar->wmi->saved_pwr_mode) {
		ret = ath6kl_wmi_powermode_cmd(ar->wmi, 0,
					       ar->wmi->saved_pwr_mode);
		if (ret)
			return ret;
	}

	ret = ath6kl_wmi_set_host_sleep_mode_cmd(ar->wmi, vif->fw_vif_idx,
						 ATH6KL_HOST_MODE_AWAKE);
	if (ret)
		return ret;

	ar->state = ATH6KL_STATE_ON;

	/* Reset scan parameter to default values */
	ret = ath6kl_wmi_scanparams_cmd(ar->wmi, vif->fw_vif_idx,
					0, 0, 0, 0, 0, 0, 3, 0, 0, 0);
	if (ret)
		return ret;

	return 0;
}

int ath6kl_cfg80211_suspend(struct ath6kl *ar,
			    enum ath6kl_cfg_suspend_mode mode,
			    struct cfg80211_wowlan *wow)
@@ -2158,15 +2229,12 @@ int ath6kl_cfg80211_suspend(struct ath6kl *ar,

	case ATH6KL_CFG_SUSPEND_DEEPSLEEP:

		ath6kl_cfg80211_stop_all(ar);

		/* save the current power mode before enabling power save */
		ar->wmi->saved_pwr_mode = ar->wmi->pwr_mode;
		ath6kl_dbg(ATH6KL_DBG_SUSPEND, "deep sleep suspend\n");

		ret = ath6kl_wmi_powermode_cmd(ar->wmi, 0, REC_POWER);
		ret = ath6kl_cfg80211_deepsleep_suspend(ar);
		if (ret) {
			ath6kl_warn("wmi powermode command failed during suspend: %d\n",
				    ret);
			ath6kl_err("deepsleep suspend failed: %d\n", ret);
			return ret;
		}

		ar->state = ATH6KL_STATE_DEEPSLEEP;
@@ -2227,17 +2295,13 @@ int ath6kl_cfg80211_resume(struct ath6kl *ar)
		break;

	case ATH6KL_STATE_DEEPSLEEP:
		if (ar->wmi->pwr_mode != ar->wmi->saved_pwr_mode) {
			ret = ath6kl_wmi_powermode_cmd(ar->wmi, 0,
						       ar->wmi->saved_pwr_mode);
		ath6kl_dbg(ATH6KL_DBG_SUSPEND, "deep sleep resume\n");

		ret = ath6kl_cfg80211_deepsleep_resume(ar);
		if (ret) {
				ath6kl_warn("wmi powermode command failed during resume: %d\n",
					    ret);
			}
			ath6kl_warn("deep sleep resume failed: %d\n", ret);
			return ret;
		}

		ar->state = ATH6KL_STATE_ON;

		break;

	case ATH6KL_STATE_CUTPOWER: