~ubuntu-branches/ubuntu/precise/linux-ti-omap4/precise

« back to all changes in this revision

Viewing changes to drivers/net/wireless/rtlwifi/ps.c

  • Committer: Bazaar Package Importer
  • Author(s): Paolo Pisati
  • Date: 2011-06-29 15:23:51 UTC
  • mfrom: (26.1.1 natty-proposed)
  • Revision ID: james.westby@ubuntu.com-20110629152351-xs96tm303d95rpbk
Tags: 3.0.0-1200.2
* Rebased against 3.0.0-6.7
* BSP from TI based on 3.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
36
36
        struct rtl_priv *rtlpriv = rtl_priv(hw);
37
37
        struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
38
38
        struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
39
 
        bool init_status = true;
40
39
 
41
40
        /*<1> reset trx ring */
42
41
        if (rtlhal->interface == INTF_PCI)
49
48
        /*<2> Enable Adapter */
50
49
        rtlpriv->cfg->ops->hw_init(hw);
51
50
        RT_CLEAR_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC);
52
 
        /*init_status = false; */
53
51
 
54
52
        /*<3> Enable Interrupt */
55
53
        rtlpriv->cfg->ops->enable_interrupt(hw);
57
55
        /*<enable timer> */
58
56
        rtl_watch_dog_timer_callback((unsigned long)hw);
59
57
 
60
 
        return init_status;
 
58
        return true;
61
59
}
62
60
EXPORT_SYMBOL(rtl_ps_enable_nic);
63
61
 
64
62
bool rtl_ps_disable_nic(struct ieee80211_hw *hw)
65
63
{
66
 
        bool status = true;
67
64
        struct rtl_priv *rtlpriv = rtl_priv(hw);
68
65
 
69
66
        /*<1> Stop all timer */
75
72
        /*<3> Disable Adapter */
76
73
        rtlpriv->cfg->ops->hw_disable(hw);
77
74
 
78
 
        return status;
 
75
        return true;
79
76
}
80
77
EXPORT_SYMBOL(rtl_ps_disable_nic);
81
78
 
86
83
        struct rtl_priv *rtlpriv = rtl_priv(hw);
87
84
        struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
88
85
        enum rf_pwrstate rtstate;
89
 
        bool b_actionallowed = false;
 
86
        bool actionallowed = false;
90
87
        u16 rfwait_cnt = 0;
91
88
        unsigned long flag;
92
89
 
139
136
                ppsc->rfoff_reason &= (~changesource);
140
137
 
141
138
                if ((changesource == RF_CHANGE_BY_HW) &&
142
 
                    (ppsc->b_hwradiooff == true)) {
143
 
                        ppsc->b_hwradiooff = false;
 
139
                    (ppsc->hwradiooff == true)) {
 
140
                        ppsc->hwradiooff = false;
144
141
                }
145
142
 
146
143
                if (!ppsc->rfoff_reason) {
147
144
                        ppsc->rfoff_reason = 0;
148
 
                        b_actionallowed = true;
 
145
                        actionallowed = true;
149
146
                }
150
147
 
151
148
                break;
153
150
        case ERFOFF:
154
151
 
155
152
                if ((changesource == RF_CHANGE_BY_HW)
156
 
                    && (ppsc->b_hwradiooff == false)) {
157
 
                        ppsc->b_hwradiooff = true;
 
153
                    && (ppsc->hwradiooff == false)) {
 
154
                        ppsc->hwradiooff = true;
158
155
                }
159
156
 
160
157
                ppsc->rfoff_reason |= changesource;
161
 
                b_actionallowed = true;
 
158
                actionallowed = true;
162
159
                break;
163
160
 
164
161
        case ERFSLEEP:
165
162
                ppsc->rfoff_reason |= changesource;
166
 
                b_actionallowed = true;
 
163
                actionallowed = true;
167
164
                break;
168
165
 
169
166
        default:
172
169
                break;
173
170
        }
174
171
 
175
 
        if (b_actionallowed)
 
172
        if (actionallowed)
176
173
                rtlpriv->cfg->ops->set_rf_power_state(hw, state_toset);
177
174
 
178
175
        if (!protect_or_not) {
181
178
                spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flag);
182
179
        }
183
180
 
184
 
        return b_actionallowed;
 
181
        return actionallowed;
185
182
}
186
183
EXPORT_SYMBOL(rtl_ps_set_rf_state);
187
184
 
191
188
        struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
192
189
        struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
193
190
 
194
 
        ppsc->b_swrf_processing = true;
 
191
        ppsc->swrf_processing = true;
195
192
 
196
 
        if (ppsc->inactive_pwrstate == ERFON && rtlhal->interface == INTF_PCI) {
 
193
        if (ppsc->inactive_pwrstate == ERFON &&
 
194
            rtlhal->interface == INTF_PCI) {
197
195
                if ((ppsc->reg_rfps_level & RT_RF_OFF_LEVL_ASPM) &&
198
 
                    RT_IN_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_ASPM) &&
 
196
                    RT_IN_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM) &&
199
197
                    rtlhal->interface == INTF_PCI) {
200
198
                        rtlpriv->intf_ops->disable_aspm(hw);
201
 
                        RT_CLEAR_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_ASPM);
 
199
                        RT_CLEAR_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM);
202
200
                }
203
201
        }
204
202
 
207
205
 
208
206
        if (ppsc->inactive_pwrstate == ERFOFF &&
209
207
            rtlhal->interface == INTF_PCI) {
210
 
                if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_ASPM) {
 
208
                if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_ASPM &&
 
209
                        !RT_IN_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM)) {
211
210
                        rtlpriv->intf_ops->enable_aspm(hw);
212
 
                        RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_ASPM);
 
211
                        RT_SET_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM);
213
212
                }
214
213
        }
215
214
 
216
 
        ppsc->b_swrf_processing = false;
 
215
        ppsc->swrf_processing = false;
217
216
}
218
217
 
219
218
void rtl_ips_nic_off_wq_callback(void *data)
233
232
                return;
234
233
        }
235
234
 
 
235
        if (mac->link_state > MAC80211_NOLINK)
 
236
                return;
 
237
 
236
238
        if (is_hal_stop(rtlhal))
237
239
                return;
238
240
 
239
241
        if (rtlpriv->sec.being_setkey)
240
242
                return;
241
243
 
242
 
        if (ppsc->b_inactiveps) {
 
244
        if (ppsc->inactiveps) {
243
245
                rtstate = ppsc->rfpwr_state;
244
246
 
245
247
                /*
246
248
                 *Do not enter IPS in the following conditions:
247
249
                 *(1) RF is already OFF or Sleep
248
 
                 *(2) b_swrf_processing (indicates the IPS is still under going)
 
250
                 *(2) swrf_processing (indicates the IPS is still under going)
249
251
                 *(3) Connectted (only disconnected can trigger IPS)
250
252
                 *(4) IBSS (send Beacon)
251
253
                 *(5) AP mode (send Beacon)
253
255
                 */
254
256
 
255
257
                if (rtstate == ERFON &&
256
 
                    !ppsc->b_swrf_processing &&
 
258
                    !ppsc->swrf_processing &&
257
259
                    (mac->link_state == MAC80211_NOLINK) &&
258
260
                    !mac->act_scanning) {
259
261
                        RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE,
260
262
                                 ("IPSEnter(): Turn off RF.\n"));
261
263
 
262
264
                        ppsc->inactive_pwrstate = ERFOFF;
263
 
                        ppsc->b_in_powersavemode = true;
 
265
                        ppsc->in_powersavemode = true;
264
266
 
265
267
                        /*rtl_pci_reset_trx_ring(hw); */
266
268
                        _rtl_ps_inactive_ps(hw);
284
286
void rtl_ips_nic_on(struct ieee80211_hw *hw)
285
287
{
286
288
        struct rtl_priv *rtlpriv = rtl_priv(hw);
 
289
        struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
287
290
        struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
288
291
        enum rf_pwrstate rtstate;
289
292
        unsigned long flags;
290
293
 
 
294
        if (mac->opmode != NL80211_IFTYPE_STATION)
 
295
                return;
 
296
 
291
297
        spin_lock_irqsave(&rtlpriv->locks.ips_lock, flags);
292
298
 
293
 
        if (ppsc->b_inactiveps) {
 
299
        if (ppsc->inactiveps) {
294
300
                rtstate = ppsc->rfpwr_state;
295
301
 
296
302
                if (rtstate != ERFON &&
297
 
                    !ppsc->b_swrf_processing &&
 
303
                    !ppsc->swrf_processing &&
298
304
                    ppsc->rfoff_reason <= RF_CHANGE_BY_IPS) {
299
305
 
300
306
                        ppsc->inactive_pwrstate = ERFON;
301
 
                        ppsc->b_in_powersavemode = false;
 
307
                        ppsc->in_powersavemode = false;
302
308
 
303
309
                        _rtl_ps_inactive_ps(hw);
304
310
                }
370
376
         *   mode and set RPWM to turn RF on.
371
377
         */
372
378
 
373
 
        if ((ppsc->b_fwctrl_lps) && (ppsc->b_leisure_ps) &&
374
 
             ppsc->report_linked) {
375
 
                bool b_fw_current_inps;
 
379
        if ((ppsc->fwctrl_lps) && ppsc->report_linked) {
 
380
                bool fw_current_inps;
376
381
                if (ppsc->dot11_psmode == EACTIVE) {
377
382
                        RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG,
378
383
                                 ("FW LPS leave ps_mode:%x\n",
385
390
                        rtlpriv->cfg->ops->set_hw_reg(hw,
386
391
                                        HW_VAR_H2C_FW_PWRMODE,
387
392
                                        (u8 *) (&fw_pwrmode));
388
 
                        b_fw_current_inps = false;
 
393
                        fw_current_inps = false;
389
394
 
390
395
                        rtlpriv->cfg->ops->set_hw_reg(hw,
391
396
                                        HW_VAR_FW_PSMODE_STATUS,
392
 
                                        (u8 *) (&b_fw_current_inps));
 
397
                                        (u8 *) (&fw_current_inps));
393
398
 
394
399
                } else {
395
400
                        if (rtl_get_fwlps_doze(hw)) {
398
403
                                                 ppsc->fwctrl_psmode));
399
404
 
400
405
                                rpwm_val = 0x02;        /* RF off */
401
 
                                b_fw_current_inps = true;
 
406
                                fw_current_inps = true;
402
407
                                rtlpriv->cfg->ops->set_hw_reg(hw,
403
408
                                                HW_VAR_FW_PSMODE_STATUS,
404
 
                                                (u8 *) (&b_fw_current_inps));
 
409
                                                (u8 *) (&fw_current_inps));
405
410
                                rtlpriv->cfg->ops->set_hw_reg(hw,
406
411
                                                HW_VAR_H2C_FW_PWRMODE,
407
412
                                                (u8 *) (&ppsc->fwctrl_psmode));
425
430
        struct rtl_priv *rtlpriv = rtl_priv(hw);
426
431
        unsigned long flag;
427
432
 
428
 
        if (!(ppsc->b_fwctrl_lps && ppsc->b_leisure_ps))
 
433
        if (!ppsc->fwctrl_lps)
429
434
                return;
430
435
 
431
436
        if (rtlpriv->sec.being_setkey)
432
437
                return;
433
438
 
434
 
        if (rtlpriv->link_info.b_busytraffic)
 
439
        if (rtlpriv->link_info.busytraffic)
435
440
                return;
436
441
 
437
442
        /*sleep after linked 10s, to let DHCP and 4-way handshake ok enough!! */
446
451
 
447
452
        spin_lock_irqsave(&rtlpriv->locks.lps_lock, flag);
448
453
 
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
        /* Idle for a while if we connect to AP a while ago. */
 
455
        if (mac->cnt_after_linked >= 2) {
 
456
                if (ppsc->dot11_psmode == EACTIVE) {
 
457
                        RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
454
458
                                        ("Enter 802.11 power save mode...\n"));
455
459
 
456
 
                                rtl_lps_set_psmode(hw, EAUTOPS);
457
 
                        }
 
460
                        rtl_lps_set_psmode(hw, EAUTOPS);
458
461
                }
459
462
        }
 
463
 
460
464
        spin_unlock_irqrestore(&rtlpriv->locks.lps_lock, flag);
461
465
}
462
466
 
470
474
 
471
475
        spin_lock_irqsave(&rtlpriv->locks.lps_lock, flag);
472
476
 
473
 
        if (ppsc->b_fwctrl_lps && ppsc->b_leisure_ps) {
 
477
        if (ppsc->fwctrl_lps) {
474
478
                if (ppsc->dot11_psmode != EACTIVE) {
475
479
 
476
480
                        /*FIX ME */
477
481
                        rtlpriv->cfg->ops->enable_interrupt(hw);
478
482
 
479
483
                        if (ppsc->reg_rfps_level & RT_RF_LPS_LEVEL_ASPM &&
480
 
                            RT_IN_PS_LEVEL(ppsc, RT_RF_LPS_LEVEL_ASPM) &&
 
484
                            RT_IN_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM) &&
481
485
                            rtlhal->interface == INTF_PCI) {
482
486
                                rtlpriv->intf_ops->disable_aspm(hw);
483
 
                                RT_CLEAR_PS_LEVEL(ppsc, RT_RF_LPS_LEVEL_ASPM);
 
487
                                RT_CLEAR_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM);
484
488
                        }
485
489
 
486
490
                        RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
491
495
        }
492
496
        spin_unlock_irqrestore(&rtlpriv->locks.lps_lock, flag);
493
497
}
 
498
 
 
499
/* For sw LPS*/
 
500
void rtl_swlps_beacon(struct ieee80211_hw *hw, void *data, unsigned int len)
 
501
{
 
502
        struct rtl_priv *rtlpriv = rtl_priv(hw);
 
503
        struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
 
504
        struct ieee80211_hdr *hdr = (void *) data;
 
505
        struct ieee80211_tim_ie *tim_ie;
 
506
        u8 *tim;
 
507
        u8 tim_len;
 
508
        bool u_buffed;
 
509
        bool m_buffed;
 
510
 
 
511
        if (mac->opmode != NL80211_IFTYPE_STATION)
 
512
                return;
 
513
 
 
514
        if (!rtlpriv->psc.swctrl_lps)
 
515
                return;
 
516
 
 
517
        if (rtlpriv->mac80211.link_state != MAC80211_LINKED)
 
518
                return;
 
519
 
 
520
        if (!rtlpriv->psc.sw_ps_enabled)
 
521
                return;
 
522
 
 
523
        if (rtlpriv->psc.fwctrl_lps)
 
524
                return;
 
525
 
 
526
        if (likely(!(hw->conf.flags & IEEE80211_CONF_PS)))
 
527
                return;
 
528
 
 
529
        /* check if this really is a beacon */
 
530
        if (!ieee80211_is_beacon(hdr->frame_control))
 
531
                return;
 
532
 
 
533
        /* min. beacon length + FCS_LEN */
 
534
        if (len <= 40 + FCS_LEN)
 
535
                return;
 
536
 
 
537
        /* and only beacons from the associated BSSID, please */
 
538
        if (compare_ether_addr(hdr->addr3, rtlpriv->mac80211.bssid))
 
539
                return;
 
540
 
 
541
        rtlpriv->psc.last_beacon = jiffies;
 
542
 
 
543
        tim = rtl_find_ie(data, len - FCS_LEN, WLAN_EID_TIM);
 
544
        if (!tim)
 
545
                return;
 
546
 
 
547
        if (tim[1] < sizeof(*tim_ie))
 
548
                return;
 
549
 
 
550
        tim_len = tim[1];
 
551
        tim_ie = (struct ieee80211_tim_ie *) &tim[2];
 
552
 
 
553
        if (!WARN_ON_ONCE(!hw->conf.ps_dtim_period))
 
554
                rtlpriv->psc.dtim_counter = tim_ie->dtim_count;
 
555
 
 
556
        /* Check whenever the PHY can be turned off again. */
 
557
 
 
558
        /* 1. What about buffered unicast traffic for our AID? */
 
559
        u_buffed = ieee80211_check_tim(tim_ie, tim_len,
 
560
                                       rtlpriv->mac80211.assoc_id);
 
561
 
 
562
        /* 2. Maybe the AP wants to send multicast/broadcast data? */
 
563
        m_buffed = tim_ie->bitmap_ctrl & 0x01;
 
564
        rtlpriv->psc.multi_buffered = m_buffed;
 
565
 
 
566
        /* unicast will process by mac80211 through
 
567
         * set ~IEEE80211_CONF_PS, So we just check
 
568
         * multicast frames here */
 
569
        if (!m_buffed) {
 
570
                /* back to low-power land. and delay is
 
571
                 * prevent null power save frame tx fail */
 
572
                queue_delayed_work(rtlpriv->works.rtl_wq,
 
573
                                &rtlpriv->works.ps_work, MSECS(5));
 
574
        } else {
 
575
                RT_TRACE(rtlpriv, COMP_POWER, DBG_DMESG, ("u_bufferd: %x, "
 
576
                                "m_buffered: %x\n", u_buffed, m_buffed));
 
577
        }
 
578
}
 
579
 
 
580
void rtl_swlps_rf_awake(struct ieee80211_hw *hw)
 
581
{
 
582
        struct rtl_priv *rtlpriv = rtl_priv(hw);
 
583
        struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
 
584
        struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
 
585
        unsigned long flag;
 
586
 
 
587
        if (!rtlpriv->psc.swctrl_lps)
 
588
                return;
 
589
        if (mac->link_state != MAC80211_LINKED)
 
590
                return;
 
591
 
 
592
        if (ppsc->reg_rfps_level & RT_RF_LPS_LEVEL_ASPM &&
 
593
                RT_IN_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM)) {
 
594
                rtlpriv->intf_ops->disable_aspm(hw);
 
595
                RT_CLEAR_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM);
 
596
        }
 
597
 
 
598
        spin_lock_irqsave(&rtlpriv->locks.lps_lock, flag);
 
599
        rtl_ps_set_rf_state(hw, ERFON, RF_CHANGE_BY_PS, false);
 
600
        spin_unlock_irqrestore(&rtlpriv->locks.lps_lock, flag);
 
601
}
 
602
 
 
603
void rtl_swlps_rfon_wq_callback(void *data)
 
604
{
 
605
        struct rtl_works *rtlworks =
 
606
            container_of_dwork_rtl(data, struct rtl_works, ps_rfon_wq);
 
607
        struct ieee80211_hw *hw = rtlworks->hw;
 
608
 
 
609
        rtl_swlps_rf_awake(hw);
 
610
}
 
611
 
 
612
void rtl_swlps_rf_sleep(struct ieee80211_hw *hw)
 
613
{
 
614
        struct rtl_priv *rtlpriv = rtl_priv(hw);
 
615
        struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
 
616
        struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
 
617
        unsigned long flag;
 
618
        u8 sleep_intv;
 
619
 
 
620
        if (!rtlpriv->psc.sw_ps_enabled)
 
621
                return;
 
622
 
 
623
        if ((rtlpriv->sec.being_setkey) ||
 
624
            (mac->opmode == NL80211_IFTYPE_ADHOC))
 
625
                return;
 
626
 
 
627
        /*sleep after linked 10s, to let DHCP and 4-way handshake ok enough!! */
 
628
        if ((mac->link_state != MAC80211_LINKED) || (mac->cnt_after_linked < 5))
 
629
                return;
 
630
 
 
631
        if (rtlpriv->link_info.busytraffic)
 
632
                return;
 
633
 
 
634
        spin_lock_irqsave(&rtlpriv->locks.rf_ps_lock, flag);
 
635
        if (rtlpriv->psc.rfchange_inprogress) {
 
636
                spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flag);
 
637
                return;
 
638
        }
 
639
        spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flag);
 
640
 
 
641
        spin_lock_irqsave(&rtlpriv->locks.lps_lock, flag);
 
642
        rtl_ps_set_rf_state(hw, ERFSLEEP, RF_CHANGE_BY_PS, false);
 
643
        spin_unlock_irqrestore(&rtlpriv->locks.lps_lock, flag);
 
644
 
 
645
        if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_ASPM &&
 
646
                !RT_IN_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM)) {
 
647
                rtlpriv->intf_ops->enable_aspm(hw);
 
648
                RT_SET_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM);
 
649
        }
 
650
 
 
651
        /* here is power save alg, when this beacon is DTIM
 
652
         * we will set sleep time to dtim_period * n;
 
653
         * when this beacon is not DTIM, we will set sleep
 
654
         * time to sleep_intv = rtlpriv->psc.dtim_counter or
 
655
         * MAX_SW_LPS_SLEEP_INTV(default set to 5) */
 
656
 
 
657
        if (rtlpriv->psc.dtim_counter == 0) {
 
658
                if (hw->conf.ps_dtim_period == 1)
 
659
                        sleep_intv = hw->conf.ps_dtim_period * 2;
 
660
                else
 
661
                        sleep_intv = hw->conf.ps_dtim_period;
 
662
        } else {
 
663
                sleep_intv = rtlpriv->psc.dtim_counter;
 
664
        }
 
665
 
 
666
        if (sleep_intv > MAX_SW_LPS_SLEEP_INTV)
 
667
                sleep_intv = MAX_SW_LPS_SLEEP_INTV;
 
668
 
 
669
        /* this print should always be dtim_conter = 0 &
 
670
         * sleep  = dtim_period, that meaons, we should
 
671
         * awake before every dtim */
 
672
        RT_TRACE(rtlpriv, COMP_POWER, DBG_DMESG,
 
673
                 ("dtim_counter:%x will sleep :%d"
 
674
                 " beacon_intv\n", rtlpriv->psc.dtim_counter, sleep_intv));
 
675
 
 
676
        /* we tested that 40ms is enough for sw & hw sw delay */
 
677
        queue_delayed_work(rtlpriv->works.rtl_wq, &rtlpriv->works.ps_rfon_wq,
 
678
                        MSECS(sleep_intv * mac->vif->bss_conf.beacon_int - 40));
 
679
}
 
680
 
 
681
 
 
682
void rtl_swlps_wq_callback(void *data)
 
683
{
 
684
        struct rtl_works *rtlworks = container_of_dwork_rtl(data,
 
685
                                     struct rtl_works,
 
686
                                     ps_work);
 
687
        struct ieee80211_hw *hw = rtlworks->hw;
 
688
        struct rtl_priv *rtlpriv = rtl_priv(hw);
 
689
        bool ps = false;
 
690
 
 
691
        ps = (hw->conf.flags & IEEE80211_CONF_PS);
 
692
 
 
693
        /* we can sleep after ps null send ok */
 
694
        if (rtlpriv->psc.state_inap) {
 
695
                rtl_swlps_rf_sleep(hw);
 
696
 
 
697
                if (rtlpriv->psc.state && !ps) {
 
698
                        rtlpriv->psc.sleep_ms = jiffies_to_msecs(jiffies -
 
699
                                        rtlpriv->psc.last_action);
 
700
                }
 
701
 
 
702
                if (ps)
 
703
                        rtlpriv->psc.last_slept = jiffies;
 
704
 
 
705
                rtlpriv->psc.last_action = jiffies;
 
706
                rtlpriv->psc.state = ps;
 
707
        }
 
708
}