]> Pileus Git - ~andy/linux/blob - drivers/staging/rtl8188eu/core/rtw_pwrctrl.c
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mason/linux...
[~andy/linux] / drivers / staging / rtl8188eu / 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 <osdep_service.h>
23 #include <drv_types.h>
24 #include <osdep_intf.h>
25 #include <linux/usb.h>
26
27 void ips_enter(struct adapter *padapter)
28 {
29         struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
30         struct xmit_priv *pxmit_priv = &padapter->xmitpriv;
31
32         if (padapter->registrypriv.mp_mode == 1)
33                 return;
34
35         if (pxmit_priv->free_xmitbuf_cnt != NR_XMITBUFF ||
36             pxmit_priv->free_xmit_extbuf_cnt != NR_XMIT_EXTBUFF) {
37                 DBG_88E_LEVEL(_drv_info_, "There are some pkts to transmit\n");
38                 DBG_88E_LEVEL(_drv_info_, "free_xmitbuf_cnt: %d, free_xmit_extbuf_cnt: %d\n",
39                               pxmit_priv->free_xmitbuf_cnt, pxmit_priv->free_xmit_extbuf_cnt);
40                 return;
41         }
42
43         _enter_pwrlock(&pwrpriv->lock);
44
45         pwrpriv->bips_processing = true;
46
47         /*  syn ips_mode with request */
48         pwrpriv->ips_mode = pwrpriv->ips_mode_req;
49
50         pwrpriv->ips_enter_cnts++;
51         DBG_88E("==>ips_enter cnts:%d\n", pwrpriv->ips_enter_cnts);
52         if (rf_off == pwrpriv->change_rfpwrstate) {
53                 pwrpriv->bpower_saving = true;
54                 DBG_88E_LEVEL(_drv_info_, "nolinked power save enter\n");
55
56                 if (pwrpriv->ips_mode == IPS_LEVEL_2)
57                         pwrpriv->bkeepfwalive = true;
58
59                 rtw_ips_pwr_down(padapter);
60                 pwrpriv->rf_pwrstate = rf_off;
61         }
62         pwrpriv->bips_processing = false;
63
64         _exit_pwrlock(&pwrpriv->lock);
65 }
66
67 int ips_leave(struct adapter *padapter)
68 {
69         struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
70         struct security_priv *psecuritypriv = &(padapter->securitypriv);
71         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
72         int result = _SUCCESS;
73         int keyid;
74
75
76         _enter_pwrlock(&pwrpriv->lock);
77
78         if ((pwrpriv->rf_pwrstate == rf_off) && (!pwrpriv->bips_processing)) {
79                 pwrpriv->bips_processing = true;
80                 pwrpriv->change_rfpwrstate = rf_on;
81                 pwrpriv->ips_leave_cnts++;
82                 DBG_88E("==>ips_leave cnts:%d\n", pwrpriv->ips_leave_cnts);
83
84                 result = rtw_ips_pwr_up(padapter);
85                 if (result == _SUCCESS) {
86                         pwrpriv->rf_pwrstate = rf_on;
87                 }
88                 DBG_88E_LEVEL(_drv_info_, "nolinked power save leave\n");
89
90                 if ((_WEP40_ == psecuritypriv->dot11PrivacyAlgrthm) || (_WEP104_ == psecuritypriv->dot11PrivacyAlgrthm)) {
91                         DBG_88E("==>%s, channel(%d), processing(%x)\n", __func__, padapter->mlmeextpriv.cur_channel, pwrpriv->bips_processing);
92                         set_channel_bwmode(padapter, padapter->mlmeextpriv.cur_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20);
93                         for (keyid = 0; keyid < 4; keyid++) {
94                                 if (pmlmepriv->key_mask & BIT(keyid)) {
95                                         if (keyid == psecuritypriv->dot11PrivacyKeyIndex)
96                                                 result = rtw_set_key(padapter, psecuritypriv, keyid, 1);
97                                         else
98                                                 result = rtw_set_key(padapter, psecuritypriv, keyid, 0);
99                                 }
100                         }
101                 }
102
103                 DBG_88E("==> ips_leave.....LED(0x%08x)...\n", rtw_read32(padapter, 0x4c));
104                 pwrpriv->bips_processing = false;
105
106                 pwrpriv->bkeepfwalive = false;
107                 pwrpriv->bpower_saving = false;
108         }
109
110         _exit_pwrlock(&pwrpriv->lock);
111
112         return result;
113 }
114
115 static bool rtw_pwr_unassociated_idle(struct adapter *adapter)
116 {
117         struct adapter *buddy = adapter->pbuddy_adapter;
118         struct mlme_priv *pmlmepriv = &(adapter->mlmepriv);
119 #ifdef CONFIG_88EU_P2P
120         struct wifidirect_info  *pwdinfo = &(adapter->wdinfo);
121 #endif
122
123         bool ret = false;
124
125         if (adapter->pwrctrlpriv.ips_deny_time >= jiffies)
126                 goto exit;
127
128         if (check_fwstate(pmlmepriv, WIFI_ASOC_STATE|WIFI_SITE_MONITOR) ||
129             check_fwstate(pmlmepriv, WIFI_UNDER_LINKING|WIFI_UNDER_WPS) ||
130             check_fwstate(pmlmepriv, WIFI_AP_STATE) ||
131             check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE|WIFI_ADHOC_STATE) ||
132 #if defined(CONFIG_88EU_P2P)
133             !rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
134 #else
135             0)
136 #endif
137                 goto exit;
138
139         /* consider buddy, if exist */
140         if (buddy) {
141                 struct mlme_priv *b_pmlmepriv = &(buddy->mlmepriv);
142                 #ifdef CONFIG_88EU_P2P
143                 struct wifidirect_info *b_pwdinfo = &(buddy->wdinfo);
144                 #endif
145
146                 if (check_fwstate(b_pmlmepriv, WIFI_ASOC_STATE|WIFI_SITE_MONITOR) ||
147                     check_fwstate(b_pmlmepriv, WIFI_UNDER_LINKING|WIFI_UNDER_WPS) ||
148                     check_fwstate(b_pmlmepriv, WIFI_AP_STATE) ||
149                     check_fwstate(b_pmlmepriv, WIFI_ADHOC_MASTER_STATE|WIFI_ADHOC_STATE) ||
150 #if defined(CONFIG_88EU_P2P)
151                     !rtw_p2p_chk_state(b_pwdinfo, P2P_STATE_NONE))
152 #else
153                     0)
154 #endif
155                         goto exit;
156         }
157         ret = true;
158
159 exit:
160         return ret;
161 }
162
163 void rtw_ps_processor(struct adapter *padapter)
164 {
165         struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
166         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
167         enum rt_rf_power_state rfpwrstate;
168
169         pwrpriv->ps_processing = true;
170
171         if (pwrpriv->bips_processing)
172                 goto exit;
173
174         if (padapter->pwrctrlpriv.bHWPwrPindetect) {
175                 rfpwrstate = RfOnOffDetect(padapter);
176                 DBG_88E("@@@@- #2  %s==> rfstate:%s\n", __func__, (rfpwrstate == rf_on) ? "rf_on" : "rf_off");
177
178                 if (rfpwrstate != pwrpriv->rf_pwrstate) {
179                         if (rfpwrstate == rf_off) {
180                                 pwrpriv->change_rfpwrstate = rf_off;
181                                 pwrpriv->brfoffbyhw = true;
182                                 padapter->bCardDisableWOHSM = true;
183                                 rtw_hw_suspend(padapter);
184                         } else {
185                                 pwrpriv->change_rfpwrstate = rf_on;
186                                 rtw_hw_resume(padapter);
187                         }
188                         DBG_88E("current rf_pwrstate(%s)\n", (pwrpriv->rf_pwrstate == rf_off) ? "rf_off" : "rf_on");
189                 }
190                 pwrpriv->pwr_state_check_cnts++;
191         }
192
193         if (pwrpriv->ips_mode_req == IPS_NONE)
194                 goto exit;
195
196         if (!rtw_pwr_unassociated_idle(padapter))
197                 goto exit;
198
199         if ((pwrpriv->rf_pwrstate == rf_on) && ((pwrpriv->pwr_state_check_cnts%4) == 0)) {
200                 DBG_88E("==>%s .fw_state(%x)\n", __func__, get_fwstate(pmlmepriv));
201                 pwrpriv->change_rfpwrstate = rf_off;
202
203                 ips_enter(padapter);
204         }
205 exit:
206         rtw_set_pwr_state_check_timer(&padapter->pwrctrlpriv);
207         pwrpriv->ps_processing = false;
208         return;
209 }
210
211 static void pwr_state_check_handler(void *FunctionContext)
212 {
213         struct adapter *padapter = (struct adapter *)FunctionContext;
214         rtw_ps_cmd(padapter);
215 }
216
217 /*
218  *
219  * Parameters
220  *      padapter
221  *      pslv                    power state level, only could be PS_STATE_S0 ~ PS_STATE_S4
222  *
223  */
224 void rtw_set_rpwm(struct adapter *padapter, u8 pslv)
225 {
226         u8      rpwm;
227         struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
228
229 _func_enter_;
230
231         pslv = PS_STATE(pslv);
232
233
234         if (pwrpriv->btcoex_rfon) {
235                 if (pslv < PS_STATE_S4)
236                         pslv = PS_STATE_S3;
237         }
238
239         if ((pwrpriv->rpwm == pslv)) {
240                 RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_err_,
241                          ("%s: Already set rpwm[0x%02X], new=0x%02X!\n", __func__, pwrpriv->rpwm, pslv));
242                 return;
243         }
244
245         if ((padapter->bSurpriseRemoved) ||
246             (!padapter->hw_init_completed)) {
247                 RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_err_,
248                          ("%s: SurpriseRemoved(%d) hw_init_completed(%d)\n",
249                          __func__, padapter->bSurpriseRemoved, padapter->hw_init_completed));
250
251                 pwrpriv->cpwm = PS_STATE_S4;
252
253                 return;
254         }
255
256         if (padapter->bDriverStopped) {
257                 RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_err_,
258                          ("%s: change power state(0x%02X) when DriverStopped\n", __func__, pslv));
259
260                 if (pslv < PS_STATE_S2) {
261                         RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_err_,
262                                  ("%s: Reject to enter PS_STATE(0x%02X) lower than S2 when DriverStopped!!\n", __func__, pslv));
263                         return;
264                 }
265         }
266
267         rpwm = pslv | pwrpriv->tog;
268         RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_notice_,
269                  ("rtw_set_rpwm: rpwm=0x%02x cpwm=0x%02x\n", rpwm, pwrpriv->cpwm));
270
271         pwrpriv->rpwm = pslv;
272
273         rtw_hal_set_hwreg(padapter, HW_VAR_SET_RPWM, (u8 *)(&rpwm));
274
275         pwrpriv->tog += 0x80;
276         pwrpriv->cpwm = pslv;
277
278 _func_exit_;
279 }
280
281 static u8 PS_RDY_CHECK(struct adapter *padapter)
282 {
283         u32 curr_time, delta_time;
284         struct pwrctrl_priv     *pwrpriv = &padapter->pwrctrlpriv;
285         struct mlme_priv        *pmlmepriv = &(padapter->mlmepriv);
286
287
288         curr_time = jiffies;
289         delta_time = curr_time - pwrpriv->DelayLPSLastTimeStamp;
290
291         if (delta_time < LPS_DELAY_TIME)
292                 return false;
293
294         if ((check_fwstate(pmlmepriv, _FW_LINKED) == false) ||
295             (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY)) ||
296             (check_fwstate(pmlmepriv, WIFI_AP_STATE)) ||
297             (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) ||
298             (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)))
299                 return false;
300         if (pwrpriv->bInSuspend)
301                 return false;
302         if ((padapter->securitypriv.dot11AuthAlgrthm == dot11AuthAlgrthm_8021X) && (padapter->securitypriv.binstallGrpkey == false)) {
303                 DBG_88E("Group handshake still in progress !!!\n");
304                 return false;
305         }
306         return true;
307 }
308
309 void rtw_set_ps_mode(struct adapter *padapter, u8 ps_mode, u8 smart_ps, u8 bcn_ant_mode)
310 {
311         struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
312 #ifdef CONFIG_88EU_P2P
313         struct wifidirect_info  *pwdinfo = &(padapter->wdinfo);
314 #endif /* CONFIG_88EU_P2P */
315
316 _func_enter_;
317
318         RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_notice_,
319                  ("%s: PowerMode=%d Smart_PS=%d\n",
320                   __func__, ps_mode, smart_ps));
321
322         if (ps_mode > PM_Card_Disable) {
323                 RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_err_, ("ps_mode:%d error\n", ps_mode));
324                 return;
325         }
326
327         if (pwrpriv->pwr_mode == ps_mode) {
328                 if (PS_MODE_ACTIVE == ps_mode)
329                         return;
330
331                 if ((pwrpriv->smart_ps == smart_ps) &&
332                     (pwrpriv->bcn_ant_mode == bcn_ant_mode))
333                         return;
334         }
335
336         /* if (pwrpriv->pwr_mode == PS_MODE_ACTIVE) */
337         if (ps_mode == PS_MODE_ACTIVE) {
338 #ifdef CONFIG_88EU_P2P
339                 if (pwdinfo->opp_ps == 0) {
340                         DBG_88E("rtw_set_ps_mode: Leave 802.11 power save\n");
341                         pwrpriv->pwr_mode = ps_mode;
342                         rtw_set_rpwm(padapter, PS_STATE_S4);
343                         rtw_hal_set_hwreg(padapter, HW_VAR_H2C_FW_PWRMODE, (u8 *)(&ps_mode));
344                         pwrpriv->bFwCurrentInPSMode = false;
345                 }
346         } else {
347 #endif /* CONFIG_88EU_P2P */
348                 if (PS_RDY_CHECK(padapter)) {
349                         DBG_88E("%s: Enter 802.11 power save\n", __func__);
350                         pwrpriv->bFwCurrentInPSMode = true;
351                         pwrpriv->pwr_mode = ps_mode;
352                         pwrpriv->smart_ps = smart_ps;
353                         pwrpriv->bcn_ant_mode = bcn_ant_mode;
354                         rtw_hal_set_hwreg(padapter, HW_VAR_H2C_FW_PWRMODE, (u8 *)(&ps_mode));
355
356 #ifdef CONFIG_88EU_P2P
357                         /*  Set CTWindow after LPS */
358                         if (pwdinfo->opp_ps == 1)
359                                 p2p_ps_wk_cmd(padapter, P2P_PS_ENABLE, 0);
360 #endif /* CONFIG_88EU_P2P */
361
362                         rtw_set_rpwm(padapter, PS_STATE_S2);
363                 }
364         }
365
366 _func_exit_;
367 }
368
369 /*
370  * Return:
371  *      0:      Leave OK
372  *      -1:     Timeout
373  *      -2:     Other error
374  */
375 s32 LPS_RF_ON_check(struct adapter *padapter, u32 delay_ms)
376 {
377         u32 start_time;
378         u8 bAwake = false;
379         s32 err = 0;
380
381
382         start_time = jiffies;
383         while (1) {
384                 rtw_hal_get_hwreg(padapter, HW_VAR_FWLPS_RF_ON, &bAwake);
385                 if (bAwake)
386                         break;
387
388                 if (padapter->bSurpriseRemoved) {
389                         err = -2;
390                         DBG_88E("%s: device surprise removed!!\n", __func__);
391                         break;
392                 }
393
394                 if (rtw_get_passing_time_ms(start_time) > delay_ms) {
395                         err = -1;
396                         DBG_88E("%s: Wait for FW LPS leave more than %u ms!!!\n", __func__, delay_ms);
397                         break;
398                 }
399                 msleep(1);
400         }
401
402         return err;
403 }
404
405 /*  */
406 /*      Description: */
407 /*              Enter the leisure power save mode. */
408 /*  */
409 void LPS_Enter(struct adapter *padapter)
410 {
411         struct pwrctrl_priv     *pwrpriv = &padapter->pwrctrlpriv;
412
413 _func_enter_;
414
415         if (PS_RDY_CHECK(padapter) == false)
416                 return;
417
418         if (pwrpriv->bLeisurePs) {
419                 /*  Idle for a while if we connect to AP a while ago. */
420                 if (pwrpriv->LpsIdleCount >= 2) { /*   4 Sec */
421                         if (pwrpriv->pwr_mode == PS_MODE_ACTIVE) {
422                                 pwrpriv->bpower_saving = true;
423                                 DBG_88E("%s smart_ps:%d\n", __func__, pwrpriv->smart_ps);
424                                 /* For Tenda W311R IOT issue */
425                                 rtw_set_ps_mode(padapter, pwrpriv->power_mgnt, pwrpriv->smart_ps, 0);
426                         }
427                 } else {
428                         pwrpriv->LpsIdleCount++;
429                 }
430         }
431
432 _func_exit_;
433 }
434
435 #define LPS_LEAVE_TIMEOUT_MS 100
436
437 /*      Description: */
438 /*              Leave the leisure power save mode. */
439 void LPS_Leave(struct adapter *padapter)
440 {
441         struct pwrctrl_priv     *pwrpriv = &padapter->pwrctrlpriv;
442
443 _func_enter_;
444
445         if (pwrpriv->bLeisurePs) {
446                 if (pwrpriv->pwr_mode != PS_MODE_ACTIVE) {
447                         rtw_set_ps_mode(padapter, PS_MODE_ACTIVE, 0, 0);
448
449                         if (pwrpriv->pwr_mode == PS_MODE_ACTIVE)
450                                 LPS_RF_ON_check(padapter, LPS_LEAVE_TIMEOUT_MS);
451                 }
452         }
453
454         pwrpriv->bpower_saving = false;
455
456 _func_exit_;
457 }
458
459 /*  */
460 /*  Description: Leave all power save mode: LPS, FwLPS, IPS if needed. */
461 /*  Move code to function by tynli. 2010.03.26. */
462 /*  */
463 void LeaveAllPowerSaveMode(struct adapter *Adapter)
464 {
465         struct mlme_priv        *pmlmepriv = &(Adapter->mlmepriv);
466         u8      enqueue = 0;
467
468 _func_enter_;
469
470         if (check_fwstate(pmlmepriv, _FW_LINKED)) { /* connect */
471                 p2p_ps_wk_cmd(Adapter, P2P_PS_DISABLE, enqueue);
472
473                 rtw_lps_ctrl_wk_cmd(Adapter, LPS_CTRL_LEAVE, enqueue);
474         }
475
476 _func_exit_;
477 }
478
479 void rtw_init_pwrctrl_priv(struct adapter *padapter)
480 {
481         struct pwrctrl_priv *pwrctrlpriv = &padapter->pwrctrlpriv;
482
483 _func_enter_;
484
485         _init_pwrlock(&pwrctrlpriv->lock);
486         pwrctrlpriv->rf_pwrstate = rf_on;
487         pwrctrlpriv->ips_enter_cnts = 0;
488         pwrctrlpriv->ips_leave_cnts = 0;
489         pwrctrlpriv->bips_processing = false;
490
491         pwrctrlpriv->ips_mode = padapter->registrypriv.ips_mode;
492         pwrctrlpriv->ips_mode_req = padapter->registrypriv.ips_mode;
493
494         pwrctrlpriv->pwr_state_check_interval = RTW_PWR_STATE_CHK_INTERVAL;
495         pwrctrlpriv->pwr_state_check_cnts = 0;
496         pwrctrlpriv->bInternalAutoSuspend = false;
497         pwrctrlpriv->bInSuspend = false;
498         pwrctrlpriv->bkeepfwalive = false;
499
500         pwrctrlpriv->LpsIdleCount = 0;
501         if (padapter->registrypriv.mp_mode == 1)
502                 pwrctrlpriv->power_mgnt = PS_MODE_ACTIVE ;
503         else
504                 pwrctrlpriv->power_mgnt = padapter->registrypriv.power_mgnt;/*  PS_MODE_MIN; */
505         pwrctrlpriv->bLeisurePs = (PS_MODE_ACTIVE != pwrctrlpriv->power_mgnt) ? true : false;
506
507         pwrctrlpriv->bFwCurrentInPSMode = false;
508
509         pwrctrlpriv->rpwm = 0;
510         pwrctrlpriv->cpwm = PS_STATE_S4;
511
512         pwrctrlpriv->pwr_mode = PS_MODE_ACTIVE;
513         pwrctrlpriv->smart_ps = padapter->registrypriv.smart_ps;
514         pwrctrlpriv->bcn_ant_mode = 0;
515
516         pwrctrlpriv->tog = 0x80;
517
518         pwrctrlpriv->btcoex_rfon = false;
519
520         _init_timer(&(pwrctrlpriv->pwr_state_check_timer), padapter->pnetdev, pwr_state_check_handler, (u8 *)padapter);
521
522 _func_exit_;
523 }
524
525 u8 rtw_interface_ps_func(struct adapter *padapter, enum hal_intf_ps_func efunc_id, u8 *val)
526 {
527         u8 bResult = true;
528         rtw_hal_intf_ps_func(padapter, efunc_id, val);
529
530         return bResult;
531 }
532
533
534 inline void rtw_set_ips_deny(struct adapter *padapter, u32 ms)
535 {
536         struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
537         pwrpriv->ips_deny_time = jiffies + rtw_ms_to_systime(ms);
538 }
539
540 /*
541 * rtw_pwr_wakeup - Wake the NIC up from: 1)IPS. 2)USB autosuspend
542 * @adapter: pointer to struct adapter structure
543 * @ips_deffer_ms: the ms wiil prevent from falling into IPS after wakeup
544 * Return _SUCCESS or _FAIL
545 */
546
547 int _rtw_pwr_wakeup(struct adapter *padapter, u32 ips_deffer_ms, const char *caller)
548 {
549         struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
550         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
551         int ret = _SUCCESS;
552
553         if (pwrpriv->ips_deny_time < jiffies + rtw_ms_to_systime(ips_deffer_ms))
554                 pwrpriv->ips_deny_time = jiffies + rtw_ms_to_systime(ips_deffer_ms);
555
556 {
557         u32 start = jiffies;
558         if (pwrpriv->ps_processing) {
559                 DBG_88E("%s wait ps_processing...\n", __func__);
560                 while (pwrpriv->ps_processing && rtw_get_passing_time_ms(start) <= 3000)
561                         msleep(10);
562                 if (pwrpriv->ps_processing)
563                         DBG_88E("%s wait ps_processing timeout\n", __func__);
564                 else
565                         DBG_88E("%s wait ps_processing done\n", __func__);
566         }
567 }
568
569         /* System suspend is not allowed to wakeup */
570         if ((!pwrpriv->bInternalAutoSuspend) && (pwrpriv->bInSuspend)) {
571                 ret = _FAIL;
572                 goto exit;
573         }
574
575         /* block??? */
576         if ((pwrpriv->bInternalAutoSuspend)  && (padapter->net_closed)) {
577                 ret = _FAIL;
578                 goto exit;
579         }
580
581         /* I think this should be check in IPS, LPS, autosuspend functions... */
582         if (check_fwstate(pmlmepriv, _FW_LINKED)) {
583                 ret = _SUCCESS;
584                 goto exit;
585         }
586         if (rf_off == pwrpriv->rf_pwrstate) {
587                 DBG_88E("%s call ips_leave....\n", __func__);
588                 if (_FAIL ==  ips_leave(padapter)) {
589                         DBG_88E("======> ips_leave fail.............\n");
590                         ret = _FAIL;
591                         goto exit;
592                 }
593         }
594
595         /* TODO: the following checking need to be merged... */
596         if (padapter->bDriverStopped || !padapter->bup ||
597             !padapter->hw_init_completed) {
598                 DBG_88E("%s: bDriverStopped=%d, bup=%d, hw_init_completed =%u\n"
599                         , caller
600                         , padapter->bDriverStopped
601                         , padapter->bup
602                         , padapter->hw_init_completed);
603                 ret = false;
604                 goto exit;
605         }
606
607 exit:
608         if (pwrpriv->ips_deny_time < jiffies + rtw_ms_to_systime(ips_deffer_ms))
609                 pwrpriv->ips_deny_time = jiffies + rtw_ms_to_systime(ips_deffer_ms);
610         return ret;
611 }
612
613 int rtw_pm_set_lps(struct adapter *padapter, u8 mode)
614 {
615         int     ret = 0;
616         struct pwrctrl_priv *pwrctrlpriv = &padapter->pwrctrlpriv;
617
618         if (mode < PS_MODE_NUM) {
619                 if (pwrctrlpriv->power_mgnt != mode) {
620                         if (PS_MODE_ACTIVE == mode)
621                                 LeaveAllPowerSaveMode(padapter);
622                         else
623                                 pwrctrlpriv->LpsIdleCount = 2;
624                         pwrctrlpriv->power_mgnt = mode;
625                         pwrctrlpriv->bLeisurePs = (PS_MODE_ACTIVE != pwrctrlpriv->power_mgnt) ? true : false;
626                 }
627         } else {
628                 ret = -EINVAL;
629         }
630
631         return ret;
632 }
633
634 int rtw_pm_set_ips(struct adapter *padapter, u8 mode)
635 {
636         struct pwrctrl_priv *pwrctrlpriv = &padapter->pwrctrlpriv;
637
638         if (mode == IPS_NORMAL || mode == IPS_LEVEL_2) {
639                 rtw_ips_mode_req(pwrctrlpriv, mode);
640                 DBG_88E("%s %s\n", __func__, mode == IPS_NORMAL ? "IPS_NORMAL" : "IPS_LEVEL_2");
641                 return 0;
642         } else if (mode == IPS_NONE) {
643                 rtw_ips_mode_req(pwrctrlpriv, mode);
644                 DBG_88E("%s %s\n", __func__, "IPS_NONE");
645                 if ((padapter->bSurpriseRemoved == 0) && (_FAIL == rtw_pwr_wakeup(padapter)))
646                         return -EFAULT;
647         } else {
648                 return -EINVAL;
649         }
650         return 0;
651 }