55c8e50f45fd143b7e606894c71e072c97480f2a
[linux-2.6.git] / drivers / net / wireless / rtlwifi / ps.c
1 /******************************************************************************
2  *
3  * Copyright(c) 2009-2010  Realtek Corporation.
4  *
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.
8  *
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
12  * more details.
13  *
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
17  *
18  * The full GNU General Public License is included in this distribution in the
19  * file called LICENSE.
20  *
21  * Contact Information:
22  * wlanfae <wlanfae@realtek.com>
23  * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
24  * Hsinchu 300, Taiwan.
25  *
26  * Larry Finger <Larry.Finger@lwfinger.net>
27  *
28  *****************************************************************************/
29
30 #include <linux/export.h>
31 #include "wifi.h"
32 #include "base.h"
33 #include "ps.h"
34
35 bool rtl_ps_enable_nic(struct ieee80211_hw *hw)
36 {
37         struct rtl_priv *rtlpriv = rtl_priv(hw);
38         struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
39         struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
40
41         /*<1> reset trx ring */
42         if (rtlhal->interface == INTF_PCI)
43                 rtlpriv->intf_ops->reset_trx_ring(hw);
44
45         if (is_hal_stop(rtlhal))
46                 RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
47                          ("Driver is already down!\n"));
48
49         /*<2> Enable Adapter */
50         rtlpriv->cfg->ops->hw_init(hw);
51         RT_CLEAR_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC);
52
53         /*<3> Enable Interrupt */
54         rtlpriv->cfg->ops->enable_interrupt(hw);
55
56         /*<enable timer> */
57         rtl_watch_dog_timer_callback((unsigned long)hw);
58
59         return true;
60 }
61 EXPORT_SYMBOL(rtl_ps_enable_nic);
62
63 bool rtl_ps_disable_nic(struct ieee80211_hw *hw)
64 {
65         struct rtl_priv *rtlpriv = rtl_priv(hw);
66
67         /*<1> Stop all timer */
68         rtl_deinit_deferred_work(hw);
69
70         /*<2> Disable Interrupt */
71         rtlpriv->cfg->ops->disable_interrupt(hw);
72         tasklet_kill(&rtlpriv->works.irq_tasklet);
73
74         /*<3> Disable Adapter */
75         rtlpriv->cfg->ops->hw_disable(hw);
76
77         return true;
78 }
79 EXPORT_SYMBOL(rtl_ps_disable_nic);
80
81 bool rtl_ps_set_rf_state(struct ieee80211_hw *hw,
82                          enum rf_pwrstate state_toset,
83                          u32 changesource)
84 {
85         struct rtl_priv *rtlpriv = rtl_priv(hw);
86         struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
87         bool actionallowed = false;
88
89         switch (state_toset) {
90         case ERFON:
91                 ppsc->rfoff_reason &= (~changesource);
92
93                 if ((changesource == RF_CHANGE_BY_HW) &&
94                     (ppsc->hwradiooff)) {
95                         ppsc->hwradiooff = false;
96                 }
97
98                 if (!ppsc->rfoff_reason) {
99                         ppsc->rfoff_reason = 0;
100                         actionallowed = true;
101                 }
102
103                 break;
104
105         case ERFOFF:
106
107                 if ((changesource == RF_CHANGE_BY_HW)
108                     && (ppsc->hwradiooff == false)) {
109                         ppsc->hwradiooff = true;
110                 }
111
112                 ppsc->rfoff_reason |= changesource;
113                 actionallowed = true;
114                 break;
115
116         case ERFSLEEP:
117                 ppsc->rfoff_reason |= changesource;
118                 actionallowed = true;
119                 break;
120
121         default:
122                 RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
123                          ("switch case not process\n"));
124                 break;
125         }
126
127         if (actionallowed)
128                 rtlpriv->cfg->ops->set_rf_power_state(hw, state_toset);
129
130         return actionallowed;
131 }
132 EXPORT_SYMBOL(rtl_ps_set_rf_state);
133
134 static void _rtl_ps_inactive_ps(struct ieee80211_hw *hw)
135 {
136         struct rtl_priv *rtlpriv = rtl_priv(hw);
137         struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
138         struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
139
140         ppsc->swrf_processing = true;
141
142         if (ppsc->inactive_pwrstate == ERFON &&
143             rtlhal->interface == INTF_PCI) {
144                 if ((ppsc->reg_rfps_level & RT_RF_OFF_LEVL_ASPM) &&
145                     RT_IN_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM) &&
146                     rtlhal->interface == INTF_PCI) {
147                         rtlpriv->intf_ops->disable_aspm(hw);
148                         RT_CLEAR_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM);
149                 }
150         }
151
152         rtl_ps_set_rf_state(hw, ppsc->inactive_pwrstate, RF_CHANGE_BY_IPS);
153
154         if (ppsc->inactive_pwrstate == ERFOFF &&
155             rtlhal->interface == INTF_PCI) {
156                 if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_ASPM &&
157                         !RT_IN_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM)) {
158                         rtlpriv->intf_ops->enable_aspm(hw);
159                         RT_SET_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM);
160                 }
161         }
162
163         ppsc->swrf_processing = false;
164 }
165
166 void rtl_ips_nic_off_wq_callback(void *data)
167 {
168         struct rtl_works *rtlworks =
169             container_of_dwork_rtl(data, struct rtl_works, ips_nic_off_wq);
170         struct ieee80211_hw *hw = rtlworks->hw;
171         struct rtl_priv *rtlpriv = rtl_priv(hw);
172         struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
173         struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
174         struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
175         enum rf_pwrstate rtstate;
176
177         if (mac->opmode != NL80211_IFTYPE_STATION) {
178                 RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
179                          ("not station return\n"));
180                 return;
181         }
182
183         if (mac->link_state > MAC80211_NOLINK)
184                 return;
185
186         if (is_hal_stop(rtlhal))
187                 return;
188
189         if (rtlpriv->sec.being_setkey)
190                 return;
191
192         if (ppsc->inactiveps) {
193                 rtstate = ppsc->rfpwr_state;
194
195                 /*
196                  *Do not enter IPS in the following conditions:
197                  *(1) RF is already OFF or Sleep
198                  *(2) swrf_processing (indicates the IPS is still under going)
199                  *(3) Connectted (only disconnected can trigger IPS)
200                  *(4) IBSS (send Beacon)
201                  *(5) AP mode (send Beacon)
202                  *(6) monitor mode (rcv packet)
203                  */
204
205                 if (rtstate == ERFON &&
206                     !ppsc->swrf_processing &&
207                     (mac->link_state == MAC80211_NOLINK) &&
208                     !mac->act_scanning) {
209                         RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE,
210                                  ("IPSEnter(): Turn off RF.\n"));
211
212                         ppsc->inactive_pwrstate = ERFOFF;
213                         ppsc->in_powersavemode = true;
214
215                         /*rtl_pci_reset_trx_ring(hw); */
216                         _rtl_ps_inactive_ps(hw);
217                 }
218         }
219 }
220
221 void rtl_ips_nic_off(struct ieee80211_hw *hw)
222 {
223         struct rtl_priv *rtlpriv = rtl_priv(hw);
224
225         /*
226          *because when link with ap, mac80211 will ask us
227          *to disable nic quickly after scan before linking,
228          *this will cause link failed, so we delay 100ms here
229          */
230         queue_delayed_work(rtlpriv->works.rtl_wq,
231                            &rtlpriv->works.ips_nic_off_wq, MSECS(100));
232 }
233
234 void rtl_ips_nic_on(struct ieee80211_hw *hw)
235 {
236         struct rtl_priv *rtlpriv = rtl_priv(hw);
237         struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
238         struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
239         enum rf_pwrstate rtstate;
240
241         if (mac->opmode != NL80211_IFTYPE_STATION)
242                 return;
243
244         spin_lock(&rtlpriv->locks.ips_lock);
245
246         if (ppsc->inactiveps) {
247                 rtstate = ppsc->rfpwr_state;
248
249                 if (rtstate != ERFON &&
250                     !ppsc->swrf_processing &&
251                     ppsc->rfoff_reason <= RF_CHANGE_BY_IPS) {
252
253                         ppsc->inactive_pwrstate = ERFON;
254                         ppsc->in_powersavemode = false;
255
256                         _rtl_ps_inactive_ps(hw);
257                 }
258         }
259
260         spin_unlock(&rtlpriv->locks.ips_lock);
261 }
262
263 /*for FW LPS*/
264
265 /*
266  *Determine if we can set Fw into PS mode
267  *in current condition.Return TRUE if it
268  *can enter PS mode.
269  */
270 static bool rtl_get_fwlps_doze(struct ieee80211_hw *hw)
271 {
272         struct rtl_priv *rtlpriv = rtl_priv(hw);
273         struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
274         struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
275         u32 ps_timediff;
276
277         ps_timediff = jiffies_to_msecs(jiffies -
278                                        ppsc->last_delaylps_stamp_jiffies);
279
280         if (ps_timediff < 2000) {
281                 RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
282                          ("Delay enter Fw LPS for DHCP, ARP,"
283                           " or EAPOL exchanging state.\n"));
284                 return false;
285         }
286
287         if (mac->link_state != MAC80211_LINKED)
288                 return false;
289
290         if (mac->opmode == NL80211_IFTYPE_ADHOC)
291                 return false;
292
293         return true;
294 }
295
296 /* Change current and default preamble mode.*/
297 static void rtl_lps_set_psmode(struct ieee80211_hw *hw, u8 rt_psmode)
298 {
299         struct rtl_priv *rtlpriv = rtl_priv(hw);
300         struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
301         struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
302         u8 rpwm_val, fw_pwrmode;
303
304         if (mac->opmode == NL80211_IFTYPE_ADHOC)
305                 return;
306
307         if (mac->link_state != MAC80211_LINKED)
308                 return;
309
310         if (ppsc->dot11_psmode == rt_psmode)
311                 return;
312
313         /* Update power save mode configured. */
314         ppsc->dot11_psmode = rt_psmode;
315
316         /*
317          *<FW control LPS>
318          *1. Enter PS mode
319          *   Set RPWM to Fw to turn RF off and send H2C fw_pwrmode
320          *   cmd to set Fw into PS mode.
321          *2. Leave PS mode
322          *   Send H2C fw_pwrmode cmd to Fw to set Fw into Active
323          *   mode and set RPWM to turn RF on.
324          */
325
326         if ((ppsc->fwctrl_lps) && ppsc->report_linked) {
327                 bool fw_current_inps;
328                 if (ppsc->dot11_psmode == EACTIVE) {
329                         RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG,
330                                  ("FW LPS leave ps_mode:%x\n",
331                                   FW_PS_ACTIVE_MODE));
332
333                         rpwm_val = 0x0C;        /* RF on */
334                         fw_pwrmode = FW_PS_ACTIVE_MODE;
335                         rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SET_RPWM,
336                                         (u8 *) (&rpwm_val));
337                         rtlpriv->cfg->ops->set_hw_reg(hw,
338                                         HW_VAR_H2C_FW_PWRMODE,
339                                         (u8 *) (&fw_pwrmode));
340                         fw_current_inps = false;
341
342                         rtlpriv->cfg->ops->set_hw_reg(hw,
343                                         HW_VAR_FW_PSMODE_STATUS,
344                                         (u8 *) (&fw_current_inps));
345
346                 } else {
347                         if (rtl_get_fwlps_doze(hw)) {
348                                 RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG,
349                                                 ("FW LPS enter ps_mode:%x\n",
350                                                  ppsc->fwctrl_psmode));
351
352                                 rpwm_val = 0x02;        /* RF off */
353                                 fw_current_inps = true;
354                                 rtlpriv->cfg->ops->set_hw_reg(hw,
355                                                 HW_VAR_FW_PSMODE_STATUS,
356                                                 (u8 *) (&fw_current_inps));
357                                 rtlpriv->cfg->ops->set_hw_reg(hw,
358                                                 HW_VAR_H2C_FW_PWRMODE,
359                                                 (u8 *) (&ppsc->fwctrl_psmode));
360
361                                 rtlpriv->cfg->ops->set_hw_reg(hw,
362                                                 HW_VAR_SET_RPWM,
363                                                 (u8 *) (&rpwm_val));
364                         } else {
365                                 /* Reset the power save related parameters. */
366                                 ppsc->dot11_psmode = EACTIVE;
367                         }
368                 }
369         }
370 }
371
372 /*Enter the leisure power save mode.*/
373 void rtl_lps_enter(struct ieee80211_hw *hw)
374 {
375         struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
376         struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
377         struct rtl_priv *rtlpriv = rtl_priv(hw);
378
379         if (!ppsc->fwctrl_lps)
380                 return;
381
382         if (rtlpriv->sec.being_setkey)
383                 return;
384
385         if (rtlpriv->link_info.busytraffic)
386                 return;
387
388         /*sleep after linked 10s, to let DHCP and 4-way handshake ok enough!! */
389         if (mac->cnt_after_linked < 5)
390                 return;
391
392         if (mac->opmode == NL80211_IFTYPE_ADHOC)
393                 return;
394
395         if (mac->link_state != MAC80211_LINKED)
396                 return;
397
398         spin_lock_irq(&rtlpriv->locks.lps_lock);
399
400         /* Idle for a while if we connect to AP a while ago. */
401         if (mac->cnt_after_linked >= 2) {
402                 if (ppsc->dot11_psmode == EACTIVE) {
403                         RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
404                                         ("Enter 802.11 power save mode...\n"));
405
406                         rtl_lps_set_psmode(hw, EAUTOPS);
407                 }
408         }
409
410         spin_unlock_irq(&rtlpriv->locks.lps_lock);
411 }
412
413 /*Leave the leisure power save mode.*/
414 void rtl_lps_leave(struct ieee80211_hw *hw)
415 {
416         struct rtl_priv *rtlpriv = rtl_priv(hw);
417         struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
418         struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
419         unsigned long flags;
420
421         spin_lock_irqsave(&rtlpriv->locks.lps_lock, flags);
422
423         if (ppsc->fwctrl_lps) {
424                 if (ppsc->dot11_psmode != EACTIVE) {
425
426                         /*FIX ME */
427                         rtlpriv->cfg->ops->enable_interrupt(hw);
428
429                         if (ppsc->reg_rfps_level & RT_RF_LPS_LEVEL_ASPM &&
430                             RT_IN_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM) &&
431                             rtlhal->interface == INTF_PCI) {
432                                 rtlpriv->intf_ops->disable_aspm(hw);
433                                 RT_CLEAR_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM);
434                         }
435
436                         RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
437                                  ("Busy Traffic,Leave 802.11 power save..\n"));
438
439                         rtl_lps_set_psmode(hw, EACTIVE);
440                 }
441         }
442         spin_unlock_irqrestore(&rtlpriv->locks.lps_lock, flags);
443 }
444
445 /* For sw LPS*/
446 void rtl_swlps_beacon(struct ieee80211_hw *hw, void *data, unsigned int len)
447 {
448         struct rtl_priv *rtlpriv = rtl_priv(hw);
449         struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
450         struct ieee80211_hdr *hdr = (void *) data;
451         struct ieee80211_tim_ie *tim_ie;
452         u8 *tim;
453         u8 tim_len;
454         bool u_buffed;
455         bool m_buffed;
456
457         if (mac->opmode != NL80211_IFTYPE_STATION)
458                 return;
459
460         if (!rtlpriv->psc.swctrl_lps)
461                 return;
462
463         if (rtlpriv->mac80211.link_state != MAC80211_LINKED)
464                 return;
465
466         if (!rtlpriv->psc.sw_ps_enabled)
467                 return;
468
469         if (rtlpriv->psc.fwctrl_lps)
470                 return;
471
472         if (likely(!(hw->conf.flags & IEEE80211_CONF_PS)))
473                 return;
474
475         /* check if this really is a beacon */
476         if (!ieee80211_is_beacon(hdr->frame_control))
477                 return;
478
479         /* min. beacon length + FCS_LEN */
480         if (len <= 40 + FCS_LEN)
481                 return;
482
483         /* and only beacons from the associated BSSID, please */
484         if (compare_ether_addr(hdr->addr3, rtlpriv->mac80211.bssid))
485                 return;
486
487         rtlpriv->psc.last_beacon = jiffies;
488
489         tim = rtl_find_ie(data, len - FCS_LEN, WLAN_EID_TIM);
490         if (!tim)
491                 return;
492
493         if (tim[1] < sizeof(*tim_ie))
494                 return;
495
496         tim_len = tim[1];
497         tim_ie = (struct ieee80211_tim_ie *) &tim[2];
498
499         if (!WARN_ON_ONCE(!hw->conf.ps_dtim_period))
500                 rtlpriv->psc.dtim_counter = tim_ie->dtim_count;
501
502         /* Check whenever the PHY can be turned off again. */
503
504         /* 1. What about buffered unicast traffic for our AID? */
505         u_buffed = ieee80211_check_tim(tim_ie, tim_len,
506                                        rtlpriv->mac80211.assoc_id);
507
508         /* 2. Maybe the AP wants to send multicast/broadcast data? */
509         m_buffed = tim_ie->bitmap_ctrl & 0x01;
510         rtlpriv->psc.multi_buffered = m_buffed;
511
512         /* unicast will process by mac80211 through
513          * set ~IEEE80211_CONF_PS, So we just check
514          * multicast frames here */
515         if (!m_buffed) {
516                 /* back to low-power land. and delay is
517                  * prevent null power save frame tx fail */
518                 queue_delayed_work(rtlpriv->works.rtl_wq,
519                                 &rtlpriv->works.ps_work, MSECS(5));
520         } else {
521                 RT_TRACE(rtlpriv, COMP_POWER, DBG_DMESG, ("u_bufferd: %x, "
522                                 "m_buffered: %x\n", u_buffed, m_buffed));
523         }
524 }
525
526 void rtl_swlps_rf_awake(struct ieee80211_hw *hw)
527 {
528         struct rtl_priv *rtlpriv = rtl_priv(hw);
529         struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
530         struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
531
532         if (!rtlpriv->psc.swctrl_lps)
533                 return;
534         if (mac->link_state != MAC80211_LINKED)
535                 return;
536
537         if (ppsc->reg_rfps_level & RT_RF_LPS_LEVEL_ASPM &&
538                 RT_IN_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM)) {
539                 rtlpriv->intf_ops->disable_aspm(hw);
540                 RT_CLEAR_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM);
541         }
542
543         spin_lock_irq(&rtlpriv->locks.lps_lock);
544         rtl_ps_set_rf_state(hw, ERFON, RF_CHANGE_BY_PS);
545         spin_unlock_irq(&rtlpriv->locks.lps_lock);
546 }
547
548 void rtl_swlps_rfon_wq_callback(void *data)
549 {
550         struct rtl_works *rtlworks =
551             container_of_dwork_rtl(data, struct rtl_works, ps_rfon_wq);
552         struct ieee80211_hw *hw = rtlworks->hw;
553
554         rtl_swlps_rf_awake(hw);
555 }
556
557 void rtl_swlps_rf_sleep(struct ieee80211_hw *hw)
558 {
559         struct rtl_priv *rtlpriv = rtl_priv(hw);
560         struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
561         struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
562         u8 sleep_intv;
563
564         if (!rtlpriv->psc.sw_ps_enabled)
565                 return;
566
567         if ((rtlpriv->sec.being_setkey) ||
568             (mac->opmode == NL80211_IFTYPE_ADHOC))
569                 return;
570
571         /*sleep after linked 10s, to let DHCP and 4-way handshake ok enough!! */
572         if ((mac->link_state != MAC80211_LINKED) || (mac->cnt_after_linked < 5))
573                 return;
574
575         if (rtlpriv->link_info.busytraffic)
576                 return;
577
578         spin_lock_irq(&rtlpriv->locks.lps_lock);
579         rtl_ps_set_rf_state(hw, ERFSLEEP, RF_CHANGE_BY_PS);
580         spin_unlock_irq(&rtlpriv->locks.lps_lock);
581
582         if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_ASPM &&
583                 !RT_IN_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM)) {
584                 rtlpriv->intf_ops->enable_aspm(hw);
585                 RT_SET_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM);
586         }
587
588         /* here is power save alg, when this beacon is DTIM
589          * we will set sleep time to dtim_period * n;
590          * when this beacon is not DTIM, we will set sleep
591          * time to sleep_intv = rtlpriv->psc.dtim_counter or
592          * MAX_SW_LPS_SLEEP_INTV(default set to 5) */
593
594         if (rtlpriv->psc.dtim_counter == 0) {
595                 if (hw->conf.ps_dtim_period == 1)
596                         sleep_intv = hw->conf.ps_dtim_period * 2;
597                 else
598                         sleep_intv = hw->conf.ps_dtim_period;
599         } else {
600                 sleep_intv = rtlpriv->psc.dtim_counter;
601         }
602
603         if (sleep_intv > MAX_SW_LPS_SLEEP_INTV)
604                 sleep_intv = MAX_SW_LPS_SLEEP_INTV;
605
606         /* this print should always be dtim_conter = 0 &
607          * sleep  = dtim_period, that meaons, we should
608          * awake before every dtim */
609         RT_TRACE(rtlpriv, COMP_POWER, DBG_DMESG,
610                  ("dtim_counter:%x will sleep :%d"
611                  " beacon_intv\n", rtlpriv->psc.dtim_counter, sleep_intv));
612
613         /* we tested that 40ms is enough for sw & hw sw delay */
614         queue_delayed_work(rtlpriv->works.rtl_wq, &rtlpriv->works.ps_rfon_wq,
615                         MSECS(sleep_intv * mac->vif->bss_conf.beacon_int - 40));
616 }
617
618
619 void rtl_swlps_wq_callback(void *data)
620 {
621         struct rtl_works *rtlworks = container_of_dwork_rtl(data,
622                                      struct rtl_works,
623                                      ps_work);
624         struct ieee80211_hw *hw = rtlworks->hw;
625         struct rtl_priv *rtlpriv = rtl_priv(hw);
626         bool ps = false;
627
628         ps = (hw->conf.flags & IEEE80211_CONF_PS);
629
630         /* we can sleep after ps null send ok */
631         if (rtlpriv->psc.state_inap) {
632                 rtl_swlps_rf_sleep(hw);
633
634                 if (rtlpriv->psc.state && !ps) {
635                         rtlpriv->psc.sleep_ms = jiffies_to_msecs(jiffies -
636                                         rtlpriv->psc.last_action);
637                 }
638
639                 if (ps)
640                         rtlpriv->psc.last_slept = jiffies;
641
642                 rtlpriv->psc.last_action = jiffies;
643                 rtlpriv->psc.state = ps;
644         }
645 }