linux/drivers/staging/rtl8723bs/core/rtw_pwrctrl.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/******************************************************************************
   3 *
   4 * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
   5 *
   6 ******************************************************************************/
   7#define _RTW_PWRCTRL_C_
   8
   9#include <drv_types.h>
  10#include <rtw_debug.h>
  11#include <hal_data.h>
  12#include <linux/jiffies.h>
  13
  14
  15void _ips_enter(struct adapter *padapter)
  16{
  17        struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
  18
  19        pwrpriv->bips_processing = true;
  20
  21        /*  syn ips_mode with request */
  22        pwrpriv->ips_mode = pwrpriv->ips_mode_req;
  23
  24        pwrpriv->ips_enter_cnts++;
  25        DBG_871X("==>ips_enter cnts:%d\n", pwrpriv->ips_enter_cnts);
  26
  27        if (rf_off == pwrpriv->change_rfpwrstate) {
  28                pwrpriv->bpower_saving = true;
  29                DBG_871X("nolinked power save enter\n");
  30
  31                if (pwrpriv->ips_mode == IPS_LEVEL_2)
  32                        pwrpriv->bkeepfwalive = true;
  33
  34                rtw_ips_pwr_down(padapter);
  35                pwrpriv->rf_pwrstate = rf_off;
  36        }
  37        pwrpriv->bips_processing = false;
  38
  39}
  40
  41void ips_enter(struct adapter *padapter)
  42{
  43        struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
  44
  45
  46        rtw_btcoex_IpsNotify(padapter, pwrpriv->ips_mode_req);
  47
  48        down(&pwrpriv->lock);
  49        _ips_enter(padapter);
  50        up(&pwrpriv->lock);
  51}
  52
  53int _ips_leave(struct adapter *padapter)
  54{
  55        struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
  56        int result = _SUCCESS;
  57
  58        if ((pwrpriv->rf_pwrstate == rf_off) && (!pwrpriv->bips_processing)) {
  59                pwrpriv->bips_processing = true;
  60                pwrpriv->change_rfpwrstate = rf_on;
  61                pwrpriv->ips_leave_cnts++;
  62                DBG_871X("==>ips_leave cnts:%d\n", pwrpriv->ips_leave_cnts);
  63
  64                result = rtw_ips_pwr_up(padapter);
  65                if (result == _SUCCESS) {
  66                        pwrpriv->rf_pwrstate = rf_on;
  67                }
  68                DBG_871X("nolinked power save leave\n");
  69
  70                DBG_871X("==> ips_leave.....LED(0x%08x)...\n", rtw_read32(padapter, 0x4c));
  71                pwrpriv->bips_processing = false;
  72
  73                pwrpriv->bkeepfwalive = false;
  74                pwrpriv->bpower_saving = false;
  75        }
  76
  77        return result;
  78}
  79
  80int ips_leave(struct adapter *padapter)
  81{
  82        struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
  83        int ret;
  84
  85        if (!is_primary_adapter(padapter))
  86                return _SUCCESS;
  87
  88        down(&pwrpriv->lock);
  89        ret = _ips_leave(padapter);
  90        up(&pwrpriv->lock);
  91
  92        if (_SUCCESS == ret)
  93                rtw_btcoex_IpsNotify(padapter, IPS_NONE);
  94
  95        return ret;
  96}
  97
  98static bool rtw_pwr_unassociated_idle(struct adapter *adapter)
  99{
 100        struct adapter *buddy = adapter->pbuddy_adapter;
 101        struct mlme_priv *pmlmepriv = &(adapter->mlmepriv);
 102        struct xmit_priv *pxmit_priv = &adapter->xmitpriv;
 103
 104        bool ret = false;
 105
 106        if (adapter_to_pwrctl(adapter)->bpower_saving == true) {
 107                /* DBG_871X("%s: already in LPS or IPS mode\n", __func__); */
 108                goto exit;
 109        }
 110
 111        if (time_before(jiffies, adapter_to_pwrctl(adapter)->ips_deny_time)) {
 112                /* DBG_871X("%s ips_deny_time\n", __func__); */
 113                goto exit;
 114        }
 115
 116        if (check_fwstate(pmlmepriv, WIFI_ASOC_STATE|WIFI_SITE_MONITOR)
 117                || check_fwstate(pmlmepriv, WIFI_UNDER_LINKING|WIFI_UNDER_WPS)
 118                || check_fwstate(pmlmepriv, WIFI_AP_STATE)
 119                || check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE|WIFI_ADHOC_STATE)
 120        )
 121                goto exit;
 122
 123        /* consider buddy, if exist */
 124        if (buddy) {
 125                struct mlme_priv *b_pmlmepriv = &(buddy->mlmepriv);
 126
 127                if (check_fwstate(b_pmlmepriv, WIFI_ASOC_STATE|WIFI_SITE_MONITOR)
 128                        || check_fwstate(b_pmlmepriv, WIFI_UNDER_LINKING|WIFI_UNDER_WPS)
 129                        || check_fwstate(b_pmlmepriv, WIFI_AP_STATE)
 130                        || check_fwstate(b_pmlmepriv, WIFI_ADHOC_MASTER_STATE|WIFI_ADHOC_STATE)
 131                )
 132                        goto exit;
 133        }
 134
 135        if (pxmit_priv->free_xmitbuf_cnt != NR_XMITBUFF ||
 136                pxmit_priv->free_xmit_extbuf_cnt != NR_XMIT_EXTBUFF) {
 137                DBG_871X_LEVEL(_drv_always_, "There are some pkts to transmit\n");
 138                DBG_871X_LEVEL(_drv_always_, "free_xmitbuf_cnt: %d, free_xmit_extbuf_cnt: %d\n",
 139                        pxmit_priv->free_xmitbuf_cnt, pxmit_priv->free_xmit_extbuf_cnt);
 140                goto exit;
 141        }
 142
 143        ret = true;
 144
 145exit:
 146        return ret;
 147}
 148
 149
 150/*
 151 * ATTENTION:
 152 *rtw_ps_processor() doesn't handle LPS.
 153 */
 154void rtw_ps_processor(struct adapter *padapter)
 155{
 156        struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
 157        struct dvobj_priv *psdpriv = padapter->dvobj;
 158        struct debug_priv *pdbgpriv = &psdpriv->drv_dbg;
 159        u32 ps_deny = 0;
 160
 161        down(&adapter_to_pwrctl(padapter)->lock);
 162        ps_deny = rtw_ps_deny_get(padapter);
 163        up(&adapter_to_pwrctl(padapter)->lock);
 164        if (ps_deny != 0) {
 165                DBG_871X(FUNC_ADPT_FMT ": ps_deny = 0x%08X, skip power save!\n",
 166                        FUNC_ADPT_ARG(padapter), ps_deny);
 167                goto exit;
 168        }
 169
 170        if (pwrpriv->bInSuspend == true) {/* system suspend or autosuspend */
 171                pdbgpriv->dbg_ps_insuspend_cnt++;
 172                DBG_871X("%s, pwrpriv->bInSuspend == true ignore this process\n", __func__);
 173                return;
 174        }
 175
 176        pwrpriv->ps_processing = true;
 177
 178        if (pwrpriv->ips_mode_req == IPS_NONE)
 179                goto exit;
 180
 181        if (rtw_pwr_unassociated_idle(padapter) == false)
 182                goto exit;
 183
 184        if ((pwrpriv->rf_pwrstate == rf_on) && ((pwrpriv->pwr_state_check_cnts%4) == 0)) {
 185                DBG_871X("==>%s\n", __func__);
 186                pwrpriv->change_rfpwrstate = rf_off;
 187                {
 188                        ips_enter(padapter);
 189                }
 190        }
 191exit:
 192        pwrpriv->ps_processing = false;
 193        return;
 194}
 195
 196static void pwr_state_check_handler(struct timer_list *t)
 197{
 198        struct pwrctrl_priv *pwrctrlpriv =
 199                from_timer(pwrctrlpriv, t, pwr_state_check_timer);
 200        struct adapter *padapter = pwrctrlpriv->adapter;
 201
 202        rtw_ps_cmd(padapter);
 203}
 204
 205void traffic_check_for_leave_lps(struct adapter *padapter, u8 tx, u32 tx_packets)
 206{
 207        static unsigned long start_time;
 208        static u32 xmit_cnt;
 209        u8 bLeaveLPS = false;
 210        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
 211
 212
 213
 214        if (tx) { /* from tx */
 215                xmit_cnt += tx_packets;
 216
 217                if (start_time == 0)
 218                        start_time = jiffies;
 219
 220                if (jiffies_to_msecs(jiffies - start_time) > 2000) { /*  2 sec == watch dog timer */
 221                        if (xmit_cnt > 8) {
 222                                if ((adapter_to_pwrctl(padapter)->bLeisurePs)
 223                                        && (adapter_to_pwrctl(padapter)->pwr_mode != PS_MODE_ACTIVE)
 224                                        && (rtw_btcoex_IsBtControlLps(padapter) == false)
 225                                        ) {
 226                                        DBG_871X("leave lps via Tx = %d\n", xmit_cnt);
 227                                        bLeaveLPS = true;
 228                                }
 229                        }
 230
 231                        start_time = jiffies;
 232                        xmit_cnt = 0;
 233                }
 234
 235        } else { /*  from rx path */
 236                if (pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod > 4/*2*/) {
 237                        if ((adapter_to_pwrctl(padapter)->bLeisurePs)
 238                                && (adapter_to_pwrctl(padapter)->pwr_mode != PS_MODE_ACTIVE)
 239                                && (rtw_btcoex_IsBtControlLps(padapter) == false)
 240                                ) {
 241                                DBG_871X("leave lps via Rx = %d\n", pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod);
 242                                bLeaveLPS = true;
 243                        }
 244                }
 245        }
 246
 247        if (bLeaveLPS)
 248                /* DBG_871X("leave lps via %s, Tx = %d, Rx = %d\n", tx?"Tx":"Rx", pmlmepriv->LinkDetectInfo.NumTxOkInPeriod, pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod); */
 249                /* rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_LEAVE, 1); */
 250                rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_LEAVE, tx?0:1);
 251}
 252
 253/*
 254 * Description:
 255 *This function MUST be called under power lock protect
 256 *
 257 * Parameters
 258 *padapter
 259 *pslv                  power state level, only could be PS_STATE_S0 ~ PS_STATE_S4
 260 *
 261 */
 262void rtw_set_rpwm(struct adapter *padapter, u8 pslv)
 263{
 264        u8 rpwm;
 265        struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
 266        u8 cpwm_orig;
 267
 268        pslv = PS_STATE(pslv);
 269
 270        if (pwrpriv->brpwmtimeout == true) {
 271                DBG_871X("%s: RPWM timeout, force to set RPWM(0x%02X) again!\n", __func__, pslv);
 272        } else{
 273                if ((pwrpriv->rpwm == pslv)
 274                        || ((pwrpriv->rpwm >= PS_STATE_S2) && (pslv >= PS_STATE_S2))) {
 275                        RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_err_,
 276                                ("%s: Already set rpwm[0x%02X], new = 0x%02X!\n", __func__, pwrpriv->rpwm, pslv));
 277                        return;
 278                }
 279        }
 280
 281        if ((padapter->bSurpriseRemoved == true) ||
 282                (padapter->hw_init_completed == false)) {
 283                RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_err_,
 284                                 ("%s: SurpriseRemoved(%d) hw_init_completed(%d)\n",
 285                                  __func__, padapter->bSurpriseRemoved, padapter->hw_init_completed));
 286
 287                pwrpriv->cpwm = PS_STATE_S4;
 288
 289                return;
 290        }
 291
 292        if (padapter->bDriverStopped == true) {
 293                RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_err_,
 294                                 ("%s: change power state(0x%02X) when DriverStopped\n", __func__, pslv));
 295
 296                if (pslv < PS_STATE_S2) {
 297                        RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_err_,
 298                                         ("%s: Reject to enter PS_STATE(0x%02X) lower than S2 when DriverStopped!!\n", __func__, pslv));
 299                        return;
 300                }
 301        }
 302
 303        rpwm = pslv | pwrpriv->tog;
 304        /*  only when from PS_STATE S0/S1 to S2 and higher needs ACK */
 305        if ((pwrpriv->cpwm < PS_STATE_S2) && (pslv >= PS_STATE_S2))
 306                rpwm |= PS_ACK;
 307        RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_notice_,
 308                         ("rtw_set_rpwm: rpwm = 0x%02x cpwm = 0x%02x\n", rpwm, pwrpriv->cpwm));
 309
 310        pwrpriv->rpwm = pslv;
 311
 312        cpwm_orig = 0;
 313        if (rpwm & PS_ACK)
 314                rtw_hal_get_hwreg(padapter, HW_VAR_CPWM, &cpwm_orig);
 315
 316        if (rpwm & PS_ACK)
 317                _set_timer(&pwrpriv->pwr_rpwm_timer, LPS_RPWM_WAIT_MS);
 318        rtw_hal_set_hwreg(padapter, HW_VAR_SET_RPWM, (u8 *)(&rpwm));
 319
 320        pwrpriv->tog += 0x80;
 321
 322        /*  No LPS 32K, No Ack */
 323        if (rpwm & PS_ACK) {
 324                unsigned long start_time;
 325                u8 cpwm_now;
 326                u8 poll_cnt = 0;
 327
 328                start_time = jiffies;
 329
 330                /*  polling cpwm */
 331                do {
 332                        mdelay(1);
 333                        poll_cnt++;
 334                        rtw_hal_get_hwreg(padapter, HW_VAR_CPWM, &cpwm_now);
 335                        if ((cpwm_orig ^ cpwm_now) & 0x80) {
 336                                pwrpriv->cpwm = PS_STATE_S4;
 337                                pwrpriv->cpwm_tog = cpwm_now & PS_TOGGLE;
 338                                break;
 339                        }
 340
 341                        if (jiffies_to_msecs(jiffies - start_time) > LPS_RPWM_WAIT_MS) {
 342                                DBG_871X("%s: polling cpwm timeout! poll_cnt =%d, cpwm_orig =%02x, cpwm_now =%02x\n", __func__, poll_cnt, cpwm_orig, cpwm_now);
 343                                _set_timer(&pwrpriv->pwr_rpwm_timer, 1);
 344                                break;
 345                        }
 346                } while (1);
 347        } else
 348                pwrpriv->cpwm = pslv;
 349}
 350
 351static u8 PS_RDY_CHECK(struct adapter *padapter)
 352{
 353        unsigned long curr_time, delta_time;
 354        struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
 355        struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
 356
 357#if defined(CONFIG_WOWLAN) || defined(CONFIG_AP_WOWLAN)
 358        if (true == pwrpriv->bInSuspend && pwrpriv->wowlan_mode)
 359                return true;
 360        else if (true == pwrpriv->bInSuspend && pwrpriv->wowlan_ap_mode)
 361                return true;
 362        else if (true == pwrpriv->bInSuspend)
 363                return false;
 364#else
 365        if (true == pwrpriv->bInSuspend)
 366                return false;
 367#endif
 368
 369        curr_time = jiffies;
 370
 371        delta_time = curr_time - pwrpriv->DelayLPSLastTimeStamp;
 372
 373        if (delta_time < LPS_DELAY_TIME)
 374                return false;
 375
 376        if (check_fwstate(pmlmepriv, WIFI_SITE_MONITOR)
 377                || check_fwstate(pmlmepriv, WIFI_UNDER_LINKING|WIFI_UNDER_WPS)
 378                || check_fwstate(pmlmepriv, WIFI_AP_STATE)
 379                || check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE|WIFI_ADHOC_STATE)
 380                || rtw_is_scan_deny(padapter)
 381        )
 382                return false;
 383
 384        if ((padapter->securitypriv.dot11AuthAlgrthm == dot11AuthAlgrthm_8021X) && (padapter->securitypriv.binstallGrpkey == false)) {
 385                DBG_871X("Group handshake still in progress !!!\n");
 386                return false;
 387        }
 388
 389        if (!rtw_cfg80211_pwr_mgmt(padapter))
 390                return false;
 391
 392        return true;
 393}
 394
 395void rtw_set_ps_mode(struct adapter *padapter, u8 ps_mode, u8 smart_ps, u8 bcn_ant_mode, const char *msg)
 396{
 397        struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
 398#if defined(CONFIG_WOWLAN) || defined(CONFIG_AP_WOWLAN)
 399        struct debug_priv *pdbgpriv = &padapter->dvobj->drv_dbg;
 400#endif
 401
 402        RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_notice_,
 403                         ("%s: PowerMode =%d Smart_PS =%d\n",
 404                          __func__, ps_mode, smart_ps));
 405
 406        if (ps_mode > PM_Card_Disable) {
 407                RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_err_, ("ps_mode:%d error\n", ps_mode));
 408                return;
 409        }
 410
 411        if (pwrpriv->pwr_mode == ps_mode)
 412                if (PS_MODE_ACTIVE == ps_mode)
 413                        return;
 414
 415
 416        down(&pwrpriv->lock);
 417
 418        /* if (pwrpriv->pwr_mode == PS_MODE_ACTIVE) */
 419        if (ps_mode == PS_MODE_ACTIVE) {
 420                if (1
 421                        && (((rtw_btcoex_IsBtControlLps(padapter) == false)
 422                                        )
 423                                || ((rtw_btcoex_IsBtControlLps(padapter) == true)
 424                                        && (rtw_btcoex_IsLpsOn(padapter) == false))
 425                                )
 426                        ) {
 427                        DBG_871X(FUNC_ADPT_FMT" Leave 802.11 power save - %s\n",
 428                                FUNC_ADPT_ARG(padapter), msg);
 429
 430                        pwrpriv->pwr_mode = ps_mode;
 431                        rtw_set_rpwm(padapter, PS_STATE_S4);
 432
 433#if defined(CONFIG_WOWLAN) || defined(CONFIG_AP_WOWLAN)
 434                        if (pwrpriv->wowlan_mode == true ||
 435                                        pwrpriv->wowlan_ap_mode == true) {
 436                                unsigned long start_time;
 437                                u32 delay_ms;
 438                                u8 val8;
 439                                delay_ms = 20;
 440                                start_time = jiffies;
 441                                do {
 442                                        rtw_hal_get_hwreg(padapter, HW_VAR_SYS_CLKR, &val8);
 443                                        if (!(val8 & BIT(4))) { /* 0x08 bit4 = 1 --> in 32k, bit4 = 0 --> leave 32k */
 444                                                pwrpriv->cpwm = PS_STATE_S4;
 445                                                break;
 446                                        }
 447                                        if (jiffies_to_msecs(jiffies - start_time) > delay_ms) {
 448                                                DBG_871X("%s: Wait for FW 32K leave more than %u ms!!!\n",
 449                                                                __func__, delay_ms);
 450                                                pdbgpriv->dbg_wow_leave_ps_fail_cnt++;
 451                                                break;
 452                                        }
 453                                        msleep(1);
 454                                } while (1);
 455                        }
 456#endif
 457                        rtw_hal_set_hwreg(padapter, HW_VAR_H2C_FW_PWRMODE, (u8 *)(&ps_mode));
 458                        pwrpriv->bFwCurrentInPSMode = false;
 459
 460                        rtw_btcoex_LpsNotify(padapter, ps_mode);
 461                }
 462        } else{
 463                if ((PS_RDY_CHECK(padapter) && check_fwstate(&padapter->mlmepriv, WIFI_ASOC_STATE))
 464                        || ((rtw_btcoex_IsBtControlLps(padapter) == true)
 465                                && (rtw_btcoex_IsLpsOn(padapter) == true))
 466                        ) {
 467                        u8 pslv;
 468
 469                        DBG_871X(FUNC_ADPT_FMT" Enter 802.11 power save - %s\n",
 470                                FUNC_ADPT_ARG(padapter), msg);
 471
 472                        rtw_btcoex_LpsNotify(padapter, ps_mode);
 473
 474                        pwrpriv->bFwCurrentInPSMode = true;
 475                        pwrpriv->pwr_mode = ps_mode;
 476                        pwrpriv->smart_ps = smart_ps;
 477                        pwrpriv->bcn_ant_mode = bcn_ant_mode;
 478                        rtw_hal_set_hwreg(padapter, HW_VAR_H2C_FW_PWRMODE, (u8 *)(&ps_mode));
 479
 480                        pslv = PS_STATE_S2;
 481                        if (pwrpriv->alives == 0)
 482                                pslv = PS_STATE_S0;
 483
 484                        if ((rtw_btcoex_IsBtDisabled(padapter) == false)
 485                                && (rtw_btcoex_IsBtControlLps(padapter) == true)) {
 486                                u8 val8;
 487
 488                                val8 = rtw_btcoex_LpsVal(padapter);
 489                                if (val8 & BIT(4))
 490                                        pslv = PS_STATE_S2;
 491                        }
 492
 493                        rtw_set_rpwm(padapter, pslv);
 494                }
 495        }
 496
 497        up(&pwrpriv->lock);
 498}
 499
 500/*
 501 * Return:
 502 *0:    Leave OK
 503 *-1:   Timeout
 504 *-2:   Other error
 505 */
 506s32 LPS_RF_ON_check(struct adapter *padapter, u32 delay_ms)
 507{
 508        unsigned long start_time;
 509        u8 bAwake = false;
 510        s32 err = 0;
 511
 512
 513        start_time = jiffies;
 514        while (1) {
 515                rtw_hal_get_hwreg(padapter, HW_VAR_FWLPS_RF_ON, &bAwake);
 516                if (true == bAwake)
 517                        break;
 518
 519                if (true == padapter->bSurpriseRemoved) {
 520                        err = -2;
 521                        DBG_871X("%s: device surprise removed!!\n", __func__);
 522                        break;
 523                }
 524
 525                if (jiffies_to_msecs(jiffies - start_time) > delay_ms) {
 526                        err = -1;
 527                        DBG_871X("%s: Wait for FW LPS leave more than %u ms!!!\n", __func__, delay_ms);
 528                        break;
 529                }
 530                msleep(1);
 531        }
 532
 533        return err;
 534}
 535
 536/*  */
 537/*      Description: */
 538/*              Enter the leisure power save mode. */
 539/*  */
 540void LPS_Enter(struct adapter *padapter, const char *msg)
 541{
 542        struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
 543        struct pwrctrl_priv *pwrpriv = dvobj_to_pwrctl(dvobj);
 544        int n_assoc_iface = 0;
 545        char buf[32] = {0};
 546
 547        if (rtw_btcoex_IsBtControlLps(padapter) == true)
 548                return;
 549
 550        /* Skip lps enter request if number of assocated adapters is not 1 */
 551        if (check_fwstate(&(dvobj->padapters->mlmepriv), WIFI_ASOC_STATE))
 552                n_assoc_iface++;
 553        if (n_assoc_iface != 1)
 554                return;
 555
 556        /* Skip lps enter request for adapter not port0 */
 557        if (get_iface_type(padapter) != IFACE_PORT0)
 558                return;
 559
 560        if (PS_RDY_CHECK(dvobj->padapters) == false)
 561                        return;
 562
 563        if (pwrpriv->bLeisurePs) {
 564                /*  Idle for a while if we connect to AP a while ago. */
 565                if (pwrpriv->LpsIdleCount >= 2) { /*   4 Sec */
 566                        if (pwrpriv->pwr_mode == PS_MODE_ACTIVE) {
 567                                sprintf(buf, "WIFI-%s", msg);
 568                                pwrpriv->bpower_saving = true;
 569                                rtw_set_ps_mode(padapter, pwrpriv->power_mgnt, padapter->registrypriv.smart_ps, 0, buf);
 570                        }
 571                } else
 572                        pwrpriv->LpsIdleCount++;
 573        }
 574
 575/*      DBG_871X("-LeisurePSEnter\n"); */
 576}
 577
 578/*  */
 579/*      Description: */
 580/*              Leave the leisure power save mode. */
 581/*  */
 582void LPS_Leave(struct adapter *padapter, const char *msg)
 583{
 584#define LPS_LEAVE_TIMEOUT_MS 100
 585
 586        struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
 587        struct pwrctrl_priv *pwrpriv = dvobj_to_pwrctl(dvobj);
 588        char buf[32] = {0};
 589
 590/*      DBG_871X("+LeisurePSLeave\n"); */
 591
 592        if (rtw_btcoex_IsBtControlLps(padapter) == true)
 593                return;
 594
 595        if (pwrpriv->bLeisurePs) {
 596                if (pwrpriv->pwr_mode != PS_MODE_ACTIVE) {
 597                        sprintf(buf, "WIFI-%s", msg);
 598                        rtw_set_ps_mode(padapter, PS_MODE_ACTIVE, 0, 0, buf);
 599
 600                        if (pwrpriv->pwr_mode == PS_MODE_ACTIVE)
 601                                LPS_RF_ON_check(padapter, LPS_LEAVE_TIMEOUT_MS);
 602                }
 603        }
 604
 605        pwrpriv->bpower_saving = false;
 606/*      DBG_871X("-LeisurePSLeave\n"); */
 607
 608}
 609
 610void LeaveAllPowerSaveModeDirect(struct adapter *Adapter)
 611{
 612        struct adapter *pri_padapter = GET_PRIMARY_ADAPTER(Adapter);
 613        struct mlme_priv *pmlmepriv = &(Adapter->mlmepriv);
 614        struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(Adapter);
 615
 616        DBG_871X("%s.....\n", __func__);
 617
 618        if (true == Adapter->bSurpriseRemoved) {
 619                DBG_871X(FUNC_ADPT_FMT ": bSurpriseRemoved =%d Skip!\n",
 620                        FUNC_ADPT_ARG(Adapter), Adapter->bSurpriseRemoved);
 621                return;
 622        }
 623
 624        if ((check_fwstate(pmlmepriv, _FW_LINKED) == true)) { /* connect */
 625
 626                if (pwrpriv->pwr_mode == PS_MODE_ACTIVE) {
 627                        DBG_871X("%s: Driver Already Leave LPS\n", __func__);
 628                        return;
 629                }
 630
 631                down(&pwrpriv->lock);
 632
 633                rtw_set_rpwm(Adapter, PS_STATE_S4);
 634
 635                up(&pwrpriv->lock);
 636
 637                rtw_lps_ctrl_wk_cmd(pri_padapter, LPS_CTRL_LEAVE, 0);
 638        } else{
 639                if (pwrpriv->rf_pwrstate == rf_off)
 640                        if (false == ips_leave(pri_padapter))
 641                                DBG_871X("======> ips_leave fail.............\n");
 642        }
 643}
 644
 645/*  */
 646/*  Description: Leave all power save mode: LPS, FwLPS, IPS if needed. */
 647/*  Move code to function by tynli. 2010.03.26. */
 648/*  */
 649void LeaveAllPowerSaveMode(struct adapter *Adapter)
 650{
 651        struct dvobj_priv *dvobj = adapter_to_dvobj(Adapter);
 652        u8 enqueue = 0;
 653        int n_assoc_iface = 0;
 654
 655        if (!Adapter->bup) {
 656                DBG_871X(FUNC_ADPT_FMT ": bup =%d Skip!\n",
 657                        FUNC_ADPT_ARG(Adapter), Adapter->bup);
 658                return;
 659        }
 660
 661        if (Adapter->bSurpriseRemoved) {
 662                DBG_871X(FUNC_ADPT_FMT ": bSurpriseRemoved =%d Skip!\n",
 663                        FUNC_ADPT_ARG(Adapter), Adapter->bSurpriseRemoved);
 664                return;
 665        }
 666
 667        if (check_fwstate(&(dvobj->padapters->mlmepriv), WIFI_ASOC_STATE))
 668                n_assoc_iface++;
 669
 670        if (n_assoc_iface) { /* connect */
 671                enqueue = 1;
 672
 673                rtw_lps_ctrl_wk_cmd(Adapter, LPS_CTRL_LEAVE, enqueue);
 674
 675                LPS_Leave_check(Adapter);
 676        } else {
 677                if (adapter_to_pwrctl(Adapter)->rf_pwrstate == rf_off) {
 678                        if (false == ips_leave(Adapter))
 679                                DBG_871X("======> ips_leave fail.............\n");
 680                }
 681        }
 682}
 683
 684void LPS_Leave_check(
 685        struct adapter *padapter)
 686{
 687        struct pwrctrl_priv *pwrpriv;
 688        unsigned long   start_time;
 689        u8 bReady;
 690
 691        pwrpriv = adapter_to_pwrctl(padapter);
 692
 693        bReady = false;
 694        start_time = jiffies;
 695
 696        cond_resched();
 697
 698        while (1) {
 699                down(&pwrpriv->lock);
 700
 701                if ((padapter->bSurpriseRemoved == true)
 702                        || (padapter->hw_init_completed == false)
 703                        || (pwrpriv->pwr_mode == PS_MODE_ACTIVE)
 704                        )
 705                        bReady = true;
 706
 707                up(&pwrpriv->lock);
 708
 709                if (true == bReady)
 710                        break;
 711
 712                if (jiffies_to_msecs(jiffies - start_time) > 100) {
 713                        DBG_871X("Wait for cpwm event  than 100 ms!!!\n");
 714                        break;
 715                }
 716                msleep(1);
 717        }
 718}
 719
 720/*
 721 * Caller:ISR handler...
 722 *
 723 * This will be called when CPWM interrupt is up.
 724 *
 725 * using to update cpwn of drv; and drv willl make a decision to up or down pwr level
 726 */
 727void cpwm_int_hdl(
 728        struct adapter *padapter,
 729        struct reportpwrstate_parm *preportpwrstate)
 730{
 731        struct pwrctrl_priv *pwrpriv;
 732
 733        pwrpriv = adapter_to_pwrctl(padapter);
 734
 735        down(&pwrpriv->lock);
 736
 737        if (pwrpriv->rpwm < PS_STATE_S2) {
 738                DBG_871X("%s: Redundant CPWM Int. RPWM = 0x%02X CPWM = 0x%02x\n", __func__, pwrpriv->rpwm, pwrpriv->cpwm);
 739                up(&pwrpriv->lock);
 740                goto exit;
 741        }
 742
 743        pwrpriv->cpwm = PS_STATE(preportpwrstate->state);
 744        pwrpriv->cpwm_tog = preportpwrstate->state & PS_TOGGLE;
 745
 746        if (pwrpriv->cpwm >= PS_STATE_S2) {
 747                if (pwrpriv->alives & CMD_ALIVE)
 748                        up(&padapter->cmdpriv.cmd_queue_sema);
 749
 750                if (pwrpriv->alives & XMIT_ALIVE)
 751                        up(&padapter->xmitpriv.xmit_sema);
 752        }
 753
 754        up(&pwrpriv->lock);
 755
 756exit:
 757        RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_notice_,
 758                         ("cpwm_int_hdl: cpwm = 0x%02x\n", pwrpriv->cpwm));
 759}
 760
 761static void cpwm_event_callback(struct work_struct *work)
 762{
 763        struct pwrctrl_priv *pwrpriv = container_of(work, struct pwrctrl_priv, cpwm_event);
 764        struct dvobj_priv *dvobj = pwrctl_to_dvobj(pwrpriv);
 765        struct adapter *adapter = dvobj->if1;
 766        struct reportpwrstate_parm report;
 767
 768        /* DBG_871X("%s\n", __func__); */
 769
 770        report.state = PS_STATE_S2;
 771        cpwm_int_hdl(adapter, &report);
 772}
 773
 774static void rpwmtimeout_workitem_callback(struct work_struct *work)
 775{
 776        struct adapter *padapter;
 777        struct dvobj_priv *dvobj;
 778        struct pwrctrl_priv *pwrpriv;
 779
 780
 781        pwrpriv = container_of(work, struct pwrctrl_priv, rpwmtimeoutwi);
 782        dvobj = pwrctl_to_dvobj(pwrpriv);
 783        padapter = dvobj->if1;
 784/*      DBG_871X("+%s: rpwm = 0x%02X cpwm = 0x%02X\n", __func__, pwrpriv->rpwm, pwrpriv->cpwm); */
 785
 786        down(&pwrpriv->lock);
 787        if ((pwrpriv->rpwm == pwrpriv->cpwm) || (pwrpriv->cpwm >= PS_STATE_S2)) {
 788                DBG_871X("%s: rpwm = 0x%02X cpwm = 0x%02X CPWM done!\n", __func__, pwrpriv->rpwm, pwrpriv->cpwm);
 789                goto exit;
 790        }
 791        up(&pwrpriv->lock);
 792
 793        if (rtw_read8(padapter, 0x100) != 0xEA) {
 794                struct reportpwrstate_parm report;
 795
 796                report.state = PS_STATE_S2;
 797                DBG_871X("\n%s: FW already leave 32K!\n\n", __func__);
 798                cpwm_int_hdl(padapter, &report);
 799
 800                return;
 801        }
 802
 803        down(&pwrpriv->lock);
 804
 805        if ((pwrpriv->rpwm == pwrpriv->cpwm) || (pwrpriv->cpwm >= PS_STATE_S2)) {
 806                DBG_871X("%s: cpwm =%d, nothing to do!\n", __func__, pwrpriv->cpwm);
 807                goto exit;
 808        }
 809        pwrpriv->brpwmtimeout = true;
 810        rtw_set_rpwm(padapter, pwrpriv->rpwm);
 811        pwrpriv->brpwmtimeout = false;
 812
 813exit:
 814        up(&pwrpriv->lock);
 815}
 816
 817/*
 818 * This function is a timer handler, can't do any IO in it.
 819 */
 820static void pwr_rpwm_timeout_handler(struct timer_list *t)
 821{
 822        struct pwrctrl_priv *pwrpriv = from_timer(pwrpriv, t, pwr_rpwm_timer);
 823
 824        DBG_871X("+%s: rpwm = 0x%02X cpwm = 0x%02X\n", __func__, pwrpriv->rpwm, pwrpriv->cpwm);
 825
 826        if ((pwrpriv->rpwm == pwrpriv->cpwm) || (pwrpriv->cpwm >= PS_STATE_S2)) {
 827                DBG_871X("+%s: cpwm =%d, nothing to do!\n", __func__, pwrpriv->cpwm);
 828                return;
 829        }
 830
 831        _set_workitem(&pwrpriv->rpwmtimeoutwi);
 832}
 833
 834static __inline void register_task_alive(struct pwrctrl_priv *pwrctrl, u32 tag)
 835{
 836        pwrctrl->alives |= tag;
 837}
 838
 839static __inline void unregister_task_alive(struct pwrctrl_priv *pwrctrl, u32 tag)
 840{
 841        pwrctrl->alives &= ~tag;
 842}
 843
 844
 845/*
 846 * Description:
 847 *Check if the fw_pwrstate is okay for I/O.
 848 *If not (cpwm is less than S2), then the sub-routine
 849 *will raise the cpwm to be greater than or equal to S2.
 850 *
 851 *Calling Context: Passive
 852 *
 853 *Constraint:
 854 *      1. this function will request pwrctrl->lock
 855 *
 856 * Return Value:
 857 *_SUCCESS      hardware is ready for I/O
 858 *_FAIL         can't I/O right now
 859 */
 860s32 rtw_register_task_alive(struct adapter *padapter, u32 task)
 861{
 862        s32 res;
 863        struct pwrctrl_priv *pwrctrl;
 864        u8 pslv;
 865
 866        res = _SUCCESS;
 867        pwrctrl = adapter_to_pwrctl(padapter);
 868        pslv = PS_STATE_S2;
 869
 870        down(&pwrctrl->lock);
 871
 872        register_task_alive(pwrctrl, task);
 873
 874        if (pwrctrl->bFwCurrentInPSMode == true) {
 875                RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_notice_,
 876                                 ("%s: task = 0x%x cpwm = 0x%02x alives = 0x%08x\n",
 877                                  __func__, task, pwrctrl->cpwm, pwrctrl->alives));
 878
 879                if (pwrctrl->cpwm < pslv) {
 880                        if (pwrctrl->cpwm < PS_STATE_S2)
 881                                res = _FAIL;
 882                        if (pwrctrl->rpwm < pslv)
 883                                rtw_set_rpwm(padapter, pslv);
 884                }
 885        }
 886
 887        up(&pwrctrl->lock);
 888
 889        if (_FAIL == res)
 890                if (pwrctrl->cpwm >= PS_STATE_S2)
 891                        res = _SUCCESS;
 892
 893        return res;
 894}
 895
 896/*
 897 * Description:
 898 *If task is done, call this func. to power down firmware again.
 899 *
 900 *Constraint:
 901 *      1. this function will request pwrctrl->lock
 902 *
 903 * Return Value:
 904 *none
 905 */
 906void rtw_unregister_task_alive(struct adapter *padapter, u32 task)
 907{
 908        struct pwrctrl_priv *pwrctrl;
 909        u8 pslv;
 910
 911        pwrctrl = adapter_to_pwrctl(padapter);
 912        pslv = PS_STATE_S0;
 913
 914        if ((rtw_btcoex_IsBtDisabled(padapter) == false)
 915                && (rtw_btcoex_IsBtControlLps(padapter) == true)) {
 916                u8 val8;
 917
 918                val8 = rtw_btcoex_LpsVal(padapter);
 919                if (val8 & BIT(4))
 920                        pslv = PS_STATE_S2;
 921        }
 922
 923        down(&pwrctrl->lock);
 924
 925        unregister_task_alive(pwrctrl, task);
 926
 927        if ((pwrctrl->pwr_mode != PS_MODE_ACTIVE)
 928                && (pwrctrl->bFwCurrentInPSMode == true)) {
 929                RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_notice_,
 930                                 ("%s: cpwm = 0x%02x alives = 0x%08x\n",
 931                                  __func__, pwrctrl->cpwm, pwrctrl->alives));
 932
 933                if (pwrctrl->cpwm > pslv)
 934                        if ((pslv >= PS_STATE_S2) || (pwrctrl->alives == 0))
 935                                rtw_set_rpwm(padapter, pslv);
 936
 937        }
 938
 939        up(&pwrctrl->lock);
 940}
 941
 942/*
 943 * Caller: rtw_xmit_thread
 944 *
 945 * Check if the fw_pwrstate is okay for xmit.
 946 * If not (cpwm is less than S3), then the sub-routine
 947 * will raise the cpwm to be greater than or equal to S3.
 948 *
 949 * Calling Context: Passive
 950 *
 951 * Return Value:
 952 * _SUCCESS     rtw_xmit_thread can write fifo/txcmd afterwards.
 953 * _FAIL                rtw_xmit_thread can not do anything.
 954 */
 955s32 rtw_register_tx_alive(struct adapter *padapter)
 956{
 957        s32 res;
 958        struct pwrctrl_priv *pwrctrl;
 959        u8 pslv;
 960
 961        res = _SUCCESS;
 962        pwrctrl = adapter_to_pwrctl(padapter);
 963        pslv = PS_STATE_S2;
 964
 965        down(&pwrctrl->lock);
 966
 967        register_task_alive(pwrctrl, XMIT_ALIVE);
 968
 969        if (pwrctrl->bFwCurrentInPSMode == true) {
 970                RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_notice_,
 971                                 ("rtw_register_tx_alive: cpwm = 0x%02x alives = 0x%08x\n",
 972                                  pwrctrl->cpwm, pwrctrl->alives));
 973
 974                if (pwrctrl->cpwm < pslv) {
 975                        if (pwrctrl->cpwm < PS_STATE_S2)
 976                                res = _FAIL;
 977                        if (pwrctrl->rpwm < pslv)
 978                                rtw_set_rpwm(padapter, pslv);
 979                }
 980        }
 981
 982        up(&pwrctrl->lock);
 983
 984        if (_FAIL == res)
 985                if (pwrctrl->cpwm >= PS_STATE_S2)
 986                        res = _SUCCESS;
 987
 988        return res;
 989}
 990
 991/*
 992 * Caller: rtw_cmd_thread
 993 *
 994 * Check if the fw_pwrstate is okay for issuing cmd.
 995 * If not (cpwm should be is less than S2), then the sub-routine
 996 * will raise the cpwm to be greater than or equal to S2.
 997 *
 998 * Calling Context: Passive
 999 *
1000 * Return Value:
1001 *_SUCCESS      rtw_cmd_thread can issue cmds to firmware afterwards.
1002 *_FAIL         rtw_cmd_thread can not do anything.
1003 */
1004s32 rtw_register_cmd_alive(struct adapter *padapter)
1005{
1006        s32 res;
1007        struct pwrctrl_priv *pwrctrl;
1008        u8 pslv;
1009
1010        res = _SUCCESS;
1011        pwrctrl = adapter_to_pwrctl(padapter);
1012        pslv = PS_STATE_S2;
1013
1014        down(&pwrctrl->lock);
1015
1016        register_task_alive(pwrctrl, CMD_ALIVE);
1017
1018        if (pwrctrl->bFwCurrentInPSMode == true) {
1019                RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_info_,
1020                                 ("rtw_register_cmd_alive: cpwm = 0x%02x alives = 0x%08x\n",
1021                                  pwrctrl->cpwm, pwrctrl->alives));
1022
1023                if (pwrctrl->cpwm < pslv) {
1024                        if (pwrctrl->cpwm < PS_STATE_S2)
1025                                res = _FAIL;
1026                        if (pwrctrl->rpwm < pslv)
1027                                rtw_set_rpwm(padapter, pslv);
1028                }
1029        }
1030
1031        up(&pwrctrl->lock);
1032
1033        if (_FAIL == res)
1034                if (pwrctrl->cpwm >= PS_STATE_S2)
1035                        res = _SUCCESS;
1036
1037        return res;
1038}
1039
1040/*
1041 * Caller: ISR
1042 *
1043 * If ISR's txdone,
1044 * No more pkts for TX,
1045 * Then driver shall call this fun. to power down firmware again.
1046 */
1047void rtw_unregister_tx_alive(struct adapter *padapter)
1048{
1049        struct pwrctrl_priv *pwrctrl;
1050        u8 pslv;
1051
1052        pwrctrl = adapter_to_pwrctl(padapter);
1053        pslv = PS_STATE_S0;
1054
1055        if ((rtw_btcoex_IsBtDisabled(padapter) == false)
1056                && (rtw_btcoex_IsBtControlLps(padapter) == true)) {
1057                u8 val8;
1058
1059                val8 = rtw_btcoex_LpsVal(padapter);
1060                if (val8 & BIT(4))
1061                        pslv = PS_STATE_S2;
1062        }
1063
1064        down(&pwrctrl->lock);
1065
1066        unregister_task_alive(pwrctrl, XMIT_ALIVE);
1067
1068        if ((pwrctrl->pwr_mode != PS_MODE_ACTIVE)
1069                && (pwrctrl->bFwCurrentInPSMode == true)) {
1070                RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_notice_,
1071                                 ("%s: cpwm = 0x%02x alives = 0x%08x\n",
1072                                  __func__, pwrctrl->cpwm, pwrctrl->alives));
1073
1074                if (pwrctrl->cpwm > pslv)
1075                        if ((pslv >= PS_STATE_S2) || (pwrctrl->alives == 0))
1076                                rtw_set_rpwm(padapter, pslv);
1077        }
1078
1079        up(&pwrctrl->lock);
1080}
1081
1082/*
1083 * Caller: ISR
1084 *
1085 * If all commands have been done,
1086 * and no more command to do,
1087 * then driver shall call this fun. to power down firmware again.
1088 */
1089void rtw_unregister_cmd_alive(struct adapter *padapter)
1090{
1091        struct pwrctrl_priv *pwrctrl;
1092        u8 pslv;
1093
1094        pwrctrl = adapter_to_pwrctl(padapter);
1095        pslv = PS_STATE_S0;
1096
1097        if ((rtw_btcoex_IsBtDisabled(padapter) == false)
1098                && (rtw_btcoex_IsBtControlLps(padapter) == true)) {
1099                u8 val8;
1100
1101                val8 = rtw_btcoex_LpsVal(padapter);
1102                if (val8 & BIT(4))
1103                        pslv = PS_STATE_S2;
1104        }
1105
1106        down(&pwrctrl->lock);
1107
1108        unregister_task_alive(pwrctrl, CMD_ALIVE);
1109
1110        if ((pwrctrl->pwr_mode != PS_MODE_ACTIVE)
1111                && (pwrctrl->bFwCurrentInPSMode == true)) {
1112                RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_info_,
1113                                 ("%s: cpwm = 0x%02x alives = 0x%08x\n",
1114                                  __func__, pwrctrl->cpwm, pwrctrl->alives));
1115
1116                if (pwrctrl->cpwm > pslv) {
1117                        if ((pslv >= PS_STATE_S2) || (pwrctrl->alives == 0))
1118                                rtw_set_rpwm(padapter, pslv);
1119                }
1120        }
1121
1122        up(&pwrctrl->lock);
1123}
1124
1125void rtw_init_pwrctrl_priv(struct adapter *padapter)
1126{
1127        struct pwrctrl_priv *pwrctrlpriv = adapter_to_pwrctl(padapter);
1128
1129        sema_init(&pwrctrlpriv->lock, 1);
1130        sema_init(&pwrctrlpriv->check_32k_lock, 1);
1131        pwrctrlpriv->rf_pwrstate = rf_on;
1132        pwrctrlpriv->ips_enter_cnts = 0;
1133        pwrctrlpriv->ips_leave_cnts = 0;
1134        pwrctrlpriv->bips_processing = false;
1135
1136        pwrctrlpriv->ips_mode = padapter->registrypriv.ips_mode;
1137        pwrctrlpriv->ips_mode_req = padapter->registrypriv.ips_mode;
1138
1139        pwrctrlpriv->pwr_state_check_interval = RTW_PWR_STATE_CHK_INTERVAL;
1140        pwrctrlpriv->pwr_state_check_cnts = 0;
1141        pwrctrlpriv->bInternalAutoSuspend = false;
1142        pwrctrlpriv->bInSuspend = false;
1143        pwrctrlpriv->bkeepfwalive = false;
1144
1145        pwrctrlpriv->LpsIdleCount = 0;
1146        pwrctrlpriv->power_mgnt = padapter->registrypriv.power_mgnt;/*  PS_MODE_MIN; */
1147        pwrctrlpriv->bLeisurePs = pwrctrlpriv->power_mgnt != PS_MODE_ACTIVE;
1148
1149        pwrctrlpriv->bFwCurrentInPSMode = false;
1150
1151        pwrctrlpriv->rpwm = 0;
1152        pwrctrlpriv->cpwm = PS_STATE_S4;
1153
1154        pwrctrlpriv->pwr_mode = PS_MODE_ACTIVE;
1155        pwrctrlpriv->smart_ps = padapter->registrypriv.smart_ps;
1156        pwrctrlpriv->bcn_ant_mode = 0;
1157        pwrctrlpriv->dtim = 0;
1158
1159        pwrctrlpriv->tog = 0x80;
1160
1161        rtw_hal_set_hwreg(padapter, HW_VAR_SET_RPWM, (u8 *)(&pwrctrlpriv->rpwm));
1162
1163        _init_workitem(&pwrctrlpriv->cpwm_event, cpwm_event_callback, NULL);
1164
1165        pwrctrlpriv->brpwmtimeout = false;
1166        pwrctrlpriv->adapter = padapter;
1167        _init_workitem(&pwrctrlpriv->rpwmtimeoutwi, rpwmtimeout_workitem_callback, NULL);
1168        timer_setup(&pwrctrlpriv->pwr_rpwm_timer, pwr_rpwm_timeout_handler, 0);
1169        timer_setup(&pwrctrlpriv->pwr_state_check_timer,
1170                    pwr_state_check_handler, 0);
1171
1172        pwrctrlpriv->wowlan_mode = false;
1173        pwrctrlpriv->wowlan_ap_mode = false;
1174
1175#ifdef CONFIG_PNO_SUPPORT
1176        pwrctrlpriv->pno_inited = false;
1177        pwrctrlpriv->pnlo_info = NULL;
1178        pwrctrlpriv->pscan_info = NULL;
1179        pwrctrlpriv->pno_ssid_list = NULL;
1180        pwrctrlpriv->pno_in_resume = true;
1181#endif
1182}
1183
1184
1185void rtw_free_pwrctrl_priv(struct adapter *adapter)
1186{
1187#ifdef CONFIG_PNO_SUPPORT
1188        if (pwrctrlpriv->pnlo_info != NULL)
1189                printk("****** pnlo_info memory leak********\n");
1190
1191        if (pwrctrlpriv->pscan_info != NULL)
1192                printk("****** pscan_info memory leak********\n");
1193
1194        if (pwrctrlpriv->pno_ssid_list != NULL)
1195                printk("****** pno_ssid_list memory leak********\n");
1196#endif
1197}
1198
1199inline void rtw_set_ips_deny(struct adapter *padapter, u32 ms)
1200{
1201        struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
1202        pwrpriv->ips_deny_time = jiffies + msecs_to_jiffies(ms);
1203}
1204
1205/*
1206* rtw_pwr_wakeup - Wake the NIC up from: 1)IPS. 2)USB autosuspend
1207* @adapter: pointer to struct adapter structure
1208* @ips_deffer_ms: the ms wiil prevent from falling into IPS after wakeup
1209* Return _SUCCESS or _FAIL
1210*/
1211
1212int _rtw_pwr_wakeup(struct adapter *padapter, u32 ips_deffer_ms, const char *caller)
1213{
1214        struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
1215        struct pwrctrl_priv *pwrpriv = dvobj_to_pwrctl(dvobj);
1216        struct mlme_priv *pmlmepriv;
1217        int ret = _SUCCESS;
1218        unsigned long start = jiffies;
1219        unsigned long deny_time = jiffies + msecs_to_jiffies(ips_deffer_ms);
1220
1221        /* for LPS */
1222        LeaveAllPowerSaveMode(padapter);
1223
1224        /* IPS still bound with primary adapter */
1225        padapter = GET_PRIMARY_ADAPTER(padapter);
1226        pmlmepriv = &padapter->mlmepriv;
1227
1228        if (time_before(pwrpriv->ips_deny_time, deny_time))
1229                pwrpriv->ips_deny_time = deny_time;
1230
1231
1232        if (pwrpriv->ps_processing) {
1233                DBG_871X("%s wait ps_processing...\n", __func__);
1234                while (pwrpriv->ps_processing && jiffies_to_msecs(jiffies - start) <= 3000)
1235                        msleep(10);
1236                if (pwrpriv->ps_processing)
1237                        DBG_871X("%s wait ps_processing timeout\n", __func__);
1238                else
1239                        DBG_871X("%s wait ps_processing done\n", __func__);
1240        }
1241
1242        if (pwrpriv->bInternalAutoSuspend == false && pwrpriv->bInSuspend) {
1243                DBG_871X("%s wait bInSuspend...\n", __func__);
1244                while (pwrpriv->bInSuspend
1245                        && jiffies_to_msecs(jiffies - start) <= 3000
1246                ) {
1247                        msleep(10);
1248                }
1249                if (pwrpriv->bInSuspend)
1250                        DBG_871X("%s wait bInSuspend timeout\n", __func__);
1251                else
1252                        DBG_871X("%s wait bInSuspend done\n", __func__);
1253        }
1254
1255        /* System suspend is not allowed to wakeup */
1256        if ((pwrpriv->bInternalAutoSuspend == false) && (true == pwrpriv->bInSuspend)) {
1257                ret = _FAIL;
1258                goto exit;
1259        }
1260
1261        /* block??? */
1262        if ((pwrpriv->bInternalAutoSuspend == true)  && (padapter->net_closed == true)) {
1263                ret = _FAIL;
1264                goto exit;
1265        }
1266
1267        /* I think this should be check in IPS, LPS, autosuspend functions... */
1268        if (check_fwstate(pmlmepriv, _FW_LINKED) == true) {
1269                ret = _SUCCESS;
1270                goto exit;
1271        }
1272
1273        if (rf_off == pwrpriv->rf_pwrstate) {
1274                {
1275                        DBG_8192C("%s call ips_leave....\n", __func__);
1276                        if (_FAIL ==  ips_leave(padapter)) {
1277                                DBG_8192C("======> ips_leave fail.............\n");
1278                                ret = _FAIL;
1279                                goto exit;
1280                        }
1281                }
1282        }
1283
1284        /* TODO: the following checking need to be merged... */
1285        if (padapter->bDriverStopped
1286                || !padapter->bup
1287                || !padapter->hw_init_completed
1288        ) {
1289                DBG_8192C("%s: bDriverStopped =%d, bup =%d, hw_init_completed =%u\n"
1290                        , caller
1291                        , padapter->bDriverStopped
1292                        , padapter->bup
1293                        , padapter->hw_init_completed);
1294                ret = false;
1295                goto exit;
1296        }
1297
1298exit:
1299        deny_time = jiffies + msecs_to_jiffies(ips_deffer_ms);
1300        if (time_before(pwrpriv->ips_deny_time, deny_time))
1301                pwrpriv->ips_deny_time = deny_time;
1302        return ret;
1303
1304}
1305
1306int rtw_pm_set_lps(struct adapter *padapter, u8 mode)
1307{
1308        int     ret = 0;
1309        struct pwrctrl_priv *pwrctrlpriv = adapter_to_pwrctl(padapter);
1310
1311        if (mode < PS_MODE_NUM) {
1312                if (pwrctrlpriv->power_mgnt != mode) {
1313                        if (PS_MODE_ACTIVE == mode)
1314                                LeaveAllPowerSaveMode(padapter);
1315                        else
1316                                pwrctrlpriv->LpsIdleCount = 2;
1317
1318                        pwrctrlpriv->power_mgnt = mode;
1319                        pwrctrlpriv->bLeisurePs =
1320                                pwrctrlpriv->power_mgnt != PS_MODE_ACTIVE;
1321                }
1322        } else
1323                ret = -EINVAL;
1324
1325        return ret;
1326}
1327
1328int rtw_pm_set_ips(struct adapter *padapter, u8 mode)
1329{
1330        struct pwrctrl_priv *pwrctrlpriv = adapter_to_pwrctl(padapter);
1331
1332        if (mode == IPS_NORMAL || mode == IPS_LEVEL_2) {
1333                rtw_ips_mode_req(pwrctrlpriv, mode);
1334                DBG_871X("%s %s\n", __func__, mode == IPS_NORMAL?"IPS_NORMAL":"IPS_LEVEL_2");
1335                return 0;
1336        } else if (mode == IPS_NONE) {
1337                rtw_ips_mode_req(pwrctrlpriv, mode);
1338                DBG_871X("%s %s\n", __func__, "IPS_NONE");
1339                if ((padapter->bSurpriseRemoved == 0) && (_FAIL == rtw_pwr_wakeup(padapter)))
1340                        return -EFAULT;
1341        } else
1342                return -EINVAL;
1343
1344        return 0;
1345}
1346
1347/*
1348 * ATTENTION:
1349 *This function will request pwrctrl LOCK!
1350 */
1351void rtw_ps_deny(struct adapter *padapter, enum PS_DENY_REASON reason)
1352{
1353        struct pwrctrl_priv *pwrpriv;
1354
1355/*      DBG_871X("+" FUNC_ADPT_FMT ": Request PS deny for %d (0x%08X)\n", */
1356/*              FUNC_ADPT_ARG(padapter), reason, BIT(reason)); */
1357
1358        pwrpriv = adapter_to_pwrctl(padapter);
1359
1360        down(&pwrpriv->lock);
1361        if (pwrpriv->ps_deny & BIT(reason)) {
1362                DBG_871X(FUNC_ADPT_FMT ": [WARNING] Reason %d had been set before!!\n",
1363                        FUNC_ADPT_ARG(padapter), reason);
1364        }
1365        pwrpriv->ps_deny |= BIT(reason);
1366        up(&pwrpriv->lock);
1367
1368/*      DBG_871X("-" FUNC_ADPT_FMT ": Now PS deny for 0x%08X\n", */
1369/*              FUNC_ADPT_ARG(padapter), pwrpriv->ps_deny); */
1370}
1371
1372/*
1373 * ATTENTION:
1374 *This function will request pwrctrl LOCK!
1375 */
1376void rtw_ps_deny_cancel(struct adapter *padapter, enum PS_DENY_REASON reason)
1377{
1378        struct pwrctrl_priv *pwrpriv;
1379
1380
1381/*      DBG_871X("+" FUNC_ADPT_FMT ": Cancel PS deny for %d(0x%08X)\n", */
1382/*              FUNC_ADPT_ARG(padapter), reason, BIT(reason)); */
1383
1384        pwrpriv = adapter_to_pwrctl(padapter);
1385
1386        down(&pwrpriv->lock);
1387        if ((pwrpriv->ps_deny & BIT(reason)) == 0) {
1388                DBG_871X(FUNC_ADPT_FMT ": [ERROR] Reason %d had been canceled before!!\n",
1389                        FUNC_ADPT_ARG(padapter), reason);
1390        }
1391        pwrpriv->ps_deny &= ~BIT(reason);
1392        up(&pwrpriv->lock);
1393
1394/*      DBG_871X("-" FUNC_ADPT_FMT ": Now PS deny for 0x%08X\n", */
1395/*              FUNC_ADPT_ARG(padapter), pwrpriv->ps_deny); */
1396}
1397
1398/*
1399 * ATTENTION:
1400 *Before calling this function pwrctrl lock should be occupied already,
1401 *otherwise it may return incorrect value.
1402 */
1403u32 rtw_ps_deny_get(struct adapter *padapter)
1404{
1405        u32 deny;
1406
1407
1408        deny = adapter_to_pwrctl(padapter)->ps_deny;
1409
1410        return deny;
1411}
1412