1 /******************************************************************************
3 * Copyright(c) 2009-2010 Realtek Corporation.
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of version 2 of the GNU General Public License as
7 * published by the Free Software Foundation.
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * You should have received a copy of the GNU General Public License along with
15 * this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
18 * The full GNU General Public License is included in this distribution in the
19 * file called LICENSE.
21 * Contact Information:
22 * wlanfae <wlanfae@realtek.com>
23 * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
24 * Hsinchu 300, Taiwan.
26 * Larry Finger <Larry.Finger@lwfinger.net>
28 *****************************************************************************/
34 bool rtl_ps_enable_nic(struct ieee80211_hw
*hw
)
36 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
37 struct rtl_ps_ctl
*ppsc
= rtl_psc(rtl_priv(hw
));
38 struct rtl_hal
*rtlhal
= rtl_hal(rtl_priv(hw
));
39 bool init_status
= true;
41 /*<1> reset trx ring */
42 if (rtlhal
->interface
== INTF_PCI
)
43 rtlpriv
->intf_ops
->reset_trx_ring(hw
);
45 if (is_hal_stop(rtlhal
))
46 RT_TRACE(rtlpriv
, COMP_ERR
, DBG_WARNING
,
47 ("Driver is already down!\n"));
49 /*<2> Enable Adapter */
50 rtlpriv
->cfg
->ops
->hw_init(hw
);
51 RT_CLEAR_PS_LEVEL(ppsc
, RT_RF_OFF_LEVL_HALT_NIC
);
52 /*init_status = false; */
54 /*<3> Enable Interrupt */
55 rtlpriv
->cfg
->ops
->enable_interrupt(hw
);
58 rtl_watch_dog_timer_callback((unsigned long)hw
);
62 EXPORT_SYMBOL(rtl_ps_enable_nic
);
64 bool rtl_ps_disable_nic(struct ieee80211_hw
*hw
)
67 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
69 /*<1> Stop all timer */
70 rtl_deinit_deferred_work(hw
);
72 /*<2> Disable Interrupt */
73 rtlpriv
->cfg
->ops
->disable_interrupt(hw
);
75 /*<3> Disable Adapter */
76 rtlpriv
->cfg
->ops
->hw_disable(hw
);
80 EXPORT_SYMBOL(rtl_ps_disable_nic
);
82 bool rtl_ps_set_rf_state(struct ieee80211_hw
*hw
,
83 enum rf_pwrstate state_toset
,
84 u32 changesource
, bool protect_or_not
)
86 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
87 struct rtl_ps_ctl
*ppsc
= rtl_psc(rtl_priv(hw
));
88 enum rf_pwrstate rtstate
;
89 bool b_actionallowed
= false;
93 /*protect_or_not = true; */
99 *Only one thread can change
100 *the RF state at one time, and others
101 *should wait to be executed.
104 spin_lock_irqsave(&rtlpriv
->locks
.rf_ps_lock
, flag
);
105 if (ppsc
->rfchange_inprogress
) {
106 spin_unlock_irqrestore(&rtlpriv
->locks
.rf_ps_lock
,
109 RT_TRACE(rtlpriv
, COMP_ERR
, DBG_WARNING
,
110 ("RF Change in progress!"
111 "Wait to set..state_toset(%d).\n",
114 /* Set RF after the previous action is done. */
115 while (ppsc
->rfchange_inprogress
) {
120 *Wait too long, return false to avoid
123 if (rfwait_cnt
> 100)
127 ppsc
->rfchange_inprogress
= true;
128 spin_unlock_irqrestore(&rtlpriv
->locks
.rf_ps_lock
,
135 rtstate
= ppsc
->rfpwr_state
;
137 switch (state_toset
) {
139 ppsc
->rfoff_reason
&= (~changesource
);
141 if ((changesource
== RF_CHANGE_BY_HW
) &&
142 (ppsc
->b_hwradiooff
== true)) {
143 ppsc
->b_hwradiooff
= false;
146 if (!ppsc
->rfoff_reason
) {
147 ppsc
->rfoff_reason
= 0;
148 b_actionallowed
= true;
155 if ((changesource
== RF_CHANGE_BY_HW
)
156 && (ppsc
->b_hwradiooff
== false)) {
157 ppsc
->b_hwradiooff
= true;
160 ppsc
->rfoff_reason
|= changesource
;
161 b_actionallowed
= true;
165 ppsc
->rfoff_reason
|= changesource
;
166 b_actionallowed
= true;
170 RT_TRACE(rtlpriv
, COMP_ERR
, DBG_EMERG
,
171 ("switch case not process\n"));
176 rtlpriv
->cfg
->ops
->set_rf_power_state(hw
, state_toset
);
178 if (!protect_or_not
) {
179 spin_lock_irqsave(&rtlpriv
->locks
.rf_ps_lock
, flag
);
180 ppsc
->rfchange_inprogress
= false;
181 spin_unlock_irqrestore(&rtlpriv
->locks
.rf_ps_lock
, flag
);
184 return b_actionallowed
;
186 EXPORT_SYMBOL(rtl_ps_set_rf_state
);
188 static void _rtl_ps_inactive_ps(struct ieee80211_hw
*hw
)
190 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
191 struct rtl_hal
*rtlhal
= rtl_hal(rtl_priv(hw
));
192 struct rtl_ps_ctl
*ppsc
= rtl_psc(rtl_priv(hw
));
194 ppsc
->b_swrf_processing
= true;
196 if (ppsc
->inactive_pwrstate
== ERFON
&& rtlhal
->interface
== INTF_PCI
) {
197 if ((ppsc
->reg_rfps_level
& RT_RF_OFF_LEVL_ASPM
) &&
198 RT_IN_PS_LEVEL(ppsc
, RT_RF_OFF_LEVL_ASPM
) &&
199 rtlhal
->interface
== INTF_PCI
) {
200 rtlpriv
->intf_ops
->disable_aspm(hw
);
201 RT_CLEAR_PS_LEVEL(ppsc
, RT_RF_OFF_LEVL_ASPM
);
205 rtl_ps_set_rf_state(hw
, ppsc
->inactive_pwrstate
,
206 RF_CHANGE_BY_IPS
, false);
208 if (ppsc
->inactive_pwrstate
== ERFOFF
&&
209 rtlhal
->interface
== INTF_PCI
) {
210 if (ppsc
->reg_rfps_level
& RT_RF_OFF_LEVL_ASPM
) {
211 rtlpriv
->intf_ops
->enable_aspm(hw
);
212 RT_SET_PS_LEVEL(ppsc
, RT_RF_OFF_LEVL_ASPM
);
216 ppsc
->b_swrf_processing
= false;
219 void rtl_ips_nic_off_wq_callback(void *data
)
221 struct rtl_works
*rtlworks
=
222 container_of_dwork_rtl(data
, struct rtl_works
, ips_nic_off_wq
);
223 struct ieee80211_hw
*hw
= rtlworks
->hw
;
224 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
225 struct rtl_hal
*rtlhal
= rtl_hal(rtl_priv(hw
));
226 struct rtl_mac
*mac
= rtl_mac(rtl_priv(hw
));
227 struct rtl_ps_ctl
*ppsc
= rtl_psc(rtl_priv(hw
));
228 enum rf_pwrstate rtstate
;
230 if (mac
->opmode
!= NL80211_IFTYPE_STATION
) {
231 RT_TRACE(rtlpriv
, COMP_ERR
, DBG_WARNING
,
232 ("not station return\n"));
236 if (is_hal_stop(rtlhal
))
239 if (rtlpriv
->sec
.being_setkey
)
242 if (ppsc
->b_inactiveps
) {
243 rtstate
= ppsc
->rfpwr_state
;
246 *Do not enter IPS in the following conditions:
247 *(1) RF is already OFF or Sleep
248 *(2) b_swrf_processing (indicates the IPS is still under going)
249 *(3) Connectted (only disconnected can trigger IPS)
250 *(4) IBSS (send Beacon)
251 *(5) AP mode (send Beacon)
252 *(6) monitor mode (rcv packet)
255 if (rtstate
== ERFON
&&
256 !ppsc
->b_swrf_processing
&&
257 (mac
->link_state
== MAC80211_NOLINK
) &&
258 !mac
->act_scanning
) {
259 RT_TRACE(rtlpriv
, COMP_RF
, DBG_TRACE
,
260 ("IPSEnter(): Turn off RF.\n"));
262 ppsc
->inactive_pwrstate
= ERFOFF
;
263 ppsc
->b_in_powersavemode
= true;
265 /*rtl_pci_reset_trx_ring(hw); */
266 _rtl_ps_inactive_ps(hw
);
271 void rtl_ips_nic_off(struct ieee80211_hw
*hw
)
273 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
276 *because when link with ap, mac80211 will ask us
277 *to disable nic quickly after scan before linking,
278 *this will cause link failed, so we delay 100ms here
280 queue_delayed_work(rtlpriv
->works
.rtl_wq
,
281 &rtlpriv
->works
.ips_nic_off_wq
, MSECS(100));
284 void rtl_ips_nic_on(struct ieee80211_hw
*hw
)
286 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
287 struct rtl_ps_ctl
*ppsc
= rtl_psc(rtl_priv(hw
));
288 enum rf_pwrstate rtstate
;
291 spin_lock_irqsave(&rtlpriv
->locks
.ips_lock
, flags
);
293 if (ppsc
->b_inactiveps
) {
294 rtstate
= ppsc
->rfpwr_state
;
296 if (rtstate
!= ERFON
&&
297 !ppsc
->b_swrf_processing
&&
298 ppsc
->rfoff_reason
<= RF_CHANGE_BY_IPS
) {
300 ppsc
->inactive_pwrstate
= ERFON
;
301 ppsc
->b_in_powersavemode
= false;
303 _rtl_ps_inactive_ps(hw
);
307 spin_unlock_irqrestore(&rtlpriv
->locks
.ips_lock
, flags
);
313 *Determine if we can set Fw into PS mode
314 *in current condition.Return TRUE if it
317 static bool rtl_get_fwlps_doze(struct ieee80211_hw
*hw
)
319 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
320 struct rtl_mac
*mac
= rtl_mac(rtl_priv(hw
));
321 struct rtl_ps_ctl
*ppsc
= rtl_psc(rtl_priv(hw
));
324 ps_timediff
= jiffies_to_msecs(jiffies
-
325 ppsc
->last_delaylps_stamp_jiffies
);
327 if (ps_timediff
< 2000) {
328 RT_TRACE(rtlpriv
, COMP_POWER
, DBG_LOUD
,
329 ("Delay enter Fw LPS for DHCP, ARP,"
330 " or EAPOL exchanging state.\n"));
334 if (mac
->link_state
!= MAC80211_LINKED
)
337 if (mac
->opmode
== NL80211_IFTYPE_ADHOC
)
343 /* Change current and default preamble mode.*/
344 static void rtl_lps_set_psmode(struct ieee80211_hw
*hw
, u8 rt_psmode
)
346 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
347 struct rtl_mac
*mac
= rtl_mac(rtl_priv(hw
));
348 struct rtl_ps_ctl
*ppsc
= rtl_psc(rtl_priv(hw
));
349 u8 rpwm_val
, fw_pwrmode
;
351 if (mac
->opmode
== NL80211_IFTYPE_ADHOC
)
354 if (mac
->link_state
!= MAC80211_LINKED
)
357 if (ppsc
->dot11_psmode
== rt_psmode
)
360 /* Update power save mode configured. */
361 ppsc
->dot11_psmode
= rt_psmode
;
366 * Set RPWM to Fw to turn RF off and send H2C fw_pwrmode
367 * cmd to set Fw into PS mode.
369 * Send H2C fw_pwrmode cmd to Fw to set Fw into Active
370 * mode and set RPWM to turn RF on.
373 if ((ppsc
->b_fwctrl_lps
) && (ppsc
->b_leisure_ps
) &&
374 ppsc
->report_linked
) {
375 bool b_fw_current_inps
;
376 if (ppsc
->dot11_psmode
== EACTIVE
) {
377 RT_TRACE(rtlpriv
, COMP_RF
, DBG_DMESG
,
378 ("FW LPS leave ps_mode:%x\n",
381 rpwm_val
= 0x0C; /* RF on */
382 fw_pwrmode
= FW_PS_ACTIVE_MODE
;
383 rtlpriv
->cfg
->ops
->set_hw_reg(hw
, HW_VAR_SET_RPWM
,
385 rtlpriv
->cfg
->ops
->set_hw_reg(hw
,
386 HW_VAR_H2C_FW_PWRMODE
,
387 (u8
*) (&fw_pwrmode
));
388 b_fw_current_inps
= false;
390 rtlpriv
->cfg
->ops
->set_hw_reg(hw
,
391 HW_VAR_FW_PSMODE_STATUS
,
392 (u8
*) (&b_fw_current_inps
));
395 if (rtl_get_fwlps_doze(hw
)) {
396 RT_TRACE(rtlpriv
, COMP_RF
, DBG_DMESG
,
397 ("FW LPS enter ps_mode:%x\n",
398 ppsc
->fwctrl_psmode
));
400 rpwm_val
= 0x02; /* RF off */
401 b_fw_current_inps
= true;
402 rtlpriv
->cfg
->ops
->set_hw_reg(hw
,
403 HW_VAR_FW_PSMODE_STATUS
,
404 (u8
*) (&b_fw_current_inps
));
405 rtlpriv
->cfg
->ops
->set_hw_reg(hw
,
406 HW_VAR_H2C_FW_PWRMODE
,
407 (u8
*) (&ppsc
->fwctrl_psmode
));
409 rtlpriv
->cfg
->ops
->set_hw_reg(hw
,
413 /* Reset the power save related parameters. */
414 ppsc
->dot11_psmode
= EACTIVE
;
420 /*Enter the leisure power save mode.*/
421 void rtl_lps_enter(struct ieee80211_hw
*hw
)
423 struct rtl_mac
*mac
= rtl_mac(rtl_priv(hw
));
424 struct rtl_ps_ctl
*ppsc
= rtl_psc(rtl_priv(hw
));
425 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
428 if (!(ppsc
->b_fwctrl_lps
&& ppsc
->b_leisure_ps
))
431 if (rtlpriv
->sec
.being_setkey
)
434 if (rtlpriv
->link_info
.b_busytraffic
)
437 /*sleep after linked 10s, to let DHCP and 4-way handshake ok enough!! */
438 if (mac
->cnt_after_linked
< 5)
441 if (mac
->opmode
== NL80211_IFTYPE_ADHOC
)
444 if (mac
->link_state
!= MAC80211_LINKED
)
447 spin_lock_irqsave(&rtlpriv
->locks
.lps_lock
, flag
);
449 if (ppsc
->b_leisure_ps
) {
450 /* Idle for a while if we connect to AP a while ago. */
451 if (mac
->cnt_after_linked
>= 2) {
452 if (ppsc
->dot11_psmode
== EACTIVE
) {
453 RT_TRACE(rtlpriv
, COMP_POWER
, DBG_LOUD
,
454 ("Enter 802.11 power save mode...\n"));
456 rtl_lps_set_psmode(hw
, EAUTOPS
);
460 spin_unlock_irqrestore(&rtlpriv
->locks
.lps_lock
, flag
);
463 /*Leave the leisure power save mode.*/
464 void rtl_lps_leave(struct ieee80211_hw
*hw
)
466 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
467 struct rtl_ps_ctl
*ppsc
= rtl_psc(rtl_priv(hw
));
468 struct rtl_hal
*rtlhal
= rtl_hal(rtl_priv(hw
));
471 spin_lock_irqsave(&rtlpriv
->locks
.lps_lock
, flag
);
473 if (ppsc
->b_fwctrl_lps
&& ppsc
->b_leisure_ps
) {
474 if (ppsc
->dot11_psmode
!= EACTIVE
) {
477 rtlpriv
->cfg
->ops
->enable_interrupt(hw
);
479 if (ppsc
->reg_rfps_level
& RT_RF_LPS_LEVEL_ASPM
&&
480 RT_IN_PS_LEVEL(ppsc
, RT_RF_LPS_LEVEL_ASPM
) &&
481 rtlhal
->interface
== INTF_PCI
) {
482 rtlpriv
->intf_ops
->disable_aspm(hw
);
483 RT_CLEAR_PS_LEVEL(ppsc
, RT_RF_LPS_LEVEL_ASPM
);
486 RT_TRACE(rtlpriv
, COMP_POWER
, DBG_LOUD
,
487 ("Busy Traffic,Leave 802.11 power save..\n"));
489 rtl_lps_set_psmode(hw
, EACTIVE
);
492 spin_unlock_irqrestore(&rtlpriv
->locks
.lps_lock
, flag
);