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        mutex_lock(&pwrpriv->lock);
  49        _ips_enter(padapter);
  50        mutex_unlock(&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        mutex_lock(&pwrpriv->lock);
  89        ret = _ips_leave(padapter);
  90        mutex_unlock(&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        mutex_lock(&adapter_to_pwrctl(padapter)->lock);
 162        ps_deny = rtw_ps_deny_get(padapter);
 163        mutex_unlock(&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        mutex_lock(&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        mutex_unlock(&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                mutex_lock(&pwrpriv->lock);
 632
 633                rtw_set_rpwm(Adapter, PS_STATE_S4);
 634
 635                mutex_unlock(&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                mutex_lock(&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                mutex_unlock(&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        mutex_lock(&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                goto exit;
 740        }
 741
 742        pwrpriv->cpwm = PS_STATE(preportpwrstate->state);
 743        pwrpriv->cpwm_tog = preportpwrstate->state & PS_TOGGLE;
 744
 745        if (pwrpriv->cpwm >= PS_STATE_S2) {
 746                if (pwrpriv->alives & CMD_ALIVE)
 747                        complete(&padapter->cmdpriv.cmd_queue_comp);
 748
 749                if (pwrpriv->alives & XMIT_ALIVE)
 750                        complete(&padapter->xmitpriv.xmit_comp);
 751        }
 752
 753exit:
 754        mutex_unlock(&pwrpriv->lock);
 755
 756        RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_notice_,
 757                         ("cpwm_int_hdl: cpwm = 0x%02x\n", pwrpriv->cpwm));
 758}
 759
 760static void cpwm_event_callback(struct work_struct *work)
 761{
 762        struct pwrctrl_priv *pwrpriv = container_of(work, struct pwrctrl_priv, cpwm_event);
 763        struct dvobj_priv *dvobj = pwrctl_to_dvobj(pwrpriv);
 764        struct adapter *adapter = dvobj->if1;
 765        struct reportpwrstate_parm report;
 766
 767        /* DBG_871X("%s\n", __func__); */
 768
 769        report.state = PS_STATE_S2;
 770        cpwm_int_hdl(adapter, &report);
 771}
 772
 773static void rpwmtimeout_workitem_callback(struct work_struct *work)
 774{
 775        struct adapter *padapter;
 776        struct dvobj_priv *dvobj;
 777        struct pwrctrl_priv *pwrpriv;
 778
 779
 780        pwrpriv = container_of(work, struct pwrctrl_priv, rpwmtimeoutwi);
 781        dvobj = pwrctl_to_dvobj(pwrpriv);
 782        padapter = dvobj->if1;
 783/*      DBG_871X("+%s: rpwm = 0x%02X cpwm = 0x%02X\n", __func__, pwrpriv->rpwm, pwrpriv->cpwm); */
 784
 785        mutex_lock(&pwrpriv->lock);
 786        if ((pwrpriv->rpwm == pwrpriv->cpwm) || (pwrpriv->cpwm >= PS_STATE_S2)) {
 787                DBG_871X("%s: rpwm = 0x%02X cpwm = 0x%02X CPWM done!\n", __func__, pwrpriv->rpwm, pwrpriv->cpwm);
 788                goto exit;
 789        }
 790        mutex_unlock(&pwrpriv->lock);
 791
 792        if (rtw_read8(padapter, 0x100) != 0xEA) {
 793                struct reportpwrstate_parm report;
 794
 795                report.state = PS_STATE_S2;
 796                DBG_871X("\n%s: FW already leave 32K!\n\n", __func__);
 797                cpwm_int_hdl(padapter, &report);
 798
 799                return;
 800        }
 801
 802        mutex_lock(&pwrpriv->lock);
 803
 804        if ((pwrpriv->rpwm == pwrpriv->cpwm) || (pwrpriv->cpwm >= PS_STATE_S2)) {
 805                DBG_871X("%s: cpwm =%d, nothing to do!\n", __func__, pwrpriv->cpwm);
 806                goto exit;
 807        }
 808        pwrpriv->brpwmtimeout = true;
 809        rtw_set_rpwm(padapter, pwrpriv->rpwm);
 810        pwrpriv->brpwmtimeout = false;
 811
 812exit:
 813        mutex_unlock(&pwrpriv->lock);
 814}
 815
 816/*
 817 * This function is a timer handler, can't do any IO in it.
 818 */
 819static void pwr_rpwm_timeout_handler(struct timer_list *t)
 820{
 821        struct pwrctrl_priv *pwrpriv = from_timer(pwrpriv, t, pwr_rpwm_timer);
 822
 823        DBG_871X("+%s: rpwm = 0x%02X cpwm = 0x%02X\n", __func__, pwrpriv->rpwm, pwrpriv->cpwm);
 824
 825        if ((pwrpriv->rpwm == pwrpriv->cpwm) || (pwrpriv->cpwm >= PS_STATE_S2)) {
 826                DBG_871X("+%s: cpwm =%d, nothing to do!\n", __func__, pwrpriv->cpwm);
 827                return;
 828        }
 829
 830        _set_workitem(&pwrpriv->rpwmtimeoutwi);
 831}
 832
 833static __inline void register_task_alive(struct pwrctrl_priv *pwrctrl, u32 tag)
 834{
 835        pwrctrl->alives |= tag;
 836}
 837
 838static __inline void unregister_task_alive(struct pwrctrl_priv *pwrctrl, u32 tag)
 839{
 840        pwrctrl->alives &= ~tag;
 841}
 842
 843
 844/*
 845 * Description:
 846 *Check if the fw_pwrstate is okay for I/O.
 847 *If not (cpwm is less than S2), then the sub-routine
 848 *will raise the cpwm to be greater than or equal to S2.
 849 *
 850 *Calling Context: Passive
 851 *
 852 *Constraint:
 853 *      1. this function will request pwrctrl->lock
 854 *
 855 * Return Value:
 856 *_SUCCESS      hardware is ready for I/O
 857 *_FAIL         can't I/O right now
 858 */
 859s32 rtw_register_task_alive(struct adapter *padapter, u32 task)
 860{
 861        s32 res;
 862        struct pwrctrl_priv *pwrctrl;
 863        u8 pslv;
 864
 865        res = _SUCCESS;
 866        pwrctrl = adapter_to_pwrctl(padapter);
 867        pslv = PS_STATE_S2;
 868
 869        mutex_lock(&pwrctrl->lock);
 870
 871        register_task_alive(pwrctrl, task);
 872
 873        if (pwrctrl->bFwCurrentInPSMode == true) {
 874                RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_notice_,
 875                                 ("%s: task = 0x%x cpwm = 0x%02x alives = 0x%08x\n",
 876                                  __func__, task, pwrctrl->cpwm, pwrctrl->alives));
 877
 878                if (pwrctrl->cpwm < pslv) {
 879                        if (pwrctrl->cpwm < PS_STATE_S2)
 880                                res = _FAIL;
 881                        if (pwrctrl->rpwm < pslv)
 882                                rtw_set_rpwm(padapter, pslv);
 883                }
 884        }
 885
 886        mutex_unlock(&pwrctrl->lock);
 887
 888        if (_FAIL == res)
 889                if (pwrctrl->cpwm >= PS_STATE_S2)
 890                        res = _SUCCESS;
 891
 892        return res;
 893}
 894
 895/*
 896 * Description:
 897 *If task is done, call this func. to power down firmware again.
 898 *
 899 *Constraint:
 900 *      1. this function will request pwrctrl->lock
 901 *
 902 * Return Value:
 903 *none
 904 */
 905void rtw_unregister_task_alive(struct adapter *padapter, u32 task)
 906{
 907        struct pwrctrl_priv *pwrctrl;
 908        u8 pslv;
 909
 910        pwrctrl = adapter_to_pwrctl(padapter);
 911        pslv = PS_STATE_S0;
 912
 913        if ((rtw_btcoex_IsBtDisabled(padapter) == false)
 914                && (rtw_btcoex_IsBtControlLps(padapter) == true)) {
 915                u8 val8;
 916
 917                val8 = rtw_btcoex_LpsVal(padapter);
 918                if (val8 & BIT(4))
 919                        pslv = PS_STATE_S2;
 920        }
 921
 922        mutex_lock(&pwrctrl->lock);
 923
 924        unregister_task_alive(pwrctrl, task);
 925
 926        if ((pwrctrl->pwr_mode != PS_MODE_ACTIVE)
 927                && (pwrctrl->bFwCurrentInPSMode == true)) {
 928                RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_notice_,
 929                                 ("%s: cpwm = 0x%02x alives = 0x%08x\n",
 930                                  __func__, pwrctrl->cpwm, pwrctrl->alives));
 931
 932                if (pwrctrl->cpwm > pslv)
 933                        if ((pslv >= PS_STATE_S2) || (pwrctrl->alives == 0))
 934                                rtw_set_rpwm(padapter, pslv);
 935
 936        }
 937
 938        mutex_unlock(&pwrctrl->lock);
 939}
 940
 941/*
 942 * Caller: rtw_xmit_thread
 943 *
 944 * Check if the fw_pwrstate is okay for xmit.
 945 * If not (cpwm is less than S3), then the sub-routine
 946 * will raise the cpwm to be greater than or equal to S3.
 947 *
 948 * Calling Context: Passive
 949 *
 950 * Return Value:
 951 * _SUCCESS     rtw_xmit_thread can write fifo/txcmd afterwards.
 952 * _FAIL                rtw_xmit_thread can not do anything.
 953 */
 954s32 rtw_register_tx_alive(struct adapter *padapter)
 955{
 956        s32 res;
 957        struct pwrctrl_priv *pwrctrl;
 958        u8 pslv;
 959
 960        res = _SUCCESS;
 961        pwrctrl = adapter_to_pwrctl(padapter);
 962        pslv = PS_STATE_S2;
 963
 964        mutex_lock(&pwrctrl->lock);
 965
 966        register_task_alive(pwrctrl, XMIT_ALIVE);
 967
 968        if (pwrctrl->bFwCurrentInPSMode == true) {
 969                RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_notice_,
 970                                 ("rtw_register_tx_alive: cpwm = 0x%02x alives = 0x%08x\n",
 971                                  pwrctrl->cpwm, pwrctrl->alives));
 972
 973                if (pwrctrl->cpwm < pslv) {
 974                        if (pwrctrl->cpwm < PS_STATE_S2)
 975                                res = _FAIL;
 976                        if (pwrctrl->rpwm < pslv)
 977                                rtw_set_rpwm(padapter, pslv);
 978                }
 979        }
 980
 981        mutex_unlock(&pwrctrl->lock);
 982
 983        if (_FAIL == res)
 984                if (pwrctrl->cpwm >= PS_STATE_S2)
 985                        res = _SUCCESS;
 986
 987        return res;
 988}
 989
 990/*
 991 * Caller: rtw_cmd_thread
 992 *
 993 * Check if the fw_pwrstate is okay for issuing cmd.
 994 * If not (cpwm should be is less than S2), then the sub-routine
 995 * will raise the cpwm to be greater than or equal to S2.
 996 *
 997 * Calling Context: Passive
 998 *
 999 * Return Value:
1000 *_SUCCESS      rtw_cmd_thread can issue cmds to firmware afterwards.
1001 *_FAIL         rtw_cmd_thread can not do anything.
1002 */
1003s32 rtw_register_cmd_alive(struct adapter *padapter)
1004{
1005        s32 res;
1006        struct pwrctrl_priv *pwrctrl;
1007        u8 pslv;
1008
1009        res = _SUCCESS;
1010        pwrctrl = adapter_to_pwrctl(padapter);
1011        pslv = PS_STATE_S2;
1012
1013        mutex_lock(&pwrctrl->lock);
1014
1015        register_task_alive(pwrctrl, CMD_ALIVE);
1016
1017        if (pwrctrl->bFwCurrentInPSMode == true) {
1018                RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_info_,
1019                                 ("rtw_register_cmd_alive: cpwm = 0x%02x alives = 0x%08x\n",
1020                                  pwrctrl->cpwm, pwrctrl->alives));
1021
1022                if (pwrctrl->cpwm < pslv) {
1023                        if (pwrctrl->cpwm < PS_STATE_S2)
1024                                res = _FAIL;
1025                        if (pwrctrl->rpwm < pslv)
1026                                rtw_set_rpwm(padapter, pslv);
1027                }
1028        }
1029
1030        mutex_unlock(&pwrctrl->lock);
1031
1032        if (_FAIL == res)
1033                if (pwrctrl->cpwm >= PS_STATE_S2)
1034                        res = _SUCCESS;
1035
1036        return res;
1037}
1038
1039/*
1040 * Caller: ISR
1041 *
1042 * If ISR's txdone,
1043 * No more pkts for TX,
1044 * Then driver shall call this fun. to power down firmware again.
1045 */
1046void rtw_unregister_tx_alive(struct adapter *padapter)
1047{
1048        struct pwrctrl_priv *pwrctrl;
1049        u8 pslv;
1050
1051        pwrctrl = adapter_to_pwrctl(padapter);
1052        pslv = PS_STATE_S0;
1053
1054        if ((rtw_btcoex_IsBtDisabled(padapter) == false)
1055                && (rtw_btcoex_IsBtControlLps(padapter) == true)) {
1056                u8 val8;
1057
1058                val8 = rtw_btcoex_LpsVal(padapter);
1059                if (val8 & BIT(4))
1060                        pslv = PS_STATE_S2;
1061        }
1062
1063        mutex_lock(&pwrctrl->lock);
1064
1065        unregister_task_alive(pwrctrl, XMIT_ALIVE);
1066
1067        if ((pwrctrl->pwr_mode != PS_MODE_ACTIVE)
1068                && (pwrctrl->bFwCurrentInPSMode == true)) {
1069                RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_notice_,
1070                                 ("%s: cpwm = 0x%02x alives = 0x%08x\n",
1071                                  __func__, pwrctrl->cpwm, pwrctrl->alives));
1072
1073                if (pwrctrl->cpwm > pslv)
1074                        if ((pslv >= PS_STATE_S2) || (pwrctrl->alives == 0))
1075                                rtw_set_rpwm(padapter, pslv);
1076        }
1077
1078        mutex_unlock(&pwrctrl->lock);
1079}
1080
1081/*
1082 * Caller: ISR
1083 *
1084 * If all commands have been done,
1085 * and no more command to do,
1086 * then driver shall call this fun. to power down firmware again.
1087 */
1088void rtw_unregister_cmd_alive(struct adapter *padapter)
1089{
1090        struct pwrctrl_priv *pwrctrl;
1091        u8 pslv;
1092
1093        pwrctrl = adapter_to_pwrctl(padapter);
1094        pslv = PS_STATE_S0;
1095
1096        if ((rtw_btcoex_IsBtDisabled(padapter) == false)
1097                && (rtw_btcoex_IsBtControlLps(padapter) == true)) {
1098                u8 val8;
1099
1100                val8 = rtw_btcoex_LpsVal(padapter);
1101                if (val8 & BIT(4))
1102                        pslv = PS_STATE_S2;
1103        }
1104
1105        mutex_lock(&pwrctrl->lock);
1106
1107        unregister_task_alive(pwrctrl, CMD_ALIVE);
1108
1109        if ((pwrctrl->pwr_mode != PS_MODE_ACTIVE)
1110                && (pwrctrl->bFwCurrentInPSMode == true)) {
1111                RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_info_,
1112                                 ("%s: cpwm = 0x%02x alives = 0x%08x\n",
1113                                  __func__, pwrctrl->cpwm, pwrctrl->alives));
1114
1115                if (pwrctrl->cpwm > pslv) {
1116                        if ((pslv >= PS_STATE_S2) || (pwrctrl->alives == 0))
1117                                rtw_set_rpwm(padapter, pslv);
1118                }
1119        }
1120
1121        mutex_unlock(&pwrctrl->lock);
1122}
1123
1124void rtw_init_pwrctrl_priv(struct adapter *padapter)
1125{
1126        struct pwrctrl_priv *pwrctrlpriv = adapter_to_pwrctl(padapter);
1127
1128        mutex_init(&pwrctrlpriv->lock);
1129        pwrctrlpriv->rf_pwrstate = rf_on;
1130        pwrctrlpriv->ips_enter_cnts = 0;
1131        pwrctrlpriv->ips_leave_cnts = 0;
1132        pwrctrlpriv->bips_processing = false;
1133
1134        pwrctrlpriv->ips_mode = padapter->registrypriv.ips_mode;
1135        pwrctrlpriv->ips_mode_req = padapter->registrypriv.ips_mode;
1136
1137        pwrctrlpriv->pwr_state_check_interval = RTW_PWR_STATE_CHK_INTERVAL;
1138        pwrctrlpriv->pwr_state_check_cnts = 0;
1139        pwrctrlpriv->bInternalAutoSuspend = false;
1140        pwrctrlpriv->bInSuspend = false;
1141        pwrctrlpriv->bkeepfwalive = false;
1142
1143        pwrctrlpriv->LpsIdleCount = 0;
1144        pwrctrlpriv->power_mgnt = padapter->registrypriv.power_mgnt;/*  PS_MODE_MIN; */
1145        pwrctrlpriv->bLeisurePs = pwrctrlpriv->power_mgnt != PS_MODE_ACTIVE;
1146
1147        pwrctrlpriv->bFwCurrentInPSMode = false;
1148
1149        pwrctrlpriv->rpwm = 0;
1150        pwrctrlpriv->cpwm = PS_STATE_S4;
1151
1152        pwrctrlpriv->pwr_mode = PS_MODE_ACTIVE;
1153        pwrctrlpriv->smart_ps = padapter->registrypriv.smart_ps;
1154        pwrctrlpriv->bcn_ant_mode = 0;
1155        pwrctrlpriv->dtim = 0;
1156
1157        pwrctrlpriv->tog = 0x80;
1158
1159        rtw_hal_set_hwreg(padapter, HW_VAR_SET_RPWM, (u8 *)(&pwrctrlpriv->rpwm));
1160
1161        _init_workitem(&pwrctrlpriv->cpwm_event, cpwm_event_callback, NULL);
1162
1163        pwrctrlpriv->brpwmtimeout = false;
1164        pwrctrlpriv->adapter = padapter;
1165        _init_workitem(&pwrctrlpriv->rpwmtimeoutwi, rpwmtimeout_workitem_callback, NULL);
1166        timer_setup(&pwrctrlpriv->pwr_rpwm_timer, pwr_rpwm_timeout_handler, 0);
1167        timer_setup(&pwrctrlpriv->pwr_state_check_timer,
1168                    pwr_state_check_handler, 0);
1169
1170        pwrctrlpriv->wowlan_mode = false;
1171        pwrctrlpriv->wowlan_ap_mode = false;
1172
1173#ifdef CONFIG_PNO_SUPPORT
1174        pwrctrlpriv->pno_inited = false;
1175        pwrctrlpriv->pnlo_info = NULL;
1176        pwrctrlpriv->pscan_info = NULL;
1177        pwrctrlpriv->pno_ssid_list = NULL;
1178        pwrctrlpriv->pno_in_resume = true;
1179#endif
1180}
1181
1182
1183void rtw_free_pwrctrl_priv(struct adapter *adapter)
1184{
1185#ifdef CONFIG_PNO_SUPPORT
1186        if (pwrctrlpriv->pnlo_info != NULL)
1187                printk("****** pnlo_info memory leak********\n");
1188
1189        if (pwrctrlpriv->pscan_info != NULL)
1190                printk("****** pscan_info memory leak********\n");
1191
1192        if (pwrctrlpriv->pno_ssid_list != NULL)
1193                printk("****** pno_ssid_list memory leak********\n");
1194#endif
1195}
1196
1197inline void rtw_set_ips_deny(struct adapter *padapter, u32 ms)
1198{
1199        struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
1200        pwrpriv->ips_deny_time = jiffies + msecs_to_jiffies(ms);
1201}
1202
1203/*
1204* rtw_pwr_wakeup - Wake the NIC up from: 1)IPS. 2)USB autosuspend
1205* @adapter: pointer to struct adapter structure
1206* @ips_deffer_ms: the ms wiil prevent from falling into IPS after wakeup
1207* Return _SUCCESS or _FAIL
1208*/
1209
1210int _rtw_pwr_wakeup(struct adapter *padapter, u32 ips_deffer_ms, const char *caller)
1211{
1212        struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
1213        struct pwrctrl_priv *pwrpriv = dvobj_to_pwrctl(dvobj);
1214        struct mlme_priv *pmlmepriv;
1215        int ret = _SUCCESS;
1216        unsigned long start = jiffies;
1217        unsigned long deny_time = jiffies + msecs_to_jiffies(ips_deffer_ms);
1218
1219        /* for LPS */
1220        LeaveAllPowerSaveMode(padapter);
1221
1222        /* IPS still bound with primary adapter */
1223        padapter = GET_PRIMARY_ADAPTER(padapter);
1224        pmlmepriv = &padapter->mlmepriv;
1225
1226        if (time_before(pwrpriv->ips_deny_time, deny_time))
1227                pwrpriv->ips_deny_time = deny_time;
1228
1229
1230        if (pwrpriv->ps_processing) {
1231                DBG_871X("%s wait ps_processing...\n", __func__);
1232                while (pwrpriv->ps_processing && jiffies_to_msecs(jiffies - start) <= 3000)
1233                        mdelay(10);
1234                if (pwrpriv->ps_processing)
1235                        DBG_871X("%s wait ps_processing timeout\n", __func__);
1236                else
1237                        DBG_871X("%s wait ps_processing done\n", __func__);
1238        }
1239
1240        if (pwrpriv->bInternalAutoSuspend == false && pwrpriv->bInSuspend) {
1241                DBG_871X("%s wait bInSuspend...\n", __func__);
1242                while (pwrpriv->bInSuspend
1243                        && jiffies_to_msecs(jiffies - start) <= 3000
1244                ) {
1245                        mdelay(10);
1246                }
1247                if (pwrpriv->bInSuspend)
1248                        DBG_871X("%s wait bInSuspend timeout\n", __func__);
1249                else
1250                        DBG_871X("%s wait bInSuspend done\n", __func__);
1251        }
1252
1253        /* System suspend is not allowed to wakeup */
1254        if ((pwrpriv->bInternalAutoSuspend == false) && (true == pwrpriv->bInSuspend)) {
1255                ret = _FAIL;
1256                goto exit;
1257        }
1258
1259        /* block??? */
1260        if ((pwrpriv->bInternalAutoSuspend == true)  && (padapter->net_closed == true)) {
1261                ret = _FAIL;
1262                goto exit;
1263        }
1264
1265        /* I think this should be check in IPS, LPS, autosuspend functions... */
1266        if (check_fwstate(pmlmepriv, _FW_LINKED) == true) {
1267                ret = _SUCCESS;
1268                goto exit;
1269        }
1270
1271        if (rf_off == pwrpriv->rf_pwrstate) {
1272                {
1273                        DBG_8192C("%s call ips_leave....\n", __func__);
1274                        if (_FAIL ==  ips_leave(padapter)) {
1275                                DBG_8192C("======> ips_leave fail.............\n");
1276                                ret = _FAIL;
1277                                goto exit;
1278                        }
1279                }
1280        }
1281
1282        /* TODO: the following checking need to be merged... */
1283        if (padapter->bDriverStopped
1284                || !padapter->bup
1285                || !padapter->hw_init_completed
1286        ) {
1287                DBG_8192C("%s: bDriverStopped =%d, bup =%d, hw_init_completed =%u\n"
1288                        , caller
1289                        , padapter->bDriverStopped
1290                        , padapter->bup
1291                        , padapter->hw_init_completed);
1292                ret = false;
1293                goto exit;
1294        }
1295
1296exit:
1297        deny_time = jiffies + msecs_to_jiffies(ips_deffer_ms);
1298        if (time_before(pwrpriv->ips_deny_time, deny_time))
1299                pwrpriv->ips_deny_time = deny_time;
1300        return ret;
1301
1302}
1303
1304int rtw_pm_set_lps(struct adapter *padapter, u8 mode)
1305{
1306        int     ret = 0;
1307        struct pwrctrl_priv *pwrctrlpriv = adapter_to_pwrctl(padapter);
1308
1309        if (mode < PS_MODE_NUM) {
1310                if (pwrctrlpriv->power_mgnt != mode) {
1311                        if (PS_MODE_ACTIVE == mode)
1312                                LeaveAllPowerSaveMode(padapter);
1313                        else
1314                                pwrctrlpriv->LpsIdleCount = 2;
1315
1316                        pwrctrlpriv->power_mgnt = mode;
1317                        pwrctrlpriv->bLeisurePs =
1318                                pwrctrlpriv->power_mgnt != PS_MODE_ACTIVE;
1319                }
1320        } else
1321                ret = -EINVAL;
1322
1323        return ret;
1324}
1325
1326int rtw_pm_set_ips(struct adapter *padapter, u8 mode)
1327{
1328        struct pwrctrl_priv *pwrctrlpriv = adapter_to_pwrctl(padapter);
1329
1330        if (mode == IPS_NORMAL || mode == IPS_LEVEL_2) {
1331                rtw_ips_mode_req(pwrctrlpriv, mode);
1332                DBG_871X("%s %s\n", __func__, mode == IPS_NORMAL?"IPS_NORMAL":"IPS_LEVEL_2");
1333                return 0;
1334        } else if (mode == IPS_NONE) {
1335                rtw_ips_mode_req(pwrctrlpriv, mode);
1336                DBG_871X("%s %s\n", __func__, "IPS_NONE");
1337                if ((padapter->bSurpriseRemoved == 0) && (_FAIL == rtw_pwr_wakeup(padapter)))
1338                        return -EFAULT;
1339        } else
1340                return -EINVAL;
1341
1342        return 0;
1343}
1344
1345/*
1346 * ATTENTION:
1347 *This function will request pwrctrl LOCK!
1348 */
1349void rtw_ps_deny(struct adapter *padapter, enum PS_DENY_REASON reason)
1350{
1351        struct pwrctrl_priv *pwrpriv;
1352
1353/*      DBG_871X("+" FUNC_ADPT_FMT ": Request PS deny for %d (0x%08X)\n", */
1354/*              FUNC_ADPT_ARG(padapter), reason, BIT(reason)); */
1355
1356        pwrpriv = adapter_to_pwrctl(padapter);
1357
1358        mutex_lock(&pwrpriv->lock);
1359        if (pwrpriv->ps_deny & BIT(reason)) {
1360                DBG_871X(FUNC_ADPT_FMT ": [WARNING] Reason %d had been set before!!\n",
1361                        FUNC_ADPT_ARG(padapter), reason);
1362        }
1363        pwrpriv->ps_deny |= BIT(reason);
1364        mutex_unlock(&pwrpriv->lock);
1365
1366/*      DBG_871X("-" FUNC_ADPT_FMT ": Now PS deny for 0x%08X\n", */
1367/*              FUNC_ADPT_ARG(padapter), pwrpriv->ps_deny); */
1368}
1369
1370/*
1371 * ATTENTION:
1372 *This function will request pwrctrl LOCK!
1373 */
1374void rtw_ps_deny_cancel(struct adapter *padapter, enum PS_DENY_REASON reason)
1375{
1376        struct pwrctrl_priv *pwrpriv;
1377
1378
1379/*      DBG_871X("+" FUNC_ADPT_FMT ": Cancel PS deny for %d(0x%08X)\n", */
1380/*              FUNC_ADPT_ARG(padapter), reason, BIT(reason)); */
1381
1382        pwrpriv = adapter_to_pwrctl(padapter);
1383
1384        mutex_lock(&pwrpriv->lock);
1385        if ((pwrpriv->ps_deny & BIT(reason)) == 0) {
1386                DBG_871X(FUNC_ADPT_FMT ": [ERROR] Reason %d had been canceled before!!\n",
1387                        FUNC_ADPT_ARG(padapter), reason);
1388        }
1389        pwrpriv->ps_deny &= ~BIT(reason);
1390        mutex_unlock(&pwrpriv->lock);
1391
1392/*      DBG_871X("-" FUNC_ADPT_FMT ": Now PS deny for 0x%08X\n", */
1393/*              FUNC_ADPT_ARG(padapter), pwrpriv->ps_deny); */
1394}
1395
1396/*
1397 * ATTENTION:
1398 *Before calling this function pwrctrl lock should be occupied already,
1399 *otherwise it may return incorrect value.
1400 */
1401u32 rtw_ps_deny_get(struct adapter *padapter)
1402{
1403        u32 deny;
1404
1405
1406        deny = adapter_to_pwrctl(padapter)->ps_deny;
1407
1408        return deny;
1409}
1410