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