/*Only one thread can change *the RF state at one time, and others *should wait to be executed.
*/ while (true) {
spin_lock(&rtlpriv->locks.rf_ps_lock); if (ppsc->rfchange_inprogress) {
spin_unlock(&rtlpriv->locks.rf_ps_lock);
rtl_dbg(rtlpriv, COMP_ERR, DBG_WARNING, "RF Change in progress! Wait to set..state_toset(%d).\n",
state_toset);
/* Set RF after the previous action is done. */ while (ppsc->rfchange_inprogress) {
rfwait_cnt++;
mdelay(1); /*Wait too long, return false to avoid *to be stuck here.
*/ if (rfwait_cnt > 100) returnfalse;
}
} else {
ppsc->rfchange_inprogress = true;
spin_unlock(&rtlpriv->locks.rf_ps_lock); break;
}
}
switch (state_toset) { case ERFON:
ppsc->rfoff_reason &= (~changesource);
if (mac->opmode != NL80211_IFTYPE_STATION) {
rtl_dbg(rtlpriv, COMP_ERR, DBG_WARNING, "not station return\n"); return;
}
if (mac->p2p_in_use) return;
if (mac->link_state > MAC80211_NOLINK) return;
if (is_hal_stop(rtlhal)) return;
if (rtlpriv->sec.being_setkey) return;
if (rtlpriv->cfg->ops->bt_coex_off_before_lps)
rtlpriv->cfg->ops->bt_coex_off_before_lps(hw);
if (ppsc->inactiveps) {
rtstate = ppsc->rfpwr_state;
/* *Do not enter IPS in the following conditions: *(1) RF is already OFF or Sleep *(2) swrf_processing (indicates the IPS is still under going) *(3) Connectted (only disconnected can trigger IPS) *(4) IBSS (send Beacon) *(5) AP mode (send Beacon) *(6) monitor mode (rcv packet)
*/
if (rtstate == ERFON &&
!ppsc->swrf_processing &&
(mac->link_state == MAC80211_NOLINK) &&
!mac->act_scanning) {
rtl_dbg(rtlpriv, COMP_RF, DBG_TRACE, "IPSEnter(): Turn off RF\n");
/* because when link with ap, mac80211 will ask us * to disable nic quickly after scan before linking, * this will cause link failed, so we delay 100ms here
*/
queue_delayed_work(rtlpriv->works.rtl_wq,
&rtlpriv->works.ips_nic_off_wq, MSECS(100));
}
/* NOTICE: any opmode should exc nic_on, or disable without * nic_on may something wrong, like adhoc TP
*/ void rtl_ips_nic_on(struct ieee80211_hw *hw)
{ struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); enum rf_pwrstate rtstate;
ppsc->inactive_pwrstate = ERFON;
ppsc->in_powersavemode = false;
_rtl_ps_inactive_ps(hw); /* call after RF on */ if (rtlpriv->cfg->ops->get_btc_status())
rtlpriv->btcoexist.btc_ops->btc_ips_notify(rtlpriv,
ppsc->inactive_pwrstate);
}
}
mutex_unlock(&rtlpriv->locks.ips_mutex);
}
EXPORT_SYMBOL_GPL(rtl_ips_nic_on);
/*for FW LPS*/
/* *Determine if we can set Fw into PS mode *in current condition.Return TRUE if it *can enter PS mode.
*/ staticbool rtl_get_fwlps_doze(struct ieee80211_hw *hw)
{ struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
u32 ps_timediff;
if (ppsc->dot11_psmode == rt_psmode && rt_psmode == EACTIVE) return;
/* Update power save mode configured. */
ppsc->dot11_psmode = rt_psmode;
/* *<FW control LPS> *1. Enter PS mode * Set RPWM to Fw to turn RF off and send H2C fw_pwrmode * cmd to set Fw into PS mode. *2. Leave PS mode * Send H2C fw_pwrmode cmd to Fw to set Fw into Active * mode and set RPWM to turn RF on.
*/
if (rtlpriv->cfg->ops->get_btc_status())
rtlpriv->btcoexist.btc_ops->btc_lps_notify(rtlpriv, rt_psmode);
} else { if (rtl_get_fwlps_doze(hw)) {
rtl_dbg(rtlpriv, COMP_RF, DBG_DMESG, "FW LPS enter ps_mode:%x\n",
ppsc->fwctrl_psmode); if (rtlpriv->cfg->ops->get_btc_status())
rtlpriv->btcoexist.btc_ops->btc_lps_notify(rtlpriv, rt_psmode);
enter_fwlps = true;
ppsc->pwr_mode = ppsc->fwctrl_psmode;
ppsc->smart_ps = 2;
rtlpriv->cfg->ops->set_hw_reg(hw,
HW_VAR_FW_LPS_ACTION,
(u8 *)(&enter_fwlps));
} else { /* Reset the power save related parameters. */
ppsc->dot11_psmode = EACTIVE;
}
}
}
}
/* Interrupt safe routine to enter the leisure power save mode.*/ staticvoid rtl_lps_enter_core(struct ieee80211_hw *hw)
{ struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); struct rtl_priv *rtlpriv = rtl_priv(hw);
if (!ppsc->fwctrl_lps) return;
if (rtlpriv->sec.being_setkey) return;
if (rtlpriv->link_info.busytraffic) return;
/*sleep after linked 10s, to let DHCP and 4-way handshake ok enough!! */ if (mac->cnt_after_linked < 5) return;
if (mac->opmode == NL80211_IFTYPE_ADHOC) return;
if (mac->link_state != MAC80211_LINKED) return;
mutex_lock(&rtlpriv->locks.lps_mutex);
/* Don't need to check (ppsc->dot11_psmode == EACTIVE), because * bt_ccoexist may ask to enter lps. * In normal case, this constraint move to rtl_lps_set_psmode().
*/
rtl_dbg(rtlpriv, COMP_POWER, DBG_LOUD, "Enter 802.11 power save mode...\n");
rtl_lps_set_psmode(hw, EAUTOPS);
mutex_unlock(&rtlpriv->locks.lps_mutex);
}
/* Interrupt safe routine to leave the leisure power save mode.*/ staticvoid rtl_lps_leave_core(struct ieee80211_hw *hw)
{ struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
mutex_lock(&rtlpriv->locks.lps_mutex);
if (ppsc->fwctrl_lps) { if (ppsc->dot11_psmode != EACTIVE) {
/*FIX ME */ /*rtlpriv->cfg->ops->enable_interrupt(hw); */
if (!WARN_ON_ONCE(!hw->conf.ps_dtim_period))
rtlpriv->psc.dtim_counter = tim_ie->dtim_count;
/* Check whenever the PHY can be turned off again. */
/* 1. What about buffered unicast traffic for our AID? */
u_buffed = ieee80211_check_tim(tim_ie, tim_len,
rtlpriv->mac80211.assoc_id);
/* 2. Maybe the AP wants to send multicast/broadcast data? */
m_buffed = tim_ie->bitmap_ctrl & 0x01;
rtlpriv->psc.multi_buffered = m_buffed;
/* unicast will process by mac80211 through * set ~IEEE80211_CONF_PS, So we just check
* multicast frames here */ if (!m_buffed) { /* back to low-power land. and delay is
* prevent null power save frame tx fail */
queue_delayed_work(rtlpriv->works.rtl_wq,
&rtlpriv->works.ps_work, MSECS(5));
} else {
rtl_dbg(rtlpriv, COMP_POWER, DBG_DMESG, "u_bufferd: %x, m_buffered: %x\n", u_buffed, m_buffed);
}
}
EXPORT_SYMBOL_GPL(rtl_swlps_beacon);
if ((rtlpriv->sec.being_setkey) ||
(mac->opmode == NL80211_IFTYPE_ADHOC)) return;
/*sleep after linked 10s, to let DHCP and 4-way handshake ok enough!! */ if ((mac->link_state != MAC80211_LINKED) || (mac->cnt_after_linked < 5)) return;
if (rtlpriv->link_info.busytraffic) return;
spin_lock(&rtlpriv->locks.rf_ps_lock); if (rtlpriv->psc.rfchange_inprogress) {
spin_unlock(&rtlpriv->locks.rf_ps_lock); return;
}
spin_unlock(&rtlpriv->locks.rf_ps_lock);
/* here is power save alg, when this beacon is DTIM * we will set sleep time to dtim_period * n; * when this beacon is not DTIM, we will set sleep * time to sleep_intv = rtlpriv->psc.dtim_counter or
* MAX_SW_LPS_SLEEP_INTV(default set to 5) */
if (sleep_intv > MAX_SW_LPS_SLEEP_INTV)
sleep_intv = MAX_SW_LPS_SLEEP_INTV;
/* this print should always be dtim_conter = 0 & * sleep = dtim_period, that meaons, we should
* awake before every dtim */
rtl_dbg(rtlpriv, COMP_POWER, DBG_DMESG, "dtim_counter:%x will sleep :%d beacon_intv\n",
rtlpriv->psc.dtim_counter, sleep_intv);
/* we tested that 40ms is enough for sw & hw sw delay */
queue_delayed_work(rtlpriv->works.rtl_wq, &rtlpriv->works.ps_rfon_wq,
MSECS(sleep_intv * mac->vif->bss_conf.beacon_int - 40));
}
if (!mac->p2p) return; if (mac->link_state != MAC80211_LINKED) return; /* min. beacon length + FCS_LEN */ if (len <= 40 + FCS_LEN) return;
/* and only beacons from the associated BSSID, please */ if (!ether_addr_equal_64bits(hdr->addr3, rtlpriv->mac80211.bssid)) return;
/* check if this really is a beacon */ if (!(ieee80211_is_beacon(hdr->frame_control) ||
ieee80211_is_probe_resp(hdr->frame_control) ||
ieee80211_is_action(hdr->frame_control))) return;
if (ieee80211_is_action(hdr->frame_control))
rtl_p2p_action_ie(hw , data , len - FCS_LEN); else
rtl_p2p_noa_ie(hw , data , len - FCS_LEN);
}
EXPORT_SYMBOL_GPL(rtl_p2p_info);
Messung V0.5
¤ Dauer der Verarbeitung: 0.4 Sekunden
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.