diff options
| author | John W. Linville <linville@tuxdriver.com> | 2011-05-05 13:32:35 -0400 |
|---|---|---|
| committer | John W. Linville <linville@tuxdriver.com> | 2011-05-05 13:32:35 -0400 |
| commit | a70171dce9cd44cb06c7d299eba9fa87a8933045 (patch) | |
| tree | 5425df5f33fadc617c7dec99578d06f0d933578e /drivers/net/wireless/rtlwifi/ps.c | |
| parent | 5a412ad7f4c95bb5b756aa12b52646e857e7c75d (diff) | |
| parent | eaef6a93bd52a2cc47b9fce201310010707afdb4 (diff) | |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6 into for-davem
Conflicts:
drivers/net/wireless/libertas/if_cs.c
drivers/net/wireless/rtlwifi/pci.c
net/bluetooth/l2cap_sock.c
Diffstat (limited to 'drivers/net/wireless/rtlwifi/ps.c')
| -rw-r--r-- | drivers/net/wireless/rtlwifi/ps.c | 258 |
1 files changed, 237 insertions, 21 deletions
diff --git a/drivers/net/wireless/rtlwifi/ps.c b/drivers/net/wireless/rtlwifi/ps.c index c8395fb0c050..2bb71195e976 100644 --- a/drivers/net/wireless/rtlwifi/ps.c +++ b/drivers/net/wireless/rtlwifi/ps.c | |||
| @@ -36,7 +36,6 @@ bool rtl_ps_enable_nic(struct ieee80211_hw *hw) | |||
| 36 | struct rtl_priv *rtlpriv = rtl_priv(hw); | 36 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
| 37 | struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); | 37 | struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); |
| 38 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | 38 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); |
| 39 | bool init_status = true; | ||
| 40 | 39 | ||
| 41 | /*<1> reset trx ring */ | 40 | /*<1> reset trx ring */ |
| 42 | if (rtlhal->interface == INTF_PCI) | 41 | if (rtlhal->interface == INTF_PCI) |
| @@ -49,7 +48,6 @@ bool rtl_ps_enable_nic(struct ieee80211_hw *hw) | |||
| 49 | /*<2> Enable Adapter */ | 48 | /*<2> Enable Adapter */ |
| 50 | rtlpriv->cfg->ops->hw_init(hw); | 49 | rtlpriv->cfg->ops->hw_init(hw); |
| 51 | RT_CLEAR_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC); | 50 | RT_CLEAR_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC); |
| 52 | /*init_status = false; */ | ||
| 53 | 51 | ||
| 54 | /*<3> Enable Interrupt */ | 52 | /*<3> Enable Interrupt */ |
| 55 | rtlpriv->cfg->ops->enable_interrupt(hw); | 53 | rtlpriv->cfg->ops->enable_interrupt(hw); |
| @@ -57,7 +55,7 @@ bool rtl_ps_enable_nic(struct ieee80211_hw *hw) | |||
| 57 | /*<enable timer> */ | 55 | /*<enable timer> */ |
| 58 | rtl_watch_dog_timer_callback((unsigned long)hw); | 56 | rtl_watch_dog_timer_callback((unsigned long)hw); |
| 59 | 57 | ||
| 60 | return init_status; | 58 | return true; |
| 61 | } | 59 | } |
| 62 | EXPORT_SYMBOL(rtl_ps_enable_nic); | 60 | EXPORT_SYMBOL(rtl_ps_enable_nic); |
| 63 | 61 | ||
| @@ -192,12 +190,13 @@ static void _rtl_ps_inactive_ps(struct ieee80211_hw *hw) | |||
| 192 | 190 | ||
| 193 | ppsc->swrf_processing = true; | 191 | ppsc->swrf_processing = true; |
| 194 | 192 | ||
| 195 | if (ppsc->inactive_pwrstate == ERFON && rtlhal->interface == INTF_PCI) { | 193 | if (ppsc->inactive_pwrstate == ERFOFF && |
| 194 | rtlhal->interface == INTF_PCI) { | ||
| 196 | if ((ppsc->reg_rfps_level & RT_RF_OFF_LEVL_ASPM) && | 195 | if ((ppsc->reg_rfps_level & RT_RF_OFF_LEVL_ASPM) && |
| 197 | RT_IN_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_ASPM) && | 196 | RT_IN_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM) && |
| 198 | rtlhal->interface == INTF_PCI) { | 197 | rtlhal->interface == INTF_PCI) { |
| 199 | rtlpriv->intf_ops->disable_aspm(hw); | 198 | rtlpriv->intf_ops->disable_aspm(hw); |
| 200 | RT_CLEAR_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_ASPM); | 199 | RT_CLEAR_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM); |
| 201 | } | 200 | } |
| 202 | } | 201 | } |
| 203 | 202 | ||
| @@ -206,9 +205,10 @@ static void _rtl_ps_inactive_ps(struct ieee80211_hw *hw) | |||
| 206 | 205 | ||
| 207 | if (ppsc->inactive_pwrstate == ERFOFF && | 206 | if (ppsc->inactive_pwrstate == ERFOFF && |
| 208 | rtlhal->interface == INTF_PCI) { | 207 | rtlhal->interface == INTF_PCI) { |
| 209 | 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)) { | ||
| 210 | rtlpriv->intf_ops->enable_aspm(hw); | 210 | rtlpriv->intf_ops->enable_aspm(hw); |
| 211 | RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_ASPM); | 211 | RT_SET_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM); |
| 212 | } | 212 | } |
| 213 | } | 213 | } |
| 214 | 214 | ||
| @@ -232,6 +232,9 @@ void rtl_ips_nic_off_wq_callback(void *data) | |||
| 232 | return; | 232 | return; |
| 233 | } | 233 | } |
| 234 | 234 | ||
| 235 | if (mac->link_state > MAC80211_NOLINK) | ||
| 236 | return; | ||
| 237 | |||
| 235 | if (is_hal_stop(rtlhal)) | 238 | if (is_hal_stop(rtlhal)) |
| 236 | return; | 239 | return; |
| 237 | 240 | ||
| @@ -283,10 +286,14 @@ void rtl_ips_nic_off(struct ieee80211_hw *hw) | |||
| 283 | void rtl_ips_nic_on(struct ieee80211_hw *hw) | 286 | void rtl_ips_nic_on(struct ieee80211_hw *hw) |
| 284 | { | 287 | { |
| 285 | struct rtl_priv *rtlpriv = rtl_priv(hw); | 288 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
| 289 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); | ||
| 286 | struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); | 290 | struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); |
| 287 | enum rf_pwrstate rtstate; | 291 | enum rf_pwrstate rtstate; |
| 288 | unsigned long flags; | 292 | unsigned long flags; |
| 289 | 293 | ||
| 294 | if (mac->opmode != NL80211_IFTYPE_STATION) | ||
| 295 | return; | ||
| 296 | |||
| 290 | spin_lock_irqsave(&rtlpriv->locks.ips_lock, flags); | 297 | spin_lock_irqsave(&rtlpriv->locks.ips_lock, flags); |
| 291 | 298 | ||
| 292 | if (ppsc->inactiveps) { | 299 | if (ppsc->inactiveps) { |
| @@ -369,8 +376,7 @@ static void rtl_lps_set_psmode(struct ieee80211_hw *hw, u8 rt_psmode) | |||
| 369 | * mode and set RPWM to turn RF on. | 376 | * mode and set RPWM to turn RF on. |
| 370 | */ | 377 | */ |
| 371 | 378 | ||
| 372 | if ((ppsc->fwctrl_lps) && (ppsc->leisure_ps) && | 379 | if ((ppsc->fwctrl_lps) && ppsc->report_linked) { |
| 373 | ppsc->report_linked) { | ||
| 374 | bool fw_current_inps; | 380 | bool fw_current_inps; |
| 375 | if (ppsc->dot11_psmode == EACTIVE) { | 381 | if (ppsc->dot11_psmode == EACTIVE) { |
| 376 | RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, | 382 | RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, |
| @@ -424,7 +430,7 @@ void rtl_lps_enter(struct ieee80211_hw *hw) | |||
| 424 | struct rtl_priv *rtlpriv = rtl_priv(hw); | 430 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
| 425 | unsigned long flag; | 431 | unsigned long flag; |
| 426 | 432 | ||
| 427 | if (!(ppsc->fwctrl_lps && ppsc->leisure_ps)) | 433 | if (!ppsc->fwctrl_lps) |
| 428 | return; | 434 | return; |
| 429 | 435 | ||
| 430 | if (rtlpriv->sec.being_setkey) | 436 | if (rtlpriv->sec.being_setkey) |
| @@ -445,17 +451,16 @@ void rtl_lps_enter(struct ieee80211_hw *hw) | |||
| 445 | 451 | ||
| 446 | spin_lock_irqsave(&rtlpriv->locks.lps_lock, flag); | 452 | spin_lock_irqsave(&rtlpriv->locks.lps_lock, flag); |
| 447 | 453 | ||
| 448 | if (ppsc->leisure_ps) { | 454 | /* Idle for a while if we connect to AP a while ago. */ |
| 449 | /* Idle for a while if we connect to AP a while ago. */ | 455 | if (mac->cnt_after_linked >= 2) { |
| 450 | if (mac->cnt_after_linked >= 2) { | 456 | if (ppsc->dot11_psmode == EACTIVE) { |
| 451 | if (ppsc->dot11_psmode == EACTIVE) { | 457 | RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, |
| 452 | RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, | ||
| 453 | ("Enter 802.11 power save mode...\n")); | 458 | ("Enter 802.11 power save mode...\n")); |
| 454 | 459 | ||
| 455 | rtl_lps_set_psmode(hw, EAUTOPS); | 460 | rtl_lps_set_psmode(hw, EAUTOPS); |
| 456 | } | ||
| 457 | } | 461 | } |
| 458 | } | 462 | } |
| 463 | |||
| 459 | spin_unlock_irqrestore(&rtlpriv->locks.lps_lock, flag); | 464 | spin_unlock_irqrestore(&rtlpriv->locks.lps_lock, flag); |
| 460 | } | 465 | } |
| 461 | 466 | ||
| @@ -469,17 +474,17 @@ void rtl_lps_leave(struct ieee80211_hw *hw) | |||
| 469 | 474 | ||
| 470 | spin_lock_irqsave(&rtlpriv->locks.lps_lock, flag); | 475 | spin_lock_irqsave(&rtlpriv->locks.lps_lock, flag); |
| 471 | 476 | ||
| 472 | if (ppsc->fwctrl_lps && ppsc->leisure_ps) { | 477 | if (ppsc->fwctrl_lps) { |
| 473 | if (ppsc->dot11_psmode != EACTIVE) { | 478 | if (ppsc->dot11_psmode != EACTIVE) { |
| 474 | 479 | ||
| 475 | /*FIX ME */ | 480 | /*FIX ME */ |
| 476 | rtlpriv->cfg->ops->enable_interrupt(hw); | 481 | rtlpriv->cfg->ops->enable_interrupt(hw); |
| 477 | 482 | ||
| 478 | if (ppsc->reg_rfps_level & RT_RF_LPS_LEVEL_ASPM && | 483 | if (ppsc->reg_rfps_level & RT_RF_LPS_LEVEL_ASPM && |
| 479 | RT_IN_PS_LEVEL(ppsc, RT_RF_LPS_LEVEL_ASPM) && | 484 | RT_IN_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM) && |
| 480 | rtlhal->interface == INTF_PCI) { | 485 | rtlhal->interface == INTF_PCI) { |
| 481 | rtlpriv->intf_ops->disable_aspm(hw); | 486 | rtlpriv->intf_ops->disable_aspm(hw); |
| 482 | RT_CLEAR_PS_LEVEL(ppsc, RT_RF_LPS_LEVEL_ASPM); | 487 | RT_CLEAR_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM); |
| 483 | } | 488 | } |
| 484 | 489 | ||
| 485 | RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, | 490 | RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, |
| @@ -490,3 +495,214 @@ void rtl_lps_leave(struct ieee80211_hw *hw) | |||
| 490 | } | 495 | } |
| 491 | spin_unlock_irqrestore(&rtlpriv->locks.lps_lock, flag); | 496 | spin_unlock_irqrestore(&rtlpriv->locks.lps_lock, flag); |
| 492 | } | 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 | } | ||
