Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /* Copyright(c) 2009-2012  Realtek Corporation.*/
0003 
0004 #include "wifi.h"
0005 #include "base.h"
0006 #include "ps.h"
0007 #include <linux/export.h>
0008 #include "btcoexist/rtl_btc.h"
0009 
0010 bool rtl_ps_enable_nic(struct ieee80211_hw *hw)
0011 {
0012     struct rtl_priv *rtlpriv = rtl_priv(hw);
0013     struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
0014     struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
0015     struct rtl_mac *rtlmac = rtl_mac(rtl_priv(hw));
0016 
0017     /*<1> reset trx ring */
0018     if (rtlhal->interface == INTF_PCI)
0019         rtlpriv->intf_ops->reset_trx_ring(hw);
0020 
0021     if (is_hal_stop(rtlhal))
0022         rtl_dbg(rtlpriv, COMP_ERR, DBG_WARNING,
0023             "Driver is already down!\n");
0024 
0025     /*<2> Enable Adapter */
0026     if (rtlpriv->cfg->ops->hw_init(hw))
0027         return false;
0028     rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RETRY_LIMIT,
0029             &rtlmac->retry_long);
0030     RT_CLEAR_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC);
0031 
0032     rtlpriv->cfg->ops->switch_channel(hw);
0033     rtlpriv->cfg->ops->set_channel_access(hw);
0034     rtlpriv->cfg->ops->set_bw_mode(hw,
0035             cfg80211_get_chandef_type(&hw->conf.chandef));
0036 
0037     /*<3> Enable Interrupt */
0038     rtlpriv->cfg->ops->enable_interrupt(hw);
0039 
0040     /*<enable timer> */
0041     rtl_watch_dog_timer_callback(&rtlpriv->works.watchdog_timer);
0042 
0043     return true;
0044 }
0045 EXPORT_SYMBOL(rtl_ps_enable_nic);
0046 
0047 bool rtl_ps_disable_nic(struct ieee80211_hw *hw)
0048 {
0049     struct rtl_priv *rtlpriv = rtl_priv(hw);
0050 
0051     /*<1> Stop all timer */
0052     rtl_deinit_deferred_work(hw, true);
0053 
0054     /*<2> Disable Interrupt */
0055     rtlpriv->cfg->ops->disable_interrupt(hw);
0056     tasklet_kill(&rtlpriv->works.irq_tasklet);
0057 
0058     /*<3> Disable Adapter */
0059     rtlpriv->cfg->ops->hw_disable(hw);
0060 
0061     return true;
0062 }
0063 EXPORT_SYMBOL(rtl_ps_disable_nic);
0064 
0065 static bool rtl_ps_set_rf_state(struct ieee80211_hw *hw,
0066                 enum rf_pwrstate state_toset,
0067                 u32 changesource)
0068 {
0069     struct rtl_priv *rtlpriv = rtl_priv(hw);
0070     struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
0071     bool actionallowed = false;
0072     u16 rfwait_cnt = 0;
0073 
0074     /*Only one thread can change
0075      *the RF state at one time, and others
0076      *should wait to be executed.
0077      */
0078     while (true) {
0079         spin_lock(&rtlpriv->locks.rf_ps_lock);
0080         if (ppsc->rfchange_inprogress) {
0081             spin_unlock(&rtlpriv->locks.rf_ps_lock);
0082 
0083             rtl_dbg(rtlpriv, COMP_ERR, DBG_WARNING,
0084                 "RF Change in progress! Wait to set..state_toset(%d).\n",
0085                 state_toset);
0086 
0087             /* Set RF after the previous action is done.  */
0088             while (ppsc->rfchange_inprogress) {
0089                 rfwait_cnt++;
0090                 mdelay(1);
0091                 /*Wait too long, return false to avoid
0092                  *to be stuck here.
0093                  */
0094                 if (rfwait_cnt > 100)
0095                     return false;
0096             }
0097         } else {
0098             ppsc->rfchange_inprogress = true;
0099             spin_unlock(&rtlpriv->locks.rf_ps_lock);
0100             break;
0101         }
0102     }
0103 
0104     switch (state_toset) {
0105     case ERFON:
0106         ppsc->rfoff_reason &= (~changesource);
0107 
0108         if ((changesource == RF_CHANGE_BY_HW) &&
0109             (ppsc->hwradiooff)) {
0110             ppsc->hwradiooff = false;
0111         }
0112 
0113         if (!ppsc->rfoff_reason) {
0114             ppsc->rfoff_reason = 0;
0115             actionallowed = true;
0116         }
0117 
0118         break;
0119 
0120     case ERFOFF:
0121 
0122         if ((changesource == RF_CHANGE_BY_HW) && !ppsc->hwradiooff) {
0123             ppsc->hwradiooff = true;
0124         }
0125 
0126         ppsc->rfoff_reason |= changesource;
0127         actionallowed = true;
0128         break;
0129 
0130     case ERFSLEEP:
0131         ppsc->rfoff_reason |= changesource;
0132         actionallowed = true;
0133         break;
0134 
0135     default:
0136         pr_err("switch case %#x not processed\n", state_toset);
0137         break;
0138     }
0139 
0140     if (actionallowed)
0141         rtlpriv->cfg->ops->set_rf_power_state(hw, state_toset);
0142 
0143     spin_lock(&rtlpriv->locks.rf_ps_lock);
0144     ppsc->rfchange_inprogress = false;
0145     spin_unlock(&rtlpriv->locks.rf_ps_lock);
0146 
0147     return actionallowed;
0148 }
0149 
0150 static void _rtl_ps_inactive_ps(struct ieee80211_hw *hw)
0151 {
0152     struct rtl_priv *rtlpriv = rtl_priv(hw);
0153     struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
0154     struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
0155 
0156     ppsc->swrf_processing = true;
0157 
0158     if (ppsc->inactive_pwrstate == ERFON &&
0159         rtlhal->interface == INTF_PCI) {
0160         if ((ppsc->reg_rfps_level & RT_RF_OFF_LEVL_ASPM) &&
0161             RT_IN_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM)) {
0162             rtlpriv->intf_ops->disable_aspm(hw);
0163             RT_CLEAR_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM);
0164         }
0165     }
0166 
0167     rtl_ps_set_rf_state(hw, ppsc->inactive_pwrstate,
0168                 RF_CHANGE_BY_IPS);
0169 
0170     if (ppsc->inactive_pwrstate == ERFOFF &&
0171         rtlhal->interface == INTF_PCI) {
0172         if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_ASPM &&
0173             !RT_IN_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM)) {
0174             rtlpriv->intf_ops->enable_aspm(hw);
0175             RT_SET_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM);
0176         }
0177     }
0178 
0179     ppsc->swrf_processing = false;
0180 }
0181 
0182 void rtl_ips_nic_off_wq_callback(struct work_struct *work)
0183 {
0184     struct rtl_works *rtlworks = container_of(work, struct rtl_works,
0185                           ips_nic_off_wq.work);
0186     struct ieee80211_hw *hw = rtlworks->hw;
0187     struct rtl_priv *rtlpriv = rtl_priv(hw);
0188     struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
0189     struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
0190     struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
0191     enum rf_pwrstate rtstate;
0192 
0193     if (mac->opmode != NL80211_IFTYPE_STATION) {
0194         rtl_dbg(rtlpriv, COMP_ERR, DBG_WARNING,
0195             "not station return\n");
0196         return;
0197     }
0198 
0199     if (mac->p2p_in_use)
0200         return;
0201 
0202     if (mac->link_state > MAC80211_NOLINK)
0203         return;
0204 
0205     if (is_hal_stop(rtlhal))
0206         return;
0207 
0208     if (rtlpriv->sec.being_setkey)
0209         return;
0210 
0211     if (rtlpriv->cfg->ops->bt_coex_off_before_lps)
0212         rtlpriv->cfg->ops->bt_coex_off_before_lps(hw);
0213 
0214     if (ppsc->inactiveps) {
0215         rtstate = ppsc->rfpwr_state;
0216 
0217         /*
0218          *Do not enter IPS in the following conditions:
0219          *(1) RF is already OFF or Sleep
0220          *(2) swrf_processing (indicates the IPS is still under going)
0221          *(3) Connectted (only disconnected can trigger IPS)
0222          *(4) IBSS (send Beacon)
0223          *(5) AP mode (send Beacon)
0224          *(6) monitor mode (rcv packet)
0225          */
0226 
0227         if (rtstate == ERFON &&
0228             !ppsc->swrf_processing &&
0229             (mac->link_state == MAC80211_NOLINK) &&
0230             !mac->act_scanning) {
0231             rtl_dbg(rtlpriv, COMP_RF, DBG_TRACE,
0232                 "IPSEnter(): Turn off RF\n");
0233 
0234             ppsc->inactive_pwrstate = ERFOFF;
0235             ppsc->in_powersavemode = true;
0236 
0237             /* call before RF off */
0238             if (rtlpriv->cfg->ops->get_btc_status())
0239                 rtlpriv->btcoexist.btc_ops->btc_ips_notify(rtlpriv,
0240                                     ppsc->inactive_pwrstate);
0241 
0242             /*rtl_pci_reset_trx_ring(hw); */
0243             _rtl_ps_inactive_ps(hw);
0244         }
0245     }
0246 }
0247 
0248 void rtl_ips_nic_off(struct ieee80211_hw *hw)
0249 {
0250     struct rtl_priv *rtlpriv = rtl_priv(hw);
0251 
0252     /* because when link with ap, mac80211 will ask us
0253      * to disable nic quickly after scan before linking,
0254      * this will cause link failed, so we delay 100ms here
0255      */
0256     queue_delayed_work(rtlpriv->works.rtl_wq,
0257                &rtlpriv->works.ips_nic_off_wq, MSECS(100));
0258 }
0259 
0260 /* NOTICE: any opmode should exc nic_on, or disable without
0261  * nic_on may something wrong, like adhoc TP
0262  */
0263 void rtl_ips_nic_on(struct ieee80211_hw *hw)
0264 {
0265     struct rtl_priv *rtlpriv = rtl_priv(hw);
0266     struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
0267     enum rf_pwrstate rtstate;
0268 
0269     cancel_delayed_work_sync(&rtlpriv->works.ips_nic_off_wq);
0270 
0271     mutex_lock(&rtlpriv->locks.ips_mutex);
0272     if (ppsc->inactiveps) {
0273         rtstate = ppsc->rfpwr_state;
0274 
0275         if (rtstate != ERFON &&
0276             !ppsc->swrf_processing &&
0277             ppsc->rfoff_reason <= RF_CHANGE_BY_IPS) {
0278 
0279             ppsc->inactive_pwrstate = ERFON;
0280             ppsc->in_powersavemode = false;
0281             _rtl_ps_inactive_ps(hw);
0282             /* call after RF on */
0283             if (rtlpriv->cfg->ops->get_btc_status())
0284                 rtlpriv->btcoexist.btc_ops->btc_ips_notify(rtlpriv,
0285                                     ppsc->inactive_pwrstate);
0286         }
0287     }
0288     mutex_unlock(&rtlpriv->locks.ips_mutex);
0289 }
0290 EXPORT_SYMBOL_GPL(rtl_ips_nic_on);
0291 
0292 /*for FW LPS*/
0293 
0294 /*
0295  *Determine if we can set Fw into PS mode
0296  *in current condition.Return TRUE if it
0297  *can enter PS mode.
0298  */
0299 static bool rtl_get_fwlps_doze(struct ieee80211_hw *hw)
0300 {
0301     struct rtl_priv *rtlpriv = rtl_priv(hw);
0302     struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
0303     struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
0304     u32 ps_timediff;
0305 
0306     ps_timediff = jiffies_to_msecs(jiffies -
0307                        ppsc->last_delaylps_stamp_jiffies);
0308 
0309     if (ps_timediff < 2000) {
0310         rtl_dbg(rtlpriv, COMP_POWER, DBG_LOUD,
0311             "Delay enter Fw LPS for DHCP, ARP, or EAPOL exchanging state\n");
0312         return false;
0313     }
0314 
0315     if (mac->link_state != MAC80211_LINKED)
0316         return false;
0317 
0318     if (mac->opmode == NL80211_IFTYPE_ADHOC)
0319         return false;
0320 
0321     return true;
0322 }
0323 
0324 /* Change current and default preamble mode.*/
0325 void rtl_lps_set_psmode(struct ieee80211_hw *hw, u8 rt_psmode)
0326 {
0327     struct rtl_priv *rtlpriv = rtl_priv(hw);
0328     struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
0329     struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
0330     bool enter_fwlps;
0331 
0332     if (mac->opmode == NL80211_IFTYPE_ADHOC)
0333         return;
0334 
0335     if (mac->link_state != MAC80211_LINKED)
0336         return;
0337 
0338     if (ppsc->dot11_psmode == rt_psmode && rt_psmode == EACTIVE)
0339         return;
0340 
0341     /* Update power save mode configured. */
0342     ppsc->dot11_psmode = rt_psmode;
0343 
0344     /*
0345      *<FW control LPS>
0346      *1. Enter PS mode
0347      *   Set RPWM to Fw to turn RF off and send H2C fw_pwrmode
0348      *   cmd to set Fw into PS mode.
0349      *2. Leave PS mode
0350      *   Send H2C fw_pwrmode cmd to Fw to set Fw into Active
0351      *   mode and set RPWM to turn RF on.
0352      */
0353 
0354     if ((ppsc->fwctrl_lps) && ppsc->report_linked) {
0355         if (ppsc->dot11_psmode == EACTIVE) {
0356             rtl_dbg(rtlpriv, COMP_RF, DBG_DMESG,
0357                 "FW LPS leave ps_mode:%x\n",
0358                 FW_PS_ACTIVE_MODE);
0359             enter_fwlps = false;
0360             ppsc->pwr_mode = FW_PS_ACTIVE_MODE;
0361             ppsc->smart_ps = 0;
0362             rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_FW_LPS_ACTION,
0363                               (u8 *)(&enter_fwlps));
0364             if (ppsc->p2p_ps_info.opp_ps)
0365                 rtl_p2p_ps_cmd(hw , P2P_PS_ENABLE);
0366 
0367             if (rtlpriv->cfg->ops->get_btc_status())
0368                 rtlpriv->btcoexist.btc_ops->btc_lps_notify(rtlpriv, rt_psmode);
0369         } else {
0370             if (rtl_get_fwlps_doze(hw)) {
0371                 rtl_dbg(rtlpriv, COMP_RF, DBG_DMESG,
0372                     "FW LPS enter ps_mode:%x\n",
0373                     ppsc->fwctrl_psmode);
0374                 if (rtlpriv->cfg->ops->get_btc_status())
0375                     rtlpriv->btcoexist.btc_ops->btc_lps_notify(rtlpriv, rt_psmode);
0376                 enter_fwlps = true;
0377                 ppsc->pwr_mode = ppsc->fwctrl_psmode;
0378                 ppsc->smart_ps = 2;
0379                 rtlpriv->cfg->ops->set_hw_reg(hw,
0380                             HW_VAR_FW_LPS_ACTION,
0381                             (u8 *)(&enter_fwlps));
0382 
0383             } else {
0384                 /* Reset the power save related parameters. */
0385                 ppsc->dot11_psmode = EACTIVE;
0386             }
0387         }
0388     }
0389 }
0390 
0391 /* Interrupt safe routine to enter the leisure power save mode.*/
0392 static void rtl_lps_enter_core(struct ieee80211_hw *hw)
0393 {
0394     struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
0395     struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
0396     struct rtl_priv *rtlpriv = rtl_priv(hw);
0397 
0398     if (!ppsc->fwctrl_lps)
0399         return;
0400 
0401     if (rtlpriv->sec.being_setkey)
0402         return;
0403 
0404     if (rtlpriv->link_info.busytraffic)
0405         return;
0406 
0407     /*sleep after linked 10s, to let DHCP and 4-way handshake ok enough!! */
0408     if (mac->cnt_after_linked < 5)
0409         return;
0410 
0411     if (mac->opmode == NL80211_IFTYPE_ADHOC)
0412         return;
0413 
0414     if (mac->link_state != MAC80211_LINKED)
0415         return;
0416 
0417     mutex_lock(&rtlpriv->locks.lps_mutex);
0418 
0419     /* Don't need to check (ppsc->dot11_psmode == EACTIVE), because
0420      * bt_ccoexist may ask to enter lps.
0421      * In normal case, this constraint move to rtl_lps_set_psmode().
0422      */
0423     rtl_dbg(rtlpriv, COMP_POWER, DBG_LOUD,
0424         "Enter 802.11 power save mode...\n");
0425     rtl_lps_set_psmode(hw, EAUTOPS);
0426 
0427     mutex_unlock(&rtlpriv->locks.lps_mutex);
0428 }
0429 
0430 /* Interrupt safe routine to leave the leisure power save mode.*/
0431 static void rtl_lps_leave_core(struct ieee80211_hw *hw)
0432 {
0433     struct rtl_priv *rtlpriv = rtl_priv(hw);
0434     struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
0435     struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
0436 
0437     mutex_lock(&rtlpriv->locks.lps_mutex);
0438 
0439     if (ppsc->fwctrl_lps) {
0440         if (ppsc->dot11_psmode != EACTIVE) {
0441 
0442             /*FIX ME */
0443             /*rtlpriv->cfg->ops->enable_interrupt(hw); */
0444 
0445             if (ppsc->reg_rfps_level & RT_RF_LPS_LEVEL_ASPM &&
0446                 RT_IN_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM) &&
0447                 rtlhal->interface == INTF_PCI) {
0448                 rtlpriv->intf_ops->disable_aspm(hw);
0449                 RT_CLEAR_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM);
0450             }
0451 
0452             rtl_dbg(rtlpriv, COMP_POWER, DBG_LOUD,
0453                 "Busy Traffic,Leave 802.11 power save..\n");
0454 
0455             rtl_lps_set_psmode(hw, EACTIVE);
0456         }
0457     }
0458     mutex_unlock(&rtlpriv->locks.lps_mutex);
0459 }
0460 
0461 /* For sw LPS*/
0462 void rtl_swlps_beacon(struct ieee80211_hw *hw, void *data, unsigned int len)
0463 {
0464     struct rtl_priv *rtlpriv = rtl_priv(hw);
0465     struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
0466     struct ieee80211_hdr *hdr = data;
0467     struct ieee80211_tim_ie *tim_ie;
0468     u8 *tim;
0469     u8 tim_len;
0470     bool u_buffed;
0471     bool m_buffed;
0472 
0473     if (mac->opmode != NL80211_IFTYPE_STATION)
0474         return;
0475 
0476     if (!rtlpriv->psc.swctrl_lps)
0477         return;
0478 
0479     if (rtlpriv->mac80211.link_state != MAC80211_LINKED)
0480         return;
0481 
0482     if (!rtlpriv->psc.sw_ps_enabled)
0483         return;
0484 
0485     if (rtlpriv->psc.fwctrl_lps)
0486         return;
0487 
0488     if (likely(!(hw->conf.flags & IEEE80211_CONF_PS)))
0489         return;
0490 
0491     /* check if this really is a beacon */
0492     if (!ieee80211_is_beacon(hdr->frame_control))
0493         return;
0494 
0495     /* min. beacon length + FCS_LEN */
0496     if (len <= 40 + FCS_LEN)
0497         return;
0498 
0499     /* and only beacons from the associated BSSID, please */
0500     if (!ether_addr_equal_64bits(hdr->addr3, rtlpriv->mac80211.bssid))
0501         return;
0502 
0503     rtlpriv->psc.last_beacon = jiffies;
0504 
0505     tim = rtl_find_ie(data, len - FCS_LEN, WLAN_EID_TIM);
0506     if (!tim)
0507         return;
0508 
0509     if (tim[1] < sizeof(*tim_ie))
0510         return;
0511 
0512     tim_len = tim[1];
0513     tim_ie = (struct ieee80211_tim_ie *) &tim[2];
0514 
0515     if (!WARN_ON_ONCE(!hw->conf.ps_dtim_period))
0516         rtlpriv->psc.dtim_counter = tim_ie->dtim_count;
0517 
0518     /* Check whenever the PHY can be turned off again. */
0519 
0520     /* 1. What about buffered unicast traffic for our AID? */
0521     u_buffed = ieee80211_check_tim(tim_ie, tim_len,
0522                        rtlpriv->mac80211.assoc_id);
0523 
0524     /* 2. Maybe the AP wants to send multicast/broadcast data? */
0525     m_buffed = tim_ie->bitmap_ctrl & 0x01;
0526     rtlpriv->psc.multi_buffered = m_buffed;
0527 
0528     /* unicast will process by mac80211 through
0529      * set ~IEEE80211_CONF_PS, So we just check
0530      * multicast frames here */
0531     if (!m_buffed) {
0532         /* back to low-power land. and delay is
0533          * prevent null power save frame tx fail */
0534         queue_delayed_work(rtlpriv->works.rtl_wq,
0535                    &rtlpriv->works.ps_work, MSECS(5));
0536     } else {
0537         rtl_dbg(rtlpriv, COMP_POWER, DBG_DMESG,
0538             "u_bufferd: %x, m_buffered: %x\n", u_buffed, m_buffed);
0539     }
0540 }
0541 EXPORT_SYMBOL_GPL(rtl_swlps_beacon);
0542 
0543 void rtl_swlps_rf_awake(struct ieee80211_hw *hw)
0544 {
0545     struct rtl_priv *rtlpriv = rtl_priv(hw);
0546     struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
0547     struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
0548 
0549     if (!rtlpriv->psc.swctrl_lps)
0550         return;
0551     if (mac->link_state != MAC80211_LINKED)
0552         return;
0553 
0554     if (ppsc->reg_rfps_level & RT_RF_LPS_LEVEL_ASPM &&
0555         RT_IN_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM)) {
0556         rtlpriv->intf_ops->disable_aspm(hw);
0557         RT_CLEAR_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM);
0558     }
0559 
0560     mutex_lock(&rtlpriv->locks.lps_mutex);
0561     rtl_ps_set_rf_state(hw, ERFON, RF_CHANGE_BY_PS);
0562     mutex_unlock(&rtlpriv->locks.lps_mutex);
0563 }
0564 
0565 void rtl_swlps_rfon_wq_callback(struct work_struct *work)
0566 {
0567     struct rtl_works *rtlworks = container_of(work, struct rtl_works,
0568                           ps_rfon_wq.work);
0569     struct ieee80211_hw *hw = rtlworks->hw;
0570 
0571     rtl_swlps_rf_awake(hw);
0572 }
0573 
0574 void rtl_swlps_rf_sleep(struct ieee80211_hw *hw)
0575 {
0576     struct rtl_priv *rtlpriv = rtl_priv(hw);
0577     struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
0578     struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
0579     u8 sleep_intv;
0580 
0581     if (!rtlpriv->psc.sw_ps_enabled)
0582         return;
0583 
0584     if ((rtlpriv->sec.being_setkey) ||
0585         (mac->opmode == NL80211_IFTYPE_ADHOC))
0586         return;
0587 
0588     /*sleep after linked 10s, to let DHCP and 4-way handshake ok enough!! */
0589     if ((mac->link_state != MAC80211_LINKED) || (mac->cnt_after_linked < 5))
0590         return;
0591 
0592     if (rtlpriv->link_info.busytraffic)
0593         return;
0594 
0595     spin_lock(&rtlpriv->locks.rf_ps_lock);
0596     if (rtlpriv->psc.rfchange_inprogress) {
0597         spin_unlock(&rtlpriv->locks.rf_ps_lock);
0598         return;
0599     }
0600     spin_unlock(&rtlpriv->locks.rf_ps_lock);
0601 
0602     mutex_lock(&rtlpriv->locks.lps_mutex);
0603     rtl_ps_set_rf_state(hw, ERFSLEEP, RF_CHANGE_BY_PS);
0604     mutex_unlock(&rtlpriv->locks.lps_mutex);
0605 
0606     if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_ASPM &&
0607         !RT_IN_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM)) {
0608         rtlpriv->intf_ops->enable_aspm(hw);
0609         RT_SET_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM);
0610     }
0611 
0612     /* here is power save alg, when this beacon is DTIM
0613      * we will set sleep time to dtim_period * n;
0614      * when this beacon is not DTIM, we will set sleep
0615      * time to sleep_intv = rtlpriv->psc.dtim_counter or
0616      * MAX_SW_LPS_SLEEP_INTV(default set to 5) */
0617 
0618     if (rtlpriv->psc.dtim_counter == 0) {
0619         if (hw->conf.ps_dtim_period == 1)
0620             sleep_intv = hw->conf.ps_dtim_period * 2;
0621         else
0622             sleep_intv = hw->conf.ps_dtim_period;
0623     } else {
0624         sleep_intv = rtlpriv->psc.dtim_counter;
0625     }
0626 
0627     if (sleep_intv > MAX_SW_LPS_SLEEP_INTV)
0628         sleep_intv = MAX_SW_LPS_SLEEP_INTV;
0629 
0630     /* this print should always be dtim_conter = 0 &
0631      * sleep  = dtim_period, that meaons, we should
0632      * awake before every dtim */
0633     rtl_dbg(rtlpriv, COMP_POWER, DBG_DMESG,
0634         "dtim_counter:%x will sleep :%d beacon_intv\n",
0635         rtlpriv->psc.dtim_counter, sleep_intv);
0636 
0637     /* we tested that 40ms is enough for sw & hw sw delay */
0638     queue_delayed_work(rtlpriv->works.rtl_wq, &rtlpriv->works.ps_rfon_wq,
0639             MSECS(sleep_intv * mac->vif->bss_conf.beacon_int - 40));
0640 }
0641 
0642 void rtl_lps_change_work_callback(struct work_struct *work)
0643 {
0644     struct rtl_works *rtlworks =
0645         container_of(work, struct rtl_works, lps_change_work);
0646     struct ieee80211_hw *hw = rtlworks->hw;
0647     struct rtl_priv *rtlpriv = rtl_priv(hw);
0648 
0649     if (rtlpriv->enter_ps)
0650         rtl_lps_enter_core(hw);
0651     else
0652         rtl_lps_leave_core(hw);
0653 }
0654 EXPORT_SYMBOL_GPL(rtl_lps_change_work_callback);
0655 
0656 void rtl_lps_enter(struct ieee80211_hw *hw, bool may_block)
0657 {
0658     struct rtl_priv *rtlpriv = rtl_priv(hw);
0659 
0660     if (may_block)
0661         return rtl_lps_enter_core(hw);
0662     rtlpriv->enter_ps = true;
0663     schedule_work(&rtlpriv->works.lps_change_work);
0664 }
0665 EXPORT_SYMBOL_GPL(rtl_lps_enter);
0666 
0667 void rtl_lps_leave(struct ieee80211_hw *hw, bool may_block)
0668 {
0669     struct rtl_priv *rtlpriv = rtl_priv(hw);
0670 
0671     if (may_block)
0672         return rtl_lps_leave_core(hw);
0673     rtlpriv->enter_ps = false;
0674     schedule_work(&rtlpriv->works.lps_change_work);
0675 }
0676 EXPORT_SYMBOL_GPL(rtl_lps_leave);
0677 
0678 void rtl_swlps_wq_callback(struct work_struct *work)
0679 {
0680     struct rtl_works *rtlworks = container_of(work, struct rtl_works,
0681                           ps_work.work);
0682     struct ieee80211_hw *hw = rtlworks->hw;
0683     struct rtl_priv *rtlpriv = rtl_priv(hw);
0684     bool ps = false;
0685 
0686     ps = (hw->conf.flags & IEEE80211_CONF_PS);
0687 
0688     /* we can sleep after ps null send ok */
0689     if (rtlpriv->psc.state_inap) {
0690         rtl_swlps_rf_sleep(hw);
0691 
0692         if (rtlpriv->psc.state && !ps) {
0693             rtlpriv->psc.sleep_ms = jiffies_to_msecs(jiffies -
0694                          rtlpriv->psc.last_action);
0695         }
0696 
0697         if (ps)
0698             rtlpriv->psc.last_slept = jiffies;
0699 
0700         rtlpriv->psc.last_action = jiffies;
0701         rtlpriv->psc.state = ps;
0702     }
0703 }
0704 
0705 static void rtl_p2p_noa_ie(struct ieee80211_hw *hw, void *data,
0706                unsigned int len)
0707 {
0708     struct rtl_priv *rtlpriv = rtl_priv(hw);
0709     struct ieee80211_mgmt *mgmt = data;
0710     struct rtl_p2p_ps_info *p2pinfo = &(rtlpriv->psc.p2p_ps_info);
0711     u8 *pos, *end, *ie;
0712     u16 noa_len;
0713     static u8 p2p_oui_ie_type[4] = {0x50, 0x6f, 0x9a, 0x09};
0714     u8 noa_num, index , i, noa_index = 0;
0715     bool find_p2p_ie = false , find_p2p_ps_ie = false;
0716 
0717     pos = (u8 *)mgmt->u.beacon.variable;
0718     end = data + len;
0719     ie = NULL;
0720 
0721     while (pos + 1 < end) {
0722         if (pos + 2 + pos[1] > end)
0723             return;
0724 
0725         if (pos[0] == 221 && pos[1] > 4) {
0726             if (memcmp(&pos[2], p2p_oui_ie_type, 4) == 0) {
0727                 ie = pos + 2+4;
0728                 break;
0729             }
0730         }
0731         pos += 2 + pos[1];
0732     }
0733 
0734     if (ie == NULL)
0735         return;
0736     find_p2p_ie = true;
0737     /*to find noa ie*/
0738     while (ie + 1 < end) {
0739         noa_len = le16_to_cpu(*((__le16 *)&ie[1]));
0740         if (ie + 3 + ie[1] > end)
0741             return;
0742 
0743         if (ie[0] == 12) {
0744             find_p2p_ps_ie = true;
0745             if ((noa_len - 2) % 13 != 0) {
0746                 rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD,
0747                     "P2P notice of absence: invalid length.%d\n",
0748                     noa_len);
0749                 return;
0750             } else {
0751                 noa_num = (noa_len - 2) / 13;
0752                 if (noa_num > P2P_MAX_NOA_NUM)
0753                     noa_num = P2P_MAX_NOA_NUM;
0754 
0755             }
0756             noa_index = ie[3];
0757             if (rtlpriv->psc.p2p_ps_info.p2p_ps_mode ==
0758                 P2P_PS_NONE || noa_index != p2pinfo->noa_index) {
0759                 rtl_dbg(rtlpriv, COMP_FW, DBG_LOUD,
0760                     "update NOA ie.\n");
0761                 p2pinfo->noa_index = noa_index;
0762                 p2pinfo->opp_ps = (ie[4] >> 7);
0763                 p2pinfo->ctwindow = ie[4] & 0x7F;
0764                 p2pinfo->noa_num = noa_num;
0765                 index = 5;
0766                 for (i = 0; i < noa_num; i++) {
0767                     p2pinfo->noa_count_type[i] =
0768                      *(u8 *)(ie + index);
0769                     index += 1;
0770                     p2pinfo->noa_duration[i] =
0771                      le32_to_cpu(*(__le32 *)(ie + index));
0772                     index += 4;
0773                     p2pinfo->noa_interval[i] =
0774                      le32_to_cpu(*(__le32 *)(ie + index));
0775                     index += 4;
0776                     p2pinfo->noa_start_time[i] =
0777                      le32_to_cpu(*(__le32 *)(ie + index));
0778                     index += 4;
0779                 }
0780 
0781                 if (p2pinfo->opp_ps == 1) {
0782                     p2pinfo->p2p_ps_mode = P2P_PS_CTWINDOW;
0783                     /* Driver should wait LPS entering
0784                      * CTWindow
0785                      */
0786                     if (rtlpriv->psc.fw_current_inpsmode)
0787                         rtl_p2p_ps_cmd(hw,
0788                                    P2P_PS_ENABLE);
0789                 } else if (p2pinfo->noa_num > 0) {
0790                     p2pinfo->p2p_ps_mode = P2P_PS_NOA;
0791                     rtl_p2p_ps_cmd(hw, P2P_PS_ENABLE);
0792                 } else if (p2pinfo->p2p_ps_mode > P2P_PS_NONE) {
0793                     rtl_p2p_ps_cmd(hw, P2P_PS_DISABLE);
0794                 }
0795             }
0796             break;
0797         }
0798         ie += 3 + noa_len;
0799     }
0800 
0801     if (find_p2p_ie) {
0802         if ((p2pinfo->p2p_ps_mode > P2P_PS_NONE) &&
0803             (!find_p2p_ps_ie))
0804             rtl_p2p_ps_cmd(hw, P2P_PS_DISABLE);
0805     }
0806 }
0807 
0808 static void rtl_p2p_action_ie(struct ieee80211_hw *hw, void *data,
0809                   unsigned int len)
0810 {
0811     struct rtl_priv *rtlpriv = rtl_priv(hw);
0812     struct ieee80211_mgmt *mgmt = data;
0813     struct rtl_p2p_ps_info *p2pinfo = &(rtlpriv->psc.p2p_ps_info);
0814     u8 noa_num, index , i , noa_index = 0;
0815     u8 *pos, *end, *ie;
0816     u16 noa_len;
0817     static u8 p2p_oui_ie_type[4] = {0x50, 0x6f, 0x9a, 0x09};
0818 
0819     pos = (u8 *)&mgmt->u.action.category;
0820     end = data + len;
0821     ie = NULL;
0822 
0823     if (pos[0] == 0x7f) {
0824         if (memcmp(&pos[1], p2p_oui_ie_type, 4) == 0)
0825             ie = pos + 3+4;
0826     }
0827 
0828     if (ie == NULL)
0829         return;
0830 
0831     rtl_dbg(rtlpriv, COMP_FW, DBG_LOUD, "action frame find P2P IE.\n");
0832     /*to find noa ie*/
0833     while (ie + 1 < end) {
0834         noa_len = le16_to_cpu(*(__le16 *)&ie[1]);
0835         if (ie + 3 + ie[1] > end)
0836             return;
0837 
0838         if (ie[0] == 12) {
0839             rtl_dbg(rtlpriv, COMP_FW, DBG_LOUD, "find NOA IE.\n");
0840             RT_PRINT_DATA(rtlpriv, COMP_FW, DBG_LOUD, "noa ie ",
0841                       ie, noa_len);
0842             if ((noa_len - 2) % 13 != 0) {
0843                 rtl_dbg(rtlpriv, COMP_FW, DBG_LOUD,
0844                     "P2P notice of absence: invalid length.%d\n",
0845                     noa_len);
0846                 return;
0847             } else {
0848                 noa_num = (noa_len - 2) / 13;
0849                 if (noa_num > P2P_MAX_NOA_NUM)
0850                     noa_num = P2P_MAX_NOA_NUM;
0851 
0852             }
0853             noa_index = ie[3];
0854             if (rtlpriv->psc.p2p_ps_info.p2p_ps_mode ==
0855                 P2P_PS_NONE || noa_index != p2pinfo->noa_index) {
0856                 p2pinfo->noa_index = noa_index;
0857                 p2pinfo->opp_ps = (ie[4] >> 7);
0858                 p2pinfo->ctwindow = ie[4] & 0x7F;
0859                 p2pinfo->noa_num = noa_num;
0860                 index = 5;
0861                 for (i = 0; i < noa_num; i++) {
0862                     p2pinfo->noa_count_type[i] =
0863                      *(u8 *)(ie + index);
0864                     index += 1;
0865                     p2pinfo->noa_duration[i] =
0866                      le32_to_cpu(*(__le32 *)(ie + index));
0867                     index += 4;
0868                     p2pinfo->noa_interval[i] =
0869                      le32_to_cpu(*(__le32 *)(ie + index));
0870                     index += 4;
0871                     p2pinfo->noa_start_time[i] =
0872                      le32_to_cpu(*(__le32 *)(ie + index));
0873                     index += 4;
0874                 }
0875 
0876                 if (p2pinfo->opp_ps == 1) {
0877                     p2pinfo->p2p_ps_mode = P2P_PS_CTWINDOW;
0878                     /* Driver should wait LPS entering
0879                      * CTWindow
0880                      */
0881                     if (rtlpriv->psc.fw_current_inpsmode)
0882                         rtl_p2p_ps_cmd(hw,
0883                                    P2P_PS_ENABLE);
0884                 } else if (p2pinfo->noa_num > 0) {
0885                     p2pinfo->p2p_ps_mode = P2P_PS_NOA;
0886                     rtl_p2p_ps_cmd(hw, P2P_PS_ENABLE);
0887                 } else if (p2pinfo->p2p_ps_mode > P2P_PS_NONE) {
0888                     rtl_p2p_ps_cmd(hw, P2P_PS_DISABLE);
0889                 }
0890             }
0891             break;
0892         }
0893         ie += 3 + noa_len;
0894     }
0895 }
0896 
0897 void rtl_p2p_ps_cmd(struct ieee80211_hw *hw , u8 p2p_ps_state)
0898 {
0899     struct rtl_priv *rtlpriv = rtl_priv(hw);
0900     struct rtl_ps_ctl *rtlps = rtl_psc(rtl_priv(hw));
0901     struct rtl_p2p_ps_info  *p2pinfo = &(rtlpriv->psc.p2p_ps_info);
0902 
0903     rtl_dbg(rtlpriv, COMP_FW, DBG_LOUD, " p2p state %x\n", p2p_ps_state);
0904     switch (p2p_ps_state) {
0905     case P2P_PS_DISABLE:
0906         p2pinfo->p2p_ps_state = p2p_ps_state;
0907         rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_H2C_FW_P2P_PS_OFFLOAD,
0908                           &p2p_ps_state);
0909         p2pinfo->noa_index = 0;
0910         p2pinfo->ctwindow = 0;
0911         p2pinfo->opp_ps = 0;
0912         p2pinfo->noa_num = 0;
0913         p2pinfo->p2p_ps_mode = P2P_PS_NONE;
0914         if (rtlps->fw_current_inpsmode) {
0915             if (rtlps->smart_ps == 0) {
0916                 rtlps->smart_ps = 2;
0917                 rtlpriv->cfg->ops->set_hw_reg(hw,
0918                      HW_VAR_H2C_FW_PWRMODE,
0919                      &rtlps->pwr_mode);
0920             }
0921 
0922         }
0923         break;
0924     case P2P_PS_ENABLE:
0925         if (p2pinfo->p2p_ps_mode > P2P_PS_NONE) {
0926             p2pinfo->p2p_ps_state = p2p_ps_state;
0927 
0928             if (p2pinfo->ctwindow > 0) {
0929                 if (rtlps->smart_ps != 0) {
0930                     rtlps->smart_ps = 0;
0931                     rtlpriv->cfg->ops->set_hw_reg(hw,
0932                          HW_VAR_H2C_FW_PWRMODE,
0933                          &rtlps->pwr_mode);
0934                 }
0935             }
0936             rtlpriv->cfg->ops->set_hw_reg(hw,
0937                  HW_VAR_H2C_FW_P2P_PS_OFFLOAD,
0938                  &p2p_ps_state);
0939 
0940         }
0941         break;
0942     case P2P_PS_SCAN:
0943     case P2P_PS_SCAN_DONE:
0944     case P2P_PS_ALLSTASLEEP:
0945         if (p2pinfo->p2p_ps_mode > P2P_PS_NONE) {
0946             p2pinfo->p2p_ps_state = p2p_ps_state;
0947             rtlpriv->cfg->ops->set_hw_reg(hw,
0948                  HW_VAR_H2C_FW_P2P_PS_OFFLOAD,
0949                  &p2p_ps_state);
0950         }
0951         break;
0952     default:
0953         break;
0954     }
0955     rtl_dbg(rtlpriv, COMP_FW, DBG_LOUD,
0956         "ctwindow %x oppps %x\n",
0957         p2pinfo->ctwindow, p2pinfo->opp_ps);
0958     rtl_dbg(rtlpriv, COMP_FW, DBG_LOUD,
0959         "count %x duration %x index %x interval %x start time %x noa num %x\n",
0960         p2pinfo->noa_count_type[0],
0961         p2pinfo->noa_duration[0],
0962         p2pinfo->noa_index,
0963         p2pinfo->noa_interval[0],
0964         p2pinfo->noa_start_time[0],
0965         p2pinfo->noa_num);
0966     rtl_dbg(rtlpriv, COMP_FW, DBG_LOUD, "end\n");
0967 }
0968 
0969 void rtl_p2p_info(struct ieee80211_hw *hw, void *data, unsigned int len)
0970 {
0971     struct rtl_priv *rtlpriv = rtl_priv(hw);
0972     struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
0973     struct ieee80211_hdr *hdr = data;
0974 
0975     if (!mac->p2p)
0976         return;
0977     if (mac->link_state != MAC80211_LINKED)
0978         return;
0979     /* min. beacon length + FCS_LEN */
0980     if (len <= 40 + FCS_LEN)
0981         return;
0982 
0983     /* and only beacons from the associated BSSID, please */
0984     if (!ether_addr_equal_64bits(hdr->addr3, rtlpriv->mac80211.bssid))
0985         return;
0986 
0987     /* check if this really is a beacon */
0988     if (!(ieee80211_is_beacon(hdr->frame_control) ||
0989           ieee80211_is_probe_resp(hdr->frame_control) ||
0990           ieee80211_is_action(hdr->frame_control)))
0991         return;
0992 
0993     if (ieee80211_is_action(hdr->frame_control))
0994         rtl_p2p_action_ie(hw , data , len - FCS_LEN);
0995     else
0996         rtl_p2p_noa_ie(hw , data , len - FCS_LEN);
0997 }
0998 EXPORT_SYMBOL_GPL(rtl_p2p_info);