bool rtl_ps_enable_nic(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)); struct rtl_mac *rtlmac = rtl_mac(rtl_priv(hw)); /*<1> reset trx ring */ if (rtlhal->interface == INTF_PCI) rtlpriv->intf_ops->reset_trx_ring(hw); if (is_hal_stop(rtlhal)) RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, "Driver is already down!\n"); /*<2> Enable Adapter */ if (rtlpriv->cfg->ops->hw_init(hw)) return false; rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RETRY_LIMIT, &rtlmac->retry_long); RT_CLEAR_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC); /*<3> Enable Interrupt */ rtlpriv->cfg->ops->enable_interrupt(hw); /*<enable timer> */ rtl_watch_dog_timer_callback(&rtlpriv->works.watchdog_timer); return true; }
/*Leave the leisure power save mode.*/ void rtl_lps_leave(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.ps_mutex); if (ppsc->fwctrl_lps) { if (ppsc->dot11_psmode != EACTIVE) { /*FIX ME */ rtlpriv->cfg->ops->enable_interrupt(hw); if (ppsc->reg_rfps_level & RT_RF_LPS_LEVEL_ASPM && RT_IN_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM) && rtlhal->interface == INTF_PCI) { rtlpriv->intf_ops->disable_aspm(hw); RT_CLEAR_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM); } RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, "Busy Traffic,Leave 802.11 power save..\n"); rtl_lps_set_psmode(hw, EACTIVE); } } mutex_unlock(&rtlpriv->locks.ps_mutex); }
bool rtl_ps_enable_nic(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)); if (rtlhal->interface == INTF_PCI) rtlpriv->intf_ops->reset_trx_ring(hw); if (is_hal_stop(rtlhal)) RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, "Driver is already down!\n"); if (rtlpriv->cfg->ops->hw_init(hw)) return 1; RT_CLEAR_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC); rtlpriv->cfg->ops->enable_interrupt(hw); rtl_watch_dog_timer_callback((unsigned long)hw); return true; }
void rtl_ips_nic_off_wq_callback(void *data) { struct rtl_works *rtlworks = container_of_dwork_rtl(data, struct rtl_works, ips_nic_off_wq); struct ieee80211_hw *hw = rtlworks->hw; struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); enum rf_pwrstate rtstate; if (mac->opmode != NL80211_IFTYPE_STATION) { RT_TRACE(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) { RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, "IPSEnter(): Turn off RF\n"); ppsc->inactive_pwrstate = ERFOFF; ppsc->in_powersavemode = true; /*rtl_pci_reset_trx_ring(hw); */ _rtl_ps_inactive_ps(hw); } } }
/* 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_mac *mac = rtl_mac(rtl_priv(hw)); struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); enum rf_pwrstate rtstate; unsigned long flags; if (mac->opmode != NL80211_IFTYPE_STATION) return; spin_lock_irqsave(&rtlpriv->locks.ips_lock, flags); if (ppsc->inactiveps) { rtstate = ppsc->rfpwr_state; if (rtstate != ERFON && !ppsc->swrf_processing && ppsc->rfoff_reason <= RF_CHANGE_BY_IPS) { ppsc->inactive_pwrstate = ERFON; ppsc->in_powersavemode = false; _rtl_ps_inactive_ps(hw); } } spin_unlock_irqrestore(&rtlpriv->locks.ips_lock, flags); }
static void rtl_op_stop( struct ieee80211_hw *hw ) { struct rtl_priv *rtlpriv = rtl_priv( hw ); struct rtl_mac *mac = rtl_mac( rtl_priv( hw ) ); struct rtl_hal *rtlhal = rtl_hal( rtl_priv( hw ) ); struct rtl_ps_ctl *ppsc = rtl_psc( rtl_priv( hw ) ); if ( is_hal_stop( rtlhal ) ) return; /* here is must, because adhoc do stop and start, * but stop with RFOFF may cause something wrong, * like adhoc TP */ if ( unlikely( ppsc->rfpwr_state == ERFOFF ) ) { rtl_ips_nic_on( hw ); } mutex_lock( &rtlpriv->locks.conf_mutex ); mac->link_state = MAC80211_NOLINK; memset( mac->bssid, 0, ETH_ALEN ); mac->vendor = PEER_UNKNOWN; /*reset sec info */ rtl_cam_reset_sec_info( hw ); rtl_deinit_deferred_work( hw ); rtlpriv->intf_ops->adapter_stop( hw ); mutex_unlock( &rtlpriv->locks.conf_mutex ); }
static void _rtl_ps_inactive_ps(struct ieee80211_hw *hw) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); ppsc->b_swrf_processing = true; if (ppsc->inactive_pwrstate == ERFON && rtlhal->interface == INTF_PCI) { if ((ppsc->reg_rfps_level & RT_RF_OFF_LEVL_ASPM) && RT_IN_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM) && rtlhal->interface == INTF_PCI) { rtlpriv->intf_ops->disable_aspm(hw); RT_CLEAR_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM); } } stg_rtl_ps_set_rf_state(hw, ppsc->inactive_pwrstate, RF_CHANGE_BY_IPS, false); if (ppsc->inactive_pwrstate == ERFOFF && rtlhal->interface == INTF_PCI) { if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_ASPM && !RT_IN_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM)) { rtlpriv->intf_ops->enable_aspm(hw); RT_SET_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM); } } ppsc->b_swrf_processing = false; }
bool stg_rtl_ps_enable_nic(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)); bool init_status = true; /*<1> reset trx ring */ if (rtlhal->interface == INTF_PCI) rtlpriv->intf_ops->reset_trx_ring(hw); if (is_hal_stop(rtlhal)) RT_TRACE(COMP_ERR, DBG_WARNING, ("Driver is already down!\n")); /*<2> Enable Adapter */ rtlpriv->cfg->ops->hw_init(hw); RT_CLEAR_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC); /*init_status = false; */ /*<3> Enable Interrupt */ rtlpriv->cfg->ops->enable_interrupt(hw); /*<enable timer> */ rtl92e_watch_dog_timer_callback((unsigned long)hw); return init_status; }
/* NOTICE: any opmode should exc nic_on, or disable without * nic_on may something wrong, like adhoc TP*/ void rtl92e_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; cancel_delayed_work(&rtlpriv->works.ips_nic_off_wq); spin_lock(&rtlpriv->locks.ips_lock); if (ppsc->b_inactiveps) { rtstate = ppsc->rfpwr_state; if (rtstate != ERFON && !ppsc->b_swrf_processing && ppsc->rfoff_reason <= RF_CHANGE_BY_IPS) { ppsc->inactive_pwrstate = ERFON; ppsc->b_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); } } spin_unlock(&rtlpriv->locks.ips_lock); }
/* *Determine if we can set Fw into PS mode *in current condition.Return TRUE if it *can enter PS mode. */ static bool 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; ps_timediff = jiffies_to_msecs(jiffies - ppsc->last_delaylps_stamp_jiffies); if (ps_timediff < 2000) { RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, ("Delay enter Fw LPS for DHCP, ARP," " or EAPOL exchanging state.\n")); return false; } if (mac->link_state != MAC80211_LINKED) return false; if (mac->opmode == NL80211_IFTYPE_ADHOC) return false; return true; }
/*Leave the leisure power save mode.*/ void rtl92e_lps_leave(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)); unsigned long flag; spin_lock_irqsave(&rtlpriv->locks.lps_lock, flag); if (ppsc->b_fwctrl_lps) { if (ppsc->dot11_psmode != EACTIVE) { if (ppsc->reg_rfps_level & RT_RF_LPS_LEVEL_ASPM && RT_IN_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM) && rtlhal->interface == INTF_PCI) { rtlpriv->intf_ops->disable_aspm(hw); RT_CLEAR_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM); } RT_TRACE(COMP_POWER, DBG_LOUD, ("Busy Traffic,Leave 802.11 power save..\n")); rtl_lps_set_psmode(hw, EACTIVE); } } spin_unlock_irqrestore(&rtlpriv->locks.lps_lock, flag); }
void rtl92su_card_disable(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)); enum nl80211_iftype opmode; u8 wait = 30; rtlpriv->cfg->ops->led_control(hw, LED_CTL_POWER_OFF); RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC); /* this is very important for ips power save */ while (wait-- >= 10 && rtlpriv->psc.pwrdomain_protect) { if (rtlpriv->psc.pwrdomain_protect) mdelay(20); else break; } mac->link_state = MAC80211_NOLINK; opmode = NL80211_IFTYPE_UNSPECIFIED; rtl92s_set_media_status(hw, opmode); rtl92s_phy_set_rfhalt(hw); udelay(100); }
static int rtl_pci_start(struct ieee80211_hw *hw) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); int err; rtl_pci_reset_trx_ring(hw); rtlpci->driver_is_goingto_unload = false; err = rtlpriv->cfg->ops->hw_init(hw); if (err) { RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, ("Failed to config hardware!\n")); return err; } rtlpriv->cfg->ops->enable_interrupt(hw); RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, ("enable_interrupt OK\n")); rtl_init_rx_config(hw); /*should after adapter start and interrupt enable. */ set_hal_start(rtlhal); RT_CLEAR_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC); rtlpci->up_first_time = false; RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, ("OK\n")); return 0; }
static void rtl_op_tx(struct ieee80211_hw *hw, struct ieee80211_tx_control *control, struct sk_buff *skb) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); struct rtl_tcb_desc tcb_desc; memset(&tcb_desc, 0, sizeof(struct rtl_tcb_desc)); if (unlikely(is_hal_stop(rtlhal) || ppsc->rfpwr_state != ERFON)) goto err_free; if (!test_bit(RTL_STATUS_INTERFACE_START, &rtlpriv->status)) goto err_free; rtl_tx_accounting(hw, skb); if (!rtlpriv->intf_ops->waitq_insert(hw, control->sta, skb)) rtlpriv->intf_ops->adapter_tx(hw, control->sta, skb, &tcb_desc); return; err_free: ieee80211_free_txskb(hw, skb); }
void rtl_swlps_rf_sleep(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)); u8 sleep_intv; if (!rtlpriv->psc.sw_ps_enabled) return; 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; mutex_lock(&rtlpriv->locks.ps_mutex); rtl_ps_set_rf_state(hw, ERFSLEEP, RF_CHANGE_BY_PS); mutex_unlock(&rtlpriv->locks.ps_mutex); if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_ASPM && !RT_IN_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM)) { rtlpriv->intf_ops->enable_aspm(hw); RT_SET_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM); } /* 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 (rtlpriv->psc.dtim_counter == 0) { if (hw->conf.ps_dtim_period == 1) sleep_intv = hw->conf.ps_dtim_period * 2; else sleep_intv = hw->conf.ps_dtim_period; } else { sleep_intv = rtlpriv->psc.dtim_counter; } 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 */ RT_TRACE(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)); }
static void rtl_op_stop(struct ieee80211_hw *hw) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); if (is_hal_stop(rtlhal)) return; if (unlikely(ppsc->rfpwr_state == ERFOFF)) { rtl_ips_nic_on(hw); mdelay(1); } mutex_lock(&rtlpriv->locks.conf_mutex); mac->link_state = MAC80211_NOLINK; memset(mac->bssid, 0, 6); mac->vendor = PEER_UNKNOWN; /*reset sec info */ rtl_cam_reset_sec_info(hw); rtl_deinit_deferred_work(hw); rtlpriv->intf_ops->adapter_stop(hw); mutex_unlock(&rtlpriv->locks.conf_mutex); }
static void _rtl8723ae_query_rxphystatus(struct ieee80211_hw *hw, struct rtl_stats *pstatus, u8 *pdesc, struct rx_fwinfo_8723e *p_drvinfo, bool bpacket_match_bssid, bool bpacket_toself, bool packet_beacon) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_ps_ctl *ppsc = rtl_psc(rtlpriv); struct phy_sts_cck_8723e_t *cck_buf; s8 rx_pwr_all, rx_pwr[4]; u8 rf_rx_num = 0, evm, pwdb_all; u8 i, max_spatial_stream; u32 rssi, total_rssi = 0; bool is_cck = pstatus->is_cck; /* Record it for next packet processing */ pstatus->packet_matchbssid = bpacket_match_bssid; pstatus->packet_toself = bpacket_toself; pstatus->packet_beacon = packet_beacon; pstatus->rx_mimo_sig_qual[0] = -1; pstatus->rx_mimo_sig_qual[1] = -1; if (is_cck) { u8 report, cck_highpwr; /* CCK Driver info Structure is not the same as OFDM packet. */ cck_buf = (struct phy_sts_cck_8723e_t *)p_drvinfo; /* (1)Hardware does not provide RSSI for CCK * (2)PWDB, Average PWDB cacluated by * hardware (for rate adaptive) */ if (ppsc->rfpwr_state == ERFON) cck_highpwr = (u8) rtl_get_bbreg(hw, RFPGA0_XA_HSSIPARAMETER2, BIT(9)); else cck_highpwr = false; if (!cck_highpwr) { u8 cck_agc_rpt = cck_buf->cck_agc_rpt; report = cck_buf->cck_agc_rpt & 0xc0; report = report >> 6; switch (report) { case 0x3: rx_pwr_all = -46 - (cck_agc_rpt & 0x3e); break; case 0x2: rx_pwr_all = -26 - (cck_agc_rpt & 0x3e); break; case 0x1: rx_pwr_all = -12 - (cck_agc_rpt & 0x3e); break; case 0x0: rx_pwr_all = 16 - (cck_agc_rpt & 0x3e); break; } } else {
static void _rtl92ce_query_rxphystatus(struct ieee80211_hw *hw, struct rtl_stats *pstats, struct rx_desc_92c *pdesc, struct rx_fwinfo_92c *p_drvinfo, bool packet_match_bssid, bool packet_toself, bool packet_beacon) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct phy_sts_cck_8192s_t *cck_buf; struct rtl_ps_ctl *ppsc = rtl_psc(rtlpriv); s8 rx_pwr_all = 0, rx_pwr[4]; u8 evm, pwdb_all, rf_rx_num = 0; u8 i, max_spatial_stream; u32 rssi, total_rssi = 0; bool is_cck_rate; is_cck_rate = RX_HAL_IS_CCK_RATE(pdesc); pstats->packet_matchbssid = packet_match_bssid; pstats->packet_toself = packet_toself; pstats->is_cck = is_cck_rate; pstats->packet_beacon = packet_beacon; pstats->rx_mimo_sig_qual[0] = -1; pstats->rx_mimo_sig_qual[1] = -1; if (is_cck_rate) { u8 report, cck_highpwr; cck_buf = (struct phy_sts_cck_8192s_t *)p_drvinfo; if (ppsc->rfpwr_state == ERFON) cck_highpwr = (u8) rtl_get_bbreg(hw, RFPGA0_XA_HSSIPARAMETER2, BIT(9)); else cck_highpwr = false; if (!cck_highpwr) { u8 cck_agc_rpt = cck_buf->cck_agc_rpt; report = cck_buf->cck_agc_rpt & 0xc0; report = report >> 6; switch (report) { case 0x3: rx_pwr_all = -46 - (cck_agc_rpt & 0x3e); break; case 0x2: rx_pwr_all = -26 - (cck_agc_rpt & 0x3e); break; case 0x1: rx_pwr_all = -12 - (cck_agc_rpt & 0x3e); break; case 0x0: rx_pwr_all = 16 - (cck_agc_rpt & 0x3e); break; } } else {
bool rtl92cu_phy_set_rf_power_state( struct ieee80211_hw *hw, enum rf_pwrstate rfpwr_state ) { struct rtl_ps_ctl *ppsc = rtl_psc( rtl_priv( hw ) ); bool bresult = false; if ( rfpwr_state == ppsc->rfpwr_state ) return bresult; bresult = _rtl92cu_phy_set_rf_power_state( hw, rfpwr_state ); return bresult; }
void rtl_swlps_rf_sleep(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)); u8 sleep_intv; if (!rtlpriv->psc.sw_ps_enabled) return; if ((rtlpriv->sec.being_setkey) || (mac->opmode == NL80211_IFTYPE_ADHOC)) return; if ((mac->link_state != MAC80211_LINKED) || (mac->cnt_after_linked < 5)) return; if (rtlpriv->link_info.busytraffic) return; mutex_lock(&rtlpriv->locks.ps_mutex); rtl_ps_set_rf_state(hw, ERFSLEEP, RF_CHANGE_BY_PS); mutex_unlock(&rtlpriv->locks.ps_mutex); if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_ASPM && !RT_IN_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM)) { rtlpriv->intf_ops->enable_aspm(hw); RT_SET_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM); } if (rtlpriv->psc.dtim_counter == 0) { if (hw->conf.ps_dtim_period == 1) sleep_intv = hw->conf.ps_dtim_period * 2; else sleep_intv = hw->conf.ps_dtim_period; } else { sleep_intv = rtlpriv->psc.dtim_counter; } if (sleep_intv > MAX_SW_LPS_SLEEP_INTV) sleep_intv = MAX_SW_LPS_SLEEP_INTV; RT_TRACE(rtlpriv, COMP_POWER, DBG_DMESG, "dtim_counter:%x will sleep :%d beacon_intv\n", rtlpriv->psc.dtim_counter, sleep_intv); queue_delayed_work(rtlpriv->works.rtl_wq, &rtlpriv->works.ps_rfon_wq, MSECS(sleep_intv * mac->vif->bss_conf.beacon_int - 40)); }
static void _rtl_pci_initialize_adapter_common(struct ieee80211_hw *hw) { struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); _rtl_pci_update_default_setting(hw); if (ppsc->reg_rfps_level & RT_RF_PS_LEVEL_ALWAYS_ASPM) { /*Always enable ASPM & Clock Req. */ rtl_pci_enable_aspm(hw); RT_SET_PS_LEVEL(ppsc, RT_RF_PS_LEVEL_ALWAYS_ASPM); } }
bool rtl_ps_set_rf_state(struct ieee80211_hw *hw, enum rf_pwrstate state_toset, u32 changesource) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); bool actionallowed = false; switch (state_toset) { case ERFON: ppsc->rfoff_reason &= (~changesource); if ((changesource == RF_CHANGE_BY_HW) && (ppsc->hwradiooff)) { ppsc->hwradiooff = false; } if (!ppsc->rfoff_reason) { ppsc->rfoff_reason = 0; actionallowed = true; } break; case ERFOFF: if ((changesource == RF_CHANGE_BY_HW) && (ppsc->hwradiooff == false)) { ppsc->hwradiooff = true; } ppsc->rfoff_reason |= changesource; actionallowed = true; break; case ERFSLEEP: ppsc->rfoff_reason |= changesource; actionallowed = true; break; default: RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, ("switch case not process\n")); break; } if (actionallowed) rtlpriv->cfg->ops->set_rf_power_state(hw, state_toset); return actionallowed; }
static void _rtl_pci_init_struct(struct ieee80211_hw *hw, struct pci_dev *pdev) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); rtlpci->up_first_time = true; rtlpci->being_init_adapter = false; rtlhal->hw = hw; rtlpci->pdev = pdev; ppsc->inactiveps = false; ppsc->leisure_ps = true; ppsc->fwctrl_lps = true; ppsc->reg_fwctrl_lps = 3; ppsc->reg_max_lps_awakeintvl = 5; if (ppsc->reg_fwctrl_lps == 1) ppsc->fwctrl_psmode = FW_PS_MIN_MODE; else if (ppsc->reg_fwctrl_lps == 2) ppsc->fwctrl_psmode = FW_PS_MAX_MODE; else if (ppsc->reg_fwctrl_lps == 3) ppsc->fwctrl_psmode = FW_PS_DTIM_MODE; /*Tx/Rx related var */ _rtl_pci_init_trx_var(hw); /*IBSS*/ mac->beacon_interval = 100; /*AMPDU*/ mac->min_space_cfg = 0; mac->max_mss_density = 0; /*set sane AMPDU defaults */ mac->current_ampdu_density = 7; mac->current_ampdu_factor = 3; /*QOS*/ rtlpci->acm_method = eAcmWay2_SW; /*task */ tasklet_init(&rtlpriv->works.irq_tasklet, (void (*)(unsigned long))_rtl_pci_irq_tasklet, (unsigned long)hw); tasklet_init(&rtlpriv->works.irq_prepare_bcn_tasklet, (void (*)(unsigned long))_rtl_pci_prepare_bcn_tasklet, (unsigned long)hw); }
/*Disable RTL8192SE ASPM & Disable Pci Bridge ASPM*/ static void rtl_pci_disable_aspm(struct ieee80211_hw *hw) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); u8 pcibridge_vendor = pcipriv->ndis_adapter.pcibridge_vendor; u32 pcicfg_addrport = pcipriv->ndis_adapter.pcicfg_addrport; u8 num4bytes = pcipriv->ndis_adapter.num4bytes; /*Retrieve original configuration settings. */ u8 linkctrl_reg = pcipriv->ndis_adapter.linkctrl_reg; u16 pcibridge_linkctrlreg = pcipriv->ndis_adapter. pcibridge_linkctrlreg; u16 aspmlevel = 0; if (pcibridge_vendor == PCI_BRIDGE_VENDOR_UNKNOWN) { RT_TRACE(rtlpriv, COMP_POWER, DBG_TRACE, ("PCI(Bridge) UNKNOWN.\n")); return; } if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_CLK_REQ) { RT_CLEAR_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_CLK_REQ); _rtl_pci_switch_clk_req(hw, 0x0); } if (1) { /*for promising device will in L0 state after an I/O. */ u8 tmp_u1b; pci_read_config_byte(rtlpci->pdev, 0x80, &tmp_u1b); } /*Set corresponding value. */ aspmlevel |= BIT(0) | BIT(1); linkctrl_reg &= ~aspmlevel; pcibridge_linkctrlreg &= ~(BIT(0) | BIT(1)); _rtl_pci_platform_switch_device_pci_aspm(hw, linkctrl_reg); udelay(50); /*4 Disable Pci Bridge ASPM */ rtl_pci_raw_write_port_ulong(PCI_CONF_ADDRESS, pcicfg_addrport + (num4bytes << 2)); rtl_pci_raw_write_port_uchar(PCI_CONF_DATA, pcibridge_linkctrlreg); udelay(50); }
void rtl8822be_led_control(struct ieee80211_hw *hw, enum led_ctl_mode ledaction) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); if (ppsc->rfoff_reason > RF_CHANGE_BY_PS && (ledaction == LED_CTL_TX || ledaction == LED_CTL_RX || ledaction == LED_CTL_SITE_SURVEY || ledaction == LED_CTL_LINK || ledaction == LED_CTL_NO_LINK || ledaction == LED_CTL_START_TO_LINK || ledaction == LED_CTL_POWER_ON)) { return; } RT_TRACE(rtlpriv, COMP_LED, DBG_TRACE, "ledaction %d,\n", ledaction); _rtl8822be_sw_led_control(hw, ledaction); }
static bool rtl_phydm_watchdog(struct rtl_priv *rtlpriv) { struct phy_dm_struct *dm = rtlpriv_to_phydm(rtlpriv); struct rtl_mac *mac = rtl_mac(rtlpriv); struct rtl_ps_ctl *ppsc = rtl_psc(rtlpriv); bool fw_current_inpsmode = false; bool fw_ps_awake = true; u8 is_linked = false; u8 bsta_state = false; u8 is_bt_enabled = false; /* check whether do watchdog */ rtlpriv->cfg->ops->get_hw_reg(rtlpriv->hw, HW_VAR_FW_PSMODE_STATUS, (u8 *)(&fw_current_inpsmode)); rtlpriv->cfg->ops->get_hw_reg(rtlpriv->hw, HW_VAR_FWLPS_RF_ON, (u8 *)(&fw_ps_awake)); if (ppsc->p2p_ps_info.p2p_ps_mode) fw_ps_awake = false; if ((ppsc->rfpwr_state == ERFON) && ((!fw_current_inpsmode) && fw_ps_awake) && (!ppsc->rfchange_inprogress)) ; else return false; /* update common info before doing watchdog */ if (mac->link_state >= MAC80211_LINKED) { is_linked = true; if (mac->vif && mac->vif->type == NL80211_IFTYPE_STATION) bsta_state = true; } if (rtlpriv->cfg->ops->get_btc_status()) is_bt_enabled = !rtlpriv->btcoexist.btc_ops->btc_is_bt_disabled( rtlpriv); odm_cmn_info_update(dm, ODM_CMNINFO_LINK, is_linked); odm_cmn_info_update(dm, ODM_CMNINFO_STATION_STATE, bsta_state); odm_cmn_info_update(dm, ODM_CMNINFO_BT_ENABLED, is_bt_enabled); /* do watchdog */ odm_dm_watchdog(dm); return true; }
void rtl_ips_nic_off_wq_callback(void *data) { struct rtl_works *rtlworks = container_of_dwork_rtl(data, struct rtl_works, ips_nic_off_wq); struct ieee80211_hw *hw = rtlworks->hw; struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); enum rf_pwrstate rtstate; if (mac->opmode != NL80211_IFTYPE_STATION) { RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, "not station return\n"); return; } if (mac->link_state > MAC80211_NOLINK) return; if (is_hal_stop(rtlhal)) return; if (rtlpriv->sec.being_setkey) return; if (ppsc->inactiveps) { rtstate = ppsc->rfpwr_state; if (rtstate == ERFON && !ppsc->swrf_processing && (mac->link_state == MAC80211_NOLINK) && !mac->act_scanning) { RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, "IPSEnter(): Turn off RF\n"); ppsc->inactive_pwrstate = ERFOFF; ppsc->in_powersavemode = true; _rtl_ps_inactive_ps(hw); } } }
void rtl92s_set_fw_pwrmode_cmd( struct ieee80211_hw *hw, u8 Mode ) { struct rtl_mac *mac = rtl_mac( rtl_priv( hw ) ); struct rtl_ps_ctl *ppsc = rtl_psc( rtl_priv( hw ) ); struct h2c_set_pwrmode_parm pwrmode; u16 max_wakeup_period = 0; pwrmode.mode = Mode; pwrmode.flag_low_traffic_en = 0; pwrmode.flag_lpnav_en = 0; pwrmode.flag_rf_low_snr_en = 0; pwrmode.flag_dps_en = 0; pwrmode.bcn_rx_en = 0; pwrmode.bcn_to = 0; SET_BITS_TO_LE_2BYTE( ( u8 * )( &pwrmode ) + 8, 0, 16, mac->vif->bss_conf.beacon_int ); pwrmode.app_itv = 0; pwrmode.awake_bcn_itvl = ppsc->reg_max_lps_awakeintvl; pwrmode.smart_ps = 1; pwrmode.bcn_pass_period= 10; /* Set beacon pass count */ if ( pwrmode.mode == FW_PS_MIN_MODE ) max_wakeup_period = mac->vif->bss_conf.beacon_int; else if ( pwrmode.mode == FW_PS_MAX_MODE ) max_wakeup_period = mac->vif->bss_conf.beacon_int * mac->vif->bss_conf.dtim_period; if ( max_wakeup_period >= 500 ) pwrmode.bcn_pass_cnt = 1; else if ( ( max_wakeup_period >= 300 ) && ( max_wakeup_period < 500 ) ) pwrmode.bcn_pass_cnt = 2; else if( ( max_wakeup_period >= 200 ) && ( max_wakeup_period < 300 ) ) pwrmode.bcn_pass_cnt = 3; else if ( ( max_wakeup_period >= 20 ) && ( max_wakeup_period < 200 ) ) pwrmode.bcn_pass_cnt = 5; else pwrmode.bcn_pass_cnt = 1; _rtl92s_firmware_set_h2c_cmd( hw ,FW_H2C_SETPWRMODE, ( u8 * )&pwrmode ); }
void halbtc_enter_lps(struct btc_coexist *btcoexist) { struct rtl_priv *rtlpriv; struct rtl_ps_ctl *ppsc; bool ap_enable = false; rtlpriv = btcoexist->adapter; ppsc = rtl_psc(rtlpriv); btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_AP_MODE_ENABLE, &ap_enable); if (ap_enable) { printk("halbtc_enter_lps()<--dont enter lps under AP mode\n"); return; } btcoexist->bt_info.bt_ctrl_lps = true; btcoexist->bt_info.bt_lps_on = false; }
static void rtl_pci_stop(struct ieee80211_hw *hw) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); unsigned long flags; u8 RFInProgressTimeOut = 0; /* *should before disable interrrupt&adapter *and will do it immediately. */ set_hal_stop(rtlhal); rtlpriv->cfg->ops->disable_interrupt(hw); spin_lock_irqsave(&rtlpriv->locks.rf_ps_lock, flags); while (ppsc->rfchange_inprogress) { spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flags); if (RFInProgressTimeOut > 100) { spin_lock_irqsave(&rtlpriv->locks.rf_ps_lock, flags); break; } mdelay(1); RFInProgressTimeOut++; spin_lock_irqsave(&rtlpriv->locks.rf_ps_lock, flags); } ppsc->rfchange_inprogress = true; spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flags); rtlpci->driver_is_goingto_unload = true; rtlpriv->cfg->ops->hw_disable(hw); rtlpriv->cfg->ops->led_control(hw, LED_CTL_POWER_OFF); spin_lock_irqsave(&rtlpriv->locks.rf_ps_lock, flags); ppsc->rfchange_inprogress = false; spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flags); rtl_pci_enable_aspm(hw); }