// SPDX-License-Identifier: GPL-2.0 #ifdef WOWLAN #include "wow.h" #include "softmac_core.h" #ifdef CONFIG_PM unsigned char img_suspend_status; int wait_for_econ_ps_cfg(struct img_priv *priv) { int count = 0; char econ_ps_cfg_done = 0; check_econ_ps_cfg_complete: mutex_lock(&priv->mutex); econ_ps_cfg_done = priv->econ_ps_cfg_stats.completed; mutex_unlock(&priv->mutex); if (!econ_ps_cfg_done && (count < PS_ECON_CFG_TIMEOUT_TICKS)) { count++; goto check_econ_ps_cfg_complete; } if (!econ_ps_cfg_done) { pr_warn("%s: Didn't get ECON_PS_CFG_DONE event\n", __func__); return -1; } RPU_DEBUG_UMACIF("%s : Received ECON_PS_CFG_DONE event\n", __func__); return 0; } int img_resume(struct ieee80211_hw *hw) { int i = 0, ret = 0; int active_vif_index = -1; struct img_priv *priv = NULL; if (hw == NULL) { pr_err("%s: Invalid parameters\n", __func__); return -EINVAL; } priv = (struct img_priv *)hw->priv; mutex_lock(&priv->mutex); for (i = 0; i < MAX_VIFS; i++) { if (priv->active_vifs & (1 << i)) active_vif_index = i; } priv->econ_ps_cfg_stats.completed = 0; priv->econ_ps_cfg_stats.result = 0; ret = rpu_prog_econ_ps_state(active_vif_index, PWRSAVE_STATE_AWAKE); if (ret) { pr_err("%s : prog econ ps failed\n", __func__); mutex_unlock(&priv->mutex); return ret; } mutex_unlock(&priv->mutex); if (!wait_for_econ_ps_cfg(priv)) { if (!priv->econ_ps_cfg_stats.result) { RPU_DEBUG_UMACIF("%s: Successful\n", __func__); img_suspend_status = 0; return 0; } pr_warn("%s: Unable to Resume\n", __func__); } return -ETIME; } int img_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) { (void)wowlan; int i = 0, ret = 0; int active_vif_index = -1; int count = 0; struct img_priv *priv = NULL; struct ieee80211_vif *vif = NULL; if (hw == NULL) { pr_err("%s: Invalid parameters\n", __func__); return -EINVAL; } if (WARN_ON((wifi->params.hw_scan_status == HW_SCAN_STATUS_PROGRESS))) return -EBUSY; priv = (struct img_priv *)hw->priv; mutex_lock(&priv->mutex); for (i = 0; i < MAX_VIFS; i++) { if (priv->active_vifs & (1 << i)) { active_vif_index = i; count++; } } if (count != 1) { pr_err("%s: Economy mode supp only for single VIF(STA mode)\n", __func__); mutex_unlock(&priv->mutex); return -ENOTSUPP; } rcu_read_lock(); vif = rcu_dereference(priv->vifs[active_vif_index]); rcu_read_unlock(); if (vif->type != NL80211_IFTYPE_STATION) { pr_err("%s: VIF is not in STA Mode\n", __func__); mutex_unlock(&priv->mutex); return -ENOTSUPP; } priv->econ_ps_cfg_stats.completed = 0; priv->econ_ps_cfg_stats.result = 0; priv->econ_ps_cfg_stats.wake_trig = -1; ret = rpu_prog_econ_ps_state(active_vif_index, PWRSAVE_STATE_DOZE); if (ret) { pr_err("%s : Error Occured\n", __func__); mutex_unlock(&priv->mutex); return ret; } mutex_unlock(&priv->mutex); if (!wait_for_econ_ps_cfg(priv)) { if (!priv->econ_ps_cfg_stats.result) { RPU_DEBUG_UMACIF("%s: Successful\n", __func__); img_suspend_status = 1; return 0; } pr_info("%s: Unable to Suspend: Active Traffic.\n", __func__); } return -ETIME; } #endif /* CONFIG_PM */ #endif /* WOWLAN */