1 /******************************************************************************
2 * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved.
4 * Based on the r8180 driver, which is:
5 * Copyright 2004-2005 Andrea Merello <andreamrl@tiscali.it>, et al.
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of version 2 of the GNU General Public License as
8 * published by the Free Software Foundation.
10 * This program is distributed in the hope that it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15 * You should have received a copy of the GNU General Public License along with
16 * this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
19 * The full GNU General Public License is included in this distribution in the
20 * file called LICENSE.
22 * Contact Information:
23 * wlanfae <wlanfae@realtek.com>
24 *****************************************************************************/
27 #include "r8192E_phy.h"
28 #include "r8192E_phyreg.h"
29 #include "r8190P_rtl8256.h" /* RTL8225 Radio frontend */
30 #include "r8192E_cmdpkt.h"
32 static void rtl8192_hw_sleep_down(struct net_device
*dev
)
34 struct r8192_priv
*priv
= rtllib_priv(dev
);
35 unsigned long flags
= 0;
36 spin_lock_irqsave(&priv
->rf_ps_lock
, flags
);
37 if (priv
->RFChangeInProgress
) {
38 spin_unlock_irqrestore(&priv
->rf_ps_lock
, flags
);
39 RT_TRACE(COMP_DBG
, "rtl8192_hw_sleep_down(): RF Change in "
43 spin_unlock_irqrestore(&priv
->rf_ps_lock
, flags
);
44 RT_TRACE(COMP_DBG
, "%s()============>come to sleep down\n", __func__
);
46 MgntActSet_RF_State(dev
, eRfSleep
, RF_CHANGE_BY_PS
, false);
49 void rtl8192_hw_sleep_wq(void *data
)
51 struct rtllib_device
*ieee
= container_of_dwork_rsl(data
,
52 struct rtllib_device
, hw_sleep_wq
);
53 struct net_device
*dev
= ieee
->dev
;
54 rtl8192_hw_sleep_down(dev
);
57 void rtl8192_hw_wakeup(struct net_device
*dev
)
59 struct r8192_priv
*priv
= rtllib_priv(dev
);
60 unsigned long flags
= 0;
61 spin_lock_irqsave(&priv
->rf_ps_lock
, flags
);
62 if (priv
->RFChangeInProgress
) {
63 spin_unlock_irqrestore(&priv
->rf_ps_lock
, flags
);
64 RT_TRACE(COMP_DBG
, "rtl8192_hw_wakeup(): RF Change in "
66 queue_delayed_work_rsl(priv
->rtllib
->wq
,
67 &priv
->rtllib
->hw_wakeup_wq
, MSECS(10));
70 spin_unlock_irqrestore(&priv
->rf_ps_lock
, flags
);
71 RT_TRACE(COMP_PS
, "%s()============>come to wake up\n", __func__
);
72 MgntActSet_RF_State(dev
, eRfOn
, RF_CHANGE_BY_PS
, false);
75 void rtl8192_hw_wakeup_wq(void *data
)
77 struct rtllib_device
*ieee
= container_of_dwork_rsl(data
,
78 struct rtllib_device
, hw_wakeup_wq
);
79 struct net_device
*dev
= ieee
->dev
;
80 rtl8192_hw_wakeup(dev
);
84 #define MIN_SLEEP_TIME 50
85 #define MAX_SLEEP_TIME 10000
86 void rtl8192_hw_to_sleep(struct net_device
*dev
, u64 time
)
88 struct r8192_priv
*priv
= rtllib_priv(dev
);
93 spin_lock_irqsave(&priv
->ps_lock
, flags
);
95 time
-= MSECS(8+16+7);
97 if ((time
- jiffies
) <= MSECS(MIN_SLEEP_TIME
)) {
98 spin_unlock_irqrestore(&priv
->ps_lock
, flags
);
99 printk(KERN_INFO
"too short to sleep::%lld < %ld\n",
100 time
- jiffies
, MSECS(MIN_SLEEP_TIME
));
104 if ((time
- jiffies
) > MSECS(MAX_SLEEP_TIME
)) {
105 printk(KERN_INFO
"========>too long to sleep:%lld > %ld\n",
106 time
- jiffies
, MSECS(MAX_SLEEP_TIME
));
107 spin_unlock_irqrestore(&priv
->ps_lock
, flags
);
110 tmp
= time
- jiffies
;
111 queue_delayed_work_rsl(priv
->rtllib
->wq
,
112 &priv
->rtllib
->hw_wakeup_wq
, tmp
);
113 queue_delayed_work_rsl(priv
->rtllib
->wq
,
114 (void *)&priv
->rtllib
->hw_sleep_wq
, 0);
115 spin_unlock_irqrestore(&priv
->ps_lock
, flags
);
118 static void InactivePsWorkItemCallback(struct net_device
*dev
)
120 struct r8192_priv
*priv
= rtllib_priv(dev
);
121 struct rt_pwr_save_ctrl
*pPSC
= (struct rt_pwr_save_ctrl
*)
122 &(priv
->rtllib
->PowerSaveControl
);
124 RT_TRACE(COMP_PS
, "InactivePsWorkItemCallback() --------->\n");
125 pPSC
->bSwRfProcessing
= true;
127 RT_TRACE(COMP_PS
, "InactivePsWorkItemCallback(): Set RF to %s.\n",
128 pPSC
->eInactivePowerState
== eRfOff
? "OFF" : "ON");
129 MgntActSet_RF_State(dev
, pPSC
->eInactivePowerState
, RF_CHANGE_BY_IPS
,
132 pPSC
->bSwRfProcessing
= false;
133 RT_TRACE(COMP_PS
, "InactivePsWorkItemCallback() <---------\n");
136 void IPSEnter(struct net_device
*dev
)
138 struct r8192_priv
*priv
= rtllib_priv(dev
);
139 struct rt_pwr_save_ctrl
*pPSC
= (struct rt_pwr_save_ctrl
*)
140 &(priv
->rtllib
->PowerSaveControl
);
141 enum rt_rf_power_state rtState
;
143 if (pPSC
->bInactivePs
) {
144 rtState
= priv
->rtllib
->eRFPowerState
;
145 if (rtState
== eRfOn
&& !pPSC
->bSwRfProcessing
&&
146 (priv
->rtllib
->state
!= RTLLIB_LINKED
) &&
147 (priv
->rtllib
->iw_mode
!= IW_MODE_MASTER
)) {
148 RT_TRACE(COMP_PS
, "IPSEnter(): Turn off RF.\n");
149 pPSC
->eInactivePowerState
= eRfOff
;
150 priv
->isRFOff
= true;
151 priv
->bInPowerSaveMode
= true;
152 InactivePsWorkItemCallback(dev
);
157 void IPSLeave(struct net_device
*dev
)
159 struct r8192_priv
*priv
= rtllib_priv(dev
);
160 struct rt_pwr_save_ctrl
*pPSC
= (struct rt_pwr_save_ctrl
*)
161 &(priv
->rtllib
->PowerSaveControl
);
162 enum rt_rf_power_state rtState
;
164 if (pPSC
->bInactivePs
) {
165 rtState
= priv
->rtllib
->eRFPowerState
;
166 if (rtState
!= eRfOn
&& !pPSC
->bSwRfProcessing
&&
167 priv
->rtllib
->RfOffReason
<= RF_CHANGE_BY_IPS
) {
168 RT_TRACE(COMP_PS
, "IPSLeave(): Turn on RF.\n");
169 pPSC
->eInactivePowerState
= eRfOn
;
170 priv
->bInPowerSaveMode
= false;
171 InactivePsWorkItemCallback(dev
);
176 void IPSLeave_wq(void *data
)
178 struct rtllib_device
*ieee
= container_of_work_rsl(data
,
179 struct rtllib_device
, ips_leave_wq
);
180 struct net_device
*dev
= ieee
->dev
;
181 struct r8192_priv
*priv
= (struct r8192_priv
*)rtllib_priv(dev
);
182 down(&priv
->rtllib
->ips_sem
);
184 up(&priv
->rtllib
->ips_sem
);
187 void rtllib_ips_leave_wq(struct net_device
*dev
)
189 struct r8192_priv
*priv
= (struct r8192_priv
*)rtllib_priv(dev
);
190 enum rt_rf_power_state rtState
;
191 rtState
= priv
->rtllib
->eRFPowerState
;
193 if (priv
->rtllib
->PowerSaveControl
.bInactivePs
) {
194 if (rtState
== eRfOff
) {
195 if (priv
->rtllib
->RfOffReason
> RF_CHANGE_BY_IPS
) {
196 RT_TRACE(COMP_ERR
, "%s(): RF is OFF.\n",
200 printk(KERN_INFO
"=========>%s(): IPSLeave\n",
202 queue_work_rsl(priv
->rtllib
->wq
,
203 &priv
->rtllib
->ips_leave_wq
);
209 void rtllib_ips_leave(struct net_device
*dev
)
211 struct r8192_priv
*priv
= (struct r8192_priv
*)rtllib_priv(dev
);
212 down(&priv
->rtllib
->ips_sem
);
214 up(&priv
->rtllib
->ips_sem
);
217 static bool MgntActSet_802_11_PowerSaveMode(struct net_device
*dev
,
220 struct r8192_priv
*priv
= rtllib_priv(dev
);
222 if (priv
->rtllib
->iw_mode
== IW_MODE_ADHOC
)
225 RT_TRACE(COMP_LPS
, "%s(): set ieee->ps = %x\n", __func__
, rtPsMode
);
227 priv
->rtllib
->ps
= rtPsMode
;
228 if (priv
->rtllib
->sta_sleep
!= LPS_IS_WAKE
&&
229 rtPsMode
== RTLLIB_PS_DISABLED
) {
232 rtl8192_hw_wakeup(dev
);
233 priv
->rtllib
->sta_sleep
= LPS_IS_WAKE
;
235 spin_lock_irqsave(&(priv
->rtllib
->mgmt_tx_lock
), flags
);
236 RT_TRACE(COMP_DBG
, "LPS leave: notify AP we are awaked"
237 " ++++++++++ SendNullFunctionData\n");
238 rtllib_sta_ps_send_null_frame(priv
->rtllib
, 0);
239 spin_unlock_irqrestore(&(priv
->rtllib
->mgmt_tx_lock
), flags
);
245 void LeisurePSEnter(struct net_device
*dev
)
247 struct r8192_priv
*priv
= rtllib_priv(dev
);
248 struct rt_pwr_save_ctrl
*pPSC
= (struct rt_pwr_save_ctrl
*)
249 &(priv
->rtllib
->PowerSaveControl
);
251 RT_TRACE(COMP_PS
, "LeisurePSEnter()...\n");
252 RT_TRACE(COMP_PS
, "pPSC->bLeisurePs = %d, ieee->ps = %d,pPSC->LpsIdle"
253 "Count is %d,RT_CHECK_FOR_HANG_PERIOD is %d\n",
254 pPSC
->bLeisurePs
, priv
->rtllib
->ps
, pPSC
->LpsIdleCount
,
255 RT_CHECK_FOR_HANG_PERIOD
);
257 if (!((priv
->rtllib
->iw_mode
== IW_MODE_INFRA
) &&
258 (priv
->rtllib
->state
== RTLLIB_LINKED
))
259 || (priv
->rtllib
->iw_mode
== IW_MODE_ADHOC
) ||
260 (priv
->rtllib
->iw_mode
== IW_MODE_MASTER
))
263 if (pPSC
->bLeisurePs
) {
264 if (pPSC
->LpsIdleCount
>= RT_CHECK_FOR_HANG_PERIOD
) {
266 if (priv
->rtllib
->ps
== RTLLIB_PS_DISABLED
) {
268 RT_TRACE(COMP_LPS
, "LeisurePSEnter(): Enter "
269 "802.11 power save mode...\n");
271 if (!pPSC
->bFwCtrlLPS
) {
272 if (priv
->rtllib
->SetFwCmdHandler
)
273 priv
->rtllib
->SetFwCmdHandler(
274 dev
, FW_CMD_LPS_ENTER
);
276 MgntActSet_802_11_PowerSaveMode(dev
,
281 pPSC
->LpsIdleCount
++;
285 void LeisurePSLeave(struct net_device
*dev
)
287 struct r8192_priv
*priv
= rtllib_priv(dev
);
288 struct rt_pwr_save_ctrl
*pPSC
= (struct rt_pwr_save_ctrl
*)
289 &(priv
->rtllib
->PowerSaveControl
);
292 RT_TRACE(COMP_PS
, "LeisurePSLeave()...\n");
293 RT_TRACE(COMP_PS
, "pPSC->bLeisurePs = %d, ieee->ps = %d\n",
294 pPSC
->bLeisurePs
, priv
->rtllib
->ps
);
296 if (pPSC
->bLeisurePs
) {
297 if (priv
->rtllib
->ps
!= RTLLIB_PS_DISABLED
) {
298 RT_TRACE(COMP_LPS
, "LeisurePSLeave(): Busy Traffic , "
299 "Leave 802.11 power save..\n");
300 MgntActSet_802_11_PowerSaveMode(dev
,
303 if (!pPSC
->bFwCtrlLPS
) {
304 if (priv
->rtllib
->SetFwCmdHandler
)
305 priv
->rtllib
->SetFwCmdHandler(dev
,