[go: nahoru, domu]

11cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger/******************************************************************************
21cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger *
31cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
41cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger *
51cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger * This program is free software; you can redistribute it and/or modify it
61cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger * under the terms of version 2 of the GNU General Public License as
71cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger * published by the Free Software Foundation.
81cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger *
91cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger * This program is distributed in the hope that it will be useful, but WITHOUT
101cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
111cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
121cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger * more details.
131cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger *
141cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger * You should have received a copy of the GNU General Public License along with
151cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger * this program; if not, write to the Free Software Foundation, Inc.,
161cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
171cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger *
181cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger *
191cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger ******************************************************************************/
201cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger#define _RTW_PWRCTRL_C_
211cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger
221cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger#include <osdep_service.h>
231cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger#include <drv_types.h>
241cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger#include <osdep_intf.h>
25e73fd15ea84a8b2411a70b62473a7bfcba74c207navin patidar#include <usb_ops_linux.h>
261cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger#include <linux/usb.h>
2795311b478fea4c489603258549c16e5819c4c153navin patidar
2895311b478fea4c489603258549c16e5819c4c153navin patidarstatic int rtw_hw_suspend(struct adapter *padapter)
2995311b478fea4c489603258549c16e5819c4c153navin patidar{
3095311b478fea4c489603258549c16e5819c4c153navin patidar	struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
3195311b478fea4c489603258549c16e5819c4c153navin patidar	struct net_device *pnetdev = padapter->pnetdev;
3295311b478fea4c489603258549c16e5819c4c153navin patidar
3395311b478fea4c489603258549c16e5819c4c153navin patidar
3495311b478fea4c489603258549c16e5819c4c153navin patidar	if ((!padapter->bup) || (padapter->bDriverStopped) ||
3595311b478fea4c489603258549c16e5819c4c153navin patidar	    (padapter->bSurpriseRemoved)) {
3695311b478fea4c489603258549c16e5819c4c153navin patidar		DBG_88E("padapter->bup=%d bDriverStopped=%d bSurpriseRemoved = %d\n",
3795311b478fea4c489603258549c16e5819c4c153navin patidar			padapter->bup, padapter->bDriverStopped,
3895311b478fea4c489603258549c16e5819c4c153navin patidar			padapter->bSurpriseRemoved);
3995311b478fea4c489603258549c16e5819c4c153navin patidar		goto error_exit;
4095311b478fea4c489603258549c16e5819c4c153navin patidar	}
4195311b478fea4c489603258549c16e5819c4c153navin patidar
4295311b478fea4c489603258549c16e5819c4c153navin patidar	/* system suspend */
4395311b478fea4c489603258549c16e5819c4c153navin patidar	LeaveAllPowerSaveMode(padapter);
4495311b478fea4c489603258549c16e5819c4c153navin patidar
4595311b478fea4c489603258549c16e5819c4c153navin patidar	DBG_88E("==> rtw_hw_suspend\n");
4695311b478fea4c489603258549c16e5819c4c153navin patidar	_enter_pwrlock(&pwrpriv->lock);
4795311b478fea4c489603258549c16e5819c4c153navin patidar	pwrpriv->bips_processing = true;
4895311b478fea4c489603258549c16e5819c4c153navin patidar	/* s1. */
4995311b478fea4c489603258549c16e5819c4c153navin patidar	if (pnetdev) {
5095311b478fea4c489603258549c16e5819c4c153navin patidar		netif_carrier_off(pnetdev);
5195311b478fea4c489603258549c16e5819c4c153navin patidar		netif_tx_stop_all_queues(pnetdev);
5295311b478fea4c489603258549c16e5819c4c153navin patidar	}
5395311b478fea4c489603258549c16e5819c4c153navin patidar
5495311b478fea4c489603258549c16e5819c4c153navin patidar	/* s2. */
5595311b478fea4c489603258549c16e5819c4c153navin patidar	rtw_disassoc_cmd(padapter, 500, false);
5695311b478fea4c489603258549c16e5819c4c153navin patidar
5795311b478fea4c489603258549c16e5819c4c153navin patidar	/* s2-2.  indicate disconnect to os */
5895311b478fea4c489603258549c16e5819c4c153navin patidar	{
5995311b478fea4c489603258549c16e5819c4c153navin patidar		struct	mlme_priv *pmlmepriv = &padapter->mlmepriv;
6095311b478fea4c489603258549c16e5819c4c153navin patidar
6195311b478fea4c489603258549c16e5819c4c153navin patidar		if (check_fwstate(pmlmepriv, _FW_LINKED)) {
6295311b478fea4c489603258549c16e5819c4c153navin patidar			_clr_fwstate_(pmlmepriv, _FW_LINKED);
6395311b478fea4c489603258549c16e5819c4c153navin patidar
6495311b478fea4c489603258549c16e5819c4c153navin patidar			rtw_led_control(padapter, LED_CTL_NO_LINK);
6595311b478fea4c489603258549c16e5819c4c153navin patidar
6695311b478fea4c489603258549c16e5819c4c153navin patidar			rtw_os_indicate_disconnect(padapter);
6795311b478fea4c489603258549c16e5819c4c153navin patidar
6895311b478fea4c489603258549c16e5819c4c153navin patidar			/* donnot enqueue cmd */
6995311b478fea4c489603258549c16e5819c4c153navin patidar			rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_DISCONNECT, 0);
7095311b478fea4c489603258549c16e5819c4c153navin patidar		}
7195311b478fea4c489603258549c16e5819c4c153navin patidar	}
7295311b478fea4c489603258549c16e5819c4c153navin patidar	/* s2-3. */
7395311b478fea4c489603258549c16e5819c4c153navin patidar	rtw_free_assoc_resources(padapter, 1);
7495311b478fea4c489603258549c16e5819c4c153navin patidar
7595311b478fea4c489603258549c16e5819c4c153navin patidar	/* s2-4. */
7695311b478fea4c489603258549c16e5819c4c153navin patidar	rtw_free_network_queue(padapter, true);
7795311b478fea4c489603258549c16e5819c4c153navin patidar	rtw_ips_dev_unload(padapter);
7895311b478fea4c489603258549c16e5819c4c153navin patidar	pwrpriv->rf_pwrstate = rf_off;
7995311b478fea4c489603258549c16e5819c4c153navin patidar	pwrpriv->bips_processing = false;
8095311b478fea4c489603258549c16e5819c4c153navin patidar
8195311b478fea4c489603258549c16e5819c4c153navin patidar	_exit_pwrlock(&pwrpriv->lock);
8295311b478fea4c489603258549c16e5819c4c153navin patidar
8395311b478fea4c489603258549c16e5819c4c153navin patidar	return 0;
8495311b478fea4c489603258549c16e5819c4c153navin patidar
8595311b478fea4c489603258549c16e5819c4c153navin patidarerror_exit:
8695311b478fea4c489603258549c16e5819c4c153navin patidar	DBG_88E("%s, failed\n", __func__);
8795311b478fea4c489603258549c16e5819c4c153navin patidar	return -1;
8895311b478fea4c489603258549c16e5819c4c153navin patidar}
8995311b478fea4c489603258549c16e5819c4c153navin patidar
9095311b478fea4c489603258549c16e5819c4c153navin patidarstatic int rtw_hw_resume(struct adapter *padapter)
9195311b478fea4c489603258549c16e5819c4c153navin patidar{
9295311b478fea4c489603258549c16e5819c4c153navin patidar	struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
9395311b478fea4c489603258549c16e5819c4c153navin patidar	struct net_device *pnetdev = padapter->pnetdev;
9495311b478fea4c489603258549c16e5819c4c153navin patidar
9595311b478fea4c489603258549c16e5819c4c153navin patidar
9695311b478fea4c489603258549c16e5819c4c153navin patidar	/* system resume */
9795311b478fea4c489603258549c16e5819c4c153navin patidar	DBG_88E("==> rtw_hw_resume\n");
9895311b478fea4c489603258549c16e5819c4c153navin patidar	_enter_pwrlock(&pwrpriv->lock);
9995311b478fea4c489603258549c16e5819c4c153navin patidar	pwrpriv->bips_processing = true;
10095311b478fea4c489603258549c16e5819c4c153navin patidar	rtw_reset_drv_sw(padapter);
10195311b478fea4c489603258549c16e5819c4c153navin patidar
10295311b478fea4c489603258549c16e5819c4c153navin patidar	if (pm_netdev_open(pnetdev, false) != 0) {
10395311b478fea4c489603258549c16e5819c4c153navin patidar		_exit_pwrlock(&pwrpriv->lock);
10495311b478fea4c489603258549c16e5819c4c153navin patidar		goto error_exit;
10595311b478fea4c489603258549c16e5819c4c153navin patidar	}
10695311b478fea4c489603258549c16e5819c4c153navin patidar
10795311b478fea4c489603258549c16e5819c4c153navin patidar	netif_device_attach(pnetdev);
10895311b478fea4c489603258549c16e5819c4c153navin patidar	netif_carrier_on(pnetdev);
10995311b478fea4c489603258549c16e5819c4c153navin patidar
11095311b478fea4c489603258549c16e5819c4c153navin patidar	if (!netif_queue_stopped(pnetdev))
11195311b478fea4c489603258549c16e5819c4c153navin patidar		netif_start_queue(pnetdev);
11295311b478fea4c489603258549c16e5819c4c153navin patidar	else
11395311b478fea4c489603258549c16e5819c4c153navin patidar		netif_wake_queue(pnetdev);
11495311b478fea4c489603258549c16e5819c4c153navin patidar
11595311b478fea4c489603258549c16e5819c4c153navin patidar	pwrpriv->bkeepfwalive = false;
11695311b478fea4c489603258549c16e5819c4c153navin patidar	pwrpriv->brfoffbyhw = false;
11795311b478fea4c489603258549c16e5819c4c153navin patidar
11895311b478fea4c489603258549c16e5819c4c153navin patidar	pwrpriv->rf_pwrstate = rf_on;
11995311b478fea4c489603258549c16e5819c4c153navin patidar	pwrpriv->bips_processing = false;
12095311b478fea4c489603258549c16e5819c4c153navin patidar
12195311b478fea4c489603258549c16e5819c4c153navin patidar	_exit_pwrlock(&pwrpriv->lock);
12295311b478fea4c489603258549c16e5819c4c153navin patidar
12395311b478fea4c489603258549c16e5819c4c153navin patidar
12495311b478fea4c489603258549c16e5819c4c153navin patidar	return 0;
12595311b478fea4c489603258549c16e5819c4c153navin patidarerror_exit:
12695311b478fea4c489603258549c16e5819c4c153navin patidar	DBG_88E("%s, Open net dev failed\n", __func__);
12795311b478fea4c489603258549c16e5819c4c153navin patidar	return -1;
12895311b478fea4c489603258549c16e5819c4c153navin patidar}
1291cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger
1301cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Fingervoid ips_enter(struct adapter *padapter)
1311cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger{
1321cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
1331cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	struct xmit_priv *pxmit_priv = &padapter->xmitpriv;
1341cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger
1351cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	if (padapter->registrypriv.mp_mode == 1)
1361cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger		return;
1371cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger
1381cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	if (pxmit_priv->free_xmitbuf_cnt != NR_XMITBUFF ||
1391cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	    pxmit_priv->free_xmit_extbuf_cnt != NR_XMIT_EXTBUFF) {
1401cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger		DBG_88E_LEVEL(_drv_info_, "There are some pkts to transmit\n");
1411cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger		DBG_88E_LEVEL(_drv_info_, "free_xmitbuf_cnt: %d, free_xmit_extbuf_cnt: %d\n",
1421cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger			      pxmit_priv->free_xmitbuf_cnt, pxmit_priv->free_xmit_extbuf_cnt);
1431cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger		return;
1441cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	}
1451cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger
1461cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	_enter_pwrlock(&pwrpriv->lock);
1471cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger
1481cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	pwrpriv->bips_processing = true;
1491cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger
1501cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	/*  syn ips_mode with request */
1511cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	pwrpriv->ips_mode = pwrpriv->ips_mode_req;
1521cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger
1531cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	pwrpriv->ips_enter_cnts++;
1541cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	DBG_88E("==>ips_enter cnts:%d\n", pwrpriv->ips_enter_cnts);
1551cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	if (rf_off == pwrpriv->change_rfpwrstate) {
1561cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger		pwrpriv->bpower_saving = true;
1571cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger		DBG_88E_LEVEL(_drv_info_, "nolinked power save enter\n");
1581cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger
1591cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger		if (pwrpriv->ips_mode == IPS_LEVEL_2)
1601cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger			pwrpriv->bkeepfwalive = true;
1611cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger
1621cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger		rtw_ips_pwr_down(padapter);
1631cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger		pwrpriv->rf_pwrstate = rf_off;
1641cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	}
1651cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	pwrpriv->bips_processing = false;
1661cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger
1671cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	_exit_pwrlock(&pwrpriv->lock);
1681cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger}
1691cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger
1701cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Fingerint ips_leave(struct adapter *padapter)
1711cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger{
1721cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
1731cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	struct security_priv *psecuritypriv = &(padapter->securitypriv);
1741cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
1751cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	int result = _SUCCESS;
1761cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	int keyid;
1771cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger
1781cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger
1791cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	_enter_pwrlock(&pwrpriv->lock);
1801cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger
1811cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	if ((pwrpriv->rf_pwrstate == rf_off) && (!pwrpriv->bips_processing)) {
1821cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger		pwrpriv->bips_processing = true;
1831cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger		pwrpriv->change_rfpwrstate = rf_on;
1841cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger		pwrpriv->ips_leave_cnts++;
1851cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger		DBG_88E("==>ips_leave cnts:%d\n", pwrpriv->ips_leave_cnts);
1861cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger
1871cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger		result = rtw_ips_pwr_up(padapter);
1881cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger		if (result == _SUCCESS) {
1891cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger			pwrpriv->rf_pwrstate = rf_on;
1901cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger		}
1911cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger		DBG_88E_LEVEL(_drv_info_, "nolinked power save leave\n");
1921cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger
1931cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger		if ((_WEP40_ == psecuritypriv->dot11PrivacyAlgrthm) || (_WEP104_ == psecuritypriv->dot11PrivacyAlgrthm)) {
1941cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger			DBG_88E("==>%s, channel(%d), processing(%x)\n", __func__, padapter->mlmeextpriv.cur_channel, pwrpriv->bips_processing);
1951cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger			set_channel_bwmode(padapter, padapter->mlmeextpriv.cur_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20);
1961cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger			for (keyid = 0; keyid < 4; keyid++) {
1971cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger				if (pmlmepriv->key_mask & BIT(keyid)) {
1981cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger					if (keyid == psecuritypriv->dot11PrivacyKeyIndex)
1991cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger						result = rtw_set_key(padapter, psecuritypriv, keyid, 1);
2001cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger					else
2011cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger						result = rtw_set_key(padapter, psecuritypriv, keyid, 0);
2021cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger				}
2031cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger			}
2041cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger		}
2051cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger
20699ecfb06f83ec7eaa9110fa887cef3f55d031bf4navin patidar		DBG_88E("==> ips_leave.....LED(0x%08x)...\n", usb_read32(padapter, 0x4c));
2071cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger		pwrpriv->bips_processing = false;
2081cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger
2091cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger		pwrpriv->bkeepfwalive = false;
2101cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger		pwrpriv->bpower_saving = false;
2111cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	}
2121cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger
2131cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	_exit_pwrlock(&pwrpriv->lock);
2141cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger
2151cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	return result;
2161cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger}
2171cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger
2181cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Fingerstatic bool rtw_pwr_unassociated_idle(struct adapter *adapter)
2191cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger{
2201cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	struct mlme_priv *pmlmepriv = &(adapter->mlmepriv);
2211cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	bool ret = false;
2221cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger
223e017a92b2e768c13503765e1eabfa566bf791807Manuel Schölling	if (time_after_eq(adapter->pwrctrlpriv.ips_deny_time, jiffies))
2241cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger		goto exit;
2251cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger
2261cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	if (check_fwstate(pmlmepriv, WIFI_ASOC_STATE|WIFI_SITE_MONITOR) ||
2271cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	    check_fwstate(pmlmepriv, WIFI_UNDER_LINKING|WIFI_UNDER_WPS) ||
2281cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	    check_fwstate(pmlmepriv, WIFI_AP_STATE) ||
2292454e79ac22da26c5ef42a0db0aef8d968d55d0fnavin patidar	    check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE|WIFI_ADHOC_STATE))
2301cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger		goto exit;
2311cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger
2321cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	ret = true;
2331cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger
2341cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Fingerexit:
2351cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	return ret;
2361cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger}
2371cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger
2381cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Fingervoid rtw_ps_processor(struct adapter *padapter)
2391cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger{
2401cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
2411cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
2421cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	enum rt_rf_power_state rfpwrstate;
2431cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger
2441cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	pwrpriv->ps_processing = true;
2451cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger
2461cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	if (pwrpriv->bips_processing)
2471cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger		goto exit;
2481cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger
2491cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	if (padapter->pwrctrlpriv.bHWPwrPindetect) {
2501cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger		rfpwrstate = RfOnOffDetect(padapter);
2511cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger		DBG_88E("@@@@- #2  %s==> rfstate:%s\n", __func__, (rfpwrstate == rf_on) ? "rf_on" : "rf_off");
2521cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger
2531cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger		if (rfpwrstate != pwrpriv->rf_pwrstate) {
2541cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger			if (rfpwrstate == rf_off) {
2551cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger				pwrpriv->change_rfpwrstate = rf_off;
2561cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger				pwrpriv->brfoffbyhw = true;
2571cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger				rtw_hw_suspend(padapter);
2581cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger			} else {
2591cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger				pwrpriv->change_rfpwrstate = rf_on;
2601cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger				rtw_hw_resume(padapter);
2611cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger			}
2621cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger			DBG_88E("current rf_pwrstate(%s)\n", (pwrpriv->rf_pwrstate == rf_off) ? "rf_off" : "rf_on");
2631cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger		}
2641cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger		pwrpriv->pwr_state_check_cnts++;
2651cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	}
2661cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger
2671cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	if (pwrpriv->ips_mode_req == IPS_NONE)
2681cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger		goto exit;
2691cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger
2705b66fb7d57462f5c0683f7d64625652ffb9f5f87Valentina Manea	if (!rtw_pwr_unassociated_idle(padapter))
2711cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger		goto exit;
2721cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger
2731cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	if ((pwrpriv->rf_pwrstate == rf_on) && ((pwrpriv->pwr_state_check_cnts%4) == 0)) {
2741cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger		DBG_88E("==>%s .fw_state(%x)\n", __func__, get_fwstate(pmlmepriv));
2751cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger		pwrpriv->change_rfpwrstate = rf_off;
2761cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger
2771cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger		ips_enter(padapter);
2781cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	}
2791cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Fingerexit:
2801cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	rtw_set_pwr_state_check_timer(&padapter->pwrctrlpriv);
2811cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	pwrpriv->ps_processing = false;
2821cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	return;
2831cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger}
2841cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger
2851cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Fingerstatic void pwr_state_check_handler(void *FunctionContext)
2861cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger{
2871cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	struct adapter *padapter = (struct adapter *)FunctionContext;
2881cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	rtw_ps_cmd(padapter);
2891cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger}
2901cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger
2911cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger/*
2921cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger *
2931cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger * Parameters
2941cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger *	padapter
2951cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger *	pslv			power state level, only could be PS_STATE_S0 ~ PS_STATE_S4
2961cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger *
2971cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger */
2981cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Fingervoid rtw_set_rpwm(struct adapter *padapter, u8 pslv)
2991cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger{
3001cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	u8	rpwm;
3011cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
3021cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger
3031cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	pslv = PS_STATE(pslv);
3041cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger
3051cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	if (pwrpriv->btcoex_rfon) {
3061cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger		if (pslv < PS_STATE_S4)
3071cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger			pslv = PS_STATE_S3;
3081cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	}
3091cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger
3101cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	if ((pwrpriv->rpwm == pslv)) {
3111cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger		RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_err_,
3121cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger			 ("%s: Already set rpwm[0x%02X], new=0x%02X!\n", __func__, pwrpriv->rpwm, pslv));
3131cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger		return;
3141cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	}
3151cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger
3161cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	if ((padapter->bSurpriseRemoved) ||
3171cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	    (!padapter->hw_init_completed)) {
3181cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger		RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_err_,
3191cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger			 ("%s: SurpriseRemoved(%d) hw_init_completed(%d)\n",
3201cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger			 __func__, padapter->bSurpriseRemoved, padapter->hw_init_completed));
3211cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger
3221cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger		pwrpriv->cpwm = PS_STATE_S4;
3231cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger
3241cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger		return;
3251cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	}
3261cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger
3271cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	if (padapter->bDriverStopped) {
3281cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger		RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_err_,
3291cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger			 ("%s: change power state(0x%02X) when DriverStopped\n", __func__, pslv));
3301cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger
3311cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger		if (pslv < PS_STATE_S2) {
3321cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger			RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_err_,
3331cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger				 ("%s: Reject to enter PS_STATE(0x%02X) lower than S2 when DriverStopped!!\n", __func__, pslv));
3341cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger			return;
3351cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger		}
3361cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	}
3371cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger
3381cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	rpwm = pslv | pwrpriv->tog;
3391cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_notice_,
3401cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger		 ("rtw_set_rpwm: rpwm=0x%02x cpwm=0x%02x\n", rpwm, pwrpriv->cpwm));
3411cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger
3421cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	pwrpriv->rpwm = pslv;
3431cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger
3441cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	rtw_hal_set_hwreg(padapter, HW_VAR_SET_RPWM, (u8 *)(&rpwm));
3451cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger
3461cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	pwrpriv->tog += 0x80;
3471cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	pwrpriv->cpwm = pslv;
3481cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger}
3491cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger
3501cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Fingerstatic u8 PS_RDY_CHECK(struct adapter *padapter)
3511cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger{
3521cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	u32 curr_time, delta_time;
3531cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	struct pwrctrl_priv	*pwrpriv = &padapter->pwrctrlpriv;
3541cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	struct mlme_priv	*pmlmepriv = &(padapter->mlmepriv);
3551cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger
3561cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger
357c01fb49636b65ceea513c00966c58b8bdb095c8fLarry Finger	curr_time = jiffies;
3581cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	delta_time = curr_time - pwrpriv->DelayLPSLastTimeStamp;
3591cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger
3601cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	if (delta_time < LPS_DELAY_TIME)
3611cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger		return false;
3621cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger
3631cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	if ((check_fwstate(pmlmepriv, _FW_LINKED) == false) ||
3641cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	    (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY)) ||
3651cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	    (check_fwstate(pmlmepriv, WIFI_AP_STATE)) ||
3661cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	    (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) ||
3671cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	    (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)))
3681cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger		return false;
3691cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	if (pwrpriv->bInSuspend)
3701cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger		return false;
3711cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	if ((padapter->securitypriv.dot11AuthAlgrthm == dot11AuthAlgrthm_8021X) && (padapter->securitypriv.binstallGrpkey == false)) {
3721cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger		DBG_88E("Group handshake still in progress !!!\n");
3731cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger		return false;
3741cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	}
3751cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	return true;
3761cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger}
3771cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger
3781cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Fingervoid rtw_set_ps_mode(struct adapter *padapter, u8 ps_mode, u8 smart_ps, u8 bcn_ant_mode)
3791cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger{
3801cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
3811cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger
3821cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_notice_,
3831cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger		 ("%s: PowerMode=%d Smart_PS=%d\n",
3841cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger		  __func__, ps_mode, smart_ps));
3851cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger
3861cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	if (ps_mode > PM_Card_Disable) {
3871cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger		RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_err_, ("ps_mode:%d error\n", ps_mode));
3881cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger		return;
3891cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	}
3901cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger
3911cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	if (pwrpriv->pwr_mode == ps_mode) {
3921cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger		if (PS_MODE_ACTIVE == ps_mode)
3931cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger			return;
3941cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger
3951cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger		if ((pwrpriv->smart_ps == smart_ps) &&
3961cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger		    (pwrpriv->bcn_ant_mode == bcn_ant_mode))
3971cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger			return;
3981cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	}
3991cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger
4001cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	/* if (pwrpriv->pwr_mode == PS_MODE_ACTIVE) */
4011cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	if (ps_mode == PS_MODE_ACTIVE) {
4021cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger		if (PS_RDY_CHECK(padapter)) {
4031cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger			DBG_88E("%s: Enter 802.11 power save\n", __func__);
4041cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger			pwrpriv->bFwCurrentInPSMode = true;
4051cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger			pwrpriv->pwr_mode = ps_mode;
4061cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger			pwrpriv->smart_ps = smart_ps;
4071cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger			pwrpriv->bcn_ant_mode = bcn_ant_mode;
4081cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger			rtw_hal_set_hwreg(padapter, HW_VAR_H2C_FW_PWRMODE, (u8 *)(&ps_mode));
4091cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger			rtw_set_rpwm(padapter, PS_STATE_S2);
4101cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger		}
4111cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	}
4121cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger}
4131cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger
4141cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger/*
4151cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger * Return:
4161cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger *	0:	Leave OK
4171cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger *	-1:	Timeout
4181cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger *	-2:	Other error
4191cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger */
4201cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Fingers32 LPS_RF_ON_check(struct adapter *padapter, u32 delay_ms)
4211cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger{
4221cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	u32 start_time;
4231cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	u8 bAwake = false;
4241cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	s32 err = 0;
4251cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger
4261cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger
427c01fb49636b65ceea513c00966c58b8bdb095c8fLarry Finger	start_time = jiffies;
4281cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	while (1) {
4291cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger		rtw_hal_get_hwreg(padapter, HW_VAR_FWLPS_RF_ON, &bAwake);
4301cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger		if (bAwake)
4311cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger			break;
4321cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger
4331cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger		if (padapter->bSurpriseRemoved) {
4341cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger			err = -2;
4351cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger			DBG_88E("%s: device surprise removed!!\n", __func__);
4361cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger			break;
4371cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger		}
4381cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger
4391cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger		if (rtw_get_passing_time_ms(start_time) > delay_ms) {
4401cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger			err = -1;
4411cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger			DBG_88E("%s: Wait for FW LPS leave more than %u ms!!!\n", __func__, delay_ms);
4421cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger			break;
4431cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger		}
444b2dcff2a91d67e2a3c35be54c731343148d19292Larry Finger		msleep(1);
4451cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	}
4461cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger
4471cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	return err;
4481cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger}
4491cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger
4501cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger/*  */
4511cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger/*	Description: */
4521cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger/*		Enter the leisure power save mode. */
4531cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger/*  */
4541cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Fingervoid LPS_Enter(struct adapter *padapter)
4551cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger{
4561cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	struct pwrctrl_priv	*pwrpriv = &padapter->pwrctrlpriv;
4571cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger
4581cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	if (PS_RDY_CHECK(padapter) == false)
4591cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger		return;
4601cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger
4611cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	if (pwrpriv->bLeisurePs) {
4621cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger		/*  Idle for a while if we connect to AP a while ago. */
4631cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger		if (pwrpriv->LpsIdleCount >= 2) { /*   4 Sec */
4641cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger			if (pwrpriv->pwr_mode == PS_MODE_ACTIVE) {
4651cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger				pwrpriv->bpower_saving = true;
4661cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger				DBG_88E("%s smart_ps:%d\n", __func__, pwrpriv->smart_ps);
4671cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger				/* For Tenda W311R IOT issue */
4681cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger				rtw_set_ps_mode(padapter, pwrpriv->power_mgnt, pwrpriv->smart_ps, 0);
4691cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger			}
4701cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger		} else {
4711cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger			pwrpriv->LpsIdleCount++;
4721cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger		}
4731cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	}
4741cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger}
4751cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger
4761cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger#define LPS_LEAVE_TIMEOUT_MS 100
4771cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger
4781cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger/*	Description: */
4791cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger/*		Leave the leisure power save mode. */
4801cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Fingervoid LPS_Leave(struct adapter *padapter)
4811cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger{
4821cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	struct pwrctrl_priv	*pwrpriv = &padapter->pwrctrlpriv;
4831cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger
4841cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	if (pwrpriv->bLeisurePs) {
4851cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger		if (pwrpriv->pwr_mode != PS_MODE_ACTIVE) {
4861cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger			rtw_set_ps_mode(padapter, PS_MODE_ACTIVE, 0, 0);
4871cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger
4881cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger			if (pwrpriv->pwr_mode == PS_MODE_ACTIVE)
4891cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger				LPS_RF_ON_check(padapter, LPS_LEAVE_TIMEOUT_MS);
4901cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger		}
4911cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	}
4921cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger
4931cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	pwrpriv->bpower_saving = false;
4941cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger}
4951cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger
4961cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger/*  */
4971cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger/*  Description: Leave all power save mode: LPS, FwLPS, IPS if needed. */
4981cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger/*  Move code to function by tynli. 2010.03.26. */
4991cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger/*  */
5001cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Fingervoid LeaveAllPowerSaveMode(struct adapter *Adapter)
5011cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger{
5021cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	struct mlme_priv	*pmlmepriv = &(Adapter->mlmepriv);
5031cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	u8	enqueue = 0;
5041cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger
5052454e79ac22da26c5ef42a0db0aef8d968d55d0fnavin patidar	if (check_fwstate(pmlmepriv, _FW_LINKED))
5061cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger		rtw_lps_ctrl_wk_cmd(Adapter, LPS_CTRL_LEAVE, enqueue);
5071cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger}
5081cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger
5091cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Fingervoid rtw_init_pwrctrl_priv(struct adapter *padapter)
5101cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger{
5111cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	struct pwrctrl_priv *pwrctrlpriv = &padapter->pwrctrlpriv;
5121cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger
5131cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	_init_pwrlock(&pwrctrlpriv->lock);
5141cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	pwrctrlpriv->rf_pwrstate = rf_on;
5151cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	pwrctrlpriv->ips_enter_cnts = 0;
5161cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	pwrctrlpriv->ips_leave_cnts = 0;
5171cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	pwrctrlpriv->bips_processing = false;
5181cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger
5191cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	pwrctrlpriv->ips_mode = padapter->registrypriv.ips_mode;
5201cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	pwrctrlpriv->ips_mode_req = padapter->registrypriv.ips_mode;
5211cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger
5221cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	pwrctrlpriv->pwr_state_check_interval = RTW_PWR_STATE_CHK_INTERVAL;
5231cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	pwrctrlpriv->pwr_state_check_cnts = 0;
5241cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	pwrctrlpriv->bInternalAutoSuspend = false;
5251cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	pwrctrlpriv->bInSuspend = false;
5261cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	pwrctrlpriv->bkeepfwalive = false;
5271cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger
5281cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	pwrctrlpriv->LpsIdleCount = 0;
5291cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	if (padapter->registrypriv.mp_mode == 1)
5301cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger		pwrctrlpriv->power_mgnt = PS_MODE_ACTIVE ;
5311cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	else
5321cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger		pwrctrlpriv->power_mgnt = padapter->registrypriv.power_mgnt;/*  PS_MODE_MIN; */
5331cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	pwrctrlpriv->bLeisurePs = (PS_MODE_ACTIVE != pwrctrlpriv->power_mgnt) ? true : false;
5341cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger
5351cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	pwrctrlpriv->bFwCurrentInPSMode = false;
5361cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger
5371cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	pwrctrlpriv->rpwm = 0;
5381cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	pwrctrlpriv->cpwm = PS_STATE_S4;
5391cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger
5401cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	pwrctrlpriv->pwr_mode = PS_MODE_ACTIVE;
5411cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	pwrctrlpriv->smart_ps = padapter->registrypriv.smart_ps;
5421cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	pwrctrlpriv->bcn_ant_mode = 0;
5431cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger
5441cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	pwrctrlpriv->tog = 0x80;
5451cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger
5461cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	pwrctrlpriv->btcoex_rfon = false;
5471cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger
5481cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	_init_timer(&(pwrctrlpriv->pwr_state_check_timer), padapter->pnetdev, pwr_state_check_handler, (u8 *)padapter);
5491cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger}
5501cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger
5511cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Fingerinline void rtw_set_ips_deny(struct adapter *padapter, u32 ms)
5521cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger{
5531cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
554ace050139cee44d06b06b4c78074b4eb80fb7c0anavin patidar	pwrpriv->ips_deny_time = jiffies + msecs_to_jiffies(ms);
5551cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger}
5561cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger
5571cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger/*
5581cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger* rtw_pwr_wakeup - Wake the NIC up from: 1)IPS. 2)USB autosuspend
5591cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger* @adapter: pointer to struct adapter structure
56040a46d8b40e326ba77e0858f3a45206ebc201660Masanari Iida* @ips_deffer_ms: the ms will prevent from falling into IPS after wakeup
5611cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger* Return _SUCCESS or _FAIL
5621cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger*/
5631cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger
5641cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Fingerint _rtw_pwr_wakeup(struct adapter *padapter, u32 ips_deffer_ms, const char *caller)
5651cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger{
5661cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
5671cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
568e017a92b2e768c13503765e1eabfa566bf791807Manuel Schölling	unsigned long expires;
5691cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	int ret = _SUCCESS;
5701cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger
571ace050139cee44d06b06b4c78074b4eb80fb7c0anavin patidar	expires = jiffies + msecs_to_jiffies(ips_deffer_ms);
572e017a92b2e768c13503765e1eabfa566bf791807Manuel Schölling	if (time_before(pwrpriv->ips_deny_time, expires))
573ace050139cee44d06b06b4c78074b4eb80fb7c0anavin patidar		pwrpriv->ips_deny_time = jiffies + msecs_to_jiffies(ips_deffer_ms);
5741cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger
5751cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger{
576c01fb49636b65ceea513c00966c58b8bdb095c8fLarry Finger	u32 start = jiffies;
5771cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	if (pwrpriv->ps_processing) {
5781cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger		DBG_88E("%s wait ps_processing...\n", __func__);
5791cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger		while (pwrpriv->ps_processing && rtw_get_passing_time_ms(start) <= 3000)
5800da46e6bb1ac0b311d0ef47e5f723f330e144d37Larry Finger			msleep(10);
5811cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger		if (pwrpriv->ps_processing)
5821cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger			DBG_88E("%s wait ps_processing timeout\n", __func__);
5831cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger		else
5841cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger			DBG_88E("%s wait ps_processing done\n", __func__);
5851cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	}
5861cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger}
5871cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger
5881cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	/* System suspend is not allowed to wakeup */
5891cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	if ((!pwrpriv->bInternalAutoSuspend) && (pwrpriv->bInSuspend)) {
5901cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger		ret = _FAIL;
5911cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger		goto exit;
5921cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	}
5931cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger
5941cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	/* block??? */
5951cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	if ((pwrpriv->bInternalAutoSuspend)  && (padapter->net_closed)) {
5961cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger		ret = _FAIL;
5971cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger		goto exit;
5981cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	}
5991cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger
6001cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	/* I think this should be check in IPS, LPS, autosuspend functions... */
6011cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	if (check_fwstate(pmlmepriv, _FW_LINKED)) {
6021cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger		ret = _SUCCESS;
6031cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger		goto exit;
6041cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	}
6051cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	if (rf_off == pwrpriv->rf_pwrstate) {
6061cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger		DBG_88E("%s call ips_leave....\n", __func__);
6071cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger		if (_FAIL ==  ips_leave(padapter)) {
6081cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger			DBG_88E("======> ips_leave fail.............\n");
6091cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger			ret = _FAIL;
6101cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger			goto exit;
6111cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger		}
6121cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	}
6131cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger
6141cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	/* TODO: the following checking need to be merged... */
6151cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	if (padapter->bDriverStopped || !padapter->bup ||
6161cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	    !padapter->hw_init_completed) {
6171cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger		DBG_88E("%s: bDriverStopped=%d, bup=%d, hw_init_completed =%u\n"
6181cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger			, caller
6191cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger			, padapter->bDriverStopped
6201cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger			, padapter->bup
6211cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger			, padapter->hw_init_completed);
6221cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger		ret = false;
6231cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger		goto exit;
6241cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	}
6251cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger
6261cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Fingerexit:
627ace050139cee44d06b06b4c78074b4eb80fb7c0anavin patidar	expires = jiffies + msecs_to_jiffies(ips_deffer_ms);
628e017a92b2e768c13503765e1eabfa566bf791807Manuel Schölling	if (time_before(pwrpriv->ips_deny_time, expires))
629ace050139cee44d06b06b4c78074b4eb80fb7c0anavin patidar		pwrpriv->ips_deny_time = jiffies + msecs_to_jiffies(ips_deffer_ms);
6301cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	return ret;
6311cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger}
6321cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger
6331cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Fingerint rtw_pm_set_lps(struct adapter *padapter, u8 mode)
6341cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger{
6351cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	int	ret = 0;
6361cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	struct pwrctrl_priv *pwrctrlpriv = &padapter->pwrctrlpriv;
6371cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger
6381cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	if (mode < PS_MODE_NUM) {
6391cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger		if (pwrctrlpriv->power_mgnt != mode) {
6401cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger			if (PS_MODE_ACTIVE == mode)
6411cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger				LeaveAllPowerSaveMode(padapter);
6421cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger			else
6431cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger				pwrctrlpriv->LpsIdleCount = 2;
6441cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger			pwrctrlpriv->power_mgnt = mode;
6451cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger			pwrctrlpriv->bLeisurePs = (PS_MODE_ACTIVE != pwrctrlpriv->power_mgnt) ? true : false;
6461cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger		}
6471cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	} else {
6481cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger		ret = -EINVAL;
6491cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	}
6501cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger
6511cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	return ret;
6521cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger}
6531cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger
6541cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Fingerint rtw_pm_set_ips(struct adapter *padapter, u8 mode)
6551cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger{
6561cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	struct pwrctrl_priv *pwrctrlpriv = &padapter->pwrctrlpriv;
6571cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger
6581cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	if (mode == IPS_NORMAL || mode == IPS_LEVEL_2) {
6591cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger		rtw_ips_mode_req(pwrctrlpriv, mode);
6601cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger		DBG_88E("%s %s\n", __func__, mode == IPS_NORMAL ? "IPS_NORMAL" : "IPS_LEVEL_2");
6611cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger		return 0;
6621cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	} else if (mode == IPS_NONE) {
6631cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger		rtw_ips_mode_req(pwrctrlpriv, mode);
6641cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger		DBG_88E("%s %s\n", __func__, "IPS_NONE");
6651cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger		if ((padapter->bSurpriseRemoved == 0) && (_FAIL == rtw_pwr_wakeup(padapter)))
6661cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger			return -EFAULT;
6671cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	} else {
6681cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger		return -EINVAL;
6691cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	}
6701cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger	return 0;
6711cc18a22b96b33119f457cac3ce5fcbbcbab1badLarry Finger}
672