void traffic_check_for_leave_lps(PADAPTER padapter, u8 tx, u32 tx_packets) { static unsigned long start_time = 0; static u32 xmit_cnt = 0; u8 bLeaveLPS = false; struct mlme_priv *pmlmepriv = &padapter->mlmepriv; if (tx) /* from tx */ { xmit_cnt += tx_packets; if (start_time == 0) start_time = jiffies; if (jiffies_to_msecs(jiffies - start_time) > 2000) /* 2 sec == watch dog timer */ { if (xmit_cnt > 8) { if ((adapter_to_pwrctl(padapter)->bLeisurePs) && (adapter_to_pwrctl(padapter)->pwr_mode != PS_MODE_ACTIVE) && (rtw_btcoex_IsBtControlLps(padapter) == false) ) { DBG_871X("leave lps via Tx = %d\n", xmit_cnt); bLeaveLPS = true; } } start_time = jiffies; xmit_cnt = 0; } } else /* from rx path */ { if (pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod > 4/*2*/) { if ((adapter_to_pwrctl(padapter)->bLeisurePs) && (adapter_to_pwrctl(padapter)->pwr_mode != PS_MODE_ACTIVE) && (rtw_btcoex_IsBtControlLps(padapter) == false) ) { DBG_871X("leave lps via Rx = %d\n", pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod); bLeaveLPS = true; } } } if (bLeaveLPS) { /* DBG_871X("leave lps via %s, Tx = %d, Rx = %d \n", tx?"Tx":"Rx", pmlmepriv->LinkDetectInfo.NumTxOkInPeriod, pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod); */ /* rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_LEAVE, 1); */ rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_LEAVE, tx?0:1); } }
void LPS_Leave(PADAPTER padapter, const char *msg) { #define LPS_LEAVE_TIMEOUT_MS 100 struct dvobj_priv *dvobj = adapter_to_dvobj(padapter); struct pwrctrl_priv *pwrpriv = dvobj_to_pwrctl(dvobj); char buf[32] = {0}; /* DBG_871X("+LeisurePSLeave\n"); */ if (rtw_btcoex_IsBtControlLps(padapter) == true) return; if (pwrpriv->bLeisurePs) { if (pwrpriv->pwr_mode != PS_MODE_ACTIVE) { sprintf(buf, "WIFI-%s", msg); rtw_set_ps_mode(padapter, PS_MODE_ACTIVE, 0, 0, buf); if (pwrpriv->pwr_mode == PS_MODE_ACTIVE) LPS_RF_ON_check(padapter, LPS_LEAVE_TIMEOUT_MS); } } pwrpriv->bpower_saving = false; /* DBG_871X("-LeisurePSLeave\n"); */ }
/* * Description: *If task is done, call this func. to power down firmware again. * *Constraint: * 1. this function will request pwrctrl->lock * * Return Value: *none */ void rtw_unregister_task_alive(struct adapter *padapter, u32 task) { struct pwrctrl_priv *pwrctrl; u8 pslv; pwrctrl = adapter_to_pwrctl(padapter); pslv = PS_STATE_S0; if ((rtw_btcoex_IsBtDisabled(padapter) == false) && (rtw_btcoex_IsBtControlLps(padapter) == true)) { u8 val8; val8 = rtw_btcoex_LpsVal(padapter); if (val8 & BIT(4)) pslv = PS_STATE_S2; } down(&pwrctrl->lock); unregister_task_alive(pwrctrl, task); if ((pwrctrl->pwr_mode != PS_MODE_ACTIVE) && (pwrctrl->bFwCurrentInPSMode == true)) { RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_notice_, ("%s: cpwm = 0x%02x alives = 0x%08x\n", __func__, pwrctrl->cpwm, pwrctrl->alives)); if (pwrctrl->cpwm > pslv) if ((pslv >= PS_STATE_S2) || (pwrctrl->alives == 0)) rtw_set_rpwm(padapter, pslv); } up(&pwrctrl->lock); }
void LPS_Enter(PADAPTER padapter, const char *msg) { struct dvobj_priv *dvobj = adapter_to_dvobj(padapter); struct pwrctrl_priv *pwrpriv = dvobj_to_pwrctl(dvobj); int n_assoc_iface = 0; int i; char buf[32] = {0}; /* DBG_871X("+LeisurePSEnter\n"); */ if (rtw_btcoex_IsBtControlLps(padapter) == true) return; /* Skip lps enter request if number of assocated adapters is not 1 */ for (i = 0; i < dvobj->iface_nums; i++) { if (check_fwstate(&(dvobj->padapters[i]->mlmepriv), WIFI_ASOC_STATE)) n_assoc_iface++; } if (n_assoc_iface != 1) return; /* Skip lps enter request for adapter not port0 */ if (get_iface_type(padapter) != IFACE_PORT0) return; for (i = 0; i < dvobj->iface_nums; i++) { if (PS_RDY_CHECK(dvobj->padapters[i]) == false) return; } if (pwrpriv->bLeisurePs) { /* Idle for a while if we connect to AP a while ago. */ if (pwrpriv->LpsIdleCount >= 2) /* 4 Sec */ { if (pwrpriv->pwr_mode == PS_MODE_ACTIVE) { sprintf(buf, "WIFI-%s", msg); pwrpriv->bpower_saving = true; rtw_set_ps_mode(padapter, pwrpriv->power_mgnt, padapter->registrypriv.smart_ps, 0, buf); } } else pwrpriv->LpsIdleCount++; } /* DBG_871X("-LeisurePSEnter\n"); */ }
void rtw_set_ps_mode(PADAPTER padapter, u8 ps_mode, u8 smart_ps, u8 bcn_ant_mode, const char *msg) { struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter); RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_notice_, ("%s: PowerMode =%d Smart_PS =%d\n", __FUNCTION__, ps_mode, smart_ps)); if (ps_mode > PM_Card_Disable) { RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_err_, ("ps_mode:%d error\n", ps_mode)); return; } if (pwrpriv->pwr_mode == ps_mode) { if (PS_MODE_ACTIVE == ps_mode) return; } down(&pwrpriv->lock); /* if (pwrpriv->pwr_mode == PS_MODE_ACTIVE) */ if (ps_mode == PS_MODE_ACTIVE) { if (1 && (((rtw_btcoex_IsBtControlLps(padapter) == false) ) || ((rtw_btcoex_IsBtControlLps(padapter) == true) && (rtw_btcoex_IsLpsOn(padapter) == false)) ) ) { DBG_871X(FUNC_ADPT_FMT" Leave 802.11 power save - %s\n", FUNC_ADPT_ARG(padapter), msg); pwrpriv->pwr_mode = ps_mode; rtw_set_rpwm(padapter, PS_STATE_S4); #if defined(CONFIG_WOWLAN) || defined(CONFIG_AP_WOWLAN) if (pwrpriv->wowlan_mode == true || pwrpriv->wowlan_ap_mode == true) { unsigned long start_time; u32 delay_ms; u8 val8; delay_ms = 20; start_time = jiffies; do { rtw_hal_get_hwreg(padapter, HW_VAR_SYS_CLKR, &val8); if (!(val8 & BIT(4))){ /* 0x08 bit4 =1 --> in 32k, bit4 = 0 --> leave 32k */ pwrpriv->cpwm = PS_STATE_S4; break; } if (jiffies_to_msecs(jiffies - start_time) > delay_ms) { DBG_871X("%s: Wait for FW 32K leave more than %u ms!!!\n", __FUNCTION__, delay_ms); pdbgpriv->dbg_wow_leave_ps_fail_cnt++; break; } msleep(1); } while (1); } #endif rtw_hal_set_hwreg(padapter, HW_VAR_H2C_FW_PWRMODE, (u8 *)(&ps_mode)); pwrpriv->bFwCurrentInPSMode = false; rtw_btcoex_LpsNotify(padapter, ps_mode); } } else { if ((PS_RDY_CHECK(padapter) && check_fwstate(&padapter->mlmepriv, WIFI_ASOC_STATE)) || ((rtw_btcoex_IsBtControlLps(padapter) == true) && (rtw_btcoex_IsLpsOn(padapter) == true)) ) { u8 pslv; DBG_871X(FUNC_ADPT_FMT" Enter 802.11 power save - %s\n", FUNC_ADPT_ARG(padapter), msg); rtw_btcoex_LpsNotify(padapter, ps_mode); pwrpriv->bFwCurrentInPSMode = true; pwrpriv->pwr_mode = ps_mode; pwrpriv->smart_ps = smart_ps; pwrpriv->bcn_ant_mode = bcn_ant_mode; rtw_hal_set_hwreg(padapter, HW_VAR_H2C_FW_PWRMODE, (u8 *)(&ps_mode)); pslv = PS_STATE_S2; if (pwrpriv->alives == 0) pslv = PS_STATE_S0; if ((rtw_btcoex_IsBtDisabled(padapter) == false) && (rtw_btcoex_IsBtControlLps(padapter) == true)) { u8 val8; val8 = rtw_btcoex_LpsVal(padapter); if (val8 & BIT(4)) pslv = PS_STATE_S2; } rtw_set_rpwm(padapter, pslv); } } up(&pwrpriv->lock); }