]> git.karo-electronics.de Git - karo-tx-linux.git/blob - drivers/staging/rtl8188eu/core/rtw_pwrctrl.c
Merge tag 'xfs-for-linus-3.16-rc1' of git://oss.sgi.com/xfs/xfs
[karo-tx-linux.git] / 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 (time_after_eq(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         pslv = PS_STATE(pslv);
230
231         if (pwrpriv->btcoex_rfon) {
232                 if (pslv < PS_STATE_S4)
233                         pslv = PS_STATE_S3;
234         }
235
236         if ((pwrpriv->rpwm == pslv)) {
237                 RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_err_,
238                          ("%s: Already set rpwm[0x%02X], new=0x%02X!\n", __func__, pwrpriv->rpwm, pslv));
239                 return;
240         }
241
242         if ((padapter->bSurpriseRemoved) ||
243             (!padapter->hw_init_completed)) {
244                 RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_err_,
245                          ("%s: SurpriseRemoved(%d) hw_init_completed(%d)\n",
246                          __func__, padapter->bSurpriseRemoved, padapter->hw_init_completed));
247
248                 pwrpriv->cpwm = PS_STATE_S4;
249
250                 return;
251         }
252
253         if (padapter->bDriverStopped) {
254                 RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_err_,
255                          ("%s: change power state(0x%02X) when DriverStopped\n", __func__, pslv));
256
257                 if (pslv < PS_STATE_S2) {
258                         RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_err_,
259                                  ("%s: Reject to enter PS_STATE(0x%02X) lower than S2 when DriverStopped!!\n", __func__, pslv));
260                         return;
261                 }
262         }
263
264         rpwm = pslv | pwrpriv->tog;
265         RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_notice_,
266                  ("rtw_set_rpwm: rpwm=0x%02x cpwm=0x%02x\n", rpwm, pwrpriv->cpwm));
267
268         pwrpriv->rpwm = pslv;
269
270         rtw_hal_set_hwreg(padapter, HW_VAR_SET_RPWM, (u8 *)(&rpwm));
271
272         pwrpriv->tog += 0x80;
273         pwrpriv->cpwm = pslv;
274 }
275
276 static u8 PS_RDY_CHECK(struct adapter *padapter)
277 {
278         u32 curr_time, delta_time;
279         struct pwrctrl_priv     *pwrpriv = &padapter->pwrctrlpriv;
280         struct mlme_priv        *pmlmepriv = &(padapter->mlmepriv);
281
282
283         curr_time = jiffies;
284         delta_time = curr_time - pwrpriv->DelayLPSLastTimeStamp;
285
286         if (delta_time < LPS_DELAY_TIME)
287                 return false;
288
289         if ((check_fwstate(pmlmepriv, _FW_LINKED) == false) ||
290             (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY)) ||
291             (check_fwstate(pmlmepriv, WIFI_AP_STATE)) ||
292             (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) ||
293             (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)))
294                 return false;
295         if (pwrpriv->bInSuspend)
296                 return false;
297         if ((padapter->securitypriv.dot11AuthAlgrthm == dot11AuthAlgrthm_8021X) && (padapter->securitypriv.binstallGrpkey == false)) {
298                 DBG_88E("Group handshake still in progress !!!\n");
299                 return false;
300         }
301         return true;
302 }
303
304 void rtw_set_ps_mode(struct adapter *padapter, u8 ps_mode, u8 smart_ps, u8 bcn_ant_mode)
305 {
306         struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
307 #ifdef CONFIG_88EU_P2P
308         struct wifidirect_info  *pwdinfo = &(padapter->wdinfo);
309 #endif /* CONFIG_88EU_P2P */
310
311         RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_notice_,
312                  ("%s: PowerMode=%d Smart_PS=%d\n",
313                   __func__, ps_mode, smart_ps));
314
315         if (ps_mode > PM_Card_Disable) {
316                 RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_err_, ("ps_mode:%d error\n", ps_mode));
317                 return;
318         }
319
320         if (pwrpriv->pwr_mode == ps_mode) {
321                 if (PS_MODE_ACTIVE == ps_mode)
322                         return;
323
324                 if ((pwrpriv->smart_ps == smart_ps) &&
325                     (pwrpriv->bcn_ant_mode == bcn_ant_mode))
326                         return;
327         }
328
329         /* if (pwrpriv->pwr_mode == PS_MODE_ACTIVE) */
330         if (ps_mode == PS_MODE_ACTIVE) {
331 #ifdef CONFIG_88EU_P2P
332                 if (pwdinfo->opp_ps == 0) {
333                         DBG_88E("rtw_set_ps_mode: Leave 802.11 power save\n");
334                         pwrpriv->pwr_mode = ps_mode;
335                         rtw_set_rpwm(padapter, PS_STATE_S4);
336                         rtw_hal_set_hwreg(padapter, HW_VAR_H2C_FW_PWRMODE, (u8 *)(&ps_mode));
337                         pwrpriv->bFwCurrentInPSMode = false;
338                 }
339         } else {
340 #endif /* CONFIG_88EU_P2P */
341                 if (PS_RDY_CHECK(padapter)) {
342                         DBG_88E("%s: Enter 802.11 power save\n", __func__);
343                         pwrpriv->bFwCurrentInPSMode = true;
344                         pwrpriv->pwr_mode = ps_mode;
345                         pwrpriv->smart_ps = smart_ps;
346                         pwrpriv->bcn_ant_mode = bcn_ant_mode;
347                         rtw_hal_set_hwreg(padapter, HW_VAR_H2C_FW_PWRMODE, (u8 *)(&ps_mode));
348
349 #ifdef CONFIG_88EU_P2P
350                         /*  Set CTWindow after LPS */
351                         if (pwdinfo->opp_ps == 1)
352                                 p2p_ps_wk_cmd(padapter, P2P_PS_ENABLE, 0);
353 #endif /* CONFIG_88EU_P2P */
354
355                         rtw_set_rpwm(padapter, PS_STATE_S2);
356                 }
357         }
358 }
359
360 /*
361  * Return:
362  *      0:      Leave OK
363  *      -1:     Timeout
364  *      -2:     Other error
365  */
366 s32 LPS_RF_ON_check(struct adapter *padapter, u32 delay_ms)
367 {
368         u32 start_time;
369         u8 bAwake = false;
370         s32 err = 0;
371
372
373         start_time = jiffies;
374         while (1) {
375                 rtw_hal_get_hwreg(padapter, HW_VAR_FWLPS_RF_ON, &bAwake);
376                 if (bAwake)
377                         break;
378
379                 if (padapter->bSurpriseRemoved) {
380                         err = -2;
381                         DBG_88E("%s: device surprise removed!!\n", __func__);
382                         break;
383                 }
384
385                 if (rtw_get_passing_time_ms(start_time) > delay_ms) {
386                         err = -1;
387                         DBG_88E("%s: Wait for FW LPS leave more than %u ms!!!\n", __func__, delay_ms);
388                         break;
389                 }
390                 msleep(1);
391         }
392
393         return err;
394 }
395
396 /*  */
397 /*      Description: */
398 /*              Enter the leisure power save mode. */
399 /*  */
400 void LPS_Enter(struct adapter *padapter)
401 {
402         struct pwrctrl_priv     *pwrpriv = &padapter->pwrctrlpriv;
403
404         if (PS_RDY_CHECK(padapter) == false)
405                 return;
406
407         if (pwrpriv->bLeisurePs) {
408                 /*  Idle for a while if we connect to AP a while ago. */
409                 if (pwrpriv->LpsIdleCount >= 2) { /*   4 Sec */
410                         if (pwrpriv->pwr_mode == PS_MODE_ACTIVE) {
411                                 pwrpriv->bpower_saving = true;
412                                 DBG_88E("%s smart_ps:%d\n", __func__, pwrpriv->smart_ps);
413                                 /* For Tenda W311R IOT issue */
414                                 rtw_set_ps_mode(padapter, pwrpriv->power_mgnt, pwrpriv->smart_ps, 0);
415                         }
416                 } else {
417                         pwrpriv->LpsIdleCount++;
418                 }
419         }
420 }
421
422 #define LPS_LEAVE_TIMEOUT_MS 100
423
424 /*      Description: */
425 /*              Leave the leisure power save mode. */
426 void LPS_Leave(struct adapter *padapter)
427 {
428         struct pwrctrl_priv     *pwrpriv = &padapter->pwrctrlpriv;
429
430         if (pwrpriv->bLeisurePs) {
431                 if (pwrpriv->pwr_mode != PS_MODE_ACTIVE) {
432                         rtw_set_ps_mode(padapter, PS_MODE_ACTIVE, 0, 0);
433
434                         if (pwrpriv->pwr_mode == PS_MODE_ACTIVE)
435                                 LPS_RF_ON_check(padapter, LPS_LEAVE_TIMEOUT_MS);
436                 }
437         }
438
439         pwrpriv->bpower_saving = false;
440 }
441
442 /*  */
443 /*  Description: Leave all power save mode: LPS, FwLPS, IPS if needed. */
444 /*  Move code to function by tynli. 2010.03.26. */
445 /*  */
446 void LeaveAllPowerSaveMode(struct adapter *Adapter)
447 {
448         struct mlme_priv        *pmlmepriv = &(Adapter->mlmepriv);
449         u8      enqueue = 0;
450
451         if (check_fwstate(pmlmepriv, _FW_LINKED)) { /* connect */
452                 p2p_ps_wk_cmd(Adapter, P2P_PS_DISABLE, enqueue);
453
454                 rtw_lps_ctrl_wk_cmd(Adapter, LPS_CTRL_LEAVE, enqueue);
455         }
456 }
457
458 void rtw_init_pwrctrl_priv(struct adapter *padapter)
459 {
460         struct pwrctrl_priv *pwrctrlpriv = &padapter->pwrctrlpriv;
461
462         _init_pwrlock(&pwrctrlpriv->lock);
463         pwrctrlpriv->rf_pwrstate = rf_on;
464         pwrctrlpriv->ips_enter_cnts = 0;
465         pwrctrlpriv->ips_leave_cnts = 0;
466         pwrctrlpriv->bips_processing = false;
467
468         pwrctrlpriv->ips_mode = padapter->registrypriv.ips_mode;
469         pwrctrlpriv->ips_mode_req = padapter->registrypriv.ips_mode;
470
471         pwrctrlpriv->pwr_state_check_interval = RTW_PWR_STATE_CHK_INTERVAL;
472         pwrctrlpriv->pwr_state_check_cnts = 0;
473         pwrctrlpriv->bInternalAutoSuspend = false;
474         pwrctrlpriv->bInSuspend = false;
475         pwrctrlpriv->bkeepfwalive = false;
476
477         pwrctrlpriv->LpsIdleCount = 0;
478         if (padapter->registrypriv.mp_mode == 1)
479                 pwrctrlpriv->power_mgnt = PS_MODE_ACTIVE ;
480         else
481                 pwrctrlpriv->power_mgnt = padapter->registrypriv.power_mgnt;/*  PS_MODE_MIN; */
482         pwrctrlpriv->bLeisurePs = (PS_MODE_ACTIVE != pwrctrlpriv->power_mgnt) ? true : false;
483
484         pwrctrlpriv->bFwCurrentInPSMode = false;
485
486         pwrctrlpriv->rpwm = 0;
487         pwrctrlpriv->cpwm = PS_STATE_S4;
488
489         pwrctrlpriv->pwr_mode = PS_MODE_ACTIVE;
490         pwrctrlpriv->smart_ps = padapter->registrypriv.smart_ps;
491         pwrctrlpriv->bcn_ant_mode = 0;
492
493         pwrctrlpriv->tog = 0x80;
494
495         pwrctrlpriv->btcoex_rfon = false;
496
497         _init_timer(&(pwrctrlpriv->pwr_state_check_timer), padapter->pnetdev, pwr_state_check_handler, (u8 *)padapter);
498 }
499
500 inline void rtw_set_ips_deny(struct adapter *padapter, u32 ms)
501 {
502         struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
503         pwrpriv->ips_deny_time = jiffies + rtw_ms_to_systime(ms);
504 }
505
506 /*
507 * rtw_pwr_wakeup - Wake the NIC up from: 1)IPS. 2)USB autosuspend
508 * @adapter: pointer to struct adapter structure
509 * @ips_deffer_ms: the ms will prevent from falling into IPS after wakeup
510 * Return _SUCCESS or _FAIL
511 */
512
513 int _rtw_pwr_wakeup(struct adapter *padapter, u32 ips_deffer_ms, const char *caller)
514 {
515         struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
516         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
517         unsigned long expires;
518         int ret = _SUCCESS;
519
520         expires = jiffies + rtw_ms_to_systime(ips_deffer_ms);
521         if (time_before(pwrpriv->ips_deny_time, expires))
522                 pwrpriv->ips_deny_time = jiffies + rtw_ms_to_systime(ips_deffer_ms);
523
524 {
525         u32 start = jiffies;
526         if (pwrpriv->ps_processing) {
527                 DBG_88E("%s wait ps_processing...\n", __func__);
528                 while (pwrpriv->ps_processing && rtw_get_passing_time_ms(start) <= 3000)
529                         msleep(10);
530                 if (pwrpriv->ps_processing)
531                         DBG_88E("%s wait ps_processing timeout\n", __func__);
532                 else
533                         DBG_88E("%s wait ps_processing done\n", __func__);
534         }
535 }
536
537         /* System suspend is not allowed to wakeup */
538         if ((!pwrpriv->bInternalAutoSuspend) && (pwrpriv->bInSuspend)) {
539                 ret = _FAIL;
540                 goto exit;
541         }
542
543         /* block??? */
544         if ((pwrpriv->bInternalAutoSuspend)  && (padapter->net_closed)) {
545                 ret = _FAIL;
546                 goto exit;
547         }
548
549         /* I think this should be check in IPS, LPS, autosuspend functions... */
550         if (check_fwstate(pmlmepriv, _FW_LINKED)) {
551                 ret = _SUCCESS;
552                 goto exit;
553         }
554         if (rf_off == pwrpriv->rf_pwrstate) {
555                 DBG_88E("%s call ips_leave....\n", __func__);
556                 if (_FAIL ==  ips_leave(padapter)) {
557                         DBG_88E("======> ips_leave fail.............\n");
558                         ret = _FAIL;
559                         goto exit;
560                 }
561         }
562
563         /* TODO: the following checking need to be merged... */
564         if (padapter->bDriverStopped || !padapter->bup ||
565             !padapter->hw_init_completed) {
566                 DBG_88E("%s: bDriverStopped=%d, bup=%d, hw_init_completed =%u\n"
567                         , caller
568                         , padapter->bDriverStopped
569                         , padapter->bup
570                         , padapter->hw_init_completed);
571                 ret = false;
572                 goto exit;
573         }
574
575 exit:
576         expires = jiffies + rtw_ms_to_systime(ips_deffer_ms);
577         if (time_before(pwrpriv->ips_deny_time, expires))
578                 pwrpriv->ips_deny_time = jiffies + rtw_ms_to_systime(ips_deffer_ms);
579         return ret;
580 }
581
582 int rtw_pm_set_lps(struct adapter *padapter, u8 mode)
583 {
584         int     ret = 0;
585         struct pwrctrl_priv *pwrctrlpriv = &padapter->pwrctrlpriv;
586
587         if (mode < PS_MODE_NUM) {
588                 if (pwrctrlpriv->power_mgnt != mode) {
589                         if (PS_MODE_ACTIVE == mode)
590                                 LeaveAllPowerSaveMode(padapter);
591                         else
592                                 pwrctrlpriv->LpsIdleCount = 2;
593                         pwrctrlpriv->power_mgnt = mode;
594                         pwrctrlpriv->bLeisurePs = (PS_MODE_ACTIVE != pwrctrlpriv->power_mgnt) ? true : false;
595                 }
596         } else {
597                 ret = -EINVAL;
598         }
599
600         return ret;
601 }
602
603 int rtw_pm_set_ips(struct adapter *padapter, u8 mode)
604 {
605         struct pwrctrl_priv *pwrctrlpriv = &padapter->pwrctrlpriv;
606
607         if (mode == IPS_NORMAL || mode == IPS_LEVEL_2) {
608                 rtw_ips_mode_req(pwrctrlpriv, mode);
609                 DBG_88E("%s %s\n", __func__, mode == IPS_NORMAL ? "IPS_NORMAL" : "IPS_LEVEL_2");
610                 return 0;
611         } else if (mode == IPS_NONE) {
612                 rtw_ips_mode_req(pwrctrlpriv, mode);
613                 DBG_88E("%s %s\n", __func__, "IPS_NONE");
614                 if ((padapter->bSurpriseRemoved == 0) && (_FAIL == rtw_pwr_wakeup(padapter)))
615                         return -EFAULT;
616         } else {
617                 return -EINVAL;
618         }
619         return 0;
620 }