WiFi: add rtl8189es/etv support, Optimization wifi configuration.
[firefly-linux-kernel-4.4.55.git] / drivers / net / wireless / rockchip_wlan / rtl8189es / core / rtw_pwrctrl.c
1 /******************************************************************************
2  *
3  * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
4  *                                        
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.
8  *
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
12  * more details.
13  *
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
17  *
18  *
19  ******************************************************************************/
20 #define _RTW_PWRCTRL_C_
21
22 #include <drv_types.h>
23
24
25 int rtw_fw_ps_state(PADAPTER padapter)
26 {
27         struct dvobj_priv *psdpriv = padapter->dvobj;
28         struct debug_priv *pdbgpriv = &psdpriv->drv_dbg;
29         int ret=_FAIL, dont_care=0;
30         u16 fw_ps_state=0;
31         u32 start_time;
32         struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
33         struct registry_priv  *registry_par = &padapter->registrypriv;
34         
35         if(registry_par->check_fw_ps != 1)
36                 return _SUCCESS;
37         
38         _enter_pwrlock(&pwrpriv->check_32k_lock);
39         
40         if ((padapter->bSurpriseRemoved == _TRUE))
41         {
42                 DBG_871X("%s: bSurpriseRemoved=%d , hw_init_completed=%d, bDriverStopped=%d \n", __FUNCTION__, padapter->bSurpriseRemoved,
43                 padapter->hw_init_completed,padapter->bDriverStopped);
44                 goto exit_fw_ps_state;
45         }
46         rtw_hal_set_hwreg(padapter, HW_VAR_SET_REQ_FW_PS, (u8 *)&dont_care);
47         {
48                 //4. if 0x88[7]=1, driver set cmd to leave LPS/IPS. 
49                 //Else, hw will keep in active mode.
50                 //debug info:
51                 //0x88[7] = 32kpermission, 
52                 //0x88[6:0] = current_ps_state
53                 //0x89[7:0] = last_rpwm
54
55                 rtw_hal_get_hwreg(padapter, HW_VAR_FW_PS_STATE, (u8 *)&fw_ps_state);
56                 
57                 if((fw_ps_state & 0x80) == 0)
58                         ret=_SUCCESS;
59                 else
60                 {
61                         pdbgpriv->dbg_poll_fail_cnt++;
62                         DBG_871X("%s: fw_ps_state=%04x \n", __FUNCTION__, fw_ps_state);
63                 }
64         }
65
66
67 exit_fw_ps_state:
68         _exit_pwrlock(&pwrpriv->check_32k_lock);
69         return ret;
70 }
71
72 #ifdef CONFIG_IPS
73 void _ips_enter(_adapter * padapter)
74 {
75         struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
76
77         pwrpriv->bips_processing = _TRUE;       
78
79         // syn ips_mode with request
80         pwrpriv->ips_mode = pwrpriv->ips_mode_req;
81         
82         pwrpriv->ips_enter_cnts++;      
83         DBG_871X("==>ips_enter cnts:%d\n",pwrpriv->ips_enter_cnts);
84
85         if(rf_off == pwrpriv->change_rfpwrstate )
86         {       
87                 pwrpriv->bpower_saving = _TRUE;
88                 DBG_871X_LEVEL(_drv_always_, "nolinked power save enter\n");
89
90                 if(pwrpriv->ips_mode == IPS_LEVEL_2)
91                         pwrpriv->bkeepfwalive = _TRUE;
92                 
93                 rtw_ips_pwr_down(padapter);
94                 pwrpriv->rf_pwrstate = rf_off;
95         }       
96         pwrpriv->bips_processing = _FALSE;      
97         
98 }
99
100 void ips_enter(_adapter * padapter)
101 {
102         struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
103
104
105 #ifdef CONFIG_BT_COEXIST
106         rtw_btcoex_IpsNotify(padapter, pwrpriv->ips_mode_req);
107 #endif // CONFIG_BT_COEXIST
108
109         _enter_pwrlock(&pwrpriv->lock);
110         _ips_enter(padapter);
111         _exit_pwrlock(&pwrpriv->lock);
112 }
113
114 int _ips_leave(_adapter * padapter)
115 {
116         struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
117         int result = _SUCCESS;
118
119         if((pwrpriv->rf_pwrstate == rf_off) &&(!pwrpriv->bips_processing))
120         {
121                 pwrpriv->bips_processing = _TRUE;
122                 pwrpriv->change_rfpwrstate = rf_on;
123                 pwrpriv->ips_leave_cnts++;
124                 DBG_871X("==>ips_leave cnts:%d\n",pwrpriv->ips_leave_cnts);
125
126                 if ((result = rtw_ips_pwr_up(padapter)) == _SUCCESS) {
127                         pwrpriv->rf_pwrstate = rf_on;
128                 }
129                 DBG_871X_LEVEL(_drv_always_, "nolinked power save leave\n");
130                 
131                 DBG_871X("==> ips_leave.....LED(0x%08x)...\n",rtw_read32(padapter,0x4c));
132                 pwrpriv->bips_processing = _FALSE;
133
134                 pwrpriv->bkeepfwalive = _FALSE;
135                 pwrpriv->bpower_saving = _FALSE;
136         }
137
138         return result;
139 }
140
141 int ips_leave(_adapter * padapter)
142 {
143         struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
144         struct dvobj_priv *psdpriv = padapter->dvobj;
145         struct debug_priv *pdbgpriv = &psdpriv->drv_dbg;
146         int ret;
147
148         if(!is_primary_adapter(padapter))
149                 return _SUCCESS;
150
151         _enter_pwrlock(&pwrpriv->lock);
152         ret = _ips_leave(padapter);
153 #ifdef DBG_CHECK_FW_PS_STATE
154         if(rtw_fw_ps_state(padapter) == _FAIL)
155         {
156                 DBG_871X("ips leave doesn't leave 32k\n");
157                 pdbgpriv->dbg_leave_ips_fail_cnt++;
158         }
159 #endif //DBG_CHECK_FW_PS_STATE
160         _exit_pwrlock(&pwrpriv->lock);
161
162 #ifdef CONFIG_BT_COEXIST
163         if (_SUCCESS == ret)
164                 rtw_btcoex_IpsNotify(padapter, IPS_NONE);
165 #endif // CONFIG_BT_COEXIST
166
167         return ret;
168 }
169 #endif /* CONFIG_IPS */
170
171 #ifdef CONFIG_AUTOSUSPEND
172 extern void autosuspend_enter(_adapter* padapter);      
173 extern int autoresume_enter(_adapter* padapter);
174 #endif
175
176 #ifdef SUPPORT_HW_RFOFF_DETECTED
177 int rtw_hw_suspend(_adapter *padapter );
178 int rtw_hw_resume(_adapter *padapter);
179 #endif
180
181 bool rtw_pwr_unassociated_idle(_adapter *adapter)
182 {
183         _adapter *buddy = adapter->pbuddy_adapter;
184         struct mlme_priv *pmlmepriv = &(adapter->mlmepriv);
185         struct xmit_priv *pxmit_priv = &adapter->xmitpriv;
186 #ifdef CONFIG_P2P
187         struct wifidirect_info  *pwdinfo = &(adapter->wdinfo);
188 #ifdef CONFIG_IOCTL_CFG80211
189         struct cfg80211_wifidirect_info *pcfg80211_wdinfo = &adapter->cfg80211_wdinfo;
190 #endif
191 #endif
192
193         bool ret = _FALSE;
194
195         if (adapter_to_pwrctl(adapter)->bpower_saving ==_TRUE ) {
196                 //DBG_871X("%s: already in LPS or IPS mode\n", __func__);
197                 goto exit;
198         }
199
200         if (adapter_to_pwrctl(adapter)->ips_deny_time >= rtw_get_current_time()) {
201                 //DBG_871X("%s ips_deny_time\n", __func__);
202                 goto exit;
203         }
204
205         if (check_fwstate(pmlmepriv, WIFI_ASOC_STATE|WIFI_SITE_MONITOR)
206                 || check_fwstate(pmlmepriv, WIFI_UNDER_LINKING|WIFI_UNDER_WPS)
207                 || check_fwstate(pmlmepriv, WIFI_AP_STATE)
208                 || check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE|WIFI_ADHOC_STATE)
209                 #if defined(CONFIG_P2P) && defined(CONFIG_IOCTL_CFG80211) && defined(CONFIG_P2P_IPS)
210                 || pcfg80211_wdinfo->is_ro_ch
211                 #elif defined(CONFIG_P2P)
212                 || !rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)
213                 #endif
214                 #if defined(CONFIG_P2P) && defined(CONFIG_IOCTL_CFG80211)
215                 || rtw_get_passing_time_ms(pcfg80211_wdinfo->last_ro_ch_time) < 3000
216                 #endif
217         ) {
218                 goto exit;
219         }
220
221         /* consider buddy, if exist */
222         if (buddy) {
223                 struct mlme_priv *b_pmlmepriv = &(buddy->mlmepriv);
224                 #ifdef CONFIG_P2P
225                 struct wifidirect_info *b_pwdinfo = &(buddy->wdinfo);
226                 #ifdef CONFIG_IOCTL_CFG80211
227                 struct cfg80211_wifidirect_info *b_pcfg80211_wdinfo = &buddy->cfg80211_wdinfo;
228                 #endif
229                 #endif
230
231                 if (check_fwstate(b_pmlmepriv, WIFI_ASOC_STATE|WIFI_SITE_MONITOR)
232                         || check_fwstate(b_pmlmepriv, WIFI_UNDER_LINKING|WIFI_UNDER_WPS)
233                         || check_fwstate(b_pmlmepriv, WIFI_AP_STATE)
234                         || check_fwstate(b_pmlmepriv, WIFI_ADHOC_MASTER_STATE|WIFI_ADHOC_STATE)
235                         #if defined(CONFIG_P2P) && defined(CONFIG_IOCTL_CFG80211) && defined(CONFIG_P2P_IPS)
236                         || b_pcfg80211_wdinfo->is_ro_ch
237                         #elif defined(CONFIG_P2P)
238                         || !rtw_p2p_chk_state(b_pwdinfo, P2P_STATE_NONE)
239                         #endif
240                         #if defined(CONFIG_P2P) && defined(CONFIG_IOCTL_CFG80211)
241                         || rtw_get_passing_time_ms(b_pcfg80211_wdinfo->last_ro_ch_time) < 3000
242                         #endif
243                 ) {
244                         goto exit;
245                 }
246         }
247
248 #if (MP_DRIVER == 1)
249         if (adapter->registrypriv.mp_mode == 1)
250                 goto exit;
251 #endif
252
253 #ifdef CONFIG_INTEL_PROXIM
254         if(adapter->proximity.proxim_on==_TRUE){
255                 return;
256         }
257 #endif
258
259         if (pxmit_priv->free_xmitbuf_cnt != NR_XMITBUFF ||
260                 pxmit_priv->free_xmit_extbuf_cnt != NR_XMIT_EXTBUFF) {
261                 DBG_871X_LEVEL(_drv_always_, "There are some pkts to transmit\n");
262                 DBG_871X_LEVEL(_drv_always_, "free_xmitbuf_cnt: %d, free_xmit_extbuf_cnt: %d\n", 
263                         pxmit_priv->free_xmitbuf_cnt, pxmit_priv->free_xmit_extbuf_cnt);        
264                 goto exit;
265         }
266
267         ret = _TRUE;
268
269 exit:
270         return ret;
271 }
272
273
274 /*
275  * ATTENTION:
276  *      rtw_ps_processor() doesn't handle LPS.
277  */
278 void rtw_ps_processor(_adapter*padapter)
279 {
280 #ifdef CONFIG_P2P
281         struct wifidirect_info  *pwdinfo = &( padapter->wdinfo );
282 #endif //CONFIG_P2P
283         struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
284         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
285         struct dvobj_priv *psdpriv = padapter->dvobj;
286         struct debug_priv *pdbgpriv = &psdpriv->drv_dbg;
287 #ifdef SUPPORT_HW_RFOFF_DETECTED
288         rt_rf_power_state rfpwrstate;
289 #endif //SUPPORT_HW_RFOFF_DETECTED
290         u32 ps_deny = 0;
291
292         _enter_pwrlock(&adapter_to_pwrctl(padapter)->lock);
293         ps_deny = rtw_ps_deny_get(padapter);
294         _exit_pwrlock(&adapter_to_pwrctl(padapter)->lock);
295         if (ps_deny != 0)
296         {
297                 DBG_871X(FUNC_ADPT_FMT ": ps_deny=0x%08X, skip power save!\n",
298                         FUNC_ADPT_ARG(padapter), ps_deny);
299                 goto exit;
300         }
301
302         if(pwrpriv->bInSuspend == _TRUE){//system suspend or autosuspend
303                 pdbgpriv->dbg_ps_insuspend_cnt++;
304                 DBG_871X("%s, pwrpriv->bInSuspend == _TRUE ignore this process\n",__FUNCTION__);
305                 return;
306         }       
307
308         pwrpriv->ps_processing = _TRUE;
309
310 #ifdef SUPPORT_HW_RFOFF_DETECTED
311         if(pwrpriv->bips_processing == _TRUE)
312                 goto exit;
313         
314         //DBG_871X("==> fw report state(0x%x)\n",rtw_read8(padapter,0x1ca));    
315         if(pwrpriv->bHWPwrPindetect) 
316         {
317         #ifdef CONFIG_AUTOSUSPEND
318                 if(padapter->registrypriv.usbss_enable)
319                 {
320                         if(pwrpriv->rf_pwrstate == rf_on)
321                         {
322                                 if(padapter->net_closed == _TRUE)
323                                         pwrpriv->ps_flag = _TRUE;
324
325                                 rfpwrstate = RfOnOffDetect(padapter);
326                                 DBG_871X("@@@@- #1  %s==> rfstate:%s \n",__FUNCTION__,(rfpwrstate==rf_on)?"rf_on":"rf_off");
327                                 if(rfpwrstate!= pwrpriv->rf_pwrstate)
328                                 {
329                                         if(rfpwrstate == rf_off)
330                                         {
331                                                 pwrpriv->change_rfpwrstate = rf_off;
332                                                 
333                                                 pwrpriv->bkeepfwalive = _TRUE;  
334                                                 pwrpriv->brfoffbyhw = _TRUE;                                            
335                                                 
336                                                 autosuspend_enter(padapter);                                                    
337                                         }
338                                 }
339                         }                       
340                 }
341                 else
342         #endif //CONFIG_AUTOSUSPEND
343                 {
344                         rfpwrstate = RfOnOffDetect(padapter);
345                         DBG_871X("@@@@- #2  %s==> rfstate:%s \n",__FUNCTION__,(rfpwrstate==rf_on)?"rf_on":"rf_off");
346
347                         if(rfpwrstate!= pwrpriv->rf_pwrstate)
348                         {
349                                 if(rfpwrstate == rf_off)
350                                 {       
351                                         pwrpriv->change_rfpwrstate = rf_off;                                                                                                            
352                                         pwrpriv->brfoffbyhw = _TRUE;
353                                         padapter->bCardDisableWOHSM = _TRUE;
354                                         rtw_hw_suspend(padapter );      
355                                 }
356                                 else
357                                 {
358                                         pwrpriv->change_rfpwrstate = rf_on;
359                                         rtw_hw_resume(padapter );                       
360                                 }
361                                 DBG_871X("current rf_pwrstate(%s)\n",(pwrpriv->rf_pwrstate == rf_off)?"rf_off":"rf_on");
362                         }
363                 }
364                 pwrpriv->pwr_state_check_cnts ++;       
365         }
366 #endif //SUPPORT_HW_RFOFF_DETECTED
367
368         if (pwrpriv->ips_mode_req == IPS_NONE)
369                 goto exit;
370
371         if (rtw_pwr_unassociated_idle(padapter) == _FALSE)
372                 goto exit;
373
374         if((pwrpriv->rf_pwrstate == rf_on) && ((pwrpriv->pwr_state_check_cnts%4)==0))
375         {
376                 DBG_871X("==>%s .fw_state(%x)\n",__FUNCTION__,get_fwstate(pmlmepriv));
377                 #if defined (CONFIG_BT_COEXIST)&& defined (CONFIG_AUTOSUSPEND)
378                 #else
379                 pwrpriv->change_rfpwrstate = rf_off;
380                 #endif
381                 #ifdef CONFIG_AUTOSUSPEND
382                 if(padapter->registrypriv.usbss_enable)
383                 {
384                         if(pwrpriv->bHWPwrPindetect) 
385                                 pwrpriv->bkeepfwalive = _TRUE;
386                         
387                         if(padapter->net_closed == _TRUE)
388                                 pwrpriv->ps_flag = _TRUE;
389
390                         #if defined (CONFIG_BT_COEXIST)&& defined (CONFIG_AUTOSUSPEND)
391                         if (_TRUE==pwrpriv->bInternalAutoSuspend) {
392                                 DBG_871X("<==%s .pwrpriv->bInternalAutoSuspend)(%x)\n",__FUNCTION__,pwrpriv->bInternalAutoSuspend);
393                         } else {
394                                 pwrpriv->change_rfpwrstate = rf_off;
395                                 padapter->bCardDisableWOHSM = _TRUE;
396                                 DBG_871X("<==%s .pwrpriv->bInternalAutoSuspend)(%x) call autosuspend_enter\n",__FUNCTION__,pwrpriv->bInternalAutoSuspend);
397                                 autosuspend_enter(padapter);
398                         }               
399                         #else
400                         padapter->bCardDisableWOHSM = _TRUE;
401                         autosuspend_enter(padapter);
402                         #endif  //if defined (CONFIG_BT_COEXIST)&& defined (CONFIG_AUTOSUSPEND)
403                 }               
404                 else if(pwrpriv->bHWPwrPindetect)
405                 {
406                 }
407                 else
408                 #endif //CONFIG_AUTOSUSPEND
409                 {
410                         #if defined (CONFIG_BT_COEXIST)&& defined (CONFIG_AUTOSUSPEND)
411                         pwrpriv->change_rfpwrstate = rf_off;
412                         #endif  //defined (CONFIG_BT_COEXIST)&& defined (CONFIG_AUTOSUSPEND)
413
414                         #ifdef CONFIG_IPS
415                         ips_enter(padapter);                    
416                         #endif
417                 }
418         }
419 exit:
420 #ifndef CONFIG_IPS_CHECK_IN_WD
421         rtw_set_pwr_state_check_timer(pwrpriv);
422 #endif
423         pwrpriv->ps_processing = _FALSE;
424         return;
425 }
426
427 void pwr_state_check_handler(RTW_TIMER_HDL_ARGS);
428 void pwr_state_check_handler(RTW_TIMER_HDL_ARGS)
429 {
430         _adapter *padapter = (_adapter *)FunctionContext;
431         rtw_ps_cmd(padapter);
432 }
433
434 #ifdef CONFIG_LPS
435 void    traffic_check_for_leave_lps(PADAPTER padapter, u8 tx, u32 tx_packets)
436 {
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;
442
443         
444
445         if(tx) //from tx
446         {
447                 xmit_cnt += tx_packets;
448
449                 if (start_time== 0)
450                         start_time= rtw_get_current_time();
451
452                 if (rtw_get_passing_time_ms(start_time) > 2000) // 2 sec == watch dog timer
453                 {               
454                         if(xmit_cnt > 8)
455                         {
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)
460 #endif
461                                         )
462                                 {
463                                         DBG_871X("leave lps via Tx = %d\n", xmit_cnt);                  
464                                         bLeaveLPS = _TRUE;
465                                 }
466                         }
467
468                         start_time= rtw_get_current_time();
469                         xmit_cnt = 0;
470                 }
471
472         }
473         else // from rx path
474         {
475                 if(pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod > 4/*2*/)
476                 {
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)
481 #endif
482                                 )
483                         {       
484                                 DBG_871X("leave lps via Rx = %d\n", pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod);  
485                                 bLeaveLPS = _TRUE;
486                         }
487                 }       
488         }       
489
490         if(bLeaveLPS)
491         {
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, LPS_CTRL_LEAVE, tx?0:1);
495         }
496 #endif //CONFIG_CHECK_LEAVE_LPS
497 }               
498
499 /*
500  * Description:
501  *      This function MUST be called under power lock protect
502  *
503  * Parameters
504  *      padapter
505  *      pslv                    power state level, only could be PS_STATE_S0 ~ PS_STATE_S4
506  *
507  */
508 void rtw_set_rpwm(PADAPTER padapter, u8 pslv)
509 {
510         u8      rpwm;
511         struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
512 #ifdef CONFIG_DETECT_CPWM_BY_POLLING
513         u8 cpwm_orig;
514 #endif // CONFIG_DETECT_CPWM_BY_POLLING
515         struct dvobj_priv *psdpriv = padapter->dvobj;
516         struct debug_priv *pdbgpriv = &psdpriv->drv_dbg;
517 _func_enter_;
518
519         pslv = PS_STATE(pslv);
520
521 #ifdef CONFIG_LPS_RPWM_TIMER
522         if (pwrpriv->brpwmtimeout == _TRUE)
523         {
524                 DBG_871X("%s: RPWM timeout, force to set RPWM(0x%02X) again!\n", __FUNCTION__, pslv);
525         }
526         else
527 #endif // CONFIG_LPS_RPWM_TIMER
528         {
529                 if ( (pwrpriv->rpwm == pslv)
530 #ifdef CONFIG_LPS_LCLK
531 #ifndef CONFIG_RTL8723A
532                         || ((pwrpriv->rpwm >= PS_STATE_S2)&&(pslv >= PS_STATE_S2))
533 #endif
534 #endif
535                         )
536                 {
537                         RT_TRACE(_module_rtl871x_pwrctrl_c_,_drv_err_,
538                                 ("%s: Already set rpwm[0x%02X], new=0x%02X!\n", __FUNCTION__, pwrpriv->rpwm, pslv));
539                         return;
540                 }
541         }
542
543         if ((padapter->bSurpriseRemoved == _TRUE) ||
544                 (padapter->hw_init_completed == _FALSE))
545         {
546                 RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_err_,
547                                  ("%s: SurpriseRemoved(%d) hw_init_completed(%d)\n",
548                                   __FUNCTION__, padapter->bSurpriseRemoved, padapter->hw_init_completed));
549
550                 pwrpriv->cpwm = PS_STATE_S4;
551
552                 return;
553         }
554
555         if (padapter->bDriverStopped == _TRUE)
556         {
557                 RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_err_,
558                                  ("%s: change power state(0x%02X) when DriverStopped\n", __FUNCTION__, pslv));
559
560                 if (pslv < PS_STATE_S2) {
561                         RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_err_,
562                                          ("%s: Reject to enter PS_STATE(0x%02X) lower than S2 when DriverStopped!!\n", __FUNCTION__, pslv));
563                         return;
564                 }
565         }
566
567         rpwm = pslv | pwrpriv->tog;
568 #ifdef CONFIG_LPS_LCLK
569         // only when from PS_STATE S0/S1 to S2 and higher needs ACK
570         if ((pwrpriv->cpwm < PS_STATE_S2) && (pslv >= PS_STATE_S2))
571                 rpwm |= PS_ACK;
572 #endif
573         RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_notice_,
574                          ("rtw_set_rpwm: rpwm=0x%02x cpwm=0x%02x\n", rpwm, pwrpriv->cpwm));
575
576         pwrpriv->rpwm = pslv;
577
578 #ifdef CONFIG_DETECT_CPWM_BY_POLLING
579         cpwm_orig = 0;
580         if (rpwm & PS_ACK)
581         {
582                 rtw_hal_get_hwreg(padapter, HW_VAR_CPWM, &cpwm_orig);
583         }
584 #endif
585
586 #if defined(CONFIG_LPS_RPWM_TIMER) && !defined(CONFIG_DETECT_CPWM_BY_POLLING)
587         if (rpwm & PS_ACK)
588                 _set_timer(&pwrpriv->pwr_rpwm_timer, LPS_RPWM_WAIT_MS);
589 #endif // CONFIG_LPS_RPWM_TIMER & !CONFIG_DETECT_CPWM_BY_POLLING
590         rtw_hal_set_hwreg(padapter, HW_VAR_SET_RPWM, (u8 *)(&rpwm));
591
592         pwrpriv->tog += 0x80;
593
594 #ifdef CONFIG_LPS_LCLK
595         // No LPS 32K, No Ack
596         if (rpwm & PS_ACK)
597         {
598 #ifdef CONFIG_DETECT_CPWM_BY_POLLING
599                 u32 start_time;
600                 u8 cpwm_now;
601                 u8 poll_cnt=0;
602
603                 start_time = rtw_get_current_time();
604
605                 // polling cpwm
606                 do {
607                         rtw_mdelay_os(1);
608                         poll_cnt++;
609                         rtw_hal_get_hwreg(padapter, HW_VAR_CPWM, &cpwm_now);
610                         if ((cpwm_orig ^ cpwm_now) & 0x80)
611                         {
612 #ifdef CONFIG_RTL8723A
613                                 pwrpriv->cpwm = PS_STATE(cpwm_now);
614 #else // !CONFIG_RTL8723A
615                                 pwrpriv->cpwm = PS_STATE_S4;
616 #endif // !CONFIG_RTL8723A
617                                 pwrpriv->cpwm_tog = cpwm_now & PS_TOGGLE;
618 #ifdef DBG_CHECK_FW_PS_STATE
619                                 DBG_871X("%s: polling cpwm OK! poll_cnt=%d, cpwm_orig=%02x, cpwm_now=%02x , 0x100=0x%x\n"
620                                 , __FUNCTION__,poll_cnt, cpwm_orig, cpwm_now, rtw_read8(padapter, REG_CR));
621                                 if(rtw_fw_ps_state(padapter) == _FAIL)
622                                 {
623                                         DBG_871X("leave 32k but fw state in 32k\n");
624                                         pdbgpriv->dbg_rpwm_toogle_cnt++;
625                                 }
626 #endif //DBG_CHECK_FW_PS_STATE
627                                 break;
628                         }
629
630                         if (rtw_get_passing_time_ms(start_time) > LPS_RPWM_WAIT_MS)
631                         {
632                                 DBG_871X("%s: polling cpwm timeout! poll_cnt=%d, cpwm_orig=%02x, cpwm_now=%02x \n", __FUNCTION__,poll_cnt, cpwm_orig, cpwm_now);
633 #ifdef DBG_CHECK_FW_PS_STATE
634                                 if(rtw_fw_ps_state(padapter) == _FAIL)
635                                 {
636                                         DBG_871X("rpwm timeout and fw ps state in 32k\n");
637                                         pdbgpriv->dbg_rpwm_timeout_fail_cnt++;
638                                 }
639 #endif //DBG_CHECK_FW_PS_STATE
640 #ifdef CONFIG_LPS_RPWM_TIMER
641                                 _set_timer(&pwrpriv->pwr_rpwm_timer, 1);
642 #endif // CONFIG_LPS_RPWM_TIMER
643                                 break;
644                         }
645                 } while (1);
646 #endif // CONFIG_DETECT_CPWM_BY_POLLING
647         }
648         else
649 #endif // CONFIG_LPS_LCLK
650         {
651                 pwrpriv->cpwm = pslv;
652         }
653
654 _func_exit_;
655 }
656
657 u8 PS_RDY_CHECK(_adapter * padapter)
658 {
659         u32 curr_time, delta_time;
660         struct pwrctrl_priv     *pwrpriv = adapter_to_pwrctl(padapter);
661         struct mlme_priv        *pmlmepriv = &(padapter->mlmepriv);
662 #ifdef CONFIG_P2P
663         struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
664 #ifdef CONFIG_IOCTL_CFG80211
665         struct cfg80211_wifidirect_info *pcfg80211_wdinfo = &padapter->cfg80211_wdinfo;
666 #endif /* CONFIG_IOCTL_CFG80211 */
667 #endif /* CONFIG_P2P */
668
669 #if defined(CONFIG_WOWLAN) || defined(CONFIG_AP_WOWLAN)
670         if(_TRUE == pwrpriv->bInSuspend && pwrpriv->wowlan_mode)
671                 return _TRUE;
672         else if(_TRUE == pwrpriv->bInSuspend && pwrpriv->wowlan_ap_mode)
673                 return _TRUE;
674         else if (_TRUE == pwrpriv->bInSuspend)
675                 return _FALSE;
676 #else
677         if(_TRUE == pwrpriv->bInSuspend )
678                 return _FALSE;
679 #endif
680
681         curr_time = rtw_get_current_time();     
682
683         delta_time = curr_time -pwrpriv->DelayLPSLastTimeStamp;
684
685         if(delta_time < LPS_DELAY_TIME)
686         {               
687                 return _FALSE;
688         }
689
690         if (check_fwstate(pmlmepriv, WIFI_SITE_MONITOR)
691                 || check_fwstate(pmlmepriv, WIFI_UNDER_LINKING|WIFI_UNDER_WPS)
692                 || check_fwstate(pmlmepriv, WIFI_AP_STATE)
693                 || check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE|WIFI_ADHOC_STATE)
694                 #if defined(CONFIG_P2P) && defined(CONFIG_IOCTL_CFG80211) && defined(CONFIG_P2P_IPS)
695                 || pcfg80211_wdinfo->is_ro_ch
696                 #elif defined(CONFIG_P2P)
697                 || !rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)
698                 #endif
699                 || rtw_is_scan_deny(padapter)
700 #ifdef CONFIG_TDLS
701                 // TDLS link is established.
702                 || ( padapter->tdlsinfo.link_established == _TRUE )
703 #endif // CONFIG_TDLS           
704         )
705                 return _FALSE;
706
707         if( (padapter->securitypriv.dot11AuthAlgrthm == dot11AuthAlgrthm_8021X) && (padapter->securitypriv.binstallGrpkey == _FALSE) )
708         {
709                 DBG_871X("Group handshake still in progress !!!\n");
710                 return _FALSE;
711         }
712
713 #ifdef CONFIG_IOCTL_CFG80211
714         if (!rtw_cfg80211_pwr_mgmt(padapter))
715                 return _FALSE;
716 #endif  
717
718         return _TRUE;
719 }
720
721 void rtw_set_ps_mode(PADAPTER padapter, u8 ps_mode, u8 smart_ps, u8 bcn_ant_mode, const char *msg)
722 {
723         struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
724         struct dvobj_priv *psdpriv = padapter->dvobj;
725         struct debug_priv *pdbgpriv = &psdpriv->drv_dbg;
726 #ifdef CONFIG_P2P
727         struct wifidirect_info  *pwdinfo = &( padapter->wdinfo );
728 #endif //CONFIG_P2P
729 #ifdef CONFIG_TDLS
730         struct sta_priv *pstapriv = &padapter->stapriv;
731         _irqL irqL;
732         int i, j;
733         _list   *plist, *phead;
734         struct sta_info *ptdls_sta;
735 #endif //CONFIG_TDLS
736
737 _func_enter_;
738
739         RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_notice_,
740                          ("%s: PowerMode=%d Smart_PS=%d\n",
741                           __FUNCTION__, ps_mode, smart_ps));
742
743         if(ps_mode > PM_Card_Disable) {
744                 RT_TRACE(_module_rtl871x_pwrctrl_c_,_drv_err_,("ps_mode:%d error\n", ps_mode));
745                 return;
746         }
747
748         if (pwrpriv->pwr_mode == ps_mode)
749         {
750                 if (PS_MODE_ACTIVE == ps_mode) return;
751
752 #ifndef CONFIG_BT_COEXIST
753                 if ((pwrpriv->smart_ps == smart_ps) &&
754                         (pwrpriv->bcn_ant_mode == bcn_ant_mode))
755                 {
756                         return;
757                 }
758 #endif // !CONFIG_BT_COEXIST
759         }
760
761 #ifdef CONFIG_LPS_LCLK
762         _enter_pwrlock(&pwrpriv->lock);
763 #endif
764
765         //if(pwrpriv->pwr_mode == PS_MODE_ACTIVE)
766         if(ps_mode == PS_MODE_ACTIVE)
767         {
768                 if (1
769 #ifdef CONFIG_BT_COEXIST
770                         && (((rtw_btcoex_IsBtControlLps(padapter) == _FALSE)
771 #ifdef CONFIG_P2P_PS
772                                         && (pwdinfo->opp_ps == 0)
773 #endif // CONFIG_P2P_PS
774                                         )
775                                 || ((rtw_btcoex_IsBtControlLps(padapter) == _TRUE)
776                                         && (rtw_btcoex_IsLpsOn(padapter) == _FALSE))
777                                 )
778 #else // !CONFIG_BT_COEXIST
779 #ifdef CONFIG_P2P_PS
780                         && (pwdinfo->opp_ps == 0)
781 #endif // CONFIG_P2P_PS
782 #endif // !CONFIG_BT_COEXIST
783                         )
784                 {
785                         DBG_871X(FUNC_ADPT_FMT" Leave 802.11 power save - %s\n",
786                                 FUNC_ADPT_ARG(padapter), msg);
787
788 #ifdef CONFIG_TDLS
789                         _enter_critical_bh(&pstapriv->sta_hash_lock, &irqL);
790
791                         for(i=0; i< NUM_STA; i++)
792                         {
793                                 phead = &(pstapriv->sta_hash[i]);
794                                 plist = get_next(phead);
795
796                                 while ((rtw_end_of_queue_search(phead, plist)) == _FALSE)
797                                 {
798                                         ptdls_sta = LIST_CONTAINOR(plist, struct sta_info, hash_list);
799
800                                         if( ptdls_sta->tdls_sta_state & TDLS_LINKED_STATE )
801                                                 issue_nulldata_to_TDLS_peer_STA(padapter, ptdls_sta->hwaddr, 0, 0, 0);
802                                         plist = get_next(plist);
803                                 }
804                         }
805
806                         _exit_critical_bh(&pstapriv->sta_hash_lock, &irqL);
807 #endif //CONFIG_TDLS
808
809                         pwrpriv->pwr_mode = ps_mode;
810                         rtw_set_rpwm(padapter, PS_STATE_S4);
811                         
812 #if defined(CONFIG_WOWLAN) || defined(CONFIG_AP_WOWLAN)
813                         if (pwrpriv->wowlan_mode == _TRUE ||
814                                         pwrpriv->wowlan_ap_mode == _TRUE)
815                         {
816                                 u32 start_time, delay_ms;
817                                 u8 val8;
818                                 delay_ms = 20;
819                                 start_time = rtw_get_current_time();
820                                 do { 
821                                         rtw_hal_get_hwreg(padapter, HW_VAR_SYS_CLKR, &val8);
822                                         if (!(val8 & BIT(4))){ //0x08 bit4 =1 --> in 32k, bit4 = 0 --> leave 32k
823                                                 pwrpriv->cpwm = PS_STATE_S4;
824                                                 break;
825                                         }
826                                         if (rtw_get_passing_time_ms(start_time) > delay_ms)
827                                         {
828                                                 DBG_871X("%s: Wait for FW 32K leave more than %u ms!!!\n", 
829                                                                 __FUNCTION__, delay_ms);
830                                                 pdbgpriv->dbg_wow_leave_ps_fail_cnt++;
831                                                 break;
832                                         }
833                                         rtw_usleep_os(100);
834                                 } while (1); 
835                         }
836 #endif
837                         rtw_hal_set_hwreg(padapter, HW_VAR_H2C_FW_PWRMODE, (u8 *)(&ps_mode));
838                         pwrpriv->bFwCurrentInPSMode = _FALSE;
839
840 #ifdef CONFIG_BT_COEXIST
841                         rtw_btcoex_LpsNotify(padapter, ps_mode);
842 #endif // CONFIG_BT_COEXIST
843                 }
844         }
845         else
846         {
847                 if ((PS_RDY_CHECK(padapter) && check_fwstate(&padapter->mlmepriv, WIFI_ASOC_STATE))
848 #ifdef CONFIG_BT_COEXIST
849                         || ((rtw_btcoex_IsBtControlLps(padapter) == _TRUE)
850                                 && (rtw_btcoex_IsLpsOn(padapter) == _TRUE))
851 #endif
852                         )
853                 {
854                         u8 pslv;
855
856                         DBG_871X(FUNC_ADPT_FMT" Enter 802.11 power save - %s\n",
857                                 FUNC_ADPT_ARG(padapter), msg);
858
859 #ifdef CONFIG_TDLS
860                         _enter_critical_bh(&pstapriv->sta_hash_lock, &irqL);
861
862                         for(i=0; i< NUM_STA; i++)
863                         {
864                                 phead = &(pstapriv->sta_hash[i]);
865                                 plist = get_next(phead);
866
867                                 while ((rtw_end_of_queue_search(phead, plist)) == _FALSE)
868                                 {
869                                         ptdls_sta = LIST_CONTAINOR(plist, struct sta_info, hash_list);
870
871                                         if( ptdls_sta->tdls_sta_state & TDLS_LINKED_STATE )
872                                                 issue_nulldata_to_TDLS_peer_STA(padapter, ptdls_sta->hwaddr, 1, 0, 0);
873                                         plist = get_next(plist);
874                                 }
875                         }
876
877                         _exit_critical_bh(&pstapriv->sta_hash_lock, &irqL);
878 #endif //CONFIG_TDLS
879
880 #ifdef CONFIG_BT_COEXIST
881                         rtw_btcoex_LpsNotify(padapter, ps_mode);
882 #endif // CONFIG_BT_COEXIST
883
884                         pwrpriv->bFwCurrentInPSMode = _TRUE;
885                         pwrpriv->pwr_mode = ps_mode;
886                         pwrpriv->smart_ps = smart_ps;
887                         pwrpriv->bcn_ant_mode = bcn_ant_mode;
888                         rtw_hal_set_hwreg(padapter, HW_VAR_H2C_FW_PWRMODE, (u8 *)(&ps_mode));
889
890 #ifdef CONFIG_P2P_PS
891                         // Set CTWindow after LPS
892                         if(pwdinfo->opp_ps == 1)
893                                 p2p_ps_wk_cmd(padapter, P2P_PS_ENABLE, 0);
894 #endif //CONFIG_P2P_PS
895
896                         pslv = PS_STATE_S2;
897 #ifdef CONFIG_LPS_LCLK
898                         if (pwrpriv->alives == 0)
899                                 pslv = PS_STATE_S0;
900 #endif // CONFIG_LPS_LCLK
901
902 #ifdef CONFIG_BT_COEXIST
903                         if ((rtw_btcoex_IsBtDisabled(padapter) == _FALSE)
904                                 && (rtw_btcoex_IsBtControlLps(padapter) == _TRUE))
905                         {
906                                 u8 val8;
907
908                                 val8 = rtw_btcoex_LpsVal(padapter);
909                                 if (val8 & BIT(4))
910                                         pslv = PS_STATE_S2;
911
912 #ifdef CONFIG_RTL8723A
913                                 val8 = rtw_btcoex_RpwmVal(padapter);
914                                 switch (val8)
915                                 {
916                                         case 0x4:
917                                                 pslv = PS_STATE_S3;
918                                                 break;
919
920                                         case 0xC:
921                                                 pslv = PS_STATE_S4;
922                                                 break;
923                                 }
924 #endif // CONFIG_RTL8723A
925                         }
926 #endif // CONFIG_BT_COEXIST
927
928                         rtw_set_rpwm(padapter, pslv);
929                 }
930         }
931
932 #ifdef CONFIG_LPS_LCLK
933         _exit_pwrlock(&pwrpriv->lock);
934 #endif
935
936 _func_exit_;
937 }
938
939 /*
940  * Return:
941  *      0:      Leave OK
942  *      -1:     Timeout
943  *      -2:     Other error
944  */
945 s32 LPS_RF_ON_check(PADAPTER padapter, u32 delay_ms)
946 {
947         u32 start_time;
948         u8 bAwake = _FALSE;
949         s32 err = 0;
950
951
952         start_time = rtw_get_current_time();
953         while (1)
954         {
955                 rtw_hal_get_hwreg(padapter, HW_VAR_FWLPS_RF_ON, &bAwake);
956                 if (_TRUE == bAwake)
957                         break;
958
959                 if (_TRUE == padapter->bSurpriseRemoved)
960                 {
961                         err = -2;
962                         DBG_871X("%s: device surprise removed!!\n", __FUNCTION__);
963                         break;
964                 }
965
966                 if (rtw_get_passing_time_ms(start_time) > delay_ms)
967                 {
968                         err = -1;
969                         DBG_871X("%s: Wait for FW LPS leave more than %u ms!!!\n", __FUNCTION__, delay_ms);
970                         break;
971                 }
972                 rtw_usleep_os(100);
973         }
974
975         return err;
976 }
977
978 //
979 //      Description:
980 //              Enter the leisure power save mode.
981 //
982 void LPS_Enter(PADAPTER padapter, const char *msg)
983 {
984         struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
985         struct pwrctrl_priv     *pwrpriv = dvobj_to_pwrctl(dvobj);
986         struct mlme_priv        *pmlmepriv = &(padapter->mlmepriv);
987         _adapter *buddy = padapter->pbuddy_adapter;
988         int n_assoc_iface = 0;
989         int i;
990         char buf[32] = {0};
991
992 _func_enter_;
993
994 //      DBG_871X("+LeisurePSEnter\n");
995
996 #ifdef CONFIG_BT_COEXIST
997         if (rtw_btcoex_IsBtControlLps(padapter) == _TRUE)
998                 return;
999 #endif
1000
1001         /* Skip lps enter request if number of assocated adapters is not 1 */
1002         for (i = 0; i < dvobj->iface_nums; i++) {
1003                 if (check_fwstate(&(dvobj->padapters[i]->mlmepriv), WIFI_ASOC_STATE))
1004                         n_assoc_iface++;
1005         }
1006         if (n_assoc_iface != 1)
1007                 return;
1008
1009         /* Skip lps enter request for adapter not port0 */
1010         if (get_iface_type(padapter) != IFACE_PORT0)
1011                 return;
1012
1013         for (i = 0; i < dvobj->iface_nums; i++) {
1014                 if (PS_RDY_CHECK(dvobj->padapters[i]) == _FALSE)
1015                         return;
1016         }
1017
1018         if (pwrpriv->bLeisurePs)
1019         {
1020                 // Idle for a while if we connect to AP a while ago.
1021                 if (pwrpriv->LpsIdleCount >= 2) //  4 Sec
1022                 {
1023                         if(pwrpriv->pwr_mode == PS_MODE_ACTIVE)
1024                         {
1025                                 sprintf(buf, "WIFI-%s", msg);
1026                                 pwrpriv->bpower_saving = _TRUE;
1027                                 rtw_set_ps_mode(padapter, pwrpriv->power_mgnt, padapter->registrypriv.smart_ps, 0, buf);
1028                         }
1029                 }
1030                 else
1031                         pwrpriv->LpsIdleCount++;
1032         }
1033
1034 //      DBG_871X("-LeisurePSEnter\n");
1035
1036 _func_exit_;
1037 }
1038
1039 //
1040 //      Description:
1041 //              Leave the leisure power save mode.
1042 //
1043 void LPS_Leave(PADAPTER padapter, const char *msg)
1044 {
1045 #define LPS_LEAVE_TIMEOUT_MS 100
1046
1047         struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
1048         struct pwrctrl_priv     *pwrpriv = dvobj_to_pwrctl(dvobj);
1049         u32 start_time;
1050         u8 bAwake = _FALSE;
1051         char buf[32] = {0};
1052         struct debug_priv *pdbgpriv = &dvobj->drv_dbg;
1053
1054 _func_enter_;
1055
1056 //      DBG_871X("+LeisurePSLeave\n");
1057
1058 #ifdef CONFIG_BT_COEXIST
1059         if (rtw_btcoex_IsBtControlLps(padapter) == _TRUE)
1060                 return;
1061 #endif
1062
1063         if (pwrpriv->bLeisurePs)
1064         {
1065                 if(pwrpriv->pwr_mode != PS_MODE_ACTIVE)
1066                 {
1067                         sprintf(buf, "WIFI-%s", msg);
1068                         rtw_set_ps_mode(padapter, PS_MODE_ACTIVE, 0, 0, buf);
1069
1070                         if(pwrpriv->pwr_mode == PS_MODE_ACTIVE)
1071                                 LPS_RF_ON_check(padapter, LPS_LEAVE_TIMEOUT_MS);
1072                 }
1073         }
1074
1075         pwrpriv->bpower_saving = _FALSE;
1076 #ifdef DBG_CHECK_FW_PS_STATE
1077         if(rtw_fw_ps_state(padapter) == _FAIL)
1078         {
1079                 DBG_871X("leave lps, fw in 32k\n");
1080                 pdbgpriv->dbg_leave_lps_fail_cnt++;
1081         }
1082 #endif //DBG_CHECK_FW_PS_STATE
1083 //      DBG_871X("-LeisurePSLeave\n");
1084
1085 _func_exit_;
1086 }
1087 #endif
1088
1089 void LeaveAllPowerSaveModeDirect(PADAPTER Adapter)
1090 {
1091         PADAPTER pri_padapter = GET_PRIMARY_ADAPTER(Adapter);
1092         struct mlme_priv        *pmlmepriv = &(Adapter->mlmepriv);
1093         struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(Adapter);
1094         struct dvobj_priv *psdpriv = Adapter->dvobj;
1095         struct debug_priv *pdbgpriv = &psdpriv->drv_dbg;
1096 #ifndef CONFIG_DETECT_CPWM_BY_POLLING
1097         u8 cpwm_orig, cpwm_now;
1098         u32 start_time;
1099 #endif // CONFIG_DETECT_CPWM_BY_POLLING
1100
1101 _func_enter_;
1102
1103         DBG_871X("%s.....\n",__FUNCTION__);
1104
1105         if (_TRUE == Adapter->bSurpriseRemoved)
1106         {
1107                 DBG_871X(FUNC_ADPT_FMT ": bSurpriseRemoved=%d Skip!\n",
1108                         FUNC_ADPT_ARG(Adapter), Adapter->bSurpriseRemoved);
1109                 return;
1110         }
1111
1112         if ((check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE)
1113 #ifdef CONFIG_CONCURRENT_MODE
1114                 || (check_buddy_fwstate(Adapter,_FW_LINKED) == _TRUE)
1115 #endif
1116                 )
1117         { //connect
1118
1119                 if(pwrpriv->pwr_mode == PS_MODE_ACTIVE) {
1120                         DBG_871X("%s: Driver Already Leave LPS\n",__FUNCTION__);
1121                         return;
1122                 }
1123
1124 #ifdef CONFIG_LPS_LCLK
1125                 _enter_pwrlock(&pwrpriv->lock);
1126
1127 #ifndef CONFIG_DETECT_CPWM_BY_POLLING
1128                 cpwm_orig = 0;
1129                 rtw_hal_get_hwreg(Adapter, HW_VAR_CPWM, &cpwm_orig);
1130 #endif //CONFIG_DETECT_CPWM_BY_POLLING
1131                 rtw_set_rpwm(Adapter, PS_STATE_S4);
1132
1133 #ifndef CONFIG_DETECT_CPWM_BY_POLLING
1134
1135                 start_time = rtw_get_current_time();
1136
1137                 // polling cpwm
1138                 do {
1139                         rtw_mdelay_os(1);
1140
1141                         rtw_hal_get_hwreg(Adapter, HW_VAR_CPWM, &cpwm_now);
1142                         if ((cpwm_orig ^ cpwm_now) & 0x80)
1143                         {
1144 #ifdef CONFIG_RTL8723A
1145                                 pwrpriv->cpwm = PS_STATE(cpwm_now);
1146 #else // !CONFIG_RTL8723A
1147                                 pwrpriv->cpwm = PS_STATE_S4;
1148 #endif // !CONFIG_RTL8723A
1149                                 pwrpriv->cpwm_tog = cpwm_now & PS_TOGGLE;
1150 #ifdef DBG_CHECK_FW_PS_STATE
1151                                 DBG_871X("%s: polling cpwm OK! cpwm_orig=%02x, cpwm_now=%02x, 0x100=0x%x \n"
1152                                 , __FUNCTION__, cpwm_orig, cpwm_now, rtw_read8(Adapter, REG_CR));
1153                                 if(rtw_fw_ps_state(Adapter) == _FAIL)
1154                                 {
1155                                         DBG_871X("%s: leave 32k but fw state in 32k\n", __FUNCTION__);
1156                                         pdbgpriv->dbg_rpwm_toogle_cnt++;
1157                                 }
1158 #endif //DBG_CHECK_FW_PS_STATE
1159                                 break;
1160                         }
1161
1162                         if (rtw_get_passing_time_ms(start_time) > LPS_RPWM_WAIT_MS)
1163                         {
1164                                 DBG_871X("%s: polling cpwm timeout! cpwm_orig=%02x, cpwm_now=%02x \n", __FUNCTION__, cpwm_orig, cpwm_now);
1165 #ifdef DBG_CHECK_FW_PS_STATE
1166                                 if(rtw_fw_ps_state(Adapter) == _FAIL)
1167                                 {
1168                                         DBG_871X("rpwm timeout and fw ps state in 32k\n");
1169                                         pdbgpriv->dbg_rpwm_timeout_fail_cnt++;
1170                                 }
1171 #endif //DBG_CHECK_FW_PS_STATE
1172                                 break;
1173                         }
1174                 } while (1);
1175 #endif // CONFIG_DETECT_CPWM_BY_POLLING
1176
1177         _exit_pwrlock(&pwrpriv->lock);
1178 #endif
1179
1180 #ifdef CONFIG_P2P_PS
1181                 p2p_ps_wk_cmd(pri_padapter, P2P_PS_DISABLE, 0);
1182 #endif //CONFIG_P2P_PS
1183
1184 #ifdef CONFIG_LPS
1185                 rtw_lps_ctrl_wk_cmd(pri_padapter, LPS_CTRL_LEAVE, 0);
1186 #endif
1187         }
1188         else
1189         {
1190                 if(pwrpriv->rf_pwrstate== rf_off)
1191                 {
1192                         #ifdef CONFIG_AUTOSUSPEND
1193                         if(Adapter->registrypriv.usbss_enable)
1194                         {
1195                                 #if (LINUX_VERSION_CODE>=KERNEL_VERSION(2,6,35))
1196                                 usb_disable_autosuspend(adapter_to_dvobj(Adapter)->pusbdev);
1197                                 #elif (LINUX_VERSION_CODE>=KERNEL_VERSION(2,6,22) && LINUX_VERSION_CODE<=KERNEL_VERSION(2,6,34))
1198                                 adapter_to_dvobj(Adapter)->pusbdev->autosuspend_disabled = Adapter->bDisableAutosuspend;//autosuspend disabled by the user
1199                                 #endif
1200                         }
1201                         else
1202                         #endif
1203                         {
1204 #if defined(CONFIG_FWLPS_IN_IPS) || defined(CONFIG_SWLPS_IN_IPS) || defined(CONFIG_RTL8188E)
1205                                 #ifdef CONFIG_IPS
1206                                 if(_FALSE == ips_leave(pri_padapter))
1207                                 {
1208                                         DBG_871X("======> ips_leave fail.............\n");                      
1209                                 }
1210                                 #endif
1211 #endif //CONFIG_SWLPS_IN_IPS || (CONFIG_PLATFORM_SPRD && CONFIG_RTL8188E)
1212                         }
1213                 }
1214         }
1215
1216 _func_exit_;
1217 }
1218
1219 //
1220 // Description: Leave all power save mode: LPS, FwLPS, IPS if needed.
1221 // Move code to function by tynli. 2010.03.26. 
1222 //
1223 void LeaveAllPowerSaveMode(IN PADAPTER Adapter)
1224 {
1225         struct dvobj_priv *dvobj = adapter_to_dvobj(Adapter);
1226         struct mlme_priv        *pmlmepriv = &(Adapter->mlmepriv);
1227         u8      enqueue = 0;
1228         int n_assoc_iface = 0;
1229         int i;
1230
1231 _func_enter_;
1232
1233         //DBG_871X("%s.....\n",__FUNCTION__);
1234
1235         if (_FALSE == Adapter->bup)
1236         {
1237                 DBG_871X(FUNC_ADPT_FMT ": bup=%d Skip!\n",
1238                         FUNC_ADPT_ARG(Adapter), Adapter->bup);
1239                 return;
1240         }
1241
1242         if (_TRUE == Adapter->bSurpriseRemoved)
1243         {
1244                 DBG_871X(FUNC_ADPT_FMT ": bSurpriseRemoved=%d Skip!\n",
1245                         FUNC_ADPT_ARG(Adapter), Adapter->bSurpriseRemoved);
1246                 return;
1247         }
1248
1249         for (i = 0; i < dvobj->iface_nums; i++) {
1250                 if (check_fwstate(&(dvobj->padapters[i]->mlmepriv), WIFI_ASOC_STATE))
1251                         n_assoc_iface++;
1252         }
1253
1254         if (n_assoc_iface)
1255         { //connect
1256 #ifdef CONFIG_LPS_LCLK
1257                 enqueue = 1;
1258 #endif
1259
1260 #ifdef CONFIG_P2P_PS
1261                 p2p_ps_wk_cmd(Adapter, P2P_PS_DISABLE, enqueue);
1262 #endif //CONFIG_P2P_PS
1263
1264 #ifdef CONFIG_LPS
1265                 rtw_lps_ctrl_wk_cmd(Adapter, LPS_CTRL_LEAVE, enqueue);
1266 #endif
1267
1268 #ifdef CONFIG_LPS_LCLK
1269                 LPS_Leave_check(Adapter);
1270 #endif  
1271         }
1272         else
1273         {
1274                 if(adapter_to_pwrctl(Adapter)->rf_pwrstate== rf_off)
1275                 {
1276                         #ifdef CONFIG_AUTOSUSPEND
1277                         if(Adapter->registrypriv.usbss_enable)
1278                         {
1279                                 #if (LINUX_VERSION_CODE>=KERNEL_VERSION(2,6,35))
1280                                 usb_disable_autosuspend(adapter_to_dvobj(Adapter)->pusbdev);
1281                                 #elif (LINUX_VERSION_CODE>=KERNEL_VERSION(2,6,22) && LINUX_VERSION_CODE<=KERNEL_VERSION(2,6,34))
1282                                 adapter_to_dvobj(Adapter)->pusbdev->autosuspend_disabled = Adapter->bDisableAutosuspend;//autosuspend disabled by the user
1283                                 #endif
1284                         }
1285                         else
1286                         #endif
1287                         {
1288 #if defined(CONFIG_FWLPS_IN_IPS) || defined(CONFIG_SWLPS_IN_IPS) || (defined(CONFIG_PLATFORM_SPRD) && defined(CONFIG_RTL8188E))
1289                                 #ifdef CONFIG_IPS
1290                                 if(_FALSE == ips_leave(Adapter))
1291                                 {
1292                                         DBG_871X("======> ips_leave fail.............\n");                      
1293                                 }
1294                                 #endif
1295 #endif //CONFIG_SWLPS_IN_IPS || (CONFIG_PLATFORM_SPRD && CONFIG_RTL8188E)
1296                         }                               
1297                 }       
1298         }
1299
1300 _func_exit_;
1301 }
1302
1303 #ifdef CONFIG_LPS_LCLK
1304 void LPS_Leave_check(
1305         PADAPTER padapter)
1306 {
1307         struct pwrctrl_priv *pwrpriv;
1308         u32     start_time;
1309         u8      bReady;
1310
1311 _func_enter_;
1312
1313         pwrpriv = adapter_to_pwrctl(padapter);
1314
1315         bReady = _FALSE;
1316         start_time = rtw_get_current_time();
1317
1318         rtw_yield_os();
1319         
1320         while(1)
1321         {
1322                 _enter_pwrlock(&pwrpriv->lock);
1323
1324                 if ((padapter->bSurpriseRemoved == _TRUE)
1325                         || (padapter->hw_init_completed == _FALSE)
1326 #ifdef CONFIG_USB_HCI
1327                         || (padapter->bDriverStopped== _TRUE)
1328 #endif
1329                         || (pwrpriv->pwr_mode == PS_MODE_ACTIVE)
1330                         )
1331                 {
1332                         bReady = _TRUE;
1333                 }
1334
1335                 _exit_pwrlock(&pwrpriv->lock);
1336
1337                 if(_TRUE == bReady)
1338                         break;
1339
1340                 if(rtw_get_passing_time_ms(start_time)>100)
1341                 {
1342                         DBG_871X("Wait for cpwm event  than 100 ms!!!\n");
1343                         break;
1344                 }
1345                 rtw_msleep_os(1);
1346         }
1347
1348 _func_exit_;
1349 }
1350
1351 /*
1352  * Caller:ISR handler...
1353  *
1354  * This will be called when CPWM interrupt is up.
1355  *
1356  * using to update cpwn of drv; and drv willl make a decision to up or down pwr level
1357  */
1358 void cpwm_int_hdl(
1359         PADAPTER padapter,
1360         struct reportpwrstate_parm *preportpwrstate)
1361 {
1362         struct pwrctrl_priv *pwrpriv;
1363
1364 _func_enter_;
1365
1366         pwrpriv = adapter_to_pwrctl(padapter);
1367 #if 0
1368         if (pwrpriv->cpwm_tog == (preportpwrstate->state & PS_TOGGLE)) {
1369                 RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_err_,
1370                                  ("cpwm_int_hdl: tog(old)=0x%02x cpwm(new)=0x%02x toggle bit didn't change!?\n",
1371                                   pwrpriv->cpwm_tog, preportpwrstate->state));
1372                 goto exit;
1373         }
1374 #endif
1375
1376         _enter_pwrlock(&pwrpriv->lock);
1377
1378 #ifdef CONFIG_LPS_RPWM_TIMER
1379         if (pwrpriv->rpwm < PS_STATE_S2)
1380         {
1381                 DBG_871X("%s: Redundant CPWM Int. RPWM=0x%02X CPWM=0x%02x\n", __func__, pwrpriv->rpwm, pwrpriv->cpwm);
1382                 _exit_pwrlock(&pwrpriv->lock);
1383                 goto exit;
1384         }
1385 #endif // CONFIG_LPS_RPWM_TIMER
1386
1387         pwrpriv->cpwm = PS_STATE(preportpwrstate->state);
1388         pwrpriv->cpwm_tog = preportpwrstate->state & PS_TOGGLE;
1389
1390         if (pwrpriv->cpwm >= PS_STATE_S2)
1391         {
1392                 if (pwrpriv->alives & CMD_ALIVE)
1393                         _rtw_up_sema(&padapter->cmdpriv.cmd_queue_sema);
1394
1395                 if (pwrpriv->alives & XMIT_ALIVE)
1396                         _rtw_up_sema(&padapter->xmitpriv.xmit_sema);
1397         }
1398
1399         _exit_pwrlock(&pwrpriv->lock);
1400
1401 exit:
1402         RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_notice_,
1403                          ("cpwm_int_hdl: cpwm=0x%02x\n", pwrpriv->cpwm));
1404
1405 _func_exit_;
1406 }
1407
1408 static void cpwm_event_callback(struct work_struct *work)
1409 {
1410         struct pwrctrl_priv *pwrpriv = container_of(work, struct pwrctrl_priv, cpwm_event);
1411         struct dvobj_priv *dvobj = pwrctl_to_dvobj(pwrpriv);
1412         _adapter *adapter = dvobj->if1;
1413         struct reportpwrstate_parm report;
1414
1415         //DBG_871X("%s\n",__FUNCTION__);
1416
1417         report.state = PS_STATE_S2;
1418         cpwm_int_hdl(adapter, &report);
1419 }
1420
1421 #ifdef CONFIG_LPS_RPWM_TIMER
1422 static void rpwmtimeout_workitem_callback(struct work_struct *work)
1423 {
1424         PADAPTER padapter;
1425         struct dvobj_priv *dvobj;
1426         struct pwrctrl_priv *pwrpriv;
1427
1428
1429         pwrpriv = container_of(work, struct pwrctrl_priv, rpwmtimeoutwi);
1430         dvobj = pwrctl_to_dvobj(pwrpriv);
1431         padapter = dvobj->if1;
1432 //      DBG_871X("+%s: rpwm=0x%02X cpwm=0x%02X\n", __func__, pwrpriv->rpwm, pwrpriv->cpwm);
1433
1434         _enter_pwrlock(&pwrpriv->lock);
1435         if ((pwrpriv->rpwm == pwrpriv->cpwm) || (pwrpriv->cpwm >= PS_STATE_S2))
1436         {
1437                 DBG_871X("%s: rpwm=0x%02X cpwm=0x%02X CPWM done!\n", __func__, pwrpriv->rpwm, pwrpriv->cpwm);
1438                 goto exit;
1439         }
1440         _exit_pwrlock(&pwrpriv->lock);
1441
1442         if (rtw_read8(padapter, 0x100) != 0xEA)
1443         {
1444 #if 1
1445                 struct reportpwrstate_parm report;
1446
1447                 report.state = PS_STATE_S2;
1448                 DBG_871X("\n%s: FW already leave 32K!\n\n", __func__);
1449                 cpwm_int_hdl(padapter, &report);
1450 #else
1451                 DBG_871X("\n%s: FW already leave 32K!\n\n", __func__);
1452                 cpwm_event_callback(&pwrpriv->cpwm_event);
1453 #endif
1454                 return;
1455         }
1456
1457         _enter_pwrlock(&pwrpriv->lock);
1458
1459         if ((pwrpriv->rpwm == pwrpriv->cpwm) || (pwrpriv->cpwm >= PS_STATE_S2))
1460         {
1461                 DBG_871X("%s: cpwm=%d, nothing to do!\n", __func__, pwrpriv->cpwm);
1462                 goto exit;
1463         }
1464         pwrpriv->brpwmtimeout = _TRUE;
1465         rtw_set_rpwm(padapter, pwrpriv->rpwm);
1466         pwrpriv->brpwmtimeout = _FALSE;
1467
1468 exit:
1469         _exit_pwrlock(&pwrpriv->lock);
1470 }
1471
1472 /*
1473  * This function is a timer handler, can't do any IO in it.
1474  */
1475 static void pwr_rpwm_timeout_handler(void *FunctionContext)
1476 {
1477         PADAPTER padapter;
1478         struct pwrctrl_priv *pwrpriv;
1479
1480
1481         padapter = (PADAPTER)FunctionContext;
1482         pwrpriv = adapter_to_pwrctl(padapter);
1483         DBG_871X("+%s: rpwm=0x%02X cpwm=0x%02X\n", __func__, pwrpriv->rpwm, pwrpriv->cpwm);
1484
1485         if ((pwrpriv->rpwm == pwrpriv->cpwm) || (pwrpriv->cpwm >= PS_STATE_S2))
1486         {
1487                 DBG_871X("+%s: cpwm=%d, nothing to do!\n", __func__, pwrpriv->cpwm);
1488                 return;
1489         }
1490
1491         _set_workitem(&pwrpriv->rpwmtimeoutwi);
1492 }
1493 #endif // CONFIG_LPS_RPWM_TIMER
1494
1495 __inline static void register_task_alive(struct pwrctrl_priv *pwrctrl, u32 tag)
1496 {
1497         pwrctrl->alives |= tag;
1498 }
1499
1500 __inline static void unregister_task_alive(struct pwrctrl_priv *pwrctrl, u32 tag)
1501 {
1502         pwrctrl->alives &= ~tag;
1503 }
1504
1505
1506 /*
1507  * Description:
1508  *      Check if the fw_pwrstate is okay for I/O.
1509  *      If not (cpwm is less than S2), then the sub-routine
1510  *      will raise the cpwm to be greater than or equal to S2.
1511  *
1512  *      Calling Context: Passive
1513  *
1514  *      Constraint:
1515  *              1. this function will request pwrctrl->lock
1516  * 
1517  * Return Value:
1518  *      _SUCCESS        hardware is ready for I/O
1519  *      _FAIL           can't I/O right now
1520  */
1521 s32 rtw_register_task_alive(PADAPTER padapter, u32 task)
1522 {
1523         s32 res;
1524         struct pwrctrl_priv *pwrctrl;
1525         u8 pslv;
1526
1527 _func_enter_;
1528
1529         res = _SUCCESS;
1530         pwrctrl = adapter_to_pwrctl(padapter);
1531         pslv = PS_STATE_S2;
1532
1533 #if defined(CONFIG_RTL8723A) && defined(CONFIG_BT_COEXIST)
1534         if (rtw_btcoex_IsBtControlLps(padapter) == _TRUE)
1535         {
1536                 u8 btcoex_rpwm;
1537                 btcoex_rpwm = rtw_btcoex_RpwmVal(padapter);
1538                 switch (btcoex_rpwm)
1539                 {
1540                         case 0x4:
1541                                 pslv = PS_STATE_S3;
1542                                 break;
1543
1544                         case 0xC:
1545                                 pslv = PS_STATE_S4;
1546                                 break;
1547                 }
1548         }
1549 #endif // CONFIG_RTL8723A & CONFIG_BT_COEXIST
1550
1551         _enter_pwrlock(&pwrctrl->lock);
1552
1553         register_task_alive(pwrctrl, task);
1554
1555         if (pwrctrl->bFwCurrentInPSMode == _TRUE)
1556         {
1557                 RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_notice_,
1558                                  ("%s: task=0x%x cpwm=0x%02x alives=0x%08x\n",
1559                                   __FUNCTION__, task, pwrctrl->cpwm, pwrctrl->alives));
1560
1561                 if (pwrctrl->cpwm < pslv)
1562                 {
1563                         if (pwrctrl->cpwm < PS_STATE_S2)
1564                                 res = _FAIL;
1565                         if (pwrctrl->rpwm < pslv)
1566                                 rtw_set_rpwm(padapter, pslv);
1567                 }
1568         }
1569
1570         _exit_pwrlock(&pwrctrl->lock);
1571
1572 #ifdef CONFIG_DETECT_CPWM_BY_POLLING
1573         if (_FAIL == res)
1574         {
1575                 if (pwrctrl->cpwm >= PS_STATE_S2)
1576                         res = _SUCCESS;
1577         }
1578 #endif // CONFIG_DETECT_CPWM_BY_POLLING
1579
1580 _func_exit_;
1581
1582         return res;     
1583 }
1584
1585 /*
1586  * Description:
1587  *      If task is done, call this func. to power down firmware again.
1588  *
1589  *      Constraint:
1590  *              1. this function will request pwrctrl->lock
1591  *
1592  * Return Value:
1593  *      none
1594  */
1595 void rtw_unregister_task_alive(PADAPTER padapter, u32 task)
1596 {
1597         struct pwrctrl_priv *pwrctrl;
1598         u8 pslv;
1599
1600 _func_enter_;
1601
1602         pwrctrl = adapter_to_pwrctl(padapter);
1603         pslv = PS_STATE_S0;
1604
1605 #ifdef CONFIG_BT_COEXIST
1606         if ((rtw_btcoex_IsBtDisabled(padapter) == _FALSE)
1607                 && (rtw_btcoex_IsBtControlLps(padapter) == _TRUE))
1608         {
1609                 u8 val8;
1610
1611                 val8 = rtw_btcoex_LpsVal(padapter);
1612                 if (val8 & BIT(4))
1613                         pslv = PS_STATE_S2;
1614
1615 #ifdef CONFIG_RTL8723A
1616                 val8 = rtw_btcoex_RpwmVal(padapter);
1617                 switch (val8)
1618                 {
1619                         case 0x4:
1620                                 pslv = PS_STATE_S3;
1621                                 break;
1622
1623                         case 0xC:
1624                                 pslv = PS_STATE_S4;
1625                                 break;
1626                 }
1627 #endif // CONFIG_RTL8723A
1628         }
1629 #endif // CONFIG_BT_COEXIST
1630
1631         _enter_pwrlock(&pwrctrl->lock);
1632
1633         unregister_task_alive(pwrctrl, task);
1634
1635         if ((pwrctrl->pwr_mode != PS_MODE_ACTIVE)
1636                 && (pwrctrl->bFwCurrentInPSMode == _TRUE))
1637         {
1638                 RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_notice_,
1639                                  ("%s: cpwm=0x%02x alives=0x%08x\n",
1640                                   __FUNCTION__, pwrctrl->cpwm, pwrctrl->alives));
1641
1642                 if (pwrctrl->cpwm > pslv)
1643                 {
1644                         if ((pslv >= PS_STATE_S2) || (pwrctrl->alives == 0))
1645                                 rtw_set_rpwm(padapter, pslv);
1646                 }
1647         }
1648
1649         _exit_pwrlock(&pwrctrl->lock);
1650
1651 _func_exit_;
1652 }
1653
1654 /*
1655  * Caller: rtw_xmit_thread
1656  * 
1657  * Check if the fw_pwrstate is okay for xmit.
1658  * If not (cpwm is less than S3), then the sub-routine
1659  * will raise the cpwm to be greater than or equal to S3. 
1660  *
1661  * Calling Context: Passive
1662  * 
1663  * Return Value:
1664  *       _SUCCESS       rtw_xmit_thread can write fifo/txcmd afterwards.
1665  *       _FAIL          rtw_xmit_thread can not do anything.
1666  */
1667 s32 rtw_register_tx_alive(PADAPTER padapter)
1668 {
1669         s32 res;
1670         struct pwrctrl_priv *pwrctrl;
1671         u8 pslv;
1672
1673 _func_enter_;
1674
1675         res = _SUCCESS;
1676         pwrctrl = adapter_to_pwrctl(padapter);
1677         pslv = PS_STATE_S2;
1678
1679 #if defined(CONFIG_RTL8723A) && defined(CONFIG_BT_COEXIST)
1680         if (rtw_btcoex_IsBtControlLps(padapter) == _TRUE)
1681         {
1682                 u8 btcoex_rpwm;
1683                 btcoex_rpwm = rtw_btcoex_RpwmVal(padapter);
1684                 switch (btcoex_rpwm)
1685                 {
1686                         case 0x4:
1687                                 pslv = PS_STATE_S3;
1688                                 break;
1689
1690                         case 0xC:
1691                                 pslv = PS_STATE_S4;
1692                                 break;
1693                 }
1694         }
1695 #endif // CONFIG_RTL8723A & CONFIG_BT_COEXIST
1696
1697         _enter_pwrlock(&pwrctrl->lock);
1698
1699         register_task_alive(pwrctrl, XMIT_ALIVE);
1700
1701         if (pwrctrl->bFwCurrentInPSMode == _TRUE)
1702         {
1703                 RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_notice_,
1704                                  ("rtw_register_tx_alive: cpwm=0x%02x alives=0x%08x\n",
1705                                   pwrctrl->cpwm, pwrctrl->alives));
1706
1707                 if (pwrctrl->cpwm < pslv)
1708                 {
1709                         if (pwrctrl->cpwm < PS_STATE_S2)
1710                                 res = _FAIL;
1711                         if (pwrctrl->rpwm < pslv)
1712                                 rtw_set_rpwm(padapter, pslv);
1713                 }
1714         }
1715
1716         _exit_pwrlock(&pwrctrl->lock);
1717
1718 #ifdef CONFIG_DETECT_CPWM_BY_POLLING
1719         if (_FAIL == res)
1720         {
1721                 if (pwrctrl->cpwm >= PS_STATE_S2)
1722                         res = _SUCCESS;
1723         }
1724 #endif // CONFIG_DETECT_CPWM_BY_POLLING
1725
1726 _func_exit_;
1727
1728         return res;     
1729 }
1730
1731 /*
1732  * Caller: rtw_cmd_thread
1733  *
1734  * Check if the fw_pwrstate is okay for issuing cmd.
1735  * If not (cpwm should be is less than S2), then the sub-routine
1736  * will raise the cpwm to be greater than or equal to S2.
1737  *
1738  * Calling Context: Passive
1739  *
1740  * Return Value:
1741  *      _SUCCESS        rtw_cmd_thread can issue cmds to firmware afterwards.
1742  *      _FAIL           rtw_cmd_thread can not do anything.
1743  */
1744 s32 rtw_register_cmd_alive(PADAPTER padapter)
1745 {
1746         s32 res;
1747         struct pwrctrl_priv *pwrctrl;
1748         u8 pslv;
1749
1750 _func_enter_;
1751
1752         res = _SUCCESS;
1753         pwrctrl = adapter_to_pwrctl(padapter);
1754         pslv = PS_STATE_S2;
1755
1756 #if defined(CONFIG_RTL8723A) && defined(CONFIG_BT_COEXIST)
1757         if (rtw_btcoex_IsBtControlLps(padapter) == _TRUE)
1758         {
1759                 u8 btcoex_rpwm;
1760                 btcoex_rpwm = rtw_btcoex_RpwmVal(padapter);
1761                 switch (btcoex_rpwm)
1762                 {
1763                         case 0x4:
1764                                 pslv = PS_STATE_S3;
1765                                 break;
1766
1767                         case 0xC:
1768                                 pslv = PS_STATE_S4;
1769                                 break;
1770                 }
1771         }
1772 #endif // CONFIG_RTL8723A & CONFIG_BT_COEXIST
1773
1774         _enter_pwrlock(&pwrctrl->lock);
1775
1776         register_task_alive(pwrctrl, CMD_ALIVE);
1777
1778         if (pwrctrl->bFwCurrentInPSMode == _TRUE)
1779         {
1780                 RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_info_,
1781                                  ("rtw_register_cmd_alive: cpwm=0x%02x alives=0x%08x\n",
1782                                   pwrctrl->cpwm, pwrctrl->alives));
1783
1784                 if (pwrctrl->cpwm < pslv)
1785                 {
1786                         if (pwrctrl->cpwm < PS_STATE_S2)
1787                                 res = _FAIL;
1788                         if (pwrctrl->rpwm < pslv)
1789                                 rtw_set_rpwm(padapter, pslv);
1790                 }
1791         }
1792
1793         _exit_pwrlock(&pwrctrl->lock);
1794
1795 #ifdef CONFIG_DETECT_CPWM_BY_POLLING
1796         if (_FAIL == res)
1797         {
1798                 if (pwrctrl->cpwm >= PS_STATE_S2)
1799                         res = _SUCCESS;
1800         }
1801 #endif // CONFIG_DETECT_CPWM_BY_POLLING
1802
1803 _func_exit_;
1804
1805         return res;
1806 }
1807
1808 /*
1809  * Caller: rx_isr
1810  *
1811  * Calling Context: Dispatch/ISR
1812  *
1813  * Return Value:
1814  *      _SUCCESS
1815  *      _FAIL
1816  */
1817 s32 rtw_register_rx_alive(PADAPTER padapter)
1818 {
1819         struct pwrctrl_priv *pwrctrl;
1820
1821 _func_enter_;
1822
1823         pwrctrl = adapter_to_pwrctl(padapter);
1824
1825         _enter_pwrlock(&pwrctrl->lock);
1826
1827         register_task_alive(pwrctrl, RECV_ALIVE);
1828         RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_notice_,
1829                          ("rtw_register_rx_alive: cpwm=0x%02x alives=0x%08x\n",
1830                           pwrctrl->cpwm, pwrctrl->alives));
1831
1832         _exit_pwrlock(&pwrctrl->lock);
1833
1834 _func_exit_;
1835
1836         return _SUCCESS;
1837 }
1838
1839 /*
1840  * Caller: evt_isr or evt_thread
1841  *
1842  * Calling Context: Dispatch/ISR or Passive
1843  *
1844  * Return Value:
1845  *      _SUCCESS
1846  *      _FAIL
1847  */
1848 s32 rtw_register_evt_alive(PADAPTER padapter)
1849 {
1850         struct pwrctrl_priv *pwrctrl;
1851
1852 _func_enter_;
1853
1854         pwrctrl = adapter_to_pwrctl(padapter);
1855
1856         _enter_pwrlock(&pwrctrl->lock);
1857
1858         register_task_alive(pwrctrl, EVT_ALIVE);
1859         RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_notice_,
1860                          ("rtw_register_evt_alive: cpwm=0x%02x alives=0x%08x\n",
1861                           pwrctrl->cpwm, pwrctrl->alives));
1862
1863         _exit_pwrlock(&pwrctrl->lock);
1864
1865 _func_exit_;
1866
1867         return _SUCCESS;
1868 }
1869
1870 /*
1871  * Caller: ISR
1872  *
1873  * If ISR's txdone,
1874  * No more pkts for TX,
1875  * Then driver shall call this fun. to power down firmware again.
1876  */
1877 void rtw_unregister_tx_alive(PADAPTER padapter)
1878 {
1879         struct pwrctrl_priv *pwrctrl;
1880         u8 pslv;
1881
1882 _func_enter_;
1883
1884         pwrctrl = adapter_to_pwrctl(padapter);
1885         pslv = PS_STATE_S0;
1886
1887 #ifdef CONFIG_BT_COEXIST
1888         if ((rtw_btcoex_IsBtDisabled(padapter) == _FALSE)
1889                 && (rtw_btcoex_IsBtControlLps(padapter) == _TRUE))
1890         {
1891                 u8 val8;
1892
1893                 val8 = rtw_btcoex_LpsVal(padapter);
1894                 if (val8 & BIT(4))
1895                         pslv = PS_STATE_S2;
1896
1897 #ifdef CONFIG_RTL8723A
1898                 val8 = rtw_btcoex_RpwmVal(padapter);
1899                 switch (val8)
1900                 {
1901                         case 0x4:
1902                                 pslv = PS_STATE_S3;
1903                                 break;
1904
1905                         case 0xC:
1906                                 pslv = PS_STATE_S4;
1907                                 break;
1908                 }
1909 #endif // CONFIG_RTL8723A
1910         }
1911 #endif // CONFIG_BT_COEXIST
1912
1913 #ifdef CONFIG_P2P_PS
1914         if(padapter->wdinfo.p2p_ps_mode > P2P_PS_NONE)
1915         {
1916                 pslv = PS_STATE_S2;
1917         }
1918 #ifdef CONFIG_CONCURRENT_MODE
1919         else if(rtw_buddy_adapter_up(padapter))
1920         {
1921                 if(padapter->pbuddy_adapter->wdinfo.p2p_ps_mode > P2P_PS_NONE)
1922                         pslv = PS_STATE_S2;
1923         }
1924 #endif
1925 #endif
1926
1927         _enter_pwrlock(&pwrctrl->lock);
1928
1929         unregister_task_alive(pwrctrl, XMIT_ALIVE);
1930
1931         if ((pwrctrl->pwr_mode != PS_MODE_ACTIVE)
1932                 && (pwrctrl->bFwCurrentInPSMode == _TRUE))
1933         {
1934                 RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_notice_,
1935                                  ("%s: cpwm=0x%02x alives=0x%08x\n",
1936                                   __FUNCTION__, pwrctrl->cpwm, pwrctrl->alives));
1937
1938                 if (pwrctrl->cpwm > pslv)
1939                 {
1940                         if ((pslv >= PS_STATE_S2) || (pwrctrl->alives == 0))
1941                                 rtw_set_rpwm(padapter, pslv);
1942                 }
1943         }
1944
1945         _exit_pwrlock(&pwrctrl->lock);
1946
1947 _func_exit_;
1948 }
1949
1950 /*
1951  * Caller: ISR
1952  *
1953  * If all commands have been done,
1954  * and no more command to do,
1955  * then driver shall call this fun. to power down firmware again.
1956  */
1957 void rtw_unregister_cmd_alive(PADAPTER padapter)
1958 {
1959         struct pwrctrl_priv *pwrctrl;
1960         u8 pslv;
1961
1962 _func_enter_;
1963
1964         pwrctrl = adapter_to_pwrctl(padapter);
1965         pslv = PS_STATE_S0;
1966
1967 #ifdef CONFIG_BT_COEXIST
1968         if ((rtw_btcoex_IsBtDisabled(padapter) == _FALSE)
1969                 && (rtw_btcoex_IsBtControlLps(padapter) == _TRUE))
1970         {
1971                 u8 val8;
1972
1973                 val8 = rtw_btcoex_LpsVal(padapter);
1974                 if (val8 & BIT(4))
1975                         pslv = PS_STATE_S2;
1976
1977 #ifdef CONFIG_RTL8723A
1978                 val8 = rtw_btcoex_RpwmVal(padapter);
1979                 switch (val8)
1980                 {
1981                         case 0x4:
1982                                 pslv = PS_STATE_S3;
1983                                 break;
1984
1985                         case 0xC:
1986                                 pslv = PS_STATE_S4;
1987                                 break;
1988                 }
1989 #endif // CONFIG_RTL8723A
1990         }
1991 #endif // CONFIG_BT_COEXIST
1992
1993 #ifdef CONFIG_P2P_PS
1994         if(padapter->wdinfo.p2p_ps_mode > P2P_PS_NONE)
1995         {
1996                 pslv = PS_STATE_S2;
1997         }
1998 #ifdef CONFIG_CONCURRENT_MODE
1999         else if(rtw_buddy_adapter_up(padapter))
2000         {
2001                 if(padapter->pbuddy_adapter->wdinfo.p2p_ps_mode > P2P_PS_NONE)
2002                         pslv = PS_STATE_S2;
2003         }
2004 #endif
2005 #endif
2006
2007         _enter_pwrlock(&pwrctrl->lock);
2008
2009         unregister_task_alive(pwrctrl, CMD_ALIVE);
2010
2011         if ((pwrctrl->pwr_mode != PS_MODE_ACTIVE)
2012                 && (pwrctrl->bFwCurrentInPSMode == _TRUE))
2013         {
2014                 RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_info_,
2015                                  ("%s: cpwm=0x%02x alives=0x%08x\n",
2016                                   __FUNCTION__, pwrctrl->cpwm, pwrctrl->alives));
2017
2018                 if (pwrctrl->cpwm > pslv)
2019                 {
2020                         if ((pslv >= PS_STATE_S2) || (pwrctrl->alives == 0))
2021                                 rtw_set_rpwm(padapter, pslv);
2022                 }
2023         }
2024
2025         _exit_pwrlock(&pwrctrl->lock);
2026
2027 _func_exit_;
2028 }
2029
2030 /*
2031  * Caller: ISR
2032  */
2033 void rtw_unregister_rx_alive(PADAPTER padapter)
2034 {
2035         struct pwrctrl_priv *pwrctrl;
2036
2037 _func_enter_;
2038
2039         pwrctrl = adapter_to_pwrctl(padapter);
2040
2041         _enter_pwrlock(&pwrctrl->lock);
2042
2043         unregister_task_alive(pwrctrl, RECV_ALIVE);
2044
2045         RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_notice_,
2046                          ("rtw_unregister_rx_alive: cpwm=0x%02x alives=0x%08x\n",
2047                           pwrctrl->cpwm, pwrctrl->alives));
2048
2049         _exit_pwrlock(&pwrctrl->lock);
2050
2051 _func_exit_;
2052 }
2053
2054 void rtw_unregister_evt_alive(PADAPTER padapter)
2055 {
2056         struct pwrctrl_priv *pwrctrl;
2057
2058 _func_enter_;
2059
2060         pwrctrl = adapter_to_pwrctl(padapter);
2061
2062         unregister_task_alive(pwrctrl, EVT_ALIVE);
2063
2064         RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_notice_,
2065                          ("rtw_unregister_evt_alive: cpwm=0x%02x alives=0x%08x\n",
2066                           pwrctrl->cpwm, pwrctrl->alives));
2067
2068         _exit_pwrlock(&pwrctrl->lock);
2069
2070 _func_exit_;
2071 }
2072 #endif  /* CONFIG_LPS_LCLK */
2073
2074 #ifdef CONFIG_RESUME_IN_WORKQUEUE
2075 static void resume_workitem_callback(struct work_struct *work);
2076 #endif //CONFIG_RESUME_IN_WORKQUEUE
2077
2078 void rtw_init_pwrctrl_priv(PADAPTER padapter)
2079 {
2080         struct pwrctrl_priv *pwrctrlpriv = adapter_to_pwrctl(padapter);
2081
2082 #if defined(CONFIG_CONCURRENT_MODE)
2083         if (padapter->adapter_type != PRIMARY_ADAPTER)
2084                 return;
2085 #endif
2086
2087 _func_enter_;
2088
2089 #ifdef PLATFORM_WINDOWS
2090         pwrctrlpriv->pnp_current_pwr_state=NdisDeviceStateD0;
2091 #endif
2092
2093         _init_pwrlock(&pwrctrlpriv->lock);
2094         _init_pwrlock(&pwrctrlpriv->check_32k_lock);
2095         pwrctrlpriv->rf_pwrstate = rf_on;
2096         pwrctrlpriv->ips_enter_cnts=0;
2097         pwrctrlpriv->ips_leave_cnts=0;
2098         pwrctrlpriv->bips_processing = _FALSE;
2099
2100         pwrctrlpriv->ips_mode = padapter->registrypriv.ips_mode;
2101         pwrctrlpriv->ips_mode_req = padapter->registrypriv.ips_mode;
2102
2103         pwrctrlpriv->pwr_state_check_interval = RTW_PWR_STATE_CHK_INTERVAL;
2104         pwrctrlpriv->pwr_state_check_cnts = 0;
2105         pwrctrlpriv->bInternalAutoSuspend = _FALSE;
2106         pwrctrlpriv->bInSuspend = _FALSE;
2107         pwrctrlpriv->bkeepfwalive = _FALSE;
2108
2109 #ifdef CONFIG_AUTOSUSPEND
2110 #ifdef SUPPORT_HW_RFOFF_DETECTED
2111         pwrctrlpriv->pwr_state_check_interval = (pwrctrlpriv->bHWPwrPindetect) ?1000:2000;              
2112 #endif
2113 #endif
2114
2115         pwrctrlpriv->LpsIdleCount = 0;
2116         //pwrctrlpriv->FWCtrlPSMode =padapter->registrypriv.power_mgnt;// PS_MODE_MIN;
2117         if (padapter->registrypriv.mp_mode == 1)
2118                 pwrctrlpriv->power_mgnt =PS_MODE_ACTIVE ;
2119         else    
2120                 pwrctrlpriv->power_mgnt =padapter->registrypriv.power_mgnt;// PS_MODE_MIN;
2121         pwrctrlpriv->bLeisurePs = (PS_MODE_ACTIVE != pwrctrlpriv->power_mgnt)?_TRUE:_FALSE;
2122
2123         pwrctrlpriv->bFwCurrentInPSMode = _FALSE;
2124
2125         pwrctrlpriv->rpwm = 0;
2126         pwrctrlpriv->cpwm = PS_STATE_S4;
2127
2128         pwrctrlpriv->pwr_mode = PS_MODE_ACTIVE;
2129         pwrctrlpriv->smart_ps = padapter->registrypriv.smart_ps;
2130         pwrctrlpriv->bcn_ant_mode = 0;
2131         pwrctrlpriv->dtim = 0;
2132
2133         pwrctrlpriv->tog = 0x80;
2134
2135 #ifdef CONFIG_LPS_LCLK
2136         rtw_hal_set_hwreg(padapter, HW_VAR_SET_RPWM, (u8 *)(&pwrctrlpriv->rpwm));
2137
2138         _init_workitem(&pwrctrlpriv->cpwm_event, cpwm_event_callback, NULL);
2139
2140 #ifdef CONFIG_LPS_RPWM_TIMER
2141         pwrctrlpriv->brpwmtimeout = _FALSE;
2142         _init_workitem(&pwrctrlpriv->rpwmtimeoutwi, rpwmtimeout_workitem_callback, NULL);
2143         _init_timer(&pwrctrlpriv->pwr_rpwm_timer, padapter->pnetdev, pwr_rpwm_timeout_handler, padapter);
2144 #endif // CONFIG_LPS_RPWM_TIMER
2145 #endif // CONFIG_LPS_LCLK
2146
2147         rtw_init_timer(&pwrctrlpriv->pwr_state_check_timer, padapter, pwr_state_check_handler);
2148
2149         pwrctrlpriv->wowlan_mode = _FALSE;
2150         pwrctrlpriv->wowlan_ap_mode = _FALSE;
2151
2152         #ifdef CONFIG_RESUME_IN_WORKQUEUE
2153         _init_workitem(&pwrctrlpriv->resume_work, resume_workitem_callback, NULL);
2154         pwrctrlpriv->rtw_workqueue = create_singlethread_workqueue("rtw_workqueue");
2155         #endif //CONFIG_RESUME_IN_WORKQUEUE
2156
2157         #if defined(CONFIG_HAS_EARLYSUSPEND) || defined(CONFIG_ANDROID_POWER)
2158         pwrctrlpriv->early_suspend.suspend = NULL;
2159         rtw_register_early_suspend(pwrctrlpriv);
2160         #endif //CONFIG_HAS_EARLYSUSPEND || CONFIG_ANDROID_POWER
2161
2162 #ifdef CONFIG_PNO_SUPPORT
2163         pwrctrlpriv->pnlo_info = NULL;
2164         pwrctrlpriv->pscan_info = NULL;
2165         pwrctrlpriv->pno_ssid_list = NULL;
2166 #endif
2167
2168 _func_exit_;
2169
2170 }
2171
2172
2173 void rtw_free_pwrctrl_priv(PADAPTER adapter)
2174 {
2175         struct pwrctrl_priv *pwrctrlpriv = adapter_to_pwrctl(adapter);
2176
2177 #if defined(CONFIG_CONCURRENT_MODE)
2178         if (adapter->adapter_type != PRIMARY_ADAPTER)
2179                 return;
2180 #endif  
2181
2182 _func_enter_;
2183
2184         //_rtw_memset((unsigned char *)pwrctrlpriv, 0, sizeof(struct pwrctrl_priv));
2185
2186
2187         #ifdef CONFIG_RESUME_IN_WORKQUEUE
2188         if (pwrctrlpriv->rtw_workqueue) { 
2189                 flush_workqueue(pwrctrlpriv->rtw_workqueue);
2190                 destroy_workqueue(pwrctrlpriv->rtw_workqueue);
2191         }
2192         #endif
2193
2194 #ifdef CONFIG_PNO_SUPPORT
2195         if (pwrctrlpriv->pnlo_info != NULL)
2196                 printk("****** pnlo_info memory leak********\n");
2197
2198         if (pwrctrlpriv->pscan_info != NULL)
2199                 printk("****** pscan_info memory leak********\n");
2200
2201         if (pwrctrlpriv->pno_ssid_list != NULL)
2202                 printk("****** pno_ssid_list memory leak********\n");
2203 #endif
2204
2205         #if defined(CONFIG_HAS_EARLYSUSPEND) || defined(CONFIG_ANDROID_POWER)
2206         rtw_unregister_early_suspend(pwrctrlpriv);
2207         #endif //CONFIG_HAS_EARLYSUSPEND || CONFIG_ANDROID_POWER
2208
2209         _free_pwrlock(&pwrctrlpriv->lock);
2210         _free_pwrlock(&pwrctrlpriv->check_32k_lock);
2211
2212 _func_exit_;
2213 }
2214
2215 #ifdef CONFIG_RESUME_IN_WORKQUEUE
2216 extern int rtw_resume_process(_adapter *padapter);
2217
2218 static void resume_workitem_callback(struct work_struct *work)
2219 {
2220         struct pwrctrl_priv *pwrpriv = container_of(work, struct pwrctrl_priv, resume_work);
2221         struct dvobj_priv *dvobj = pwrctl_to_dvobj(pwrpriv);
2222         _adapter *adapter = dvobj->if1;
2223
2224         DBG_871X("%s\n",__FUNCTION__);
2225
2226         rtw_resume_process(adapter);
2227
2228         rtw_resume_unlock_suspend();
2229 }
2230
2231 void rtw_resume_in_workqueue(struct pwrctrl_priv *pwrpriv)
2232 {
2233         // accquire system's suspend lock preventing from falliing asleep while resume in workqueue
2234         //rtw_lock_suspend();
2235         rtw_resume_lock_suspend();
2236         
2237         #if 1
2238         queue_work(pwrpriv->rtw_workqueue, &pwrpriv->resume_work);      
2239         #else
2240         _set_workitem(&pwrpriv->resume_work);
2241         #endif
2242 }
2243 #endif //CONFIG_RESUME_IN_WORKQUEUE
2244
2245 #if defined(CONFIG_HAS_EARLYSUSPEND) || defined(CONFIG_ANDROID_POWER)
2246 inline bool rtw_is_earlysuspend_registered(struct pwrctrl_priv *pwrpriv)
2247 {
2248         return (pwrpriv->early_suspend.suspend) ? _TRUE : _FALSE;
2249 }
2250
2251 inline bool rtw_is_do_late_resume(struct pwrctrl_priv *pwrpriv)
2252 {
2253         return (pwrpriv->do_late_resume) ? _TRUE : _FALSE;
2254 }
2255
2256 inline void rtw_set_do_late_resume(struct pwrctrl_priv *pwrpriv, bool enable)
2257 {
2258         pwrpriv->do_late_resume = enable;
2259 }
2260 #endif
2261
2262 #ifdef CONFIG_HAS_EARLYSUSPEND
2263 extern int rtw_resume_process(_adapter *padapter);
2264 static void rtw_early_suspend(struct early_suspend *h)
2265 {
2266         struct pwrctrl_priv *pwrpriv = container_of(h, struct pwrctrl_priv, early_suspend);
2267         DBG_871X("%s\n",__FUNCTION__);
2268
2269         rtw_set_do_late_resume(pwrpriv, _FALSE);
2270 }
2271
2272 static void rtw_late_resume(struct early_suspend *h)
2273 {
2274         struct pwrctrl_priv *pwrpriv = container_of(h, struct pwrctrl_priv, early_suspend);
2275         struct dvobj_priv *dvobj = pwrctl_to_dvobj(pwrpriv);
2276         _adapter *adapter = dvobj->if1;
2277
2278         DBG_871X("%s\n",__FUNCTION__);
2279
2280         if(pwrpriv->do_late_resume) {
2281                 rtw_set_do_late_resume(pwrpriv, _FALSE);
2282                 rtw_resume_process(adapter);
2283         }
2284 }
2285
2286 void rtw_register_early_suspend(struct pwrctrl_priv *pwrpriv)
2287 {
2288         DBG_871X("%s\n", __FUNCTION__);
2289
2290         //jeff: set the early suspend level before blank screen, so we wll do late resume after scree is lit
2291         pwrpriv->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN - 20;
2292         pwrpriv->early_suspend.suspend = rtw_early_suspend;
2293         pwrpriv->early_suspend.resume = rtw_late_resume;
2294         register_early_suspend(&pwrpriv->early_suspend);        
2295
2296         
2297 }
2298
2299 void rtw_unregister_early_suspend(struct pwrctrl_priv *pwrpriv)
2300 {
2301         DBG_871X("%s\n", __FUNCTION__);
2302
2303         rtw_set_do_late_resume(pwrpriv, _FALSE);
2304
2305         if (pwrpriv->early_suspend.suspend) 
2306                 unregister_early_suspend(&pwrpriv->early_suspend);
2307
2308         pwrpriv->early_suspend.suspend = NULL;
2309         pwrpriv->early_suspend.resume = NULL;
2310 }
2311 #endif //CONFIG_HAS_EARLYSUSPEND
2312
2313 #ifdef CONFIG_ANDROID_POWER
2314 #if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) || defined(CONFIG_GSPI_HCI)
2315 extern int rtw_resume_process(PADAPTER padapter);
2316 #endif
2317 static void rtw_early_suspend(android_early_suspend_t *h)
2318 {
2319         struct pwrctrl_priv *pwrpriv = container_of(h, struct pwrctrl_priv, early_suspend);
2320         DBG_871X("%s\n",__FUNCTION__);
2321
2322         rtw_set_do_late_resume(pwrpriv, _FALSE);
2323 }
2324
2325 static void rtw_late_resume(android_early_suspend_t *h)
2326 {
2327         struct pwrctrl_priv *pwrpriv = container_of(h, struct pwrctrl_priv, early_suspend);
2328         struct dvobj_priv *dvobj = pwrctl_to_dvobj(pwrpriv);
2329         _adapter *adapter = dvobj->if1;
2330
2331         DBG_871X("%s\n",__FUNCTION__);
2332         if(pwrpriv->do_late_resume) {
2333                 #if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) || defined(CONFIG_GSPI_HCI)
2334                 rtw_set_do_late_resume(pwrpriv, _FALSE);
2335                 rtw_resume_process(adapter);
2336                 #endif
2337         }
2338 }
2339
2340 void rtw_register_early_suspend(struct pwrctrl_priv *pwrpriv)
2341 {
2342         DBG_871X("%s\n", __FUNCTION__);
2343
2344         //jeff: set the early suspend level before blank screen, so we wll do late resume after scree is lit
2345         pwrpriv->early_suspend.level = ANDROID_EARLY_SUSPEND_LEVEL_BLANK_SCREEN - 20;
2346         pwrpriv->early_suspend.suspend = rtw_early_suspend;
2347         pwrpriv->early_suspend.resume = rtw_late_resume;
2348         android_register_early_suspend(&pwrpriv->early_suspend);        
2349 }
2350
2351 void rtw_unregister_early_suspend(struct pwrctrl_priv *pwrpriv)
2352 {
2353         DBG_871X("%s\n", __FUNCTION__);
2354
2355         rtw_set_do_late_resume(pwrpriv, _FALSE);
2356
2357         if (pwrpriv->early_suspend.suspend) 
2358                 android_unregister_early_suspend(&pwrpriv->early_suspend);
2359
2360         pwrpriv->early_suspend.suspend = NULL;
2361         pwrpriv->early_suspend.resume = NULL;
2362 }
2363 #endif //CONFIG_ANDROID_POWER
2364
2365 u8 rtw_interface_ps_func(_adapter *padapter,HAL_INTF_PS_FUNC efunc_id,u8* val)
2366 {
2367         u8 bResult = _TRUE;
2368         rtw_hal_intf_ps_func(padapter,efunc_id,val);
2369         
2370         return bResult;
2371 }
2372
2373
2374 inline void rtw_set_ips_deny(_adapter *padapter, u32 ms)
2375 {
2376         struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
2377         pwrpriv->ips_deny_time = rtw_get_current_time() + rtw_ms_to_systime(ms);
2378 }
2379
2380 /*
2381 * rtw_pwr_wakeup - Wake the NIC up from: 1)IPS. 2)USB autosuspend
2382 * @adapter: pointer to _adapter structure
2383 * @ips_deffer_ms: the ms wiil prevent from falling into IPS after wakeup
2384 * Return _SUCCESS or _FAIL
2385 */
2386
2387 int _rtw_pwr_wakeup(_adapter *padapter, u32 ips_deffer_ms, const char *caller)
2388 {
2389         struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
2390         struct pwrctrl_priv *pwrpriv = dvobj_to_pwrctl(dvobj);
2391         struct mlme_priv *pmlmepriv;
2392         int ret = _SUCCESS;
2393         int i;
2394         u32 start = rtw_get_current_time();
2395
2396         /* for LPS */
2397         LeaveAllPowerSaveMode(padapter);
2398
2399         /* IPS still bound with primary adapter */
2400         padapter = GET_PRIMARY_ADAPTER(padapter);
2401         pmlmepriv = &padapter->mlmepriv;
2402
2403         if (pwrpriv->ips_deny_time < rtw_get_current_time() + rtw_ms_to_systime(ips_deffer_ms))
2404                 pwrpriv->ips_deny_time = rtw_get_current_time() + rtw_ms_to_systime(ips_deffer_ms);
2405
2406
2407         if (pwrpriv->ps_processing) {
2408                 DBG_871X("%s wait ps_processing...\n", __func__);
2409                 while (pwrpriv->ps_processing && rtw_get_passing_time_ms(start) <= 3000)
2410                         rtw_msleep_os(10);
2411                 if (pwrpriv->ps_processing)
2412                         DBG_871X("%s wait ps_processing timeout\n", __func__);
2413                 else
2414                         DBG_871X("%s wait ps_processing done\n", __func__);
2415         }
2416
2417 #ifdef DBG_CONFIG_ERROR_DETECT
2418         if (rtw_hal_sreset_inprogress(padapter)) {
2419                 DBG_871X("%s wait sreset_inprogress...\n", __func__);
2420                 while (rtw_hal_sreset_inprogress(padapter) && rtw_get_passing_time_ms(start) <= 4000)
2421                         rtw_msleep_os(10);
2422                 if (rtw_hal_sreset_inprogress(padapter))
2423                         DBG_871X("%s wait sreset_inprogress timeout\n", __func__);
2424                 else
2425                         DBG_871X("%s wait sreset_inprogress done\n", __func__);
2426         }
2427 #endif
2428
2429         if (pwrpriv->bInternalAutoSuspend == _FALSE && pwrpriv->bInSuspend) {
2430                 DBG_871X("%s wait bInSuspend...\n", __func__);
2431                 while (pwrpriv->bInSuspend 
2432                         && ((rtw_get_passing_time_ms(start) <= 3000 && !rtw_is_do_late_resume(pwrpriv))
2433                                 || (rtw_get_passing_time_ms(start) <= 500 && rtw_is_do_late_resume(pwrpriv)))
2434                 ) {
2435                         rtw_msleep_os(10);
2436                 }
2437                 if (pwrpriv->bInSuspend)
2438                         DBG_871X("%s wait bInSuspend timeout\n", __func__);
2439                 else
2440                         DBG_871X("%s wait bInSuspend done\n", __func__);
2441         }
2442
2443         //System suspend is not allowed to wakeup
2444         if((pwrpriv->bInternalAutoSuspend == _FALSE) && (_TRUE == pwrpriv->bInSuspend )){
2445                 ret = _FAIL;
2446                 goto exit;
2447         }
2448
2449         //block???
2450         if((pwrpriv->bInternalAutoSuspend == _TRUE)  && (padapter->net_closed == _TRUE)) {
2451                 ret = _FAIL;
2452                 goto exit;
2453         }
2454
2455         //I think this should be check in IPS, LPS, autosuspend functions...
2456         if (check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE)
2457         {
2458 #if defined (CONFIG_BT_COEXIST)&& defined (CONFIG_AUTOSUSPEND)
2459                 if(_TRUE==pwrpriv->bInternalAutoSuspend){
2460                         if(0==pwrpriv->autopm_cnt){
2461                         #if (LINUX_VERSION_CODE>=KERNEL_VERSION(2,6,33))                                
2462                                 if (usb_autopm_get_interface(adapter_to_dvobj(padapter)->pusbintf) < 0) 
2463                                 {
2464                                         DBG_871X( "can't get autopm: \n");
2465                                 }                       
2466                         #elif (LINUX_VERSION_CODE>=KERNEL_VERSION(2,6,20))                              
2467                                 usb_autopm_disable(adapter_to_dvobj(padapter)->pusbintf);
2468                         #else
2469                                 usb_autoresume_device(adapter_to_dvobj(padapter)->pusbdev, 1);
2470                         #endif
2471                         pwrpriv->autopm_cnt++;
2472                         }
2473 #endif  //#if defined (CONFIG_BT_COEXIST)&& defined (CONFIG_AUTOSUSPEND)
2474                 ret = _SUCCESS;
2475                 goto exit;
2476 #if defined (CONFIG_BT_COEXIST)&& defined (CONFIG_AUTOSUSPEND)
2477                 }
2478 #endif  //#if defined (CONFIG_BT_COEXIST)&& defined (CONFIG_AUTOSUSPEND)
2479         }       
2480
2481         if(rf_off == pwrpriv->rf_pwrstate )
2482         {               
2483 #ifdef CONFIG_USB_HCI
2484 #ifdef CONFIG_AUTOSUSPEND
2485                  if(pwrpriv->brfoffbyhw==_TRUE)
2486                 {
2487                         DBG_8192C("hw still in rf_off state ...........\n");
2488                         ret = _FAIL;
2489                         goto exit;
2490                 }
2491                 else if(padapter->registrypriv.usbss_enable)
2492                 {
2493                         DBG_8192C("%s call autoresume_enter....\n",__FUNCTION__);
2494                         if(_FAIL ==  autoresume_enter(padapter))
2495                         {
2496                                 DBG_8192C("======> autoresume fail.............\n");
2497                                 ret = _FAIL;
2498                                 goto exit;
2499                         }       
2500                 }
2501                 else
2502 #endif
2503 #endif
2504                 {
2505 #ifdef CONFIG_IPS
2506                         DBG_8192C("%s call ips_leave....\n",__FUNCTION__);
2507                         if(_FAIL ==  ips_leave(padapter))
2508                         {
2509                                 DBG_8192C("======> ips_leave fail.............\n");
2510                                 ret = _FAIL;
2511                                 goto exit;
2512                         }
2513 #endif
2514                 }
2515         }
2516
2517         //TODO: the following checking need to be merged...
2518         if(padapter->bDriverStopped
2519                 || !padapter->bup
2520                 || !padapter->hw_init_completed
2521         ){
2522                 DBG_8192C("%s: bDriverStopped=%d, bup=%d, hw_init_completed=%u\n"
2523                         , caller
2524                         , padapter->bDriverStopped
2525                         , padapter->bup
2526                         , padapter->hw_init_completed);
2527                 ret= _FALSE;
2528                 goto exit;
2529         }
2530
2531 exit:
2532         if (pwrpriv->ips_deny_time < rtw_get_current_time() + rtw_ms_to_systime(ips_deffer_ms))
2533                 pwrpriv->ips_deny_time = rtw_get_current_time() + rtw_ms_to_systime(ips_deffer_ms);
2534         return ret;
2535
2536 }
2537
2538 int rtw_pm_set_lps(_adapter *padapter, u8 mode)
2539 {
2540         int     ret = 0;        
2541         struct pwrctrl_priv *pwrctrlpriv = adapter_to_pwrctl(padapter);
2542         
2543         if ( mode < PS_MODE_NUM )
2544         {
2545                 if(pwrctrlpriv->power_mgnt !=mode)
2546                 {
2547                         if(PS_MODE_ACTIVE == mode)
2548                         {
2549                                 LeaveAllPowerSaveMode(padapter);
2550                         }
2551                         else
2552                         {
2553                                 pwrctrlpriv->LpsIdleCount = 2;
2554                         }
2555                         pwrctrlpriv->power_mgnt = mode;
2556                         pwrctrlpriv->bLeisurePs = (PS_MODE_ACTIVE != pwrctrlpriv->power_mgnt)?_TRUE:_FALSE;
2557                 }
2558         }
2559         else
2560         {
2561                 ret = -EINVAL;
2562         }
2563
2564         return ret;
2565 }
2566
2567 int rtw_pm_set_ips(_adapter *padapter, u8 mode)
2568 {
2569         struct pwrctrl_priv *pwrctrlpriv = adapter_to_pwrctl(padapter);
2570
2571         if( mode == IPS_NORMAL || mode == IPS_LEVEL_2 ) {
2572                 rtw_ips_mode_req(pwrctrlpriv, mode);
2573                 DBG_871X("%s %s\n", __FUNCTION__, mode == IPS_NORMAL?"IPS_NORMAL":"IPS_LEVEL_2");
2574                 return 0;
2575         } 
2576         else if(mode ==IPS_NONE){
2577                 rtw_ips_mode_req(pwrctrlpriv, mode);
2578                 DBG_871X("%s %s\n", __FUNCTION__, "IPS_NONE");
2579                 if((padapter->bSurpriseRemoved ==0)&&(_FAIL == rtw_pwr_wakeup(padapter)) )
2580                         return -EFAULT;
2581         }
2582         else {
2583                 return -EINVAL;
2584         }
2585         return 0;
2586 }
2587
2588 /*
2589  * ATTENTION:
2590  *      This function will request pwrctrl LOCK!
2591  */
2592 void rtw_ps_deny(PADAPTER padapter, PS_DENY_REASON reason)
2593 {
2594         struct pwrctrl_priv *pwrpriv;
2595         s32 ret;
2596
2597
2598 //      DBG_871X("+" FUNC_ADPT_FMT ": Request PS deny for %d (0x%08X)\n",
2599 //              FUNC_ADPT_ARG(padapter), reason, BIT(reason));
2600
2601         pwrpriv = adapter_to_pwrctl(padapter);
2602
2603         _enter_pwrlock(&pwrpriv->lock);
2604         if (pwrpriv->ps_deny & BIT(reason))
2605         {
2606                 DBG_871X(FUNC_ADPT_FMT ": [WARNING] Reason %d had been set before!!\n",
2607                         FUNC_ADPT_ARG(padapter), reason);
2608         }
2609         pwrpriv->ps_deny |= BIT(reason);
2610         _exit_pwrlock(&pwrpriv->lock);
2611
2612 //      DBG_871X("-" FUNC_ADPT_FMT ": Now PS deny for 0x%08X\n",
2613 //              FUNC_ADPT_ARG(padapter), pwrpriv->ps_deny);
2614 }
2615
2616 /*
2617  * ATTENTION:
2618  *      This function will request pwrctrl LOCK!
2619  */
2620 void rtw_ps_deny_cancel(PADAPTER padapter, PS_DENY_REASON reason)
2621 {
2622         struct pwrctrl_priv *pwrpriv;
2623
2624
2625 //      DBG_871X("+" FUNC_ADPT_FMT ": Cancel PS deny for %d(0x%08X)\n",
2626 //              FUNC_ADPT_ARG(padapter), reason, BIT(reason));
2627
2628         pwrpriv = adapter_to_pwrctl(padapter);
2629
2630         _enter_pwrlock(&pwrpriv->lock);
2631         if ((pwrpriv->ps_deny & BIT(reason)) == 0)
2632         {
2633                 DBG_871X(FUNC_ADPT_FMT ": [ERROR] Reason %d had been canceled before!!\n",
2634                         FUNC_ADPT_ARG(padapter), reason);
2635         }
2636         pwrpriv->ps_deny &= ~BIT(reason);
2637         _exit_pwrlock(&pwrpriv->lock);
2638
2639 //      DBG_871X("-" FUNC_ADPT_FMT ": Now PS deny for 0x%08X\n",
2640 //              FUNC_ADPT_ARG(padapter), pwrpriv->ps_deny);
2641 }
2642
2643 /*
2644  * ATTENTION:
2645  *      Before calling this function pwrctrl lock should be occupied already,
2646  *      otherwise it may return incorrect value.
2647  */
2648 u32 rtw_ps_deny_get(PADAPTER padapter)
2649 {
2650         u32 deny;
2651
2652
2653         deny = adapter_to_pwrctl(padapter)->ps_deny;
2654
2655         return deny;
2656 }
2657