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