1 /******************************************************************************
3 * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of version 2 of the GNU General Public License as
7 * published by the Free Software Foundation.
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * You should have received a copy of the GNU General Public License along with
15 * this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
19 ******************************************************************************/
20 #define _RTW_PWRCTRL_C_
22 #include <drv_types.h>
24 #include <hal_com_h2c.h>
26 int rtw_fw_ps_state(PADAPTER padapter)
28 struct dvobj_priv *psdpriv = padapter->dvobj;
29 struct debug_priv *pdbgpriv = &psdpriv->drv_dbg;
30 int ret=_FAIL, dont_care=0;
33 struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
34 struct registry_priv *registry_par = &padapter->registrypriv;
36 if(registry_par->check_fw_ps != 1)
39 _enter_pwrlock(&pwrpriv->check_32k_lock);
41 if (RTW_CANNOT_RUN(padapter)) {
42 DBG_871X("%s: bSurpriseRemoved=%s , hw_init_completed=%d, bDriverStopped=%s\n", __func__
43 , rtw_is_surprise_removed(padapter)?"True":"False"
44 , rtw_get_hw_init_completed(padapter)
45 , rtw_is_drv_stopped(padapter)?"True":"False");
46 goto exit_fw_ps_state;
48 rtw_hal_set_hwreg(padapter, HW_VAR_SET_REQ_FW_PS, (u8 *)&dont_care);
50 //4. if 0x88[7]=1, driver set cmd to leave LPS/IPS.
51 //Else, hw will keep in active mode.
53 //0x88[7] = 32kpermission,
54 //0x88[6:0] = current_ps_state
55 //0x89[7:0] = last_rpwm
57 rtw_hal_get_hwreg(padapter, HW_VAR_FW_PS_STATE, (u8 *)&fw_ps_state);
59 if((fw_ps_state & 0x80) == 0)
63 pdbgpriv->dbg_poll_fail_cnt++;
64 DBG_871X("%s: fw_ps_state=%04x \n", __FUNCTION__, fw_ps_state);
70 _exit_pwrlock(&pwrpriv->check_32k_lock);
75 void _ips_enter(_adapter * padapter)
77 struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
79 pwrpriv->bips_processing = _TRUE;
81 // syn ips_mode with request
82 pwrpriv->ips_mode = pwrpriv->ips_mode_req;
84 pwrpriv->ips_enter_cnts++;
85 DBG_871X("==>ips_enter cnts:%d\n",pwrpriv->ips_enter_cnts);
87 if(rf_off == pwrpriv->change_rfpwrstate )
89 pwrpriv->bpower_saving = _TRUE;
90 DBG_871X_LEVEL(_drv_always_, "nolinked power save enter\n");
92 if(pwrpriv->ips_mode == IPS_LEVEL_2)
93 pwrpriv->bkeepfwalive = _TRUE;
95 rtw_ips_pwr_down(padapter);
96 pwrpriv->rf_pwrstate = rf_off;
98 pwrpriv->bips_processing = _FALSE;
102 void ips_enter(_adapter * padapter)
104 struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
107 #ifdef CONFIG_BT_COEXIST
108 rtw_btcoex_IpsNotify(padapter, pwrpriv->ips_mode_req);
109 #endif // CONFIG_BT_COEXIST
111 _enter_pwrlock(&pwrpriv->lock);
112 _ips_enter(padapter);
113 _exit_pwrlock(&pwrpriv->lock);
116 int _ips_leave(_adapter * padapter)
118 struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
119 int result = _SUCCESS;
121 if((pwrpriv->rf_pwrstate == rf_off) &&(!pwrpriv->bips_processing))
123 pwrpriv->bips_processing = _TRUE;
124 pwrpriv->change_rfpwrstate = rf_on;
125 pwrpriv->ips_leave_cnts++;
126 DBG_871X("==>ips_leave cnts:%d\n",pwrpriv->ips_leave_cnts);
128 if ((result = rtw_ips_pwr_up(padapter)) == _SUCCESS) {
129 pwrpriv->rf_pwrstate = rf_on;
131 DBG_871X_LEVEL(_drv_always_, "nolinked power save leave\n");
133 DBG_871X("==> ips_leave.....LED(0x%08x)...\n",rtw_read32(padapter,0x4c));
134 pwrpriv->bips_processing = _FALSE;
136 pwrpriv->bkeepfwalive = _FALSE;
137 pwrpriv->bpower_saving = _FALSE;
143 int ips_leave(_adapter * padapter)
145 struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
146 struct dvobj_priv *psdpriv = padapter->dvobj;
147 struct debug_priv *pdbgpriv = &psdpriv->drv_dbg;
150 if(!is_primary_adapter(padapter))
153 _enter_pwrlock(&pwrpriv->lock);
154 ret = _ips_leave(padapter);
155 #ifdef DBG_CHECK_FW_PS_STATE
156 if(rtw_fw_ps_state(padapter) == _FAIL)
158 DBG_871X("ips leave doesn't leave 32k\n");
159 pdbgpriv->dbg_leave_ips_fail_cnt++;
161 #endif //DBG_CHECK_FW_PS_STATE
162 _exit_pwrlock(&pwrpriv->lock);
165 ODM_DMReset(&GET_HAL_DATA(padapter)->odmpriv);
167 #ifdef CONFIG_BT_COEXIST
169 rtw_btcoex_IpsNotify(padapter, IPS_NONE);
170 #endif // CONFIG_BT_COEXIST
174 #endif /* CONFIG_IPS */
176 #ifdef CONFIG_AUTOSUSPEND
177 extern void autosuspend_enter(_adapter* padapter);
178 extern int autoresume_enter(_adapter* padapter);
181 #ifdef SUPPORT_HW_RFOFF_DETECTED
182 int rtw_hw_suspend(_adapter *padapter );
183 int rtw_hw_resume(_adapter *padapter);
186 bool rtw_pwr_unassociated_idle(_adapter *adapter)
188 _adapter *buddy = adapter->pbuddy_adapter;
189 struct mlme_priv *pmlmepriv = &(adapter->mlmepriv);
190 struct xmit_priv *pxmit_priv = &adapter->xmitpriv;
192 struct wifidirect_info *pwdinfo = &(adapter->wdinfo);
193 #ifdef CONFIG_IOCTL_CFG80211
194 struct cfg80211_wifidirect_info *pcfg80211_wdinfo = &adapter->cfg80211_wdinfo;
200 if (adapter_to_pwrctl(adapter)->bpower_saving ==_TRUE ) {
201 //DBG_871X("%s: already in LPS or IPS mode\n", __func__);
205 if (adapter_to_pwrctl(adapter)->ips_deny_time >= rtw_get_current_time()) {
206 //DBG_871X("%s ips_deny_time\n", __func__);
210 if (check_fwstate(pmlmepriv, WIFI_ASOC_STATE|WIFI_SITE_MONITOR)
211 || check_fwstate(pmlmepriv, WIFI_UNDER_LINKING|WIFI_UNDER_WPS)
212 || check_fwstate(pmlmepriv, WIFI_AP_STATE)
213 || check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE|WIFI_ADHOC_STATE)
214 #if defined(CONFIG_P2P) && defined(CONFIG_IOCTL_CFG80211)
215 || pcfg80211_wdinfo->is_ro_ch
216 #elif defined(CONFIG_P2P)
217 || !rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)
219 #if defined(CONFIG_P2P) && defined(CONFIG_IOCTL_CFG80211)
220 || rtw_get_passing_time_ms(pcfg80211_wdinfo->last_ro_ch_time) < 3000
226 /* consider buddy, if exist */
228 struct mlme_priv *b_pmlmepriv = &(buddy->mlmepriv);
230 struct wifidirect_info *b_pwdinfo = &(buddy->wdinfo);
231 #ifdef CONFIG_IOCTL_CFG80211
232 struct cfg80211_wifidirect_info *b_pcfg80211_wdinfo = &buddy->cfg80211_wdinfo;
236 if (check_fwstate(b_pmlmepriv, WIFI_ASOC_STATE|WIFI_SITE_MONITOR)
237 || check_fwstate(b_pmlmepriv, WIFI_UNDER_LINKING|WIFI_UNDER_WPS)
238 || check_fwstate(b_pmlmepriv, WIFI_AP_STATE)
239 || check_fwstate(b_pmlmepriv, WIFI_ADHOC_MASTER_STATE|WIFI_ADHOC_STATE)
240 #if defined(CONFIG_P2P) && defined(CONFIG_IOCTL_CFG80211)
241 || b_pcfg80211_wdinfo->is_ro_ch
242 #elif defined(CONFIG_P2P)
243 || !rtw_p2p_chk_state(b_pwdinfo, P2P_STATE_NONE)
245 #if defined(CONFIG_P2P) && defined(CONFIG_IOCTL_CFG80211)
246 || rtw_get_passing_time_ms(b_pcfg80211_wdinfo->last_ro_ch_time) < 3000
256 #ifdef CONFIG_INTEL_PROXIM
257 if(adapter->proximity.proxim_on==_TRUE){
262 if (pxmit_priv->free_xmitbuf_cnt != NR_XMITBUFF ||
263 pxmit_priv->free_xmit_extbuf_cnt != NR_XMIT_EXTBUFF) {
264 DBG_871X_LEVEL(_drv_always_, "There are some pkts to transmit\n");
265 DBG_871X_LEVEL(_drv_always_, "free_xmitbuf_cnt: %d, free_xmit_extbuf_cnt: %d\n",
266 pxmit_priv->free_xmitbuf_cnt, pxmit_priv->free_xmit_extbuf_cnt);
279 * rtw_ps_processor() doesn't handle LPS.
281 void rtw_ps_processor(_adapter*padapter)
284 struct wifidirect_info *pwdinfo = &( padapter->wdinfo );
286 struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
287 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
288 struct dvobj_priv *psdpriv = padapter->dvobj;
289 struct debug_priv *pdbgpriv = &psdpriv->drv_dbg;
290 #ifdef SUPPORT_HW_RFOFF_DETECTED
291 rt_rf_power_state rfpwrstate;
292 #endif //SUPPORT_HW_RFOFF_DETECTED
295 _enter_pwrlock(&adapter_to_pwrctl(padapter)->lock);
296 ps_deny = rtw_ps_deny_get(padapter);
297 _exit_pwrlock(&adapter_to_pwrctl(padapter)->lock);
300 DBG_871X(FUNC_ADPT_FMT ": ps_deny=0x%08X, skip power save!\n",
301 FUNC_ADPT_ARG(padapter), ps_deny);
305 if(pwrpriv->bInSuspend == _TRUE){//system suspend or autosuspend
306 pdbgpriv->dbg_ps_insuspend_cnt++;
307 DBG_871X("%s, pwrpriv->bInSuspend == _TRUE ignore this process\n",__FUNCTION__);
311 pwrpriv->ps_processing = _TRUE;
313 #ifdef SUPPORT_HW_RFOFF_DETECTED
314 if(pwrpriv->bips_processing == _TRUE)
317 //DBG_871X("==> fw report state(0x%x)\n",rtw_read8(padapter,0x1ca));
318 if(pwrpriv->bHWPwrPindetect)
320 #ifdef CONFIG_AUTOSUSPEND
321 if(padapter->registrypriv.usbss_enable)
323 if(pwrpriv->rf_pwrstate == rf_on)
325 if(padapter->net_closed == _TRUE)
326 pwrpriv->ps_flag = _TRUE;
328 rfpwrstate = RfOnOffDetect(padapter);
329 DBG_871X("@@@@- #1 %s==> rfstate:%s \n",__FUNCTION__,(rfpwrstate==rf_on)?"rf_on":"rf_off");
330 if(rfpwrstate!= pwrpriv->rf_pwrstate)
332 if(rfpwrstate == rf_off)
334 pwrpriv->change_rfpwrstate = rf_off;
336 pwrpriv->bkeepfwalive = _TRUE;
337 pwrpriv->brfoffbyhw = _TRUE;
339 autosuspend_enter(padapter);
345 #endif //CONFIG_AUTOSUSPEND
347 rfpwrstate = RfOnOffDetect(padapter);
348 DBG_871X("@@@@- #2 %s==> rfstate:%s \n",__FUNCTION__,(rfpwrstate==rf_on)?"rf_on":"rf_off");
350 if(rfpwrstate!= pwrpriv->rf_pwrstate)
352 if(rfpwrstate == rf_off)
354 pwrpriv->change_rfpwrstate = rf_off;
355 pwrpriv->brfoffbyhw = _TRUE;
356 rtw_hw_suspend(padapter );
360 pwrpriv->change_rfpwrstate = rf_on;
361 rtw_hw_resume(padapter );
363 DBG_871X("current rf_pwrstate(%s)\n",(pwrpriv->rf_pwrstate == rf_off)?"rf_off":"rf_on");
366 pwrpriv->pwr_state_check_cnts ++;
368 #endif //SUPPORT_HW_RFOFF_DETECTED
370 if (pwrpriv->ips_mode_req == IPS_NONE)
373 if (rtw_pwr_unassociated_idle(padapter) == _FALSE)
376 if((pwrpriv->rf_pwrstate == rf_on) && ((pwrpriv->pwr_state_check_cnts%4)==0))
378 DBG_871X("==>%s .fw_state(%x)\n",__FUNCTION__,get_fwstate(pmlmepriv));
379 #if defined (CONFIG_BT_COEXIST)&& defined (CONFIG_AUTOSUSPEND)
381 pwrpriv->change_rfpwrstate = rf_off;
383 #ifdef CONFIG_AUTOSUSPEND
384 if(padapter->registrypriv.usbss_enable)
386 if(pwrpriv->bHWPwrPindetect)
387 pwrpriv->bkeepfwalive = _TRUE;
389 if(padapter->net_closed == _TRUE)
390 pwrpriv->ps_flag = _TRUE;
392 #if defined (CONFIG_BT_COEXIST)&& defined (CONFIG_AUTOSUSPEND)
393 if (_TRUE==pwrpriv->bInternalAutoSuspend) {
394 DBG_871X("<==%s .pwrpriv->bInternalAutoSuspend)(%x)\n",__FUNCTION__,pwrpriv->bInternalAutoSuspend);
396 pwrpriv->change_rfpwrstate = rf_off;
397 DBG_871X("<==%s .pwrpriv->bInternalAutoSuspend)(%x) call autosuspend_enter\n",__FUNCTION__,pwrpriv->bInternalAutoSuspend);
398 autosuspend_enter(padapter);
401 autosuspend_enter(padapter);
402 #endif //if defined (CONFIG_BT_COEXIST)&& defined (CONFIG_AUTOSUSPEND)
404 else if(pwrpriv->bHWPwrPindetect)
408 #endif //CONFIG_AUTOSUSPEND
410 #if defined (CONFIG_BT_COEXIST)&& defined (CONFIG_AUTOSUSPEND)
411 pwrpriv->change_rfpwrstate = rf_off;
412 #endif //defined (CONFIG_BT_COEXIST)&& defined (CONFIG_AUTOSUSPEND)
420 #ifndef CONFIG_IPS_CHECK_IN_WD
421 rtw_set_pwr_state_check_timer(pwrpriv);
423 pwrpriv->ps_processing = _FALSE;
427 void pwr_state_check_handler(RTW_TIMER_HDL_ARGS);
428 void pwr_state_check_handler(RTW_TIMER_HDL_ARGS)
430 _adapter *padapter = (_adapter *)FunctionContext;
431 rtw_ps_cmd(padapter);
435 void traffic_check_for_leave_lps(PADAPTER padapter, u8 tx, u32 tx_packets)
437 #ifdef CONFIG_CHECK_LEAVE_LPS
438 static u32 start_time = 0;
439 static u32 xmit_cnt = 0;
440 u8 bLeaveLPS = _FALSE;
441 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
447 xmit_cnt += tx_packets;
450 start_time= rtw_get_current_time();
452 if (rtw_get_passing_time_ms(start_time) > 2000) // 2 sec == watch dog timer
456 if ((adapter_to_pwrctl(padapter)->bLeisurePs)
457 && (adapter_to_pwrctl(padapter)->pwr_mode != PS_MODE_ACTIVE)
458 #ifdef CONFIG_BT_COEXIST
459 && (rtw_btcoex_IsBtControlLps(padapter) == _FALSE)
463 //DBG_871X("leave lps via Tx = %d\n", xmit_cnt);
468 start_time= rtw_get_current_time();
475 if(pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod > 4/*2*/)
477 if ((adapter_to_pwrctl(padapter)->bLeisurePs)
478 && (adapter_to_pwrctl(padapter)->pwr_mode != PS_MODE_ACTIVE)
479 #ifdef CONFIG_BT_COEXIST
480 && (rtw_btcoex_IsBtControlLps(padapter) == _FALSE)
484 //DBG_871X("leave lps via Rx = %d\n", pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod);
492 //DBG_871X("leave lps via %s, Tx = %d, Rx = %d \n", tx?"Tx":"Rx", pmlmepriv->LinkDetectInfo.NumTxOkInPeriod,pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod);
493 //rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_LEAVE, 1);
494 rtw_lps_ctrl_wk_cmd(padapter, tx?LPS_CTRL_TX_TRAFFIC_LEAVE:LPS_CTRL_RX_TRAFFIC_LEAVE, tx?0:1);
496 #endif //CONFIG_CHECK_LEAVE_LPS
501 * This function MUST be called under power lock protect
505 * pslv power state level, only could be PS_STATE_S0 ~ PS_STATE_S4
508 void rtw_set_rpwm(PADAPTER padapter, u8 pslv)
511 struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
512 #ifdef CONFIG_DETECT_CPWM_BY_POLLING
514 #endif // CONFIG_DETECT_CPWM_BY_POLLING
515 struct dvobj_priv *psdpriv = padapter->dvobj;
516 struct debug_priv *pdbgpriv = &psdpriv->drv_dbg;
519 pslv = PS_STATE(pslv);
521 #ifdef CONFIG_LPS_RPWM_TIMER
522 if (pwrpriv->brpwmtimeout == _TRUE)
524 DBG_871X("%s: RPWM timeout, force to set RPWM(0x%02X) again!\n", __FUNCTION__, pslv);
527 #endif // CONFIG_LPS_RPWM_TIMER
529 if ( (pwrpriv->rpwm == pslv)
530 #ifdef CONFIG_LPS_LCLK
531 || ((pwrpriv->rpwm >= PS_STATE_S2)&&(pslv >= PS_STATE_S2))
535 RT_TRACE(_module_rtl871x_pwrctrl_c_,_drv_err_,
536 ("%s: Already set rpwm[0x%02X], new=0x%02X!\n", __FUNCTION__, pwrpriv->rpwm, pslv));
541 if (rtw_is_surprise_removed(padapter) ||
542 (!rtw_is_hw_init_completed(padapter)))
544 RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_err_,
545 ("%s: SurpriseRemoved(%s) hw_init_completed(%s)\n"
547 , rtw_is_surprise_removed(padapter)?"True":"False"
548 , rtw_is_hw_init_completed(padapter)?"True":"False"));
550 pwrpriv->cpwm = PS_STATE_S4;
555 if (rtw_is_drv_stopped(padapter)) {
556 RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_err_,
557 ("%s: change power state(0x%02X) when DriverStopped\n", __FUNCTION__, pslv));
559 if (pslv < PS_STATE_S2) {
560 RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_err_,
561 ("%s: Reject to enter PS_STATE(0x%02X) lower than S2 when DriverStopped!!\n", __FUNCTION__, pslv));
566 rpwm = pslv | pwrpriv->tog;
567 #ifdef CONFIG_LPS_LCLK
568 // only when from PS_STATE S0/S1 to S2 and higher needs ACK
569 if ((pwrpriv->cpwm < PS_STATE_S2) && (pslv >= PS_STATE_S2))
572 RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_notice_,
573 ("rtw_set_rpwm: rpwm=0x%02x cpwm=0x%02x\n", rpwm, pwrpriv->cpwm));
575 pwrpriv->rpwm = pslv;
577 #ifdef CONFIG_DETECT_CPWM_BY_POLLING
581 rtw_hal_get_hwreg(padapter, HW_VAR_CPWM, &cpwm_orig);
585 #if defined(CONFIG_LPS_RPWM_TIMER) && !defined(CONFIG_DETECT_CPWM_BY_POLLING)
587 _set_timer(&pwrpriv->pwr_rpwm_timer, LPS_RPWM_WAIT_MS);
588 #endif // CONFIG_LPS_RPWM_TIMER & !CONFIG_DETECT_CPWM_BY_POLLING
589 rtw_hal_set_hwreg(padapter, HW_VAR_SET_RPWM, (u8 *)(&rpwm));
591 pwrpriv->tog += 0x80;
593 #ifdef CONFIG_LPS_LCLK
594 // No LPS 32K, No Ack
597 #ifdef CONFIG_DETECT_CPWM_BY_POLLING
602 start_time = rtw_get_current_time();
609 rtw_hal_get_hwreg(padapter, HW_VAR_CPWM, &cpwm_now);
610 if ((cpwm_orig ^ cpwm_now) & 0x80)
612 pwrpriv->cpwm = PS_STATE_S4;
613 pwrpriv->cpwm_tog = cpwm_now & PS_TOGGLE;
614 #ifdef DBG_CHECK_FW_PS_STATE
615 DBG_871X("%s: polling cpwm OK! poll_cnt=%d, cpwm_orig=%02x, cpwm_now=%02x , 0x100=0x%x\n"
616 , __FUNCTION__,poll_cnt, cpwm_orig, cpwm_now, rtw_read8(padapter, REG_CR));
617 if(rtw_fw_ps_state(padapter) == _FAIL)
619 DBG_871X("leave 32k but fw state in 32k\n");
620 pdbgpriv->dbg_rpwm_toogle_cnt++;
622 #endif //DBG_CHECK_FW_PS_STATE
626 if (rtw_get_passing_time_ms(start_time) > LPS_RPWM_WAIT_MS)
628 DBG_871X("%s: polling cpwm timeout! poll_cnt=%d, cpwm_orig=%02x, cpwm_now=%02x \n", __FUNCTION__,poll_cnt, cpwm_orig, cpwm_now);
629 #ifdef DBG_CHECK_FW_PS_STATE
630 if(rtw_fw_ps_state(padapter) == _FAIL)
632 DBG_871X("rpwm timeout and fw ps state in 32k\n");
633 pdbgpriv->dbg_rpwm_timeout_fail_cnt++;
635 #endif //DBG_CHECK_FW_PS_STATE
636 #ifdef CONFIG_LPS_RPWM_TIMER
637 _set_timer(&pwrpriv->pwr_rpwm_timer, 1);
638 #endif // CONFIG_LPS_RPWM_TIMER
642 #endif // CONFIG_DETECT_CPWM_BY_POLLING
645 #endif // CONFIG_LPS_LCLK
647 pwrpriv->cpwm = pslv;
653 u8 PS_RDY_CHECK(_adapter * padapter)
655 u32 curr_time, delta_time;
656 struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
657 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
659 struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
660 #ifdef CONFIG_IOCTL_CFG80211
661 struct cfg80211_wifidirect_info *pcfg80211_wdinfo = &padapter->cfg80211_wdinfo;
662 #endif /* CONFIG_IOCTL_CFG80211 */
663 #endif /* CONFIG_P2P */
665 if(_TRUE == pwrpriv->bInSuspend )
668 curr_time = rtw_get_current_time();
670 delta_time = curr_time -pwrpriv->DelayLPSLastTimeStamp;
672 if(delta_time < LPS_DELAY_TIME)
677 if (check_fwstate(pmlmepriv, WIFI_SITE_MONITOR)
678 || check_fwstate(pmlmepriv, WIFI_UNDER_LINKING|WIFI_UNDER_WPS)
679 || check_fwstate(pmlmepriv, WIFI_AP_STATE)
680 || check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE|WIFI_ADHOC_STATE)
681 #if defined(CONFIG_P2P) && defined(CONFIG_IOCTL_CFG80211)
682 || pcfg80211_wdinfo->is_ro_ch
683 #elif defined(CONFIG_P2P)
684 || !rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)
686 || rtw_is_scan_deny(padapter)
688 // TDLS link is established.
689 || ( padapter->tdlsinfo.link_established == _TRUE )
690 #endif // CONFIG_TDLS
694 if( (padapter->securitypriv.dot11AuthAlgrthm == dot11AuthAlgrthm_8021X) && (padapter->securitypriv.binstallGrpkey == _FALSE) )
696 DBG_871X("Group handshake still in progress !!!\n");
700 #ifdef CONFIG_IOCTL_CFG80211
701 if (!rtw_cfg80211_pwr_mgmt(padapter))
708 #if defined(CONFIG_FWLPS_IN_IPS)
709 void rtw_set_fw_in_ips_mode(PADAPTER padapter, u8 enable)
711 struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
715 u8 cpwm_orig = 0, cpwm_now = 0;
716 u8 parm[H2C_INACTIVE_PS_LEN]={0};
718 if (padapter->netif_up == _FALSE) {
719 DBG_871X("%s: ERROR, netif is down\n", __func__);
723 //u8 cmd_param; //BIT0:enable, BIT1:NoConnect32k
725 #ifdef CONFIG_BT_COEXIST
726 rtw_btcoex_IpsNotify(padapter, pwrpriv->ips_mode_req);
729 DBG_871X("%s: issue H2C to FW when entering IPS\n", __func__);
735 rtw_hal_fill_h2c_cmd(padapter, //H2C_FWLPS_IN_IPS_,
737 H2C_INACTIVE_PS_LEN, parm);
738 //poll 0x1cc to make sure H2C command already finished by FW; MAC_0x1cc=0 means H2C done by FW.
740 val8 = rtw_read8(padapter, REG_HMETFR);
742 DBG_871X("%s polling REG_HMETFR=0x%x, cnt=%d \n",
743 __func__, val8, cnt);
745 }while(cnt<100 && (val8!=0));
747 //H2C done, enter 32k
749 //ser rpwm to enter 32k
750 val8 = rtw_read8(padapter, SDIO_LOCAL_BASE|SDIO_REG_HRPWM1);
751 DBG_871X("%s: read rpwm=%02x\n", __FUNCTION__, val8);
754 rtw_write8(padapter, SDIO_LOCAL_BASE|SDIO_REG_HRPWM1, val8);
755 DBG_871X("%s: write rpwm=%02x\n", __FUNCTION__, val8);
756 adapter_to_pwrctl(padapter)->tog = (val8 + 0x80) & 0x80;
758 if (parm[1] == 0 || parm[2] == 0) {
760 val8 = rtw_read8(padapter, REG_CR);
762 DBG_871X("%s polling 0x100=0x%x, cnt=%d \n",
763 __func__, val8, cnt);
764 DBG_871X("%s 0x08:%02x, 0x03:%02x\n",
766 rtw_read8(padapter, 0x08),
767 rtw_read8(padapter, 0x03));
769 } while(cnt<20 && (val8!=0xEA));
774 DBG_871X("%s: Leaving IPS in FWLPS state\n", __func__);
778 rtw_hal_get_hwreg(padapter, HW_VAR_CPWM, &cpwm_orig);
781 val8 = rtw_read8(padapter, SDIO_LOCAL_BASE|SDIO_REG_HRPWM1);
785 rtw_write8(padapter, SDIO_LOCAL_BASE|SDIO_REG_HRPWM1, val8);
786 DBG_871X("%s: write rpwm=%02x\n", __FUNCTION__, val8);
787 adapter_to_pwrctl(padapter)->tog = (val8 + 0x80) & 0x80;
790 start_time = rtw_get_current_time();
795 rtw_hal_get_hwreg(padapter, HW_VAR_CPWM, &cpwm_now);
796 if ((cpwm_orig ^ cpwm_now) & 0x80) {
800 if (rtw_get_passing_time_ms(start_time) > 100)
802 DBG_871X("%s: polling cpwm timeout when leaving IPS in FWLPS state\n", __FUNCTION__);
810 rtw_hal_fill_h2c_cmd(padapter, H2C_INACTIVE_PS_,
811 H2C_INACTIVE_PS_LEN, parm);
812 #ifdef CONFIG_BT_COEXIST
813 rtw_btcoex_IpsNotify(padapter, IPS_NONE);
819 void rtw_set_ps_mode(PADAPTER padapter, u8 ps_mode, u8 smart_ps, u8 bcn_ant_mode, const char *msg)
821 struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
822 struct dvobj_priv *psdpriv = padapter->dvobj;
823 struct debug_priv *pdbgpriv = &psdpriv->drv_dbg;
825 struct wifidirect_info *pwdinfo = &( padapter->wdinfo );
828 struct sta_priv *pstapriv = &padapter->stapriv;
831 _list *plist, *phead;
832 struct sta_info *ptdls_sta;
837 RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_notice_,
838 ("%s: PowerMode=%d Smart_PS=%d\n",
839 __FUNCTION__, ps_mode, smart_ps));
841 if(ps_mode > PM_Card_Disable) {
842 RT_TRACE(_module_rtl871x_pwrctrl_c_,_drv_err_,("ps_mode:%d error\n", ps_mode));
846 if (pwrpriv->pwr_mode == ps_mode)
848 if (PS_MODE_ACTIVE == ps_mode) return;
850 #ifndef CONFIG_BT_COEXIST
851 if ((pwrpriv->smart_ps == smart_ps) &&
852 (pwrpriv->bcn_ant_mode == bcn_ant_mode))
856 #endif // !CONFIG_BT_COEXIST
859 #ifdef CONFIG_LPS_LCLK
860 _enter_pwrlock(&pwrpriv->lock);
863 //if(pwrpriv->pwr_mode == PS_MODE_ACTIVE)
864 if(ps_mode == PS_MODE_ACTIVE)
867 #ifdef CONFIG_BT_COEXIST
868 && (((rtw_btcoex_IsBtControlLps(padapter) == _FALSE)
870 && (pwdinfo->opp_ps == 0)
871 #endif // CONFIG_P2P_PS
873 || ((rtw_btcoex_IsBtControlLps(padapter) == _TRUE)
874 && (rtw_btcoex_IsLpsOn(padapter) == _FALSE))
876 #else // !CONFIG_BT_COEXIST
878 && (pwdinfo->opp_ps == 0)
879 #endif // CONFIG_P2P_PS
880 #endif // !CONFIG_BT_COEXIST
883 DBG_871X(FUNC_ADPT_FMT" Leave 802.11 power save - %s\n",
884 FUNC_ADPT_ARG(padapter), msg);
886 if (pwrpriv->lps_leave_cnts < UINT_MAX)
887 pwrpriv->lps_leave_cnts++;
889 pwrpriv->lps_leave_cnts = 0;
891 for(i=0; i< NUM_STA; i++)
893 phead = &(pstapriv->sta_hash[i]);
894 plist = get_next(phead);
896 while ((rtw_end_of_queue_search(phead, plist)) == _FALSE)
898 ptdls_sta = LIST_CONTAINOR(plist, struct sta_info, hash_list);
900 if( ptdls_sta->tdls_sta_state & TDLS_LINKED_STATE )
901 issue_nulldata_to_TDLS_peer_STA(padapter, ptdls_sta->hwaddr, 0, 0, 0);
902 plist = get_next(plist);
907 pwrpriv->pwr_mode = ps_mode;
908 rtw_set_rpwm(padapter, PS_STATE_S4);
910 rtw_hal_set_hwreg(padapter, HW_VAR_H2C_FW_PWRMODE, (u8 *)(&ps_mode));
911 pwrpriv->bFwCurrentInPSMode = _FALSE;
913 #ifdef CONFIG_BT_COEXIST
914 rtw_btcoex_LpsNotify(padapter, ps_mode);
915 #endif // CONFIG_BT_COEXIST
920 if ((PS_RDY_CHECK(padapter) && check_fwstate(&padapter->mlmepriv, WIFI_ASOC_STATE))
921 #ifdef CONFIG_BT_COEXIST
922 || ((rtw_btcoex_IsBtControlLps(padapter) == _TRUE)
923 && (rtw_btcoex_IsLpsOn(padapter) == _TRUE))
925 #ifdef CONFIG_P2P_WOWLAN
926 ||( _TRUE == pwrpriv->wowlan_p2p_mode)
927 #endif //CONFIG_P2P_WOWLAN
932 DBG_871X(FUNC_ADPT_FMT" Enter 802.11 power save - %s\n",
933 FUNC_ADPT_ARG(padapter), msg);
935 if (pwrpriv->lps_enter_cnts < UINT_MAX)
936 pwrpriv->lps_enter_cnts++;
938 pwrpriv->lps_enter_cnts = 0;
940 for(i=0; i< NUM_STA; i++)
942 phead = &(pstapriv->sta_hash[i]);
943 plist = get_next(phead);
945 while ((rtw_end_of_queue_search(phead, plist)) == _FALSE)
947 ptdls_sta = LIST_CONTAINOR(plist, struct sta_info, hash_list);
949 if( ptdls_sta->tdls_sta_state & TDLS_LINKED_STATE )
950 issue_nulldata_to_TDLS_peer_STA(padapter, ptdls_sta->hwaddr, 1, 0, 0);
951 plist = get_next(plist);
956 #ifdef CONFIG_BT_COEXIST
957 rtw_btcoex_LpsNotify(padapter, ps_mode);
958 #endif // CONFIG_BT_COEXIST
960 pwrpriv->bFwCurrentInPSMode = _TRUE;
961 pwrpriv->pwr_mode = ps_mode;
962 pwrpriv->smart_ps = smart_ps;
963 pwrpriv->bcn_ant_mode = bcn_ant_mode;
964 rtw_hal_set_hwreg(padapter, HW_VAR_H2C_FW_PWRMODE, (u8 *)(&ps_mode));
967 // Set CTWindow after LPS
968 if(pwdinfo->opp_ps == 1)
969 p2p_ps_wk_cmd(padapter, P2P_PS_ENABLE, 0);
970 #endif //CONFIG_P2P_PS
973 #ifdef CONFIG_LPS_LCLK
974 if (pwrpriv->alives == 0)
976 #endif // CONFIG_LPS_LCLK
978 #ifdef CONFIG_BT_COEXIST
979 if ((rtw_btcoex_IsBtDisabled(padapter) == _FALSE)
980 && (rtw_btcoex_IsBtControlLps(padapter) == _TRUE))
984 val8 = rtw_btcoex_LpsVal(padapter);
989 #endif // CONFIG_BT_COEXIST
991 rtw_set_rpwm(padapter, pslv);
995 #ifdef CONFIG_LPS_LCLK
996 _exit_pwrlock(&pwrpriv->lock);
1008 s32 LPS_RF_ON_check(PADAPTER padapter, u32 delay_ms)
1015 start_time = rtw_get_current_time();
1018 rtw_hal_get_hwreg(padapter, HW_VAR_FWLPS_RF_ON, &bAwake);
1019 if (_TRUE == bAwake)
1022 if (rtw_is_surprise_removed(padapter)) {
1024 DBG_871X("%s: device surprise removed!!\n", __FUNCTION__);
1028 if (rtw_get_passing_time_ms(start_time) > delay_ms)
1031 DBG_871X("%s: Wait for FW LPS leave more than %u ms!!!\n", __FUNCTION__, delay_ms);
1042 // Enter the leisure power save mode.
1044 void LPS_Enter(PADAPTER padapter, const char *msg)
1046 struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
1047 struct pwrctrl_priv *pwrpriv = dvobj_to_pwrctl(dvobj);
1048 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
1049 _adapter *buddy = padapter->pbuddy_adapter;
1050 int n_assoc_iface = 0;
1056 // DBG_871X("+LeisurePSEnter\n");
1058 #ifdef CONFIG_BT_COEXIST
1059 if (rtw_btcoex_IsBtControlLps(padapter) == _TRUE)
1063 /* Skip lps enter request if number of assocated adapters is not 1 */
1064 for (i = 0; i < dvobj->iface_nums; i++) {
1065 if (check_fwstate(&(dvobj->padapters[i]->mlmepriv), WIFI_ASOC_STATE))
1068 if (n_assoc_iface != 1)
1071 /* Skip lps enter request for adapter not port0 */
1072 if (get_iface_type(padapter) != IFACE_PORT0)
1075 for (i = 0; i < dvobj->iface_nums; i++) {
1076 if (PS_RDY_CHECK(dvobj->padapters[i]) == _FALSE)
1080 #ifdef CONFIG_P2P_PS
1081 if(padapter->wdinfo.p2p_ps_mode == P2P_PS_NOA)
1083 return;//supporting p2p client ps NOA via H2C_8723B_P2P_PS_OFFLOAD
1085 #endif //CONFIG_P2P_PS
1087 if (pwrpriv->bLeisurePs)
1089 // Idle for a while if we connect to AP a while ago.
1090 if (pwrpriv->LpsIdleCount >= 2) // 4 Sec
1092 if(pwrpriv->pwr_mode == PS_MODE_ACTIVE)
1094 sprintf(buf, "WIFI-%s", msg);
1095 pwrpriv->bpower_saving = _TRUE;
1096 rtw_set_ps_mode(padapter, pwrpriv->power_mgnt, padapter->registrypriv.smart_ps, 0, buf);
1100 pwrpriv->LpsIdleCount++;
1103 // DBG_871X("-LeisurePSEnter\n");
1110 // Leave the leisure power save mode.
1112 void LPS_Leave(PADAPTER padapter, const char *msg)
1114 #define LPS_LEAVE_TIMEOUT_MS 100
1116 struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
1117 struct pwrctrl_priv *pwrpriv = dvobj_to_pwrctl(dvobj);
1121 struct debug_priv *pdbgpriv = &dvobj->drv_dbg;
1125 // DBG_871X("+LeisurePSLeave\n");
1127 #ifdef CONFIG_BT_COEXIST
1128 if (rtw_btcoex_IsBtControlLps(padapter) == _TRUE)
1132 if (pwrpriv->bLeisurePs)
1134 if(pwrpriv->pwr_mode != PS_MODE_ACTIVE)
1136 sprintf(buf, "WIFI-%s", msg);
1137 rtw_set_ps_mode(padapter, PS_MODE_ACTIVE, 0, 0, buf);
1139 if(pwrpriv->pwr_mode == PS_MODE_ACTIVE)
1140 LPS_RF_ON_check(padapter, LPS_LEAVE_TIMEOUT_MS);
1144 pwrpriv->bpower_saving = _FALSE;
1145 #ifdef DBG_CHECK_FW_PS_STATE
1146 if(rtw_fw_ps_state(padapter) == _FAIL)
1148 DBG_871X("leave lps, fw in 32k\n");
1149 pdbgpriv->dbg_leave_lps_fail_cnt++;
1151 #endif //DBG_CHECK_FW_PS_STATE
1152 // DBG_871X("-LeisurePSLeave\n");
1158 void LeaveAllPowerSaveModeDirect(PADAPTER Adapter)
1160 PADAPTER pri_padapter = GET_PRIMARY_ADAPTER(Adapter);
1161 struct mlme_priv *pmlmepriv = &(Adapter->mlmepriv);
1162 struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(Adapter);
1163 struct dvobj_priv *psdpriv = Adapter->dvobj;
1164 struct debug_priv *pdbgpriv = &psdpriv->drv_dbg;
1165 #ifndef CONFIG_DETECT_CPWM_BY_POLLING
1166 u8 cpwm_orig, cpwm_now;
1168 #endif // CONFIG_DETECT_CPWM_BY_POLLING
1172 DBG_871X("%s.....\n",__FUNCTION__);
1174 if (rtw_is_surprise_removed(Adapter)) {
1175 DBG_871X(FUNC_ADPT_FMT ": bSurpriseRemoved=_TRUE Skip!\n", FUNC_ADPT_ARG(Adapter));
1179 if ((check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE)
1180 #ifdef CONFIG_CONCURRENT_MODE
1181 || (check_buddy_fwstate(Adapter,_FW_LINKED) == _TRUE)
1186 if(pwrpriv->pwr_mode == PS_MODE_ACTIVE) {
1187 DBG_871X("%s: Driver Already Leave LPS\n",__FUNCTION__);
1191 #ifdef CONFIG_LPS_LCLK
1192 _enter_pwrlock(&pwrpriv->lock);
1194 #ifndef CONFIG_DETECT_CPWM_BY_POLLING
1196 rtw_hal_get_hwreg(Adapter, HW_VAR_CPWM, &cpwm_orig);
1197 #endif //CONFIG_DETECT_CPWM_BY_POLLING
1198 rtw_set_rpwm(Adapter, PS_STATE_S4);
1200 #ifndef CONFIG_DETECT_CPWM_BY_POLLING
1202 start_time = rtw_get_current_time();
1208 rtw_hal_get_hwreg(Adapter, HW_VAR_CPWM, &cpwm_now);
1209 if ((cpwm_orig ^ cpwm_now) & 0x80)
1211 pwrpriv->cpwm = PS_STATE_S4;
1212 pwrpriv->cpwm_tog = cpwm_now & PS_TOGGLE;
1213 #ifdef DBG_CHECK_FW_PS_STATE
1214 DBG_871X("%s: polling cpwm OK! cpwm_orig=%02x, cpwm_now=%02x, 0x100=0x%x \n"
1215 , __FUNCTION__, cpwm_orig, cpwm_now, rtw_read8(Adapter, REG_CR));
1216 if(rtw_fw_ps_state(Adapter) == _FAIL)
1218 DBG_871X("%s: leave 32k but fw state in 32k\n", __FUNCTION__);
1219 pdbgpriv->dbg_rpwm_toogle_cnt++;
1221 #endif //DBG_CHECK_FW_PS_STATE
1225 if (rtw_get_passing_time_ms(start_time) > LPS_RPWM_WAIT_MS)
1227 DBG_871X("%s: polling cpwm timeout! cpwm_orig=%02x, cpwm_now=%02x \n", __FUNCTION__, cpwm_orig, cpwm_now);
1228 #ifdef DBG_CHECK_FW_PS_STATE
1229 if(rtw_fw_ps_state(Adapter) == _FAIL)
1231 DBG_871X("rpwm timeout and fw ps state in 32k\n");
1232 pdbgpriv->dbg_rpwm_timeout_fail_cnt++;
1234 #endif //DBG_CHECK_FW_PS_STATE
1238 #endif // CONFIG_DETECT_CPWM_BY_POLLING
1240 _exit_pwrlock(&pwrpriv->lock);
1243 #ifdef CONFIG_P2P_PS
1244 p2p_ps_wk_cmd(pri_padapter, P2P_PS_DISABLE, 0);
1245 #endif //CONFIG_P2P_PS
1248 rtw_lps_ctrl_wk_cmd(pri_padapter, LPS_CTRL_LEAVE, 0);
1253 if(pwrpriv->rf_pwrstate== rf_off)
1255 #ifdef CONFIG_AUTOSUSPEND
1256 if(Adapter->registrypriv.usbss_enable)
1258 #if (LINUX_VERSION_CODE>=KERNEL_VERSION(2,6,35))
1259 usb_disable_autosuspend(adapter_to_dvobj(Adapter)->pusbdev);
1260 #elif (LINUX_VERSION_CODE>=KERNEL_VERSION(2,6,22) && LINUX_VERSION_CODE<=KERNEL_VERSION(2,6,34))
1261 adapter_to_dvobj(Adapter)->pusbdev->autosuspend_disabled = Adapter->bDisableAutosuspend;//autosuspend disabled by the user
1267 #if defined(CONFIG_FWLPS_IN_IPS) || defined(CONFIG_SWLPS_IN_IPS)
1269 if(_FALSE == ips_leave(pri_padapter))
1271 DBG_871X("======> ips_leave fail.............\n");
1274 #endif //CONFIG_SWLPS_IN_IPS || (CONFIG_PLATFORM_SPRD)
1283 // Description: Leave all power save mode: LPS, FwLPS, IPS if needed.
1284 // Move code to function by tynli. 2010.03.26.
1286 void LeaveAllPowerSaveMode(IN PADAPTER Adapter)
1288 struct dvobj_priv *dvobj = adapter_to_dvobj(Adapter);
1289 struct mlme_priv *pmlmepriv = &(Adapter->mlmepriv);
1291 int n_assoc_iface = 0;
1296 //DBG_871X("%s.....\n",__FUNCTION__);
1298 if (_FALSE == Adapter->bup)
1300 DBG_871X(FUNC_ADPT_FMT ": bup=%d Skip!\n",
1301 FUNC_ADPT_ARG(Adapter), Adapter->bup);
1305 if (rtw_is_surprise_removed(Adapter)) {
1306 DBG_871X(FUNC_ADPT_FMT ": bSurpriseRemoved=_TRUE Skip!\n", FUNC_ADPT_ARG(Adapter));
1310 for (i = 0; i < dvobj->iface_nums; i++) {
1311 if (check_fwstate(&(dvobj->padapters[i]->mlmepriv), WIFI_ASOC_STATE))
1317 #ifdef CONFIG_LPS_LCLK
1321 #ifdef CONFIG_P2P_PS
1322 p2p_ps_wk_cmd(Adapter, P2P_PS_DISABLE, enqueue);
1323 #endif //CONFIG_P2P_PS
1326 rtw_lps_ctrl_wk_cmd(Adapter, LPS_CTRL_LEAVE, enqueue);
1329 #ifdef CONFIG_LPS_LCLK
1330 LPS_Leave_check(Adapter);
1335 if(adapter_to_pwrctl(Adapter)->rf_pwrstate== rf_off)
1337 #ifdef CONFIG_AUTOSUSPEND
1338 if(Adapter->registrypriv.usbss_enable)
1340 #if (LINUX_VERSION_CODE>=KERNEL_VERSION(2,6,35))
1341 usb_disable_autosuspend(adapter_to_dvobj(Adapter)->pusbdev);
1342 #elif (LINUX_VERSION_CODE>=KERNEL_VERSION(2,6,22) && LINUX_VERSION_CODE<=KERNEL_VERSION(2,6,34))
1343 adapter_to_dvobj(Adapter)->pusbdev->autosuspend_disabled = Adapter->bDisableAutosuspend;//autosuspend disabled by the user
1349 #if defined(CONFIG_FWLPS_IN_IPS) || defined(CONFIG_SWLPS_IN_IPS)
1351 if(_FALSE == ips_leave(Adapter))
1353 DBG_871X("======> ips_leave fail.............\n");
1356 #endif //CONFIG_SWLPS_IN_IPS
1364 #ifdef CONFIG_LPS_LCLK
1365 void LPS_Leave_check(
1368 struct pwrctrl_priv *pwrpriv;
1374 pwrpriv = adapter_to_pwrctl(padapter);
1377 start_time = rtw_get_current_time();
1383 _enter_pwrlock(&pwrpriv->lock);
1385 if (rtw_is_surprise_removed(padapter)
1386 || (!rtw_is_hw_init_completed(padapter))
1387 #ifdef CONFIG_USB_HCI
1388 || rtw_is_drv_stopped(padapter)
1390 || (pwrpriv->pwr_mode == PS_MODE_ACTIVE)
1396 _exit_pwrlock(&pwrpriv->lock);
1401 if(rtw_get_passing_time_ms(start_time)>100)
1403 DBG_871X("Wait for cpwm event than 100 ms!!!\n");
1413 * Caller:ISR handler...
1415 * This will be called when CPWM interrupt is up.
1417 * using to update cpwn of drv; and drv willl make a decision to up or down pwr level
1421 struct reportpwrstate_parm *preportpwrstate)
1423 struct pwrctrl_priv *pwrpriv;
1427 pwrpriv = adapter_to_pwrctl(padapter);
1429 if (pwrpriv->cpwm_tog == (preportpwrstate->state & PS_TOGGLE)) {
1430 RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_err_,
1431 ("cpwm_int_hdl: tog(old)=0x%02x cpwm(new)=0x%02x toggle bit didn't change!?\n",
1432 pwrpriv->cpwm_tog, preportpwrstate->state));
1437 _enter_pwrlock(&pwrpriv->lock);
1439 #ifdef CONFIG_LPS_RPWM_TIMER
1440 if (pwrpriv->rpwm < PS_STATE_S2)
1442 DBG_871X("%s: Redundant CPWM Int. RPWM=0x%02X CPWM=0x%02x\n", __func__, pwrpriv->rpwm, pwrpriv->cpwm);
1443 _exit_pwrlock(&pwrpriv->lock);
1446 #endif // CONFIG_LPS_RPWM_TIMER
1448 pwrpriv->cpwm = PS_STATE(preportpwrstate->state);
1449 pwrpriv->cpwm_tog = preportpwrstate->state & PS_TOGGLE;
1451 if (pwrpriv->cpwm >= PS_STATE_S2)
1453 if (pwrpriv->alives & CMD_ALIVE)
1454 _rtw_up_sema(&padapter->cmdpriv.cmd_queue_sema);
1456 if (pwrpriv->alives & XMIT_ALIVE)
1457 _rtw_up_sema(&padapter->xmitpriv.xmit_sema);
1460 _exit_pwrlock(&pwrpriv->lock);
1463 RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_notice_,
1464 ("cpwm_int_hdl: cpwm=0x%02x\n", pwrpriv->cpwm));
1469 static void cpwm_event_callback(struct work_struct *work)
1471 struct pwrctrl_priv *pwrpriv = container_of(work, struct pwrctrl_priv, cpwm_event);
1472 struct dvobj_priv *dvobj = pwrctl_to_dvobj(pwrpriv);
1473 _adapter *adapter = dvobj->padapters[IFACE_ID0];
1474 struct reportpwrstate_parm report;
1476 //DBG_871X("%s\n",__FUNCTION__);
1478 report.state = PS_STATE_S2;
1479 cpwm_int_hdl(adapter, &report);
1482 #ifdef CONFIG_LPS_RPWM_TIMER
1483 static void rpwmtimeout_workitem_callback(struct work_struct *work)
1486 struct dvobj_priv *dvobj;
1487 struct pwrctrl_priv *pwrpriv;
1490 pwrpriv = container_of(work, struct pwrctrl_priv, rpwmtimeoutwi);
1491 dvobj = pwrctl_to_dvobj(pwrpriv);
1492 padapter = dvobj->padapters[IFACE_ID0];
1493 // DBG_871X("+%s: rpwm=0x%02X cpwm=0x%02X\n", __func__, pwrpriv->rpwm, pwrpriv->cpwm);
1495 _enter_pwrlock(&pwrpriv->lock);
1496 if ((pwrpriv->rpwm == pwrpriv->cpwm) || (pwrpriv->cpwm >= PS_STATE_S2))
1498 DBG_871X("%s: rpwm=0x%02X cpwm=0x%02X CPWM done!\n", __func__, pwrpriv->rpwm, pwrpriv->cpwm);
1501 _exit_pwrlock(&pwrpriv->lock);
1503 if (rtw_read8(padapter, 0x100) != 0xEA)
1506 struct reportpwrstate_parm report;
1508 report.state = PS_STATE_S2;
1509 DBG_871X("\n%s: FW already leave 32K!\n\n", __func__);
1510 cpwm_int_hdl(padapter, &report);
1512 DBG_871X("\n%s: FW already leave 32K!\n\n", __func__);
1513 cpwm_event_callback(&pwrpriv->cpwm_event);
1518 _enter_pwrlock(&pwrpriv->lock);
1520 if ((pwrpriv->rpwm == pwrpriv->cpwm) || (pwrpriv->cpwm >= PS_STATE_S2))
1522 DBG_871X("%s: cpwm=%d, nothing to do!\n", __func__, pwrpriv->cpwm);
1525 pwrpriv->brpwmtimeout = _TRUE;
1526 rtw_set_rpwm(padapter, pwrpriv->rpwm);
1527 pwrpriv->brpwmtimeout = _FALSE;
1530 _exit_pwrlock(&pwrpriv->lock);
1534 * This function is a timer handler, can't do any IO in it.
1536 static void pwr_rpwm_timeout_handler(void *FunctionContext)
1539 struct pwrctrl_priv *pwrpriv;
1542 padapter = (PADAPTER)FunctionContext;
1543 pwrpriv = adapter_to_pwrctl(padapter);
1544 DBG_871X("+%s: rpwm=0x%02X cpwm=0x%02X\n", __func__, pwrpriv->rpwm, pwrpriv->cpwm);
1546 if ((pwrpriv->rpwm == pwrpriv->cpwm) || (pwrpriv->cpwm >= PS_STATE_S2))
1548 DBG_871X("+%s: cpwm=%d, nothing to do!\n", __func__, pwrpriv->cpwm);
1552 _set_workitem(&pwrpriv->rpwmtimeoutwi);
1554 #endif // CONFIG_LPS_RPWM_TIMER
1556 __inline static void register_task_alive(struct pwrctrl_priv *pwrctrl, u32 tag)
1558 pwrctrl->alives |= tag;
1561 __inline static void unregister_task_alive(struct pwrctrl_priv *pwrctrl, u32 tag)
1563 pwrctrl->alives &= ~tag;
1569 * Check if the fw_pwrstate is okay for I/O.
1570 * If not (cpwm is less than S2), then the sub-routine
1571 * will raise the cpwm to be greater than or equal to S2.
1573 * Calling Context: Passive
1576 * 1. this function will request pwrctrl->lock
1579 * _SUCCESS hardware is ready for I/O
1580 * _FAIL can't I/O right now
1582 s32 rtw_register_task_alive(PADAPTER padapter, u32 task)
1585 struct pwrctrl_priv *pwrctrl;
1591 pwrctrl = adapter_to_pwrctl(padapter);
1594 _enter_pwrlock(&pwrctrl->lock);
1596 register_task_alive(pwrctrl, task);
1598 if (pwrctrl->bFwCurrentInPSMode == _TRUE)
1600 RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_notice_,
1601 ("%s: task=0x%x cpwm=0x%02x alives=0x%08x\n",
1602 __FUNCTION__, task, pwrctrl->cpwm, pwrctrl->alives));
1604 if (pwrctrl->cpwm < pslv)
1606 if (pwrctrl->cpwm < PS_STATE_S2)
1608 if (pwrctrl->rpwm < pslv)
1609 rtw_set_rpwm(padapter, pslv);
1613 _exit_pwrlock(&pwrctrl->lock);
1615 #ifdef CONFIG_DETECT_CPWM_BY_POLLING
1618 if (pwrctrl->cpwm >= PS_STATE_S2)
1621 #endif // CONFIG_DETECT_CPWM_BY_POLLING
1630 * If task is done, call this func. to power down firmware again.
1633 * 1. this function will request pwrctrl->lock
1638 void rtw_unregister_task_alive(PADAPTER padapter, u32 task)
1640 struct pwrctrl_priv *pwrctrl;
1645 pwrctrl = adapter_to_pwrctl(padapter);
1648 #ifdef CONFIG_BT_COEXIST
1649 if ((rtw_btcoex_IsBtDisabled(padapter) == _FALSE)
1650 && (rtw_btcoex_IsBtControlLps(padapter) == _TRUE))
1654 val8 = rtw_btcoex_LpsVal(padapter);
1659 #endif // CONFIG_BT_COEXIST
1661 _enter_pwrlock(&pwrctrl->lock);
1663 unregister_task_alive(pwrctrl, task);
1665 if ((pwrctrl->pwr_mode != PS_MODE_ACTIVE)
1666 && (pwrctrl->bFwCurrentInPSMode == _TRUE))
1668 RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_notice_,
1669 ("%s: cpwm=0x%02x alives=0x%08x\n",
1670 __FUNCTION__, pwrctrl->cpwm, pwrctrl->alives));
1672 if (pwrctrl->cpwm > pslv)
1674 if ((pslv >= PS_STATE_S2) || (pwrctrl->alives == 0))
1675 rtw_set_rpwm(padapter, pslv);
1679 _exit_pwrlock(&pwrctrl->lock);
1685 * Caller: rtw_xmit_thread
1687 * Check if the fw_pwrstate is okay for xmit.
1688 * If not (cpwm is less than S3), then the sub-routine
1689 * will raise the cpwm to be greater than or equal to S3.
1691 * Calling Context: Passive
1694 * _SUCCESS rtw_xmit_thread can write fifo/txcmd afterwards.
1695 * _FAIL rtw_xmit_thread can not do anything.
1697 s32 rtw_register_tx_alive(PADAPTER padapter)
1700 struct pwrctrl_priv *pwrctrl;
1706 pwrctrl = adapter_to_pwrctl(padapter);
1709 _enter_pwrlock(&pwrctrl->lock);
1711 register_task_alive(pwrctrl, XMIT_ALIVE);
1713 if (pwrctrl->bFwCurrentInPSMode == _TRUE)
1715 RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_notice_,
1716 ("rtw_register_tx_alive: cpwm=0x%02x alives=0x%08x\n",
1717 pwrctrl->cpwm, pwrctrl->alives));
1719 if (pwrctrl->cpwm < pslv)
1721 if (pwrctrl->cpwm < PS_STATE_S2)
1723 if (pwrctrl->rpwm < pslv)
1724 rtw_set_rpwm(padapter, pslv);
1728 _exit_pwrlock(&pwrctrl->lock);
1730 #ifdef CONFIG_DETECT_CPWM_BY_POLLING
1733 if (pwrctrl->cpwm >= PS_STATE_S2)
1736 #endif // CONFIG_DETECT_CPWM_BY_POLLING
1744 * Caller: rtw_cmd_thread
1746 * Check if the fw_pwrstate is okay for issuing cmd.
1747 * If not (cpwm should be is less than S2), then the sub-routine
1748 * will raise the cpwm to be greater than or equal to S2.
1750 * Calling Context: Passive
1753 * _SUCCESS rtw_cmd_thread can issue cmds to firmware afterwards.
1754 * _FAIL rtw_cmd_thread can not do anything.
1756 s32 rtw_register_cmd_alive(PADAPTER padapter)
1759 struct pwrctrl_priv *pwrctrl;
1765 pwrctrl = adapter_to_pwrctl(padapter);
1768 _enter_pwrlock(&pwrctrl->lock);
1770 register_task_alive(pwrctrl, CMD_ALIVE);
1772 if (pwrctrl->bFwCurrentInPSMode == _TRUE)
1774 RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_info_,
1775 ("rtw_register_cmd_alive: cpwm=0x%02x alives=0x%08x\n",
1776 pwrctrl->cpwm, pwrctrl->alives));
1778 if (pwrctrl->cpwm < pslv)
1780 if (pwrctrl->cpwm < PS_STATE_S2)
1782 if (pwrctrl->rpwm < pslv)
1783 rtw_set_rpwm(padapter, pslv);
1787 _exit_pwrlock(&pwrctrl->lock);
1789 #ifdef CONFIG_DETECT_CPWM_BY_POLLING
1792 if (pwrctrl->cpwm >= PS_STATE_S2)
1795 #endif // CONFIG_DETECT_CPWM_BY_POLLING
1805 * Calling Context: Dispatch/ISR
1811 s32 rtw_register_rx_alive(PADAPTER padapter)
1813 struct pwrctrl_priv *pwrctrl;
1817 pwrctrl = adapter_to_pwrctl(padapter);
1819 _enter_pwrlock(&pwrctrl->lock);
1821 register_task_alive(pwrctrl, RECV_ALIVE);
1822 RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_notice_,
1823 ("rtw_register_rx_alive: cpwm=0x%02x alives=0x%08x\n",
1824 pwrctrl->cpwm, pwrctrl->alives));
1826 _exit_pwrlock(&pwrctrl->lock);
1834 * Caller: evt_isr or evt_thread
1836 * Calling Context: Dispatch/ISR or Passive
1842 s32 rtw_register_evt_alive(PADAPTER padapter)
1844 struct pwrctrl_priv *pwrctrl;
1848 pwrctrl = adapter_to_pwrctl(padapter);
1850 _enter_pwrlock(&pwrctrl->lock);
1852 register_task_alive(pwrctrl, EVT_ALIVE);
1853 RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_notice_,
1854 ("rtw_register_evt_alive: cpwm=0x%02x alives=0x%08x\n",
1855 pwrctrl->cpwm, pwrctrl->alives));
1857 _exit_pwrlock(&pwrctrl->lock);
1868 * No more pkts for TX,
1869 * Then driver shall call this fun. to power down firmware again.
1871 void rtw_unregister_tx_alive(PADAPTER padapter)
1873 struct pwrctrl_priv *pwrctrl;
1878 pwrctrl = adapter_to_pwrctl(padapter);
1881 #ifdef CONFIG_BT_COEXIST
1882 if ((rtw_btcoex_IsBtDisabled(padapter) == _FALSE)
1883 && (rtw_btcoex_IsBtControlLps(padapter) == _TRUE))
1887 val8 = rtw_btcoex_LpsVal(padapter);
1892 #endif // CONFIG_BT_COEXIST
1894 #ifdef CONFIG_P2P_PS
1895 if(padapter->wdinfo.p2p_ps_mode > P2P_PS_NONE)
1899 #ifdef CONFIG_CONCURRENT_MODE
1900 else if(rtw_buddy_adapter_up(padapter))
1902 if(padapter->pbuddy_adapter->wdinfo.p2p_ps_mode > P2P_PS_NONE)
1908 _enter_pwrlock(&pwrctrl->lock);
1910 unregister_task_alive(pwrctrl, XMIT_ALIVE);
1912 if ((pwrctrl->pwr_mode != PS_MODE_ACTIVE)
1913 && (pwrctrl->bFwCurrentInPSMode == _TRUE))
1915 RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_notice_,
1916 ("%s: cpwm=0x%02x alives=0x%08x\n",
1917 __FUNCTION__, pwrctrl->cpwm, pwrctrl->alives));
1919 if (pwrctrl->cpwm > pslv)
1921 if ((pslv >= PS_STATE_S2) || (pwrctrl->alives == 0))
1922 rtw_set_rpwm(padapter, pslv);
1926 _exit_pwrlock(&pwrctrl->lock);
1934 * If all commands have been done,
1935 * and no more command to do,
1936 * then driver shall call this fun. to power down firmware again.
1938 void rtw_unregister_cmd_alive(PADAPTER padapter)
1940 struct pwrctrl_priv *pwrctrl;
1945 pwrctrl = adapter_to_pwrctl(padapter);
1948 #ifdef CONFIG_BT_COEXIST
1949 if ((rtw_btcoex_IsBtDisabled(padapter) == _FALSE)
1950 && (rtw_btcoex_IsBtControlLps(padapter) == _TRUE))
1954 val8 = rtw_btcoex_LpsVal(padapter);
1959 #endif // CONFIG_BT_COEXIST
1961 #ifdef CONFIG_P2P_PS
1962 if(padapter->wdinfo.p2p_ps_mode > P2P_PS_NONE)
1966 #ifdef CONFIG_CONCURRENT_MODE
1967 else if(rtw_buddy_adapter_up(padapter))
1969 if(padapter->pbuddy_adapter->wdinfo.p2p_ps_mode > P2P_PS_NONE)
1975 _enter_pwrlock(&pwrctrl->lock);
1977 unregister_task_alive(pwrctrl, CMD_ALIVE);
1979 if ((pwrctrl->pwr_mode != PS_MODE_ACTIVE)
1980 && (pwrctrl->bFwCurrentInPSMode == _TRUE))
1982 RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_info_,
1983 ("%s: cpwm=0x%02x alives=0x%08x\n",
1984 __FUNCTION__, pwrctrl->cpwm, pwrctrl->alives));
1986 if (pwrctrl->cpwm > pslv)
1988 if ((pslv >= PS_STATE_S2) || (pwrctrl->alives == 0))
1989 rtw_set_rpwm(padapter, pslv);
1993 _exit_pwrlock(&pwrctrl->lock);
2001 void rtw_unregister_rx_alive(PADAPTER padapter)
2003 struct pwrctrl_priv *pwrctrl;
2007 pwrctrl = adapter_to_pwrctl(padapter);
2009 _enter_pwrlock(&pwrctrl->lock);
2011 unregister_task_alive(pwrctrl, RECV_ALIVE);
2013 RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_notice_,
2014 ("rtw_unregister_rx_alive: cpwm=0x%02x alives=0x%08x\n",
2015 pwrctrl->cpwm, pwrctrl->alives));
2017 _exit_pwrlock(&pwrctrl->lock);
2022 void rtw_unregister_evt_alive(PADAPTER padapter)
2024 struct pwrctrl_priv *pwrctrl;
2028 pwrctrl = adapter_to_pwrctl(padapter);
2030 unregister_task_alive(pwrctrl, EVT_ALIVE);
2032 RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_notice_,
2033 ("rtw_unregister_evt_alive: cpwm=0x%02x alives=0x%08x\n",
2034 pwrctrl->cpwm, pwrctrl->alives));
2036 _exit_pwrlock(&pwrctrl->lock);
2040 #endif /* CONFIG_LPS_LCLK */
2042 #ifdef CONFIG_RESUME_IN_WORKQUEUE
2043 static void resume_workitem_callback(struct work_struct *work);
2044 #endif //CONFIG_RESUME_IN_WORKQUEUE
2046 void rtw_init_pwrctrl_priv(PADAPTER padapter)
2048 struct pwrctrl_priv *pwrctrlpriv = adapter_to_pwrctl(padapter);
2052 #if defined(CONFIG_CONCURRENT_MODE)
2053 if (padapter->adapter_type != PRIMARY_ADAPTER)
2059 #ifdef PLATFORM_WINDOWS
2060 pwrctrlpriv->pnp_current_pwr_state=NdisDeviceStateD0;
2063 _init_pwrlock(&pwrctrlpriv->lock);
2064 _init_pwrlock(&pwrctrlpriv->check_32k_lock);
2065 pwrctrlpriv->rf_pwrstate = rf_on;
2066 pwrctrlpriv->ips_enter_cnts=0;
2067 pwrctrlpriv->ips_leave_cnts=0;
2068 pwrctrlpriv->lps_enter_cnts=0;
2069 pwrctrlpriv->lps_leave_cnts=0;
2070 pwrctrlpriv->bips_processing = _FALSE;
2072 pwrctrlpriv->ips_mode = padapter->registrypriv.ips_mode;
2073 pwrctrlpriv->ips_mode_req = padapter->registrypriv.ips_mode;
2075 pwrctrlpriv->pwr_state_check_interval = RTW_PWR_STATE_CHK_INTERVAL;
2076 pwrctrlpriv->pwr_state_check_cnts = 0;
2077 pwrctrlpriv->bInternalAutoSuspend = _FALSE;
2078 pwrctrlpriv->bInSuspend = _FALSE;
2079 pwrctrlpriv->bkeepfwalive = _FALSE;
2081 #ifdef CONFIG_AUTOSUSPEND
2082 #ifdef SUPPORT_HW_RFOFF_DETECTED
2083 pwrctrlpriv->pwr_state_check_interval = (pwrctrlpriv->bHWPwrPindetect) ?1000:2000;
2087 pwrctrlpriv->LpsIdleCount = 0;
2088 //pwrctrlpriv->FWCtrlPSMode =padapter->registrypriv.power_mgnt;// PS_MODE_MIN;
2089 pwrctrlpriv->power_mgnt =padapter->registrypriv.power_mgnt;// PS_MODE_MIN;
2090 pwrctrlpriv->bLeisurePs = (PS_MODE_ACTIVE != pwrctrlpriv->power_mgnt)?_TRUE:_FALSE;
2092 pwrctrlpriv->bFwCurrentInPSMode = _FALSE;
2094 pwrctrlpriv->rpwm = 0;
2095 pwrctrlpriv->cpwm = PS_STATE_S4;
2097 pwrctrlpriv->pwr_mode = PS_MODE_ACTIVE;
2098 pwrctrlpriv->smart_ps = padapter->registrypriv.smart_ps;
2099 pwrctrlpriv->bcn_ant_mode = 0;
2100 pwrctrlpriv->dtim = 0;
2102 pwrctrlpriv->tog = 0x80;
2104 #ifdef CONFIG_LPS_LCLK
2105 rtw_hal_set_hwreg(padapter, HW_VAR_SET_RPWM, (u8 *)(&pwrctrlpriv->rpwm));
2107 _init_workitem(&pwrctrlpriv->cpwm_event, cpwm_event_callback, NULL);
2109 #ifdef CONFIG_LPS_RPWM_TIMER
2110 pwrctrlpriv->brpwmtimeout = _FALSE;
2111 _init_workitem(&pwrctrlpriv->rpwmtimeoutwi, rpwmtimeout_workitem_callback, NULL);
2112 _init_timer(&pwrctrlpriv->pwr_rpwm_timer, padapter->pnetdev, pwr_rpwm_timeout_handler, padapter);
2113 #endif // CONFIG_LPS_RPWM_TIMER
2114 #endif // CONFIG_LPS_LCLK
2116 rtw_init_timer(&pwrctrlpriv->pwr_state_check_timer, padapter, pwr_state_check_handler);
2118 pwrctrlpriv->wowlan_mode = _FALSE;
2119 pwrctrlpriv->wowlan_ap_mode = _FALSE;
2120 pwrctrlpriv->wowlan_p2p_mode = _FALSE;
2122 #ifdef CONFIG_RESUME_IN_WORKQUEUE
2123 _init_workitem(&pwrctrlpriv->resume_work, resume_workitem_callback, NULL);
2124 pwrctrlpriv->rtw_workqueue = create_singlethread_workqueue("rtw_workqueue");
2125 #endif //CONFIG_RESUME_IN_WORKQUEUE
2127 #if defined(CONFIG_HAS_EARLYSUSPEND) || defined(CONFIG_ANDROID_POWER)
2128 pwrctrlpriv->early_suspend.suspend = NULL;
2129 rtw_register_early_suspend(pwrctrlpriv);
2130 #endif //CONFIG_HAS_EARLYSUSPEND || CONFIG_ANDROID_POWER
2137 void rtw_free_pwrctrl_priv(PADAPTER adapter)
2139 struct pwrctrl_priv *pwrctrlpriv = adapter_to_pwrctl(adapter);
2141 #if defined(CONFIG_CONCURRENT_MODE)
2142 if (adapter->adapter_type != PRIMARY_ADAPTER)
2148 //_rtw_memset((unsigned char *)pwrctrlpriv, 0, sizeof(struct pwrctrl_priv));
2151 #ifdef CONFIG_RESUME_IN_WORKQUEUE
2152 if (pwrctrlpriv->rtw_workqueue) {
2153 flush_workqueue(pwrctrlpriv->rtw_workqueue);
2154 destroy_workqueue(pwrctrlpriv->rtw_workqueue);
2158 #if defined(CONFIG_HAS_EARLYSUSPEND) || defined(CONFIG_ANDROID_POWER)
2159 rtw_unregister_early_suspend(pwrctrlpriv);
2160 #endif //CONFIG_HAS_EARLYSUSPEND || CONFIG_ANDROID_POWER
2162 _free_pwrlock(&pwrctrlpriv->lock);
2163 _free_pwrlock(&pwrctrlpriv->check_32k_lock);
2168 #ifdef CONFIG_RESUME_IN_WORKQUEUE
2169 extern int rtw_resume_process(_adapter *padapter);
2171 static void resume_workitem_callback(struct work_struct *work)
2173 struct pwrctrl_priv *pwrpriv = container_of(work, struct pwrctrl_priv, resume_work);
2174 struct dvobj_priv *dvobj = pwrctl_to_dvobj(pwrpriv);
2175 _adapter *adapter = dvobj->padapters[IFACE_ID0];
2177 DBG_871X("%s\n",__FUNCTION__);
2179 rtw_resume_process(adapter);
2181 rtw_resume_unlock_suspend();
2184 void rtw_resume_in_workqueue(struct pwrctrl_priv *pwrpriv)
2186 // accquire system's suspend lock preventing from falliing asleep while resume in workqueue
2187 //rtw_lock_suspend();
2189 rtw_resume_lock_suspend();
2192 queue_work(pwrpriv->rtw_workqueue, &pwrpriv->resume_work);
2194 _set_workitem(&pwrpriv->resume_work);
2197 #endif //CONFIG_RESUME_IN_WORKQUEUE
2199 #if defined(CONFIG_HAS_EARLYSUSPEND) || defined(CONFIG_ANDROID_POWER)
2200 inline bool rtw_is_earlysuspend_registered(struct pwrctrl_priv *pwrpriv)
2202 return (pwrpriv->early_suspend.suspend) ? _TRUE : _FALSE;
2205 inline bool rtw_is_do_late_resume(struct pwrctrl_priv *pwrpriv)
2207 return (pwrpriv->do_late_resume) ? _TRUE : _FALSE;
2210 inline void rtw_set_do_late_resume(struct pwrctrl_priv *pwrpriv, bool enable)
2212 pwrpriv->do_late_resume = enable;
2216 #ifdef CONFIG_HAS_EARLYSUSPEND
2217 extern int rtw_resume_process(_adapter *padapter);
2218 static void rtw_early_suspend(struct early_suspend *h)
2220 struct pwrctrl_priv *pwrpriv = container_of(h, struct pwrctrl_priv, early_suspend);
2221 DBG_871X("%s\n",__FUNCTION__);
2223 rtw_set_do_late_resume(pwrpriv, _FALSE);
2226 static void rtw_late_resume(struct early_suspend *h)
2228 struct pwrctrl_priv *pwrpriv = container_of(h, struct pwrctrl_priv, early_suspend);
2229 struct dvobj_priv *dvobj = pwrctl_to_dvobj(pwrpriv);
2230 _adapter *adapter = dvobj->padapters[IFACE_ID0];
2232 DBG_871X("%s\n",__FUNCTION__);
2234 if(pwrpriv->do_late_resume) {
2235 rtw_set_do_late_resume(pwrpriv, _FALSE);
2236 rtw_resume_process(adapter);
2240 void rtw_register_early_suspend(struct pwrctrl_priv *pwrpriv)
2242 DBG_871X("%s\n", __FUNCTION__);
2244 //jeff: set the early suspend level before blank screen, so we wll do late resume after scree is lit
2245 pwrpriv->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN - 20;
2246 pwrpriv->early_suspend.suspend = rtw_early_suspend;
2247 pwrpriv->early_suspend.resume = rtw_late_resume;
2248 register_early_suspend(&pwrpriv->early_suspend);
2253 void rtw_unregister_early_suspend(struct pwrctrl_priv *pwrpriv)
2255 DBG_871X("%s\n", __FUNCTION__);
2257 rtw_set_do_late_resume(pwrpriv, _FALSE);
2259 if (pwrpriv->early_suspend.suspend)
2260 unregister_early_suspend(&pwrpriv->early_suspend);
2262 pwrpriv->early_suspend.suspend = NULL;
2263 pwrpriv->early_suspend.resume = NULL;
2265 #endif //CONFIG_HAS_EARLYSUSPEND
2267 #ifdef CONFIG_ANDROID_POWER
2268 #if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) || defined(CONFIG_GSPI_HCI)
2269 extern int rtw_resume_process(PADAPTER padapter);
2271 static void rtw_early_suspend(android_early_suspend_t *h)
2273 struct pwrctrl_priv *pwrpriv = container_of(h, struct pwrctrl_priv, early_suspend);
2274 DBG_871X("%s\n",__FUNCTION__);
2276 rtw_set_do_late_resume(pwrpriv, _FALSE);
2279 static void rtw_late_resume(android_early_suspend_t *h)
2281 struct pwrctrl_priv *pwrpriv = container_of(h, struct pwrctrl_priv, early_suspend);
2282 struct dvobj_priv *dvobj = pwrctl_to_dvobj(pwrpriv);
2283 _adapter *adapter = dvobj->padapters[IFACE_ID0];
2285 DBG_871X("%s\n",__FUNCTION__);
2286 if(pwrpriv->do_late_resume) {
2287 #if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) || defined(CONFIG_GSPI_HCI)
2288 rtw_set_do_late_resume(pwrpriv, _FALSE);
2289 rtw_resume_process(adapter);
2294 void rtw_register_early_suspend(struct pwrctrl_priv *pwrpriv)
2296 DBG_871X("%s\n", __FUNCTION__);
2298 //jeff: set the early suspend level before blank screen, so we wll do late resume after scree is lit
2299 pwrpriv->early_suspend.level = ANDROID_EARLY_SUSPEND_LEVEL_BLANK_SCREEN - 20;
2300 pwrpriv->early_suspend.suspend = rtw_early_suspend;
2301 pwrpriv->early_suspend.resume = rtw_late_resume;
2302 android_register_early_suspend(&pwrpriv->early_suspend);
2305 void rtw_unregister_early_suspend(struct pwrctrl_priv *pwrpriv)
2307 DBG_871X("%s\n", __FUNCTION__);
2309 rtw_set_do_late_resume(pwrpriv, _FALSE);
2311 if (pwrpriv->early_suspend.suspend)
2312 android_unregister_early_suspend(&pwrpriv->early_suspend);
2314 pwrpriv->early_suspend.suspend = NULL;
2315 pwrpriv->early_suspend.resume = NULL;
2317 #endif //CONFIG_ANDROID_POWER
2319 u8 rtw_interface_ps_func(_adapter *padapter,HAL_INTF_PS_FUNC efunc_id,u8* val)
2322 rtw_hal_intf_ps_func(padapter,efunc_id,val);
2328 inline void rtw_set_ips_deny(_adapter *padapter, u32 ms)
2330 struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
2331 pwrpriv->ips_deny_time = rtw_get_current_time() + rtw_ms_to_systime(ms);
2335 * rtw_pwr_wakeup - Wake the NIC up from: 1)IPS. 2)USB autosuspend
2336 * @adapter: pointer to _adapter structure
2337 * @ips_deffer_ms: the ms wiil prevent from falling into IPS after wakeup
2338 * Return _SUCCESS or _FAIL
2341 int _rtw_pwr_wakeup(_adapter *padapter, u32 ips_deffer_ms, const char *caller)
2343 struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
2344 struct pwrctrl_priv *pwrpriv = dvobj_to_pwrctl(dvobj);
2345 struct mlme_priv *pmlmepriv;
2348 u32 start = rtw_get_current_time();
2351 LeaveAllPowerSaveMode(padapter);
2353 /* IPS still bound with primary adapter */
2354 padapter = GET_PRIMARY_ADAPTER(padapter);
2355 pmlmepriv = &padapter->mlmepriv;
2357 if (pwrpriv->ips_deny_time < rtw_get_current_time() + rtw_ms_to_systime(ips_deffer_ms))
2358 pwrpriv->ips_deny_time = rtw_get_current_time() + rtw_ms_to_systime(ips_deffer_ms);
2361 if (pwrpriv->ps_processing) {
2362 DBG_871X("%s wait ps_processing...\n", __func__);
2363 while (pwrpriv->ps_processing && rtw_get_passing_time_ms(start) <= 3000)
2365 if (pwrpriv->ps_processing)
2366 DBG_871X("%s wait ps_processing timeout\n", __func__);
2368 DBG_871X("%s wait ps_processing done\n", __func__);
2371 #ifdef DBG_CONFIG_ERROR_DETECT
2372 if (rtw_hal_sreset_inprogress(padapter)) {
2373 DBG_871X("%s wait sreset_inprogress...\n", __func__);
2374 while (rtw_hal_sreset_inprogress(padapter) && rtw_get_passing_time_ms(start) <= 4000)
2376 if (rtw_hal_sreset_inprogress(padapter))
2377 DBG_871X("%s wait sreset_inprogress timeout\n", __func__);
2379 DBG_871X("%s wait sreset_inprogress done\n", __func__);
2383 if (pwrpriv->bInternalAutoSuspend == _FALSE && pwrpriv->bInSuspend) {
2384 DBG_871X("%s wait bInSuspend...\n", __func__);
2385 while (pwrpriv->bInSuspend
2386 && ((rtw_get_passing_time_ms(start) <= 3000 && !rtw_is_do_late_resume(pwrpriv))
2387 || (rtw_get_passing_time_ms(start) <= 500 && rtw_is_do_late_resume(pwrpriv)))
2391 if (pwrpriv->bInSuspend)
2392 DBG_871X("%s wait bInSuspend timeout\n", __func__);
2394 DBG_871X("%s wait bInSuspend done\n", __func__);
2397 //System suspend is not allowed to wakeup
2398 if((pwrpriv->bInternalAutoSuspend == _FALSE) && (_TRUE == pwrpriv->bInSuspend )){
2404 if((pwrpriv->bInternalAutoSuspend == _TRUE) && (padapter->net_closed == _TRUE)) {
2409 //I think this should be check in IPS, LPS, autosuspend functions...
2410 if (check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE)
2412 #if defined (CONFIG_BT_COEXIST)&& defined (CONFIG_AUTOSUSPEND)
2413 if(_TRUE==pwrpriv->bInternalAutoSuspend){
2414 if(0==pwrpriv->autopm_cnt){
2415 #if (LINUX_VERSION_CODE>=KERNEL_VERSION(2,6,33))
2416 if (usb_autopm_get_interface(adapter_to_dvobj(padapter)->pusbintf) < 0)
2418 DBG_871X( "can't get autopm: \n");
2420 #elif (LINUX_VERSION_CODE>=KERNEL_VERSION(2,6,20))
2421 usb_autopm_disable(adapter_to_dvobj(padapter)->pusbintf);
2423 usb_autoresume_device(adapter_to_dvobj(padapter)->pusbdev, 1);
2425 pwrpriv->autopm_cnt++;
2427 #endif //#if defined (CONFIG_BT_COEXIST)&& defined (CONFIG_AUTOSUSPEND)
2430 #if defined (CONFIG_BT_COEXIST)&& defined (CONFIG_AUTOSUSPEND)
2432 #endif //#if defined (CONFIG_BT_COEXIST)&& defined (CONFIG_AUTOSUSPEND)
2435 if(rf_off == pwrpriv->rf_pwrstate )
2437 #ifdef CONFIG_USB_HCI
2438 #ifdef CONFIG_AUTOSUSPEND
2439 if(pwrpriv->brfoffbyhw==_TRUE)
2441 DBG_8192C("hw still in rf_off state ...........\n");
2445 else if(padapter->registrypriv.usbss_enable)
2447 DBG_8192C("%s call autoresume_enter....\n",__FUNCTION__);
2448 if(_FAIL == autoresume_enter(padapter))
2450 DBG_8192C("======> autoresume fail.............\n");
2460 DBG_8192C("%s call ips_leave....\n",__FUNCTION__);
2461 if(_FAIL == ips_leave(padapter))
2463 DBG_8192C("======> ips_leave fail.............\n");
2471 //TODO: the following checking need to be merged...
2472 if (rtw_is_drv_stopped(padapter)
2474 || !rtw_is_hw_init_completed(padapter)
2476 DBG_8192C("%s: bDriverStopped=%s, bup=%d, hw_init_completed=%u\n"
2478 , rtw_is_drv_stopped(padapter)?"True":"False"
2480 , rtw_get_hw_init_completed(padapter));
2486 if (pwrpriv->ips_deny_time < rtw_get_current_time() + rtw_ms_to_systime(ips_deffer_ms))
2487 pwrpriv->ips_deny_time = rtw_get_current_time() + rtw_ms_to_systime(ips_deffer_ms);
2492 int rtw_pm_set_lps(_adapter *padapter, u8 mode)
2495 struct pwrctrl_priv *pwrctrlpriv = adapter_to_pwrctl(padapter);
2497 if ( mode < PS_MODE_NUM )
2499 if(pwrctrlpriv->power_mgnt !=mode)
2501 if(PS_MODE_ACTIVE == mode)
2503 LeaveAllPowerSaveMode(padapter);
2507 pwrctrlpriv->LpsIdleCount = 2;
2509 pwrctrlpriv->power_mgnt = mode;
2510 pwrctrlpriv->bLeisurePs = (PS_MODE_ACTIVE != pwrctrlpriv->power_mgnt)?_TRUE:_FALSE;
2521 int rtw_pm_set_ips(_adapter *padapter, u8 mode)
2523 struct pwrctrl_priv *pwrctrlpriv = adapter_to_pwrctl(padapter);
2525 if( mode == IPS_NORMAL || mode == IPS_LEVEL_2 ) {
2526 rtw_ips_mode_req(pwrctrlpriv, mode);
2527 DBG_871X("%s %s\n", __FUNCTION__, mode == IPS_NORMAL?"IPS_NORMAL":"IPS_LEVEL_2");
2530 else if(mode ==IPS_NONE){
2531 rtw_ips_mode_req(pwrctrlpriv, mode);
2532 DBG_871X("%s %s\n", __FUNCTION__, "IPS_NONE");
2533 if (!rtw_is_surprise_removed(padapter) && (_FAIL == rtw_pwr_wakeup(padapter)))
2544 * This function will request pwrctrl LOCK!
2546 void rtw_ps_deny(PADAPTER padapter, PS_DENY_REASON reason)
2548 struct pwrctrl_priv *pwrpriv;
2552 // DBG_871X("+" FUNC_ADPT_FMT ": Request PS deny for %d (0x%08X)\n",
2553 // FUNC_ADPT_ARG(padapter), reason, BIT(reason));
2555 pwrpriv = adapter_to_pwrctl(padapter);
2557 _enter_pwrlock(&pwrpriv->lock);
2558 if (pwrpriv->ps_deny & BIT(reason))
2560 DBG_871X(FUNC_ADPT_FMT ": [WARNING] Reason %d had been set before!!\n",
2561 FUNC_ADPT_ARG(padapter), reason);
2563 pwrpriv->ps_deny |= BIT(reason);
2564 _exit_pwrlock(&pwrpriv->lock);
2566 // DBG_871X("-" FUNC_ADPT_FMT ": Now PS deny for 0x%08X\n",
2567 // FUNC_ADPT_ARG(padapter), pwrpriv->ps_deny);
2572 * This function will request pwrctrl LOCK!
2574 void rtw_ps_deny_cancel(PADAPTER padapter, PS_DENY_REASON reason)
2576 struct pwrctrl_priv *pwrpriv;
2579 // DBG_871X("+" FUNC_ADPT_FMT ": Cancel PS deny for %d(0x%08X)\n",
2580 // FUNC_ADPT_ARG(padapter), reason, BIT(reason));
2582 pwrpriv = adapter_to_pwrctl(padapter);
2584 _enter_pwrlock(&pwrpriv->lock);
2585 if ((pwrpriv->ps_deny & BIT(reason)) == 0)
2587 DBG_871X(FUNC_ADPT_FMT ": [ERROR] Reason %d had been canceled before!!\n",
2588 FUNC_ADPT_ARG(padapter), reason);
2590 pwrpriv->ps_deny &= ~BIT(reason);
2591 _exit_pwrlock(&pwrpriv->lock);
2593 // DBG_871X("-" FUNC_ADPT_FMT ": Now PS deny for 0x%08X\n",
2594 // FUNC_ADPT_ARG(padapter), pwrpriv->ps_deny);
2599 * Before calling this function pwrctrl lock should be occupied already,
2600 * otherwise it may return incorrect value.
2602 u32 rtw_ps_deny_get(PADAPTER padapter)
2607 deny = adapter_to_pwrctl(padapter)->ps_deny;