/*InitializeVariables8812E*/ int rtl8821ae_init_sw_vars(struct ieee80211_hw *hw) { int err = 0; struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); rtl8821ae_bt_reg_init(hw); rtlpriv->btcoexist.btc_ops = rtl_btc_get_ops_pointer(); rtlpriv->dm.dm_initialgain_enable = 1; rtlpriv->dm.dm_flag = 0; rtlpriv->dm.disable_framebursting = 0; rtlpriv->dm.thermalvalue = 0; rtlpci->transmit_config = CFENDFORM | BIT(15) | BIT(24) | BIT(25); mac->ht_enable = true; mac->ht_cur_stbc = mac->ht_stbc_cap = 0; mac->vht_cur_ldpc = mac->vht_ldpc_cap = 0; mac->vht_cur_stbc = mac->vht_stbc_cap = 0; rtlpriv->rtlhal.current_bandtype = BAND_ON_2_4G; /*following 2 is for register 5G band, refer to _rtl_init_mac80211()*/ rtlpriv->rtlhal.bandset = BAND_ON_BOTH; rtlpriv->rtlhal.macphymode = SINGLEMAC_SINGLEPHY; rtlpci->receive_config = (RCR_APPFCS | RCR_APP_MIC | RCR_APP_ICV | RCR_APP_PHYST_RXFF | RCR_NONQOS_VHT | RCR_HTC_LOC_CTRL | RCR_AMF | RCR_ACF | /*This bit controls the PS-Poll packet filter.*/ RCR_ADF | RCR_AICV | RCR_ACRC32 | RCR_AB | RCR_AM | RCR_APM | 0); rtlpci->irq_mask[0] = (u32) (IMR_PSTIMEOUT | IMR_GTINT3 | /*IMR_TBDER | IMR_TBDOK | IMR_BCNDMAINT0 |*/ IMR_HSISR_IND_ON_INT | IMR_C2HCMD | IMR_HIGHDOK | IMR_MGNTDOK | IMR_BKDOK | IMR_BEDOK | IMR_VIDOK | IMR_VODOK | IMR_RDU | IMR_ROK | 0); rtlpci->irq_mask[1] = (u32)(IMR_RXFOVW | IMR_TXFOVW | 0); rtlpci->sys_irq_mask = (u32) (HSIMR_PDN_INT_EN | HSIMR_RON_INT_EN | 0); /* for WOWLAN */ /* if kernel >= 3.11, revise this var, * remember revise 'rtl_wowlan_support' at the same time */ rtlpriv->psc.wo_wlan_mode = WAKE_ON_MAGIC_PACKET | WAKE_ON_PATTERN_MATCH; /* for debug level */ rtlpriv->dbg.global_debuglevel = rtlpriv->cfg->mod_params->debug; /* for LPS & IPS */ rtlpriv->psc.inactiveps = rtlpriv->cfg->mod_params->inactiveps; rtlpriv->psc.swctrl_lps = rtlpriv->cfg->mod_params->swctrl_lps; rtlpriv->psc.fwctrl_lps = rtlpriv->cfg->mod_params->fwctrl_lps; rtlpci->msi_support = rtlpriv->cfg->mod_params->msi_support; rtlpci->int_clear = rtlpriv->cfg->mod_params->int_clear; rtlpriv->cfg->mod_params->sw_crypto = rtlpriv->cfg->mod_params->sw_crypto; rtlpriv->cfg->mod_params->disable_watchdog = rtlpriv->cfg->mod_params->disable_watchdog; if (rtlpriv->cfg->mod_params->disable_watchdog) pr_info("watchdog disabled\n"); rtlpriv->psc.reg_fwctrl_lps = 3; rtlpriv->psc.reg_max_lps_awakeintvl = 5; /* for ASPM, you can close aspm through * set const_support_pciaspm = 0 */ rtl8821ae_init_aspm_vars(hw); if (rtlpriv->psc.reg_fwctrl_lps == 1) rtlpriv->psc.fwctrl_psmode = FW_PS_MIN_MODE; else if (rtlpriv->psc.reg_fwctrl_lps == 2) rtlpriv->psc.fwctrl_psmode = FW_PS_MAX_MODE; else if (rtlpriv->psc.reg_fwctrl_lps == 3) rtlpriv->psc.fwctrl_psmode = FW_PS_DTIM_MODE; rtlpriv->rtl_fw_second_cb = load_wowlan_fw; /* for firmware buf */ rtlpriv->rtlhal.pfirmware = vzalloc(0x8000); if (!rtlpriv->rtlhal.pfirmware) { RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "Can't alloc buffer for fw.\n"); return 1; } if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE) rtlpriv->cfg->fw_name = "rtlwifi/rtl8812aefw.bin"; else rtlpriv->cfg->fw_name = "rtlwifi/rtl8821aefw.bin"; rtlpriv->max_fw_size = 0x8000; pr_info("Using firmware %s\n", rtlpriv->cfg->fw_name); err = request_firmware_nowait(THIS_MODULE, 1, rtlpriv->cfg->fw_name, rtlpriv->io.dev, GFP_KERNEL, hw, rtl_fw_cb); if (err) { RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "Failed to request firmware!\n"); return 1; } return 0; }
static void rtl_op_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_bss_conf *bss_conf, u32 changed) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_hal *rtlhal = rtl_hal(rtlpriv); struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); struct ieee80211_sta *sta = NULL; mutex_lock(&rtlpriv->locks.conf_mutex); if ((vif->type == NL80211_IFTYPE_ADHOC) || (vif->type == NL80211_IFTYPE_AP) || (vif->type == NL80211_IFTYPE_MESH_POINT)) { if ((changed & BSS_CHANGED_BEACON) || (changed & BSS_CHANGED_BEACON_ENABLED && bss_conf->enable_beacon)) { if (mac->beacon_enabled == 0) { RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG, "BSS_CHANGED_BEACON_ENABLED\n"); /*start hw beacon interrupt. */ /*rtlpriv->cfg->ops->set_bcn_reg(hw); */ mac->beacon_enabled = 1; rtlpriv->cfg->ops->update_interrupt_mask(hw, rtlpriv->cfg->maps [RTL_IBSS_INT_MASKS], 0); if (rtlpriv->cfg->ops->linked_set_reg) rtlpriv->cfg->ops->linked_set_reg(hw); } } if ((changed & BSS_CHANGED_BEACON_ENABLED && !bss_conf->enable_beacon)) { if (mac->beacon_enabled == 1) { RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG, "ADHOC DISABLE BEACON\n"); mac->beacon_enabled = 0; rtlpriv->cfg->ops->update_interrupt_mask(hw, 0, rtlpriv->cfg->maps [RTL_IBSS_INT_MASKS]); } } if (changed & BSS_CHANGED_BEACON_INT) { RT_TRACE(rtlpriv, COMP_BEACON, DBG_TRACE, "BSS_CHANGED_BEACON_INT\n"); mac->beacon_interval = bss_conf->beacon_int; rtlpriv->cfg->ops->set_bcn_intv(hw); } } /*TODO: reference to enum ieee80211_bss_change */ if (changed & BSS_CHANGED_ASSOC) { if (bss_conf->assoc) { struct ieee80211_sta *sta = NULL; /* we should reset all sec info & cam * before set cam after linked, we should not * reset in disassoc, that will cause tkip->wep * fail because some flag will be wrong */ /* reset sec info */ rtl_cam_reset_sec_info(hw); /* reset cam to fix wep fail issue * when change from wpa to wep */ rtl_cam_reset_all_entry(hw); mac->link_state = MAC80211_LINKED; mac->cnt_after_linked = 0; mac->assoc_id = bss_conf->aid; memcpy(mac->bssid, bss_conf->bssid, ETH_ALEN); if (rtlpriv->cfg->ops->linked_set_reg) rtlpriv->cfg->ops->linked_set_reg(hw); rcu_read_lock(); sta = ieee80211_find_sta(vif, (u8 *)bss_conf->bssid); if (!sta) { pr_err("ieee80211_find_sta returned NULL\n"); rcu_read_unlock(); goto out; } if (vif->type == NL80211_IFTYPE_STATION && sta) rtlpriv->cfg->ops->update_rate_tbl(hw, sta, 0); RT_TRACE(rtlpriv, COMP_EASY_CONCURRENT, DBG_LOUD, "send PS STATIC frame\n"); if (rtlpriv->dm.supp_phymode_switch) { if (sta->ht_cap.ht_supported) rtl_send_smps_action(hw, sta, IEEE80211_SMPS_STATIC); } rcu_read_unlock(); RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG, "BSS_CHANGED_ASSOC\n"); } else { if (mac->link_state == MAC80211_LINKED) { rtlpriv->enter_ps = false; schedule_work(&rtlpriv->works.lps_change_work); } if (ppsc->p2p_ps_info.p2p_ps_mode > P2P_PS_NONE) rtl_p2p_ps_cmd(hw, P2P_PS_DISABLE); mac->link_state = MAC80211_NOLINK; memset(mac->bssid, 0, ETH_ALEN); mac->vendor = PEER_UNKNOWN; if (rtlpriv->dm.supp_phymode_switch) { if (rtlpriv->cfg->ops->chk_switch_dmdp) rtlpriv->cfg->ops->chk_switch_dmdp(hw); } RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG, "BSS_CHANGED_UN_ASSOC\n"); } } if (changed & BSS_CHANGED_ERP_CTS_PROT) { RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE, "BSS_CHANGED_ERP_CTS_PROT\n"); mac->use_cts_protect = bss_conf->use_cts_prot; } if (changed & BSS_CHANGED_ERP_PREAMBLE) { RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, "BSS_CHANGED_ERP_PREAMBLE use short preamble:%x\n", bss_conf->use_short_preamble); mac->short_preamble = bss_conf->use_short_preamble; rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_ACK_PREAMBLE, &mac->short_preamble); } if (changed & BSS_CHANGED_ERP_SLOT) { RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE, "BSS_CHANGED_ERP_SLOT\n"); if (bss_conf->use_short_slot) mac->slot_time = RTL_SLOT_TIME_9; else mac->slot_time = RTL_SLOT_TIME_20; rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SLOT_TIME, &mac->slot_time); } if (changed & BSS_CHANGED_HT) { RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE, "BSS_CHANGED_HT\n"); rcu_read_lock(); sta = get_sta(hw, vif, bss_conf->bssid); if (sta) { if (sta->ht_cap.ampdu_density > mac->current_ampdu_density) mac->current_ampdu_density = sta->ht_cap.ampdu_density; if (sta->ht_cap.ampdu_factor < mac->current_ampdu_factor) mac->current_ampdu_factor = sta->ht_cap.ampdu_factor; } rcu_read_unlock(); rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SHORTGI_DENSITY, &mac->max_mss_density); rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_AMPDU_FACTOR, &mac->current_ampdu_factor); rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_AMPDU_MIN_SPACE, &mac->current_ampdu_density); } if (changed & BSS_CHANGED_BSSID) { u32 basic_rates; rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_BSSID, (u8 *) bss_conf->bssid); RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG, "%pM\n", bss_conf->bssid); mac->vendor = PEER_UNKNOWN; memcpy(mac->bssid, bss_conf->bssid, ETH_ALEN); rtlpriv->cfg->ops->set_network_type(hw, vif->type); rcu_read_lock(); sta = get_sta(hw, vif, bss_conf->bssid); if (!sta) { rcu_read_unlock(); goto out; } if (rtlhal->current_bandtype == BAND_ON_5G) { mac->mode = WIRELESS_MODE_A; } else { if (sta->supp_rates[0] <= 0xf) mac->mode = WIRELESS_MODE_B; else mac->mode = WIRELESS_MODE_G; } if (sta->ht_cap.ht_supported) { if (rtlhal->current_bandtype == BAND_ON_2_4G) mac->mode = WIRELESS_MODE_N_24G; else mac->mode = WIRELESS_MODE_N_5G; } /* just station need it, because ibss & ap mode will * set in sta_add, and will be NULL here */ if (mac->opmode == NL80211_IFTYPE_STATION) { struct rtl_sta_info *sta_entry; sta_entry = (struct rtl_sta_info *) sta->drv_priv; sta_entry->wireless_mode = mac->mode; } if (sta->ht_cap.ht_supported) { mac->ht_enable = true; /* * for cisco 1252 bw20 it's wrong * if (ht_cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) { * mac->bw_40 = true; * } * */ } if (changed & BSS_CHANGED_BASIC_RATES) { /* for 5G must << RATE_6M_INDEX = 4, * because 5G have no cck rate*/ if (rtlhal->current_bandtype == BAND_ON_5G) basic_rates = sta->supp_rates[1] << 4; else basic_rates = sta->supp_rates[0]; mac->basic_rates = basic_rates; rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_BASIC_RATE, (u8 *)(&basic_rates)); } rcu_read_unlock(); } /* * For FW LPS: * To tell firmware we have connected * to an AP. For 92SE/CE power save v2. */ if (changed & BSS_CHANGED_ASSOC) { if (bss_conf->assoc) { if (ppsc->fwctrl_lps) { u8 mstatus = RT_MEDIA_CONNECT; u8 keep_alive = 10; rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_KEEP_ALIVE, &keep_alive); rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_H2C_FW_JOINBSSRPT, &mstatus); ppsc->report_linked = true; } } else { if (ppsc->fwctrl_lps) { u8 mstatus = RT_MEDIA_DISCONNECT; rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_H2C_FW_JOINBSSRPT, &mstatus); ppsc->report_linked = false; } } if (rtlpriv->cfg->ops->bt_wifi_media_status_notify) rtlpriv->cfg->ops->bt_wifi_media_status_notify(hw, ppsc->report_linked); } out: mutex_unlock(&rtlpriv->locks.conf_mutex); }
static int rtl_op_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); int err = 0; vif->driver_flags |= IEEE80211_VIF_BEACON_FILTER; if (mac->vif) { RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, "vif has been set!! mac->vif = 0x%p\n", mac->vif); return -EOPNOTSUPP; } rtl_ips_nic_on(hw); mutex_lock(&rtlpriv->locks.conf_mutex); switch (ieee80211_vif_type_p2p(vif)) { case NL80211_IFTYPE_P2P_CLIENT: mac->p2p = P2P_ROLE_CLIENT; /*fall through*/ case NL80211_IFTYPE_STATION: if (mac->beacon_enabled == 1) { RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, "NL80211_IFTYPE_STATION\n"); mac->beacon_enabled = 0; rtlpriv->cfg->ops->update_interrupt_mask(hw, 0, rtlpriv->cfg->maps [RTL_IBSS_INT_MASKS]); } mac->link_state = MAC80211_LINKED; break; case NL80211_IFTYPE_ADHOC: RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, "NL80211_IFTYPE_ADHOC\n"); mac->link_state = MAC80211_LINKED; rtlpriv->cfg->ops->set_bcn_reg(hw); if (rtlpriv->rtlhal.current_bandtype == BAND_ON_2_4G) mac->basic_rates = 0xfff; else mac->basic_rates = 0xff0; rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_BASIC_RATE, (u8 *) (&mac->basic_rates)); break; case NL80211_IFTYPE_P2P_GO: mac->p2p = P2P_ROLE_GO; /*fall through*/ case NL80211_IFTYPE_AP: RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, "NL80211_IFTYPE_AP\n"); mac->link_state = MAC80211_LINKED; rtlpriv->cfg->ops->set_bcn_reg(hw); if (rtlpriv->rtlhal.current_bandtype == BAND_ON_2_4G) mac->basic_rates = 0xfff; else mac->basic_rates = 0xff0; rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_BASIC_RATE, (u8 *) (&mac->basic_rates)); break; case NL80211_IFTYPE_MESH_POINT: RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, "NL80211_IFTYPE_MESH_POINT\n"); mac->link_state = MAC80211_LINKED; rtlpriv->cfg->ops->set_bcn_reg(hw); if (rtlpriv->rtlhal.current_bandtype == BAND_ON_2_4G) mac->basic_rates = 0xfff; else mac->basic_rates = 0xff0; rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_BASIC_RATE, (u8 *)(&mac->basic_rates)); break; default: RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "operation mode %d is not supported!\n", vif->type); err = -EOPNOTSUPP; goto out; } if (mac->p2p) { RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, "p2p role %x\n", vif->type); mac->basic_rates = 0xff0;/*disable cck rate for p2p*/ rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_BASIC_RATE, (u8 *)(&mac->basic_rates)); } mac->vif = vif; mac->opmode = vif->type; rtlpriv->cfg->ops->set_network_type(hw, vif->type); memcpy(mac->mac_addr, vif->addr, ETH_ALEN); rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_ETHER_ADDR, mac->mac_addr); out: mutex_unlock(&rtlpriv->locks.conf_mutex); return err; }
/* Change current and default preamble mode.*/ void rtl_lps_set_psmode(struct ieee80211_hw *hw, u8 rt_psmode) { 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)); bool enter_fwlps; if (mac->opmode == NL80211_IFTYPE_ADHOC) return; if (mac->link_state != MAC80211_LINKED) return; if (ppsc->dot11_psmode == rt_psmode) 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 ((ppsc->fwctrl_lps) && ppsc->report_linked) { if (ppsc->dot11_psmode == EACTIVE) { RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, "FW LPS leave ps_mode:%x\n", FW_PS_ACTIVE_MODE); enter_fwlps = false; ppsc->pwr_mode = FW_PS_ACTIVE_MODE; ppsc->smart_ps = 0; rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_FW_LPS_ACTION, (u8 *)(&enter_fwlps)); if (ppsc->p2p_ps_info.opp_ps) rtl_p2p_ps_cmd(hw , P2P_PS_ENABLE); if (rtlpriv->cfg->ops->get_btc_status()) rtlpriv->btcoexist.btc_ops->btc_lps_notify(rtlpriv, rt_psmode); } else { if (rtl_get_fwlps_doze(hw)) { RT_TRACE(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; } } } }
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)); unsigned long flag; 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; 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); spin_lock_irqsave(&rtlpriv->locks.lps_lock, flag); rtl_ps_set_rf_state(hw, ERFSLEEP, RF_CHANGE_BY_PS); spin_unlock_irqrestore(&rtlpriv->locks.lps_lock, flag); 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)); }
void rtl92cu_phy_set_bw_mode_callback(struct ieee80211_hw *hw) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); struct rtl_phy *rtlphy = &(rtlpriv->phy); struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); u8 reg_bw_opmode; u8 reg_prsr_rsc; RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, "Switch to %s bandwidth\n", rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20 ? "20MHz" : "40MHz"); if (is_hal_stop(rtlhal)) { rtlphy->set_bwmode_inprogress = false; return; } reg_bw_opmode = rtl_read_byte(rtlpriv, REG_BWOPMODE); reg_prsr_rsc = rtl_read_byte(rtlpriv, REG_RRSR + 2); switch (rtlphy->current_chan_bw) { case HT_CHANNEL_WIDTH_20: reg_bw_opmode |= BW_OPMODE_20MHZ; rtl_write_byte(rtlpriv, REG_BWOPMODE, reg_bw_opmode); break; case HT_CHANNEL_WIDTH_20_40: reg_bw_opmode &= ~BW_OPMODE_20MHZ; rtl_write_byte(rtlpriv, REG_BWOPMODE, reg_bw_opmode); reg_prsr_rsc = (reg_prsr_rsc & 0x90) | (mac->cur_40_prime_sc << 5); rtl_write_byte(rtlpriv, REG_RRSR + 2, reg_prsr_rsc); break; default: RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "unknown bandwidth: %#X\n", rtlphy->current_chan_bw); break; } switch (rtlphy->current_chan_bw) { case HT_CHANNEL_WIDTH_20: rtl_set_bbreg(hw, RFPGA0_RFMOD, BRFMOD, 0x0); rtl_set_bbreg(hw, RFPGA1_RFMOD, BRFMOD, 0x0); rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER2, BIT(10), 1); break; case HT_CHANNEL_WIDTH_20_40: rtl_set_bbreg(hw, RFPGA0_RFMOD, BRFMOD, 0x1); rtl_set_bbreg(hw, RFPGA1_RFMOD, BRFMOD, 0x1); rtl_set_bbreg(hw, RCCK0_SYSTEM, BCCK_SIDEBAND, (mac->cur_40_prime_sc >> 1)); rtl_set_bbreg(hw, ROFDM1_LSTF, 0xC00, mac->cur_40_prime_sc); rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER2, BIT(10), 0); rtl_set_bbreg(hw, 0x818, (BIT(26) | BIT(27)), (mac->cur_40_prime_sc == HAL_PRIME_CHNL_OFFSET_LOWER) ? 2 : 1); break; default: RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "unknown bandwidth: %#X\n", rtlphy->current_chan_bw); break; } rtl92cu_phy_rf6052_set_bandwidth(hw, rtlphy->current_chan_bw); rtlphy->set_bwmode_inprogress = false; RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, "<==\n"); }
/*InitializeVariables8812E*/ int rtl8821ae_init_sw_vars(struct ieee80211_hw *hw) { int err = 0; struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); const struct firmware *firmware; struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); char *fw_name = NULL; rtl8821ae_bt_reg_init(hw); rtlpriv->btcoexist.btc_ops = rtl_btc_get_ops_pointer(); rtlpriv->dm.b_dm_initialgain_enable = 1; rtlpriv->dm.dm_flag = 0; rtlpriv->dm.b_disable_framebursting = 0;; rtlpriv->dm.thermalvalue = 0; rtlpci->transmit_config = CFENDFORM | BIT(15) | BIT(24) | BIT(25); mac->ht_enable = true; rtlpriv->rtlhal.current_bandtype = BAND_ON_2_4G; /*following 2 is for register 5G band, refer to _rtl_init_mac80211()*/ rtlpriv->rtlhal.bandset = BAND_ON_BOTH; rtlpriv->rtlhal.macphymode = SINGLEMAC_SINGLEPHY; rtlpci->receive_config = (RCR_APPFCS | RCR_APP_MIC | RCR_APP_ICV | RCR_APP_PHYST_RXFF | RCR_NONQOS_VHT | RCR_HTC_LOC_CTRL | RCR_AMF | RCR_ACF | RCR_ADF | /*This bit controls the PS-Poll packet filter.*/ RCR_AICV | RCR_ACRC32 | RCR_AB | RCR_AM | RCR_APM | 0); rtlpci->irq_mask[0] = (u32) (IMR_PSTIMEOUT | IMR_GTINT3 | /*IMR_TBDER | IMR_TBDOK | IMR_BCNDMAINT0 |*/ IMR_HSISR_IND_ON_INT | IMR_C2HCMD | IMR_HIGHDOK | IMR_MGNTDOK | IMR_BKDOK | IMR_BEDOK | IMR_VIDOK | IMR_VODOK | IMR_RDU | IMR_ROK | 0); rtlpci->irq_mask[1] = (u32)( IMR_RXFOVW | IMR_TXFOVW | 0); /* for LPS & IPS */ rtlpriv->psc.b_inactiveps = rtlpriv->cfg->mod_params->b_inactiveps; rtlpriv->psc.b_swctrl_lps = rtlpriv->cfg->mod_params->b_swctrl_lps; rtlpriv->psc.b_fwctrl_lps = rtlpriv->cfg->mod_params->b_fwctrl_lps; rtlpriv->psc.b_reg_fwctrl_lps = 3; rtlpriv->psc.reg_max_lps_awakeintvl = 5; /* for ASPM, you can close aspm through * set const_support_pciaspm = 0 */ rtl8821ae_init_aspm_vars(hw); if (rtlpriv->psc.b_reg_fwctrl_lps == 1) rtlpriv->psc.fwctrl_psmode = FW_PS_MIN_MODE; else if (rtlpriv->psc.b_reg_fwctrl_lps == 2) rtlpriv->psc.fwctrl_psmode = FW_PS_MAX_MODE; else if (rtlpriv->psc.b_reg_fwctrl_lps == 3) rtlpriv->psc.fwctrl_psmode = FW_PS_DTIM_MODE; /* for firmware buf */ rtlpriv->rtlhal.pfirmware = (u8 *) vmalloc(0x8000); if (!rtlpriv->rtlhal.pfirmware) { RT_TRACE(COMP_ERR, DBG_EMERG, ("Can't alloc buffer for fw.\n")); return 1; } fw_name = "rtlwifi/rtl8821aefw.bin"; err = request_firmware(&firmware, fw_name, rtlpriv->io.dev); if (err) { RT_TRACE(COMP_ERR, DBG_EMERG, ("Failed to request firmware!\n")); return 1; } if (firmware->size > 0x8000) { RT_TRACE(COMP_ERR, DBG_EMERG, ("Firmware is too big!\n")); release_firmware(firmware); return 1; } memcpy(rtlpriv->rtlhal.pfirmware, firmware->data, firmware->size); rtlpriv->rtlhal.fwsize = firmware->size; release_firmware(firmware); if (rtlpriv->cfg->ops->get_btc_status()){ rtlpriv->btcoexist.btc_ops->btc_init_variables(rtlpriv); rtlpriv->btcoexist.btc_ops->btc_init_hal_vars(rtlpriv); } RT_TRACE(COMP_INIT, DBG_LOUD, (" FirmwareDownload OK\n")); return err; }
static void rtl8723ae_dm_check_edca_turbo( struct ieee80211_hw *hw ) { struct rtl_priv *rtlpriv = rtl_priv( hw ); struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv( hw ); struct rtl_mac *mac = rtl_mac( rtl_priv( hw ) ); u64 cur_txok_cnt = 0; u64 cur_rxok_cnt = 0; u32 edca_be_ul = 0x5ea42b; u32 edca_be_dl = 0x5ea42b; bool bt_change_edca = false; if ( ( mac->last_bt_edca_ul != rtlpcipriv->bt_coexist.bt_edca_ul ) || ( mac->last_bt_edca_dl != rtlpcipriv->bt_coexist.bt_edca_dl ) ) { rtlpriv->dm.current_turbo_edca = false; mac->last_bt_edca_ul = rtlpcipriv->bt_coexist.bt_edca_ul; mac->last_bt_edca_dl = rtlpcipriv->bt_coexist.bt_edca_dl; } if ( rtlpcipriv->bt_coexist.bt_edca_ul != 0 ) { edca_be_ul = rtlpcipriv->bt_coexist.bt_edca_ul; bt_change_edca = true; } if ( rtlpcipriv->bt_coexist.bt_edca_dl != 0 ) { edca_be_ul = rtlpcipriv->bt_coexist.bt_edca_dl; bt_change_edca = true; } if ( mac->link_state != MAC80211_LINKED ) { rtlpriv->dm.current_turbo_edca = false; return; } if ( ( !mac->ht_enable ) && ( !rtlpcipriv->bt_coexist.bt_coexistence ) ) { if ( !( edca_be_ul & 0xffff0000 ) ) edca_be_ul |= 0x005e0000; if ( !( edca_be_dl & 0xffff0000 ) ) edca_be_dl |= 0x005e0000; } if ( ( bt_change_edca ) || ( ( !rtlpriv->dm.is_any_nonbepkts ) && ( !rtlpriv->dm.disable_framebursting ) ) ) { cur_txok_cnt = rtlpriv->stats.txbytesunicast - mac->last_txok_cnt; cur_rxok_cnt = rtlpriv->stats.rxbytesunicast - mac->last_rxok_cnt; if ( cur_rxok_cnt > 4 * cur_txok_cnt ) { if ( !rtlpriv->dm.is_cur_rdlstate || !rtlpriv->dm.current_turbo_edca ) { rtl_write_dword( rtlpriv, REG_EDCA_BE_PARAM, edca_be_dl ); rtlpriv->dm.is_cur_rdlstate = true; } } else { if ( rtlpriv->dm.is_cur_rdlstate || !rtlpriv->dm.current_turbo_edca ) { rtl_write_dword( rtlpriv, REG_EDCA_BE_PARAM, edca_be_ul ); rtlpriv->dm.is_cur_rdlstate = false; } } rtlpriv->dm.current_turbo_edca = true; } else { if ( rtlpriv->dm.current_turbo_edca ) { u8 tmp = AC0_BE; rtlpriv->cfg->ops->set_hw_reg( hw, HW_VAR_AC_PARAM, ( u8 * ) ( &tmp ) ); rtlpriv->dm.current_turbo_edca = false; } } rtlpriv->dm.is_any_nonbepkts = false; mac->last_txok_cnt = rtlpriv->stats.txbytesunicast; mac->last_rxok_cnt = rtlpriv->stats.rxbytesunicast; }
static void rtl8723ae_dm_refresh_rate_adaptive_mask( struct ieee80211_hw *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 rate_adaptive *p_ra = &( rtlpriv->ra ); u32 low_rssithresh_for_ra, high_rssithresh_for_ra; struct ieee80211_sta *sta = NULL; if ( is_hal_stop( rtlhal ) ) { RT_TRACE( rtlpriv, COMP_RATE, DBG_LOUD, " driver is going to unload\n" ); return; } if ( !rtlpriv->dm.useramask ) { RT_TRACE( rtlpriv, COMP_RATE, DBG_LOUD, " driver does not control rate adaptive mask\n" ); return; } if ( mac->link_state == MAC80211_LINKED && mac->opmode == NL80211_IFTYPE_STATION ) { switch ( p_ra->pre_ratr_state ) { case DM_RATR_STA_HIGH: high_rssithresh_for_ra = 50; low_rssithresh_for_ra = 20; break; case DM_RATR_STA_MIDDLE: high_rssithresh_for_ra = 55; low_rssithresh_for_ra = 20; break; case DM_RATR_STA_LOW: high_rssithresh_for_ra = 50; low_rssithresh_for_ra = 25; break; default: high_rssithresh_for_ra = 50; low_rssithresh_for_ra = 20; break; } if ( rtlpriv->dm.undec_sm_pwdb > high_rssithresh_for_ra ) p_ra->ratr_state = DM_RATR_STA_HIGH; else if ( rtlpriv->dm.undec_sm_pwdb > low_rssithresh_for_ra ) p_ra->ratr_state = DM_RATR_STA_MIDDLE; else p_ra->ratr_state = DM_RATR_STA_LOW; if ( p_ra->pre_ratr_state != p_ra->ratr_state ) { RT_TRACE( rtlpriv, COMP_RATE, DBG_LOUD, "RSSI = %ld\n", rtlpriv->dm.undec_sm_pwdb ); RT_TRACE( rtlpriv, COMP_RATE, DBG_LOUD, "RSSI_LEVEL = %d\n", p_ra->ratr_state ); RT_TRACE( rtlpriv, COMP_RATE, DBG_LOUD, "PreState = %d, CurState = %d\n", p_ra->pre_ratr_state, p_ra->ratr_state ); rcu_read_lock(); sta = rtl_find_sta( hw, mac->bssid ); if ( sta ) rtlpriv->cfg->ops->update_rate_tbl( hw, sta, p_ra->ratr_state ); rcu_read_unlock(); p_ra->pre_ratr_state = p_ra->ratr_state; } } }
static bool rtl_phydm_query_phy_status(struct rtl_priv *rtlpriv, u8 *phystrpt, struct ieee80211_hdr *hdr, struct rtl_stats *pstatus) { /* NOTE: phystrpt may be NULL, and need to fill default value */ struct phy_dm_struct *dm = rtlpriv_to_phydm(rtlpriv); struct rtl_efuse *rtlefuse = rtl_efuse(rtlpriv); struct rtl_mac *mac = rtl_mac(rtlpriv); struct dm_per_pkt_info pktinfo; /* input of pydm */ struct dm_phy_status_info phy_info; /* output of phydm */ __le16 fc = hdr->frame_control; /* fill driver pstatus */ ether_addr_copy(pstatus->psaddr, ieee80211_get_SA(hdr)); /* fill pktinfo */ memset(&pktinfo, 0, sizeof(pktinfo)); pktinfo.data_rate = pstatus->rate; if (rtlpriv->mac80211.opmode == NL80211_IFTYPE_STATION) { pktinfo.station_id = 0; } else { /* TODO: use rtl_find_sta() to find ID */ pktinfo.station_id = 0xFF; } pktinfo.is_packet_match_bssid = (!ieee80211_is_ctl(fc) && (ether_addr_equal(mac->bssid, ieee80211_has_tods(fc) ? hdr->addr1 : ieee80211_has_fromds(fc) ? hdr->addr2 : hdr->addr3)) && (!pstatus->hwerror) && (!pstatus->crc) && (!pstatus->icv)); pktinfo.is_packet_to_self = pktinfo.is_packet_match_bssid && (ether_addr_equal(hdr->addr1, rtlefuse->dev_addr)); pktinfo.is_to_self = (!pstatus->icv) && (!pstatus->crc) && (ether_addr_equal(hdr->addr1, rtlefuse->dev_addr)); pktinfo.is_packet_beacon = (ieee80211_is_beacon(fc) ? true : false); /* query phy status */ if (phystrpt) odm_phy_status_query(dm, &phy_info, phystrpt, &pktinfo); else memset(&phy_info, 0, sizeof(phy_info)); /* copy phy_info from phydm to driver */ pstatus->rx_pwdb_all = phy_info.rx_pwdb_all; pstatus->bt_rx_rssi_percentage = phy_info.bt_rx_rssi_percentage; pstatus->recvsignalpower = phy_info.recv_signal_power; pstatus->signalquality = phy_info.signal_quality; pstatus->rx_mimo_signalquality[0] = phy_info.rx_mimo_signal_quality[0]; pstatus->rx_mimo_signalquality[1] = phy_info.rx_mimo_signal_quality[1]; pstatus->rx_packet_bw = phy_info.band_width; /* HT_CHANNEL_WIDTH_20 <- ODM_BW20M */ /* fill driver pstatus */ pstatus->packet_matchbssid = pktinfo.is_packet_match_bssid; pstatus->packet_toself = pktinfo.is_packet_to_self; pstatus->packet_beacon = pktinfo.is_packet_beacon; return true; }
static void rtl8723ae_dm_dynamic_txpower( struct ieee80211_hw *hw ) { struct rtl_priv *rtlpriv = rtl_priv( hw ); struct rtl_phy *rtlphy = &( rtlpriv->phy ); struct rtl_mac *mac = rtl_mac( rtl_priv( hw ) ); long undec_sm_pwdb; if ( !rtlpriv->dm.dynamic_txpower_enable ) return; if ( rtlpriv->dm.dm_flag & HAL_DM_HIPWR_DISABLE ) { rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL; return; } if ( ( mac->link_state < MAC80211_LINKED ) && ( rtlpriv->dm.entry_min_undec_sm_pwdb == 0 ) ) { RT_TRACE( rtlpriv, COMP_POWER, DBG_TRACE, "Not connected\n" ); rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL; rtlpriv->dm.last_dtp_lvl = TXHIGHPWRLEVEL_NORMAL; return; } if ( mac->link_state >= MAC80211_LINKED ) { if ( mac->opmode == NL80211_IFTYPE_ADHOC ) { undec_sm_pwdb = rtlpriv->dm.entry_min_undec_sm_pwdb; RT_TRACE( rtlpriv, COMP_POWER, DBG_LOUD, "AP Client PWDB = 0x%lx\n", undec_sm_pwdb ); } else { undec_sm_pwdb = rtlpriv->dm.undec_sm_pwdb; RT_TRACE( rtlpriv, COMP_POWER, DBG_LOUD, "STA Default Port PWDB = 0x%lx\n", undec_sm_pwdb ); } } else { undec_sm_pwdb = rtlpriv->dm.entry_min_undec_sm_pwdb; RT_TRACE( rtlpriv, COMP_POWER, DBG_LOUD, "AP Ext Port PWDB = 0x%lx\n", undec_sm_pwdb ); } if ( undec_sm_pwdb >= TX_POWER_NEAR_FIELD_THRESH_LVL2 ) { rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_LEVEL1; RT_TRACE( rtlpriv, COMP_POWER, DBG_LOUD, "TXHIGHPWRLEVEL_LEVEL1 (TxPwr=0x0)\n" ); } else if ( ( undec_sm_pwdb < ( TX_POWER_NEAR_FIELD_THRESH_LVL2 - 3 ) ) && ( undec_sm_pwdb >= TX_POWER_NEAR_FIELD_THRESH_LVL1 ) ) { rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_LEVEL1; RT_TRACE( rtlpriv, COMP_POWER, DBG_LOUD, "TXHIGHPWRLEVEL_LEVEL1 (TxPwr=0x10)\n" ); } else if ( undec_sm_pwdb < ( TX_POWER_NEAR_FIELD_THRESH_LVL1 - 5 ) ) { rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL; RT_TRACE( rtlpriv, COMP_POWER, DBG_LOUD, "TXHIGHPWRLEVEL_NORMAL\n" ); } if ( ( rtlpriv->dm.dynamic_txhighpower_lvl != rtlpriv->dm.last_dtp_lvl ) ) { RT_TRACE( rtlpriv, COMP_POWER, DBG_LOUD, "PHY_SetTxPowerLevel8192S() Channel = %d\n", rtlphy->current_channel ); rtl8723ae_phy_set_txpower_level( hw, rtlphy->current_channel ); } rtlpriv->dm.last_dtp_lvl = rtlpriv->dm.dynamic_txhighpower_lvl; }
static int _rtl_phydm_init_com_info(struct rtl_priv *rtlpriv, enum odm_ic_type ic_type, struct rtl_phydm_params *params) { struct phy_dm_struct *dm = rtlpriv_to_phydm(rtlpriv); struct rtl_hal *rtlhal = rtl_hal(rtlpriv); struct rtl_phy *rtlphy = &rtlpriv->phy; struct rtl_mac *mac = rtl_mac(rtlpriv); struct rtl_ps_ctl *ppsc = rtl_psc(rtlpriv); struct rtl_efuse *rtlefuse = rtl_efuse(rtlpriv); u8 odm_board_type = ODM_BOARD_DEFAULT; u32 support_ability; int i; dm->adapter = (void *)rtlpriv; odm_cmn_info_init(dm, ODM_CMNINFO_PLATFORM, ODM_CE); odm_cmn_info_init(dm, ODM_CMNINFO_IC_TYPE, ic_type); odm_cmn_info_init(dm, ODM_CMNINFO_INTERFACE, ODM_ITRF_PCIE); odm_cmn_info_init(dm, ODM_CMNINFO_MP_TEST_CHIP, params->mp_chip); odm_cmn_info_init(dm, ODM_CMNINFO_PATCH_ID, rtlhal->oem_id); odm_cmn_info_init(dm, ODM_CMNINFO_BWIFI_TEST, 1); if (rtlphy->rf_type == RF_1T1R) odm_cmn_info_init(dm, ODM_CMNINFO_RF_TYPE, ODM_1T1R); else if (rtlphy->rf_type == RF_1T2R) odm_cmn_info_init(dm, ODM_CMNINFO_RF_TYPE, ODM_1T2R); else if (rtlphy->rf_type == RF_2T2R) odm_cmn_info_init(dm, ODM_CMNINFO_RF_TYPE, ODM_2T2R); else if (rtlphy->rf_type == RF_2T2R_GREEN) odm_cmn_info_init(dm, ODM_CMNINFO_RF_TYPE, ODM_2T2R_GREEN); else if (rtlphy->rf_type == RF_2T3R) odm_cmn_info_init(dm, ODM_CMNINFO_RF_TYPE, ODM_2T3R); else if (rtlphy->rf_type == RF_2T4R) odm_cmn_info_init(dm, ODM_CMNINFO_RF_TYPE, ODM_2T4R); else if (rtlphy->rf_type == RF_3T3R) odm_cmn_info_init(dm, ODM_CMNINFO_RF_TYPE, ODM_3T3R); else if (rtlphy->rf_type == RF_3T4R) odm_cmn_info_init(dm, ODM_CMNINFO_RF_TYPE, ODM_3T4R); else if (rtlphy->rf_type == RF_4T4R) odm_cmn_info_init(dm, ODM_CMNINFO_RF_TYPE, ODM_4T4R); else odm_cmn_info_init(dm, ODM_CMNINFO_RF_TYPE, ODM_XTXR); /* 1 ======= BoardType: ODM_CMNINFO_BOARD_TYPE ======= */ if (rtlhal->external_lna_2g != 0) { odm_board_type |= ODM_BOARD_EXT_LNA; odm_cmn_info_init(dm, ODM_CMNINFO_EXT_LNA, 1); } if (rtlhal->external_lna_5g != 0) { odm_board_type |= ODM_BOARD_EXT_LNA_5G; odm_cmn_info_init(dm, ODM_CMNINFO_5G_EXT_LNA, 1); } if (rtlhal->external_pa_2g != 0) { odm_board_type |= ODM_BOARD_EXT_PA; odm_cmn_info_init(dm, ODM_CMNINFO_EXT_PA, 1); } if (rtlhal->external_pa_5g != 0) { odm_board_type |= ODM_BOARD_EXT_PA_5G; odm_cmn_info_init(dm, ODM_CMNINFO_5G_EXT_PA, 1); } if (rtlpriv->cfg->ops->get_btc_status()) odm_board_type |= ODM_BOARD_BT; odm_cmn_info_init(dm, ODM_CMNINFO_BOARD_TYPE, odm_board_type); /* 1 ============== End of BoardType ============== */ odm_cmn_info_init(dm, ODM_CMNINFO_GPA, rtlhal->type_gpa); odm_cmn_info_init(dm, ODM_CMNINFO_APA, rtlhal->type_apa); odm_cmn_info_init(dm, ODM_CMNINFO_GLNA, rtlhal->type_glna); odm_cmn_info_init(dm, ODM_CMNINFO_ALNA, rtlhal->type_alna); odm_cmn_info_init(dm, ODM_CMNINFO_RFE_TYPE, rtlhal->rfe_type); odm_cmn_info_init(dm, ODM_CMNINFO_EXT_TRSW, 0); /*Add by YuChen for kfree init*/ odm_cmn_info_init(dm, ODM_CMNINFO_REGRFKFREEENABLE, 2); odm_cmn_info_init(dm, ODM_CMNINFO_RFKFREEENABLE, 0); /*Antenna diversity relative parameters*/ odm_cmn_info_hook(dm, ODM_CMNINFO_ANT_DIV, &rtlefuse->antenna_div_cfg); odm_cmn_info_init(dm, ODM_CMNINFO_RF_ANTENNA_TYPE, rtlefuse->antenna_div_type); odm_cmn_info_init(dm, ODM_CMNINFO_BE_FIX_TX_ANT, 0); odm_cmn_info_init(dm, ODM_CMNINFO_WITH_EXT_ANTENNA_SWITCH, 0); /* (8822B) efuse 0x3D7 & 0x3D8 for TX PA bias */ odm_cmn_info_init(dm, ODM_CMNINFO_EFUSE0X3D7, params->efuse0x3d7); odm_cmn_info_init(dm, ODM_CMNINFO_EFUSE0X3D8, params->efuse0x3d8); /*Add by YuChen for adaptivity init*/ odm_cmn_info_hook(dm, ODM_CMNINFO_ADAPTIVITY, &rtlpriv->phydm.adaptivity_en); phydm_adaptivity_info_init(dm, PHYDM_ADAPINFO_CARRIER_SENSE_ENABLE, false); phydm_adaptivity_info_init(dm, PHYDM_ADAPINFO_DCBACKOFF, 0); phydm_adaptivity_info_init(dm, PHYDM_ADAPINFO_DYNAMICLINKADAPTIVITY, false); phydm_adaptivity_info_init(dm, PHYDM_ADAPINFO_TH_L2H_INI, 0); phydm_adaptivity_info_init(dm, PHYDM_ADAPINFO_TH_EDCCA_HL_DIFF, 0); odm_cmn_info_init(dm, ODM_CMNINFO_IQKFWOFFLOAD, 0); /* Pointer reference */ odm_cmn_info_hook(dm, ODM_CMNINFO_TX_UNI, &rtlpriv->stats.txbytesunicast); odm_cmn_info_hook(dm, ODM_CMNINFO_RX_UNI, &rtlpriv->stats.rxbytesunicast); odm_cmn_info_hook(dm, ODM_CMNINFO_BAND, &rtlhal->current_bandtype); odm_cmn_info_hook(dm, ODM_CMNINFO_FORCED_RATE, &rtlpriv->phydm.forced_data_rate); odm_cmn_info_hook(dm, ODM_CMNINFO_FORCED_IGI_LB, &rtlpriv->phydm.forced_igi_lb); odm_cmn_info_hook(dm, ODM_CMNINFO_SEC_CHNL_OFFSET, &mac->cur_40_prime_sc); odm_cmn_info_hook(dm, ODM_CMNINFO_BW, &rtlphy->current_chan_bw); odm_cmn_info_hook(dm, ODM_CMNINFO_CHNL, &rtlphy->current_channel); odm_cmn_info_hook(dm, ODM_CMNINFO_SCAN, &mac->act_scanning); odm_cmn_info_hook(dm, ODM_CMNINFO_POWER_SAVING, &ppsc->dot11_psmode); /* may add new boolean flag */ /*Add by Yuchen for phydm beamforming*/ odm_cmn_info_hook(dm, ODM_CMNINFO_TX_TP, &rtlpriv->stats.txbytesunicast_inperiod_tp); odm_cmn_info_hook(dm, ODM_CMNINFO_RX_TP, &rtlpriv->stats.rxbytesunicast_inperiod_tp); odm_cmn_info_hook(dm, ODM_CMNINFO_ANT_TEST, &rtlpriv->phydm.antenna_test); for (i = 0; i < ODM_ASSOCIATE_ENTRY_NUM; i++) odm_cmn_info_ptr_array_hook(dm, ODM_CMNINFO_STA_STATUS, i, NULL); phydm_init_debug_setting(dm); odm_cmn_info_init(dm, ODM_CMNINFO_FAB_VER, params->fab_ver); odm_cmn_info_init(dm, ODM_CMNINFO_CUT_VER, params->cut_ver); /* after ifup, ability is updated again */ support_ability = ODM_RF_CALIBRATION | ODM_RF_TX_PWR_TRACK; odm_cmn_info_update(dm, ODM_CMNINFO_ABILITY, support_ability); return 0; }
static void _rtl_init_mac80211(struct ieee80211_hw *hw) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_hal *rtlhal = rtl_hal(rtlpriv); struct rtl_mac *rtlmac = rtl_mac(rtl_priv(hw)); struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); struct ieee80211_supported_band *sband; if (rtlhal->macphymode == SINGLEMAC_SINGLEPHY && rtlhal->bandset == BAND_ON_BOTH) { sband = &(rtlmac->bands[IEEE80211_BAND_2GHZ]); memcpy(&(rtlmac->bands[IEEE80211_BAND_2GHZ]), &rtl_band_2ghz, sizeof(struct ieee80211_supported_band)); _rtl_init_hw_ht_capab(hw, &sband->ht_cap); hw->wiphy->bands[IEEE80211_BAND_2GHZ] = sband; sband = &(rtlmac->bands[IEEE80211_BAND_5GHZ]); memcpy(&(rtlmac->bands[IEEE80211_BAND_5GHZ]), &rtl_band_5ghz, sizeof(struct ieee80211_supported_band)); _rtl_init_hw_ht_capab(hw, &sband->ht_cap); hw->wiphy->bands[IEEE80211_BAND_5GHZ] = sband; } else { if (rtlhal->current_bandtype == BAND_ON_2_4G) { sband = &(rtlmac->bands[IEEE80211_BAND_2GHZ]); memcpy(&(rtlmac->bands[IEEE80211_BAND_2GHZ]), &rtl_band_2ghz, sizeof(struct ieee80211_supported_band)); _rtl_init_hw_ht_capab(hw, &sband->ht_cap); hw->wiphy->bands[IEEE80211_BAND_2GHZ] = sband; } else if (rtlhal->current_bandtype == BAND_ON_5G) { sband = &(rtlmac->bands[IEEE80211_BAND_5GHZ]); memcpy(&(rtlmac->bands[IEEE80211_BAND_5GHZ]), &rtl_band_5ghz, sizeof(struct ieee80211_supported_band)); _rtl_init_hw_ht_capab(hw, &sband->ht_cap); hw->wiphy->bands[IEEE80211_BAND_5GHZ] = sband; } else { RT_TRACE(rtlpriv, COMP_INIT, DBG_EMERG, "Err BAND %d\n", rtlhal->current_bandtype); } } hw->flags = IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_RX_INCLUDES_FCS | IEEE80211_HW_AMPDU_AGGREGATION | IEEE80211_HW_CONNECTION_MONITOR | IEEE80211_HW_REPORTS_TX_ACK_STATUS | 0; if (rtlpriv->psc.swctrl_lps) hw->flags |= IEEE80211_HW_SUPPORTS_PS | IEEE80211_HW_PS_NULLFUNC_STACK | 0; hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_AP) | BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_ADHOC); hw->wiphy->rts_threshold = 2347; hw->queues = AC_MAX; hw->extra_tx_headroom = RTL_TX_HEADER_SIZE; hw->channel_change_time = 100; hw->max_listen_interval = 10; hw->max_rate_tries = 4; hw->sta_data_size = sizeof(struct rtl_sta_info); if (is_valid_ether_addr(rtlefuse->dev_addr)) { SET_IEEE80211_PERM_ADDR(hw, rtlefuse->dev_addr); } else { u8 rtlmac1[] = { 0x00, 0xe0, 0x4c, 0x81, 0x92, 0x00 }; get_random_bytes((rtlmac1 + (ETH_ALEN - 1)), 1); SET_IEEE80211_PERM_ADDR(hw, rtlmac1); } }
void rtl_watchdog_wq_callback(void *data) { struct rtl_works *rtlworks = container_of_dwork_rtl(data, struct rtl_works, watchdog_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)); bool busytraffic = false; bool higher_busytraffic = false; bool higher_busyrxtraffic = false; u8 idx, tid; u32 rx_cnt_inp4eriod = 0; u32 tx_cnt_inp4eriod = 0; u32 aver_rx_cnt_inperiod = 0; u32 aver_tx_cnt_inperiod = 0; u32 aver_tidtx_inperiod[MAX_TID_COUNT] = {0}; u32 tidtx_inp4eriod[MAX_TID_COUNT] = {0}; bool enter_ps = false; if (is_hal_stop(rtlhal)) return; if (mac->link_state > MAC80211_NOLINK) { if (mac->cnt_after_linked < 20) mac->cnt_after_linked++; } else { mac->cnt_after_linked = 0; } if (mac->link_state >= MAC80211_LINKED) { for (idx = 0; idx <= 2; idx++) { rtlpriv->link_info.num_rx_in4period[idx] = rtlpriv->link_info.num_rx_in4period[idx + 1]; rtlpriv->link_info.num_tx_in4period[idx] = rtlpriv->link_info.num_tx_in4period[idx + 1]; } rtlpriv->link_info.num_rx_in4period[3] = rtlpriv->link_info.num_rx_inperiod; rtlpriv->link_info.num_tx_in4period[3] = rtlpriv->link_info.num_tx_inperiod; for (idx = 0; idx <= 3; idx++) { rx_cnt_inp4eriod += rtlpriv->link_info.num_rx_in4period[idx]; tx_cnt_inp4eriod += rtlpriv->link_info.num_tx_in4period[idx]; } aver_rx_cnt_inperiod = rx_cnt_inp4eriod / 4; aver_tx_cnt_inperiod = tx_cnt_inp4eriod / 4; if (aver_rx_cnt_inperiod > 100 || aver_tx_cnt_inperiod > 100) busytraffic = true; if (aver_rx_cnt_inperiod > 4000 || aver_tx_cnt_inperiod > 4000) { higher_busytraffic = true; if (aver_rx_cnt_inperiod > 5000) higher_busyrxtraffic = true; } for (tid = 0; tid <= 7; tid++) { for (idx = 0; idx <= 2; idx++) rtlpriv->link_info.tidtx_in4period[tid][idx] = rtlpriv->link_info.tidtx_in4period[tid] [idx + 1]; rtlpriv->link_info.tidtx_in4period[tid][3] = rtlpriv->link_info.tidtx_inperiod[tid]; for (idx = 0; idx <= 3; idx++) tidtx_inp4eriod[tid] += rtlpriv->link_info.tidtx_in4period[tid][idx]; aver_tidtx_inperiod[tid] = tidtx_inp4eriod[tid] / 4; if (aver_tidtx_inperiod[tid] > 5000) rtlpriv->link_info.higher_busytxtraffic[tid] = true; else rtlpriv->link_info.higher_busytxtraffic[tid] = false; } if (((rtlpriv->link_info.num_rx_inperiod + rtlpriv->link_info.num_tx_inperiod) > 8) || (rtlpriv->link_info.num_rx_inperiod > 2)) enter_ps = false; else enter_ps = true; if (enter_ps) rtl_lps_enter(hw); else rtl_lps_leave(hw); } rtlpriv->link_info.num_rx_inperiod = 0; rtlpriv->link_info.num_tx_inperiod = 0; for (tid = 0; tid <= 7; tid++) rtlpriv->link_info.tidtx_inperiod[tid] = 0; rtlpriv->link_info.busytraffic = busytraffic; rtlpriv->link_info.higher_busytraffic = higher_busytraffic; rtlpriv->link_info.higher_busyrxtraffic = higher_busyrxtraffic; rtlpriv->cfg->ops->dm_watchdog(hw); }
void rtl_get_tcb_desc(struct ieee80211_hw *hw, struct ieee80211_tx_info *info, struct ieee80211_sta *sta, struct sk_buff *skb, struct rtl_tcb_desc *tcb_desc) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_mac *rtlmac = rtl_mac(rtl_priv(hw)); struct ieee80211_hdr *hdr = rtl_get_hdr(skb); struct ieee80211_rate *txrate; __le16 fc = hdr->frame_control; txrate = ieee80211_get_tx_rate(hw, info); if (txrate) tcb_desc->hw_rate = txrate->hw_value; else tcb_desc->hw_rate = 0; if (ieee80211_is_data(fc)) { /* *we set data rate INX 0 *in rtl_rc.c if skb is special data or *mgt which need low data rate. */ /* *So tcb_desc->hw_rate is just used for *special data and mgt frames */ if (info->control.rates[0].idx == 0 || ieee80211_is_nullfunc(fc)) { tcb_desc->use_driver_rate = true; tcb_desc->ratr_index = RATR_INX_WIRELESS_MC; tcb_desc->disable_ratefallback = 1; } else { /* *because hw will nerver use hw_rate *when tcb_desc->use_driver_rate = false *so we never set highest N rate here, *and N rate will all be controlled by FW *when tcb_desc->use_driver_rate = false */ if (sta && (sta->ht_cap.ht_supported)) { tcb_desc->hw_rate = _rtl_get_highest_n_rate(hw); } else { if (rtlmac->mode == WIRELESS_MODE_B) { tcb_desc->hw_rate = rtlpriv->cfg->maps[RTL_RC_CCK_RATE11M]; } else { tcb_desc->hw_rate = rtlpriv->cfg->maps[RTL_RC_OFDM_RATE54M]; } } } if (is_multicast_ether_addr(ieee80211_get_DA(hdr))) tcb_desc->multicast = 1; else if (is_broadcast_ether_addr(ieee80211_get_DA(hdr))) tcb_desc->broadcast = 1; _rtl_txrate_selectmode(hw, sta, tcb_desc); _rtl_query_bandwidth_mode(hw, sta, tcb_desc); _rtl_qurey_shortpreamble_mode(hw, tcb_desc, info); _rtl_query_shortgi(hw, sta, tcb_desc, info); _rtl_query_protection_mode(hw, tcb_desc, info); } else { tcb_desc->use_driver_rate = true; tcb_desc->ratr_index = RATR_INX_WIRELESS_MC; tcb_desc->disable_ratefallback = 1; tcb_desc->mac_id = 0; tcb_desc->packet_bw = false; } }
static void _rtl92s_dm_refresh_rateadaptive_mask(struct ieee80211_hw *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 rate_adaptive *ra = &(rtlpriv->ra); struct ieee80211_sta *sta = NULL; u32 low_rssi_thresh = 0; u32 middle_rssi_thresh = 0; u32 high_rssi_thresh = 0; if (is_hal_stop(rtlhal)) return; if (!rtlpriv->dm.useramask) return; if (hal_get_firmwareversion(rtlpriv) >= 61 && !rtlpriv->dm.inform_fw_driverctrldm) { rtl92s_phy_set_fw_cmd(hw, FW_CMD_CTRL_DM_BY_DRIVER); rtlpriv->dm.inform_fw_driverctrldm = true; } if ((mac->link_state == MAC80211_LINKED) && (mac->opmode == NL80211_IFTYPE_STATION)) { switch (ra->pre_ratr_state) { case DM_RATR_STA_HIGH: high_rssi_thresh = 40; middle_rssi_thresh = 30; low_rssi_thresh = 20; break; case DM_RATR_STA_MIDDLE: high_rssi_thresh = 44; middle_rssi_thresh = 30; low_rssi_thresh = 20; break; case DM_RATR_STA_LOW: high_rssi_thresh = 44; middle_rssi_thresh = 34; low_rssi_thresh = 20; break; case DM_RATR_STA_ULTRALOW: high_rssi_thresh = 44; middle_rssi_thresh = 34; low_rssi_thresh = 24; break; default: high_rssi_thresh = 44; middle_rssi_thresh = 34; low_rssi_thresh = 24; break; } if (rtlpriv->dm.undec_sm_pwdb > (long)high_rssi_thresh) { ra->ratr_state = DM_RATR_STA_HIGH; } else if (rtlpriv->dm.undec_sm_pwdb > (long)middle_rssi_thresh) { ra->ratr_state = DM_RATR_STA_LOW; } else if (rtlpriv->dm.undec_sm_pwdb > (long)low_rssi_thresh) { ra->ratr_state = DM_RATR_STA_LOW; } else { ra->ratr_state = DM_RATR_STA_ULTRALOW; } if (ra->pre_ratr_state != ra->ratr_state) { RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD, "RSSI = %ld RSSI_LEVEL = %d PreState = %d, CurState = %d\n", rtlpriv->dm.undec_sm_pwdb, ra->ratr_state, ra->pre_ratr_state, ra->ratr_state); rcu_read_lock(); sta = rtl_find_sta(hw, mac->bssid); if (sta) rtlpriv->cfg->ops->update_rate_tbl(hw, sta, ra->ratr_state); rcu_read_unlock(); ra->pre_ratr_state = ra->ratr_state; } } }
void rtl92c_set_key(struct ieee80211_hw *hw, u32 key_index, u8 *p_macaddr, bool is_group, u8 enc_algo, bool is_wepkey, bool clear_all) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); u8 *macaddr = p_macaddr; u32 entry_id = 0; bool is_pairwise = false; static u8 cam_const_addr[4][6] = { {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x01}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x02}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x03} }; static u8 cam_const_broad[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; if (clear_all) { u8 idx = 0; u8 cam_offset = 0; u8 clear_number = 5; RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, "clear_all\n"); for (idx = 0; idx < clear_number; idx++) { rtl_cam_mark_invalid(hw, cam_offset + idx); rtl_cam_empty_entry(hw, cam_offset + idx); if (idx < 5) { memset(rtlpriv->sec.key_buf[idx], 0, MAX_KEY_LEN); rtlpriv->sec.key_len[idx] = 0; } } } else { switch (enc_algo) { case WEP40_ENCRYPTION: enc_algo = CAM_WEP40; break; case WEP104_ENCRYPTION: enc_algo = CAM_WEP104; break; case TKIP_ENCRYPTION: enc_algo = CAM_TKIP; break; case AESCCMP_ENCRYPTION: enc_algo = CAM_AES; break; default: RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "illegal switch case\n"); enc_algo = CAM_TKIP; break; } if (is_wepkey || rtlpriv->sec.use_defaultkey) { macaddr = cam_const_addr[key_index]; entry_id = key_index; } else { if (is_group) { macaddr = cam_const_broad; entry_id = key_index; } else { if (mac->opmode == NL80211_IFTYPE_AP || mac->opmode == NL80211_IFTYPE_MESH_POINT) { entry_id = rtl_cam_get_free_entry(hw, p_macaddr); if (entry_id >= TOTAL_CAM_ENTRY) { RT_TRACE(rtlpriv, COMP_SEC, DBG_EMERG, "Can not find free hw security cam entry\n"); return; } } else { entry_id = CAM_PAIRWISE_KEY_POSITION; } key_index = PAIRWISE_KEYIDX; is_pairwise = true; } } if (rtlpriv->sec.key_len[key_index] == 0) { RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, "delete one entry\n"); if (mac->opmode == NL80211_IFTYPE_AP || mac->opmode == NL80211_IFTYPE_MESH_POINT) rtl_cam_del_entry(hw, p_macaddr); rtl_cam_delete_one_entry(hw, p_macaddr, entry_id); } else { RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD, "The insert KEY length is %d\n", rtlpriv->sec.key_len[PAIRWISE_KEYIDX]); RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD, "The insert KEY is %x %x\n", rtlpriv->sec.key_buf[0][0], rtlpriv->sec.key_buf[0][1]); RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, "add one entry\n"); if (is_pairwise) { RT_PRINT_DATA(rtlpriv, COMP_SEC, DBG_LOUD, "Pairwise Key content", rtlpriv->sec.pairwise_key, rtlpriv->sec. key_len[PAIRWISE_KEYIDX]); RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, "set Pairwise key\n"); rtl_cam_add_one_entry(hw, macaddr, key_index, entry_id, enc_algo, CAM_CONFIG_NO_USEDK, rtlpriv->sec. key_buf[key_index]); } else { RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, "set group key\n"); if (mac->opmode == NL80211_IFTYPE_ADHOC) { rtl_cam_add_one_entry(hw, rtlefuse->dev_addr, PAIRWISE_KEYIDX, CAM_PAIRWISE_KEY_POSITION, enc_algo, CAM_CONFIG_NO_USEDK, rtlpriv->sec.key_buf [entry_id]); } rtl_cam_add_one_entry(hw, macaddr, key_index, entry_id, enc_algo, CAM_CONFIG_NO_USEDK, rtlpriv->sec.key_buf[entry_id]); } } } }
static void _rtl92s_dm_dynamic_txpower(struct ieee80211_hw *hw) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_phy *rtlphy = &(rtlpriv->phy); struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); long undec_sm_pwdb; long txpwr_threshold_lv1, txpwr_threshold_lv2; /* 2T2R TP issue */ if (rtlphy->rf_type == RF_2T2R) return; if (!rtlpriv->dm.dynamic_txpower_enable || rtlpriv->dm.dm_flag & HAL_DM_HIPWR_DISABLE) { rtlpriv->dm.dynamic_txhighpower_lvl = TX_HIGHPWR_LEVEL_NORMAL; return; } if ((mac->link_state < MAC80211_LINKED) && (rtlpriv->dm.entry_min_undec_sm_pwdb == 0)) { RT_TRACE(rtlpriv, COMP_POWER, DBG_TRACE, "Not connected to any\n"); rtlpriv->dm.dynamic_txhighpower_lvl = TX_HIGHPWR_LEVEL_NORMAL; rtlpriv->dm.last_dtp_lvl = TX_HIGHPWR_LEVEL_NORMAL; return; } if (mac->link_state >= MAC80211_LINKED) { if (mac->opmode == NL80211_IFTYPE_ADHOC) { undec_sm_pwdb = rtlpriv->dm.entry_min_undec_sm_pwdb; RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, "AP Client PWDB = 0x%lx\n", undec_sm_pwdb); } else { undec_sm_pwdb = rtlpriv->dm.undec_sm_pwdb; RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, "STA Default Port PWDB = 0x%lx\n", undec_sm_pwdb); } } else { undec_sm_pwdb = rtlpriv->dm.entry_min_undec_sm_pwdb; RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, "AP Ext Port PWDB = 0x%lx\n", undec_sm_pwdb); } txpwr_threshold_lv2 = TX_POWER_NEAR_FIELD_THRESH_LVL2; txpwr_threshold_lv1 = TX_POWER_NEAR_FIELD_THRESH_LVL1; if (rtl_get_bbreg(hw, 0xc90, MASKBYTE0) == 1) rtlpriv->dm.dynamic_txhighpower_lvl = TX_HIGHPWR_LEVEL_NORMAL; else if (undec_sm_pwdb >= txpwr_threshold_lv2) rtlpriv->dm.dynamic_txhighpower_lvl = TX_HIGHPWR_LEVEL_NORMAL2; else if ((undec_sm_pwdb < (txpwr_threshold_lv2 - 3)) && (undec_sm_pwdb >= txpwr_threshold_lv1)) rtlpriv->dm.dynamic_txhighpower_lvl = TX_HIGHPWR_LEVEL_NORMAL1; else if (undec_sm_pwdb < (txpwr_threshold_lv1 - 3)) rtlpriv->dm.dynamic_txhighpower_lvl = TX_HIGHPWR_LEVEL_NORMAL; if ((rtlpriv->dm.dynamic_txhighpower_lvl != rtlpriv->dm.last_dtp_lvl)) rtl92s_phy_set_txpower(hw, rtlphy->current_channel); rtlpriv->dm.last_dtp_lvl = rtlpriv->dm.dynamic_txhighpower_lvl; }
static bool _rtl92cu_phy_set_rf_power_state(struct ieee80211_hw *hw, enum rf_pwrstate rfpwr_state) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); bool bresult = true; u8 i, queue_id; struct rtl8192_tx_ring *ring = NULL; switch (rfpwr_state) { case ERFON: if ((ppsc->rfpwr_state == ERFOFF) && RT_IN_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC)) { bool rtstatus; u32 InitializeCount = 0; do { InitializeCount++; RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, "IPS Set eRf nic enable\n"); rtstatus = rtl_ps_enable_nic(hw); } while (!rtstatus && (InitializeCount < 10)); RT_CLEAR_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC); } else { RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, "Set ERFON sleeped:%d ms\n", jiffies_to_msecs(jiffies - ppsc->last_sleep_jiffies)); ppsc->last_awake_jiffies = jiffies; rtl92ce_phy_set_rf_on(hw); } if (mac->link_state == MAC80211_LINKED) { rtlpriv->cfg->ops->led_control(hw, LED_CTL_LINK); } else { rtlpriv->cfg->ops->led_control(hw, LED_CTL_NO_LINK); } break; case ERFOFF: for (queue_id = 0, i = 0; queue_id < RTL_PCI_MAX_TX_QUEUE_COUNT;) { ring = &pcipriv->dev.tx_ring[queue_id]; if (skb_queue_len(&ring->queue) == 0 || queue_id == BEACON_QUEUE) { queue_id++; continue; } else { RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, "eRf Off/Sleep: %d times TcbBusyQueue[%d] =%d before doze!\n", i + 1, queue_id, skb_queue_len(&ring->queue)); udelay(10); i++; } if (i >= MAX_DOZE_WAITING_TIMES_9x) { RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, "ERFOFF: %d times TcbBusyQueue[%d] = %d !\n", MAX_DOZE_WAITING_TIMES_9x, queue_id, skb_queue_len(&ring->queue)); break; } } if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_HALT_NIC) { RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, "IPS Set eRf nic disable\n"); rtl_ps_disable_nic(hw); RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC); } else { if (ppsc->rfoff_reason == RF_CHANGE_BY_IPS) { rtlpriv->cfg->ops->led_control(hw, LED_CTL_NO_LINK); } else { rtlpriv->cfg->ops->led_control(hw, LED_CTL_POWER_OFF); } } break; case ERFSLEEP: if (ppsc->rfpwr_state == ERFOFF) return false; for (queue_id = 0, i = 0; queue_id < RTL_PCI_MAX_TX_QUEUE_COUNT;) { ring = &pcipriv->dev.tx_ring[queue_id]; if (skb_queue_len(&ring->queue) == 0) { queue_id++; continue; } else { RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, "eRf Off/Sleep: %d times TcbBusyQueue[%d] =%d before doze!\n", i + 1, queue_id, skb_queue_len(&ring->queue)); udelay(10); i++; } if (i >= MAX_DOZE_WAITING_TIMES_9x) { RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, "ERFSLEEP: %d times TcbBusyQueue[%d] = %d !\n", MAX_DOZE_WAITING_TIMES_9x, queue_id, skb_queue_len(&ring->queue)); break; } } RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, "Set ERFSLEEP awaked:%d ms\n", jiffies_to_msecs(jiffies - ppsc->last_awake_jiffies)); ppsc->last_sleep_jiffies = jiffies; _rtl92c_phy_set_rf_sleep(hw); break; default: RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "switch case not processed\n"); bresult = false; break; } if (bresult) ppsc->rfpwr_state = rfpwr_state; return bresult; }
static void _rtl92s_dm_check_edca_turbo(struct ieee80211_hw *hw) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); static u64 last_txok_cnt; static u64 last_rxok_cnt; u64 cur_txok_cnt = 0; u64 cur_rxok_cnt = 0; u32 edca_be_ul = edca_setting_ul[mac->vendor]; u32 edca_be_dl = edca_setting_dl[mac->vendor]; u32 edca_gmode = edca_setting_dl_gmode[mac->vendor]; if (mac->link_state != MAC80211_LINKED) { rtlpriv->dm.current_turbo_edca = false; goto dm_checkedcaturbo_exit; } if ((!rtlpriv->dm.is_any_nonbepkts) && (!rtlpriv->dm.disable_framebursting)) { cur_txok_cnt = rtlpriv->stats.txbytesunicast - last_txok_cnt; cur_rxok_cnt = rtlpriv->stats.rxbytesunicast - last_rxok_cnt; if (rtlpriv->phy.rf_type == RF_1T2R) { if (cur_txok_cnt > 4 * cur_rxok_cnt) { /* Uplink TP is present. */ if (rtlpriv->dm.is_cur_rdlstate || !rtlpriv->dm.current_turbo_edca) { rtl_write_dword(rtlpriv, EDCAPARA_BE, edca_be_ul); rtlpriv->dm.is_cur_rdlstate = false; } } else {/* Balance TP is present. */ if (!rtlpriv->dm.is_cur_rdlstate || !rtlpriv->dm.current_turbo_edca) { if (mac->mode == WIRELESS_MODE_G || mac->mode == WIRELESS_MODE_B) rtl_write_dword(rtlpriv, EDCAPARA_BE, edca_gmode); else rtl_write_dword(rtlpriv, EDCAPARA_BE, edca_be_dl); rtlpriv->dm.is_cur_rdlstate = true; } } rtlpriv->dm.current_turbo_edca = true; } else { if (cur_rxok_cnt > 4 * cur_txok_cnt) { if (!rtlpriv->dm.is_cur_rdlstate || !rtlpriv->dm.current_turbo_edca) { if (mac->mode == WIRELESS_MODE_G || mac->mode == WIRELESS_MODE_B) rtl_write_dword(rtlpriv, EDCAPARA_BE, edca_gmode); else rtl_write_dword(rtlpriv, EDCAPARA_BE, edca_be_dl); rtlpriv->dm.is_cur_rdlstate = true; } } else { if (rtlpriv->dm.is_cur_rdlstate || !rtlpriv->dm.current_turbo_edca) { rtl_write_dword(rtlpriv, EDCAPARA_BE, edca_be_ul); rtlpriv->dm.is_cur_rdlstate = false; } } rtlpriv->dm.current_turbo_edca = true; } } else { if (rtlpriv->dm.current_turbo_edca) { u8 tmp = AC0_BE; rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_AC_PARAM, &tmp); rtlpriv->dm.current_turbo_edca = false; } } dm_checkedcaturbo_exit: rtlpriv->dm.is_any_nonbepkts = false; last_txok_cnt = rtlpriv->stats.txbytesunicast; last_rxok_cnt = rtlpriv->stats.rxbytesunicast; }
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; /* call before RF off */ if (rtlpriv->cfg->ops->get_btc_status()) rtlpriv->btcoexist.btc_ops->btc_ips_notify(rtlpriv, ppsc->inactive_pwrstate); /*rtl_pci_reset_trx_ring(hw); */ _rtl_ps_inactive_ps(hw); } } }
static int rtl92su_init_sw_vars(struct ieee80211_hw *hw) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); struct rtl_usb *rtlusb = rtl_usbdev(rtl_usbpriv(hw)); int err = 0; u16 earlyrxthreshold = 7; hw->wiphy->max_scan_ssids = 1; rtlpriv->dm.dm_initialgain_enable = true; rtlpriv->dm.dm_flag = 0; rtlpriv->dm.disable_framebursting = false; rtlpriv->dm.thermalvalue = 0; rtlpriv->dm.useramask = true; rtlpriv->dbg.global_debuglevel = rtlpriv->cfg->mod_params->debug; /* compatible 5G band 91su just 2.4G band & smsp */ rtlpriv->rtlhal.current_bandtype = BAND_ON_2_4G; rtlpriv->rtlhal.bandset = BAND_ON_2_4G; rtlpriv->rtlhal.macphymode = SINGLEMAC_SINGLEPHY; mac->rx_conf = RCR_APPFCS | RCR_APWRMGT | /*RCR_ADD3 |*/ RCR_ACF | RCR_AMF | RCR_ADF | RCR_APP_MIC | RCR_APP_ICV | RCR_AICV | /* Accept ICV error, CRC32 Error */ RCR_ACRC32 | RCR_AB | /* Accept Broadcast, Multicast */ RCR_AM | /* Accept Physical match */ RCR_APM | /* Accept Destination Address packets */ /*RCR_AAP |*/ RCR_APP_PHYST_STAFF | /* Accept PHY status */ RCR_APP_PHYST_RXFF | RCR_RX_TCPOFDL_EN | (earlyrxthreshold << RCR_FIFO_OFFSET); rtlusb->irq_mask[0] = 0; rtlusb->irq_mask[1] = (u32) 0; /* for LPS & IPS */ rtlpriv->psc.inactiveps = rtlpriv->cfg->mod_params->inactiveps; rtlpriv->psc.swctrl_lps = rtlpriv->cfg->mod_params->swctrl_lps; rtlpriv->psc.fwctrl_lps = rtlpriv->cfg->mod_params->fwctrl_lps; if (!rtlpriv->psc.inactiveps) pr_info("Power Save off (module option)\n"); if (!rtlpriv->psc.fwctrl_lps) pr_info("FW Power Save off (module option)\n"); rtlpriv->psc.reg_fwctrl_lps = 3; rtlpriv->psc.reg_max_lps_awakeintvl = 5; rtlpriv->psc.hwradiooff = false; if (rtlpriv->psc.reg_fwctrl_lps == 1) rtlpriv->psc.fwctrl_psmode = FW_PS_MIN_MODE; else if (rtlpriv->psc.reg_fwctrl_lps == 2) rtlpriv->psc.fwctrl_psmode = FW_PS_MAX_MODE; else if (rtlpriv->psc.reg_fwctrl_lps == 3) rtlpriv->psc.fwctrl_psmode = FW_PS_DTIM_MODE; /* for firmware buf */ rtlpriv->rtlhal.pfirmware = vzalloc(sizeof(struct rt_firmware)); if (!rtlpriv->rtlhal.pfirmware) return -ENOMEM; rtlpriv->max_fw_size = RTL8192_MAX_RAW_FIRMWARE_CODE_SIZE; pr_info("Driver for Realtek RTL8192SU/RTL8191SU/RTL8188SU\n" "Loading firmware %s\n", rtlpriv->cfg->fw_name); /* request fw */ err = request_firmware_nowait(THIS_MODULE, 1, rtlpriv->cfg->fw_name, rtlpriv->io.dev, GFP_KERNEL, hw, rtl92su_fw_cb); if (err) { RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "Failed to request firmware!\n"); return 1; } return err; }
/* For sw LPS*/ void rtl_swlps_beacon(struct ieee80211_hw *hw, void *data, unsigned int len) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); struct ieee80211_hdr *hdr = data; struct ieee80211_tim_ie *tim_ie; u8 *tim; u8 tim_len; bool u_buffed; bool m_buffed; if (mac->opmode != NL80211_IFTYPE_STATION) return; if (!rtlpriv->psc.swctrl_lps) return; if (rtlpriv->mac80211.link_state != MAC80211_LINKED) return; if (!rtlpriv->psc.sw_ps_enabled) return; if (rtlpriv->psc.fwctrl_lps) return; if (likely(!(hw->conf.flags & IEEE80211_CONF_PS))) return; /* check if this really is a beacon */ if (!ieee80211_is_beacon(hdr->frame_control)) 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; rtlpriv->psc.last_beacon = jiffies; tim = rtl_find_ie(data, len - FCS_LEN, WLAN_EID_TIM); if (!tim) return; if (tim[1] < sizeof(*tim_ie)) return; tim_len = tim[1]; tim_ie = (struct ieee80211_tim_ie *) &tim[2]; 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 { RT_TRACE(rtlpriv, COMP_POWER, DBG_DMESG, "u_bufferd: %x, m_buffered: %x\n", u_buffed, m_buffed); } }
/********************************************************* * * wq & timer callback functions * *********************************************************/ void rtl_watchdog_wq_callback(void *data) { struct rtl_works *rtlworks = container_of_dwork_rtl(data, struct rtl_works, watchdog_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)); bool busytraffic = false; bool higher_busytraffic = false; bool higher_busyrxtraffic = false; u8 idx, tid; u32 rx_cnt_inp4eriod = 0; u32 tx_cnt_inp4eriod = 0; u32 aver_rx_cnt_inperiod = 0; u32 aver_tx_cnt_inperiod = 0; u32 aver_tidtx_inperiod[MAX_TID_COUNT] = {0}; u32 tidtx_inp4eriod[MAX_TID_COUNT] = {0}; bool enter_ps = false; if (is_hal_stop(rtlhal)) return; /* <1> Determine if action frame is allowed */ if (mac->link_state > MAC80211_NOLINK) { if (mac->cnt_after_linked < 20) mac->cnt_after_linked++; } else { mac->cnt_after_linked = 0; } /* *<2> to check if traffic busy, if * busytraffic we don't change channel */ if (mac->link_state >= MAC80211_LINKED) { /* (1) get aver_rx_cnt_inperiod & aver_tx_cnt_inperiod */ for (idx = 0; idx <= 2; idx++) { rtlpriv->link_info.num_rx_in4period[idx] = rtlpriv->link_info.num_rx_in4period[idx + 1]; rtlpriv->link_info.num_tx_in4period[idx] = rtlpriv->link_info.num_tx_in4period[idx + 1]; } rtlpriv->link_info.num_rx_in4period[3] = rtlpriv->link_info.num_rx_inperiod; rtlpriv->link_info.num_tx_in4period[3] = rtlpriv->link_info.num_tx_inperiod; for (idx = 0; idx <= 3; idx++) { rx_cnt_inp4eriod += rtlpriv->link_info.num_rx_in4period[idx]; tx_cnt_inp4eriod += rtlpriv->link_info.num_tx_in4period[idx]; } aver_rx_cnt_inperiod = rx_cnt_inp4eriod / 4; aver_tx_cnt_inperiod = tx_cnt_inp4eriod / 4; /* (2) check traffic busy */ if (aver_rx_cnt_inperiod > 100 || aver_tx_cnt_inperiod > 100) busytraffic = true; /* Higher Tx/Rx data. */ if (aver_rx_cnt_inperiod > 4000 || aver_tx_cnt_inperiod > 4000) { higher_busytraffic = true; /* Extremely high Rx data. */ if (aver_rx_cnt_inperiod > 5000) higher_busyrxtraffic = true; } /* check every tid's tx traffic */ for (tid = 0; tid <= 7; tid++) { for (idx = 0; idx <= 2; idx++) rtlpriv->link_info.tidtx_in4period[tid][idx] = rtlpriv->link_info.tidtx_in4period[tid] [idx + 1]; rtlpriv->link_info.tidtx_in4period[tid][3] = rtlpriv->link_info.tidtx_inperiod[tid]; for (idx = 0; idx <= 3; idx++) tidtx_inp4eriod[tid] += rtlpriv->link_info.tidtx_in4period[tid][idx]; aver_tidtx_inperiod[tid] = tidtx_inp4eriod[tid] / 4; if (aver_tidtx_inperiod[tid] > 5000) rtlpriv->link_info.higher_busytxtraffic[tid] = true; else rtlpriv->link_info.higher_busytxtraffic[tid] = false; } if (((rtlpriv->link_info.num_rx_inperiod + rtlpriv->link_info.num_tx_inperiod) > 8) || (rtlpriv->link_info.num_rx_inperiod > 2)) enter_ps = false; else enter_ps = true; /* LeisurePS only work in infra mode. */ if (enter_ps) rtl_lps_enter(hw); else rtl_lps_leave(hw); } rtlpriv->link_info.num_rx_inperiod = 0; rtlpriv->link_info.num_tx_inperiod = 0; for (tid = 0; tid <= 7; tid++) rtlpriv->link_info.tidtx_inperiod[tid] = 0; rtlpriv->link_info.busytraffic = busytraffic; rtlpriv->link_info.higher_busytraffic = higher_busytraffic; rtlpriv->link_info.higher_busyrxtraffic = higher_busyrxtraffic; /* <3> DM */ rtlpriv->cfg->ops->dm_watchdog(hw); }
static void rtl_op_configure_filter(struct ieee80211_hw *hw, unsigned int changed_flags, unsigned int *new_flags, u64 multicast) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); u32 rx_conf; *new_flags &= RTL_SUPPORTED_FILTERS; if (!changed_flags) return; /* if ssid not set to hw don't check bssid * here just used for linked scanning, & linked * and nolink check bssid is set in set network_type */ if ((changed_flags & FIF_BCN_PRBRESP_PROMISC) && (mac->link_state >= MAC80211_LINKED)) { if (mac->opmode != NL80211_IFTYPE_AP && mac->opmode != NL80211_IFTYPE_MESH_POINT) { if (*new_flags & FIF_BCN_PRBRESP_PROMISC) { rtlpriv->cfg->ops->set_chk_bssid(hw, false); } else { rtlpriv->cfg->ops->set_chk_bssid(hw, true); } } } /* must be called after set_chk_bssid since that function modifies the * RCR register too. */ rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_RCR, (u8 *)(&rx_conf)); /*TODO: we disable broadcase now, so enable here */ if (changed_flags & FIF_ALLMULTI) { if (*new_flags & FIF_ALLMULTI) { rx_conf |= rtlpriv->cfg->maps[MAC_RCR_AM] | rtlpriv->cfg->maps[MAC_RCR_AB]; RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, "Enable receive multicast frame\n"); } else { rx_conf &= ~(rtlpriv->cfg->maps[MAC_RCR_AM] | rtlpriv->cfg->maps[MAC_RCR_AB]); RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, "Disable receive multicast frame\n"); } } if (changed_flags & FIF_FCSFAIL) { if (*new_flags & FIF_FCSFAIL) { rx_conf |= rtlpriv->cfg->maps[MAC_RCR_ACRC32]; RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, "Enable receive FCS error frame\n"); } else { rx_conf &= ~rtlpriv->cfg->maps[MAC_RCR_ACRC32]; RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, "Disable receive FCS error frame\n"); } } if (changed_flags & FIF_CONTROL) { if (*new_flags & FIF_CONTROL) { rx_conf |= rtlpriv->cfg->maps[MAC_RCR_ACF]; RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, "Enable receive control frame\n"); } else { rx_conf &= ~rtlpriv->cfg->maps[MAC_RCR_ACF]; RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, "Disable receive control frame\n"); } } if (changed_flags & FIF_OTHER_BSS) { if (*new_flags & FIF_OTHER_BSS) { rx_conf |= rtlpriv->cfg->maps[MAC_RCR_AAP]; RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, "Enable receive other BSS's frame\n"); } else { rx_conf &= ~rtlpriv->cfg->maps[MAC_RCR_AAP]; RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, "Disable receive other BSS's frame\n"); } } rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RCR, (u8 *)(&rx_conf)); }
void rtl_recognize_peer(struct ieee80211_hw *hw, u8 *data, unsigned int len) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); struct ieee80211_hdr *hdr = (void *)data; u32 vendor = PEER_UNKNOWN; static u8 ap3_1[3] = { 0x00, 0x14, 0xbf }; static u8 ap3_2[3] = { 0x00, 0x1a, 0x70 }; static u8 ap3_3[3] = { 0x00, 0x1d, 0x7e }; static u8 ap4_1[3] = { 0x00, 0x90, 0xcc }; static u8 ap4_2[3] = { 0x00, 0x0e, 0x2e }; static u8 ap4_3[3] = { 0x00, 0x18, 0x02 }; static u8 ap4_4[3] = { 0x00, 0x17, 0x3f }; static u8 ap4_5[3] = { 0x00, 0x1c, 0xdf }; static u8 ap5_1[3] = { 0x00, 0x1c, 0xf0 }; static u8 ap5_2[3] = { 0x00, 0x21, 0x91 }; static u8 ap5_3[3] = { 0x00, 0x24, 0x01 }; static u8 ap5_4[3] = { 0x00, 0x15, 0xe9 }; static u8 ap5_5[3] = { 0x00, 0x17, 0x9A }; static u8 ap5_6[3] = { 0x00, 0x18, 0xE7 }; static u8 ap6_1[3] = { 0x00, 0x17, 0x94 }; static u8 ap7_1[3] = { 0x00, 0x14, 0xa4 }; if (mac->opmode != NL80211_IFTYPE_STATION) return; if (mac->link_state == MAC80211_NOLINK) { mac->vendor = PEER_UNKNOWN; return; } if (mac->cnt_after_linked > 2) return; /* check if this really is a beacon */ if (!ieee80211_is_beacon(hdr->frame_control)) return; /* min. beacon length + FCS_LEN */ if (len <= 40 + FCS_LEN) return; /* and only beacons from the associated BSSID, please */ if (!ether_addr_equal(hdr->addr3, rtlpriv->mac80211.bssid)) return; if (rtl_find_221_ie(hw, data, len)) vendor = mac->vendor; if ((memcmp(mac->bssid, ap5_1, 3) == 0) || (memcmp(mac->bssid, ap5_2, 3) == 0) || (memcmp(mac->bssid, ap5_3, 3) == 0) || (memcmp(mac->bssid, ap5_4, 3) == 0) || (memcmp(mac->bssid, ap5_5, 3) == 0) || (memcmp(mac->bssid, ap5_6, 3) == 0) || vendor == PEER_ATH) { vendor = PEER_ATH; RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, "=>ath find\n"); } else if ((memcmp(mac->bssid, ap4_4, 3) == 0) || (memcmp(mac->bssid, ap4_5, 3) == 0) || (memcmp(mac->bssid, ap4_1, 3) == 0) || (memcmp(mac->bssid, ap4_2, 3) == 0) || (memcmp(mac->bssid, ap4_3, 3) == 0) || vendor == PEER_RAL) { RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, "=>ral find\n"); vendor = PEER_RAL; } else if (memcmp(mac->bssid, ap6_1, 3) == 0 || vendor == PEER_CISCO) { vendor = PEER_CISCO; RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, "=>cisco find\n"); } else if ((memcmp(mac->bssid, ap3_1, 3) == 0) || (memcmp(mac->bssid, ap3_2, 3) == 0) || (memcmp(mac->bssid, ap3_3, 3) == 0) || vendor == PEER_BROAD) { RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, "=>broad find\n"); vendor = PEER_BROAD; } else if (memcmp(mac->bssid, ap7_1, 3) == 0 || vendor == PEER_MARV) { vendor = PEER_MARV; RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, "=>marv find\n"); } mac->vendor = vendor; }
static int rtl_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, struct ieee80211_vif *vif, struct ieee80211_sta *sta, struct ieee80211_key_conf *key) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); u8 key_type = NO_ENCRYPTION; u8 key_idx; bool group_key = false; bool wep_only = false; int err = 0; u8 mac_addr[ETH_ALEN]; u8 bcast_addr[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; if (rtlpriv->cfg->mod_params->sw_crypto || rtlpriv->sec.use_sw_sec) { RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, "not open hw encryption\n"); return -ENOSPC; /*User disabled HW-crypto */ } /* To support IBSS, use sw-crypto for GTK */ if (((vif->type == NL80211_IFTYPE_ADHOC) || (vif->type == NL80211_IFTYPE_MESH_POINT)) && !(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) return -ENOSPC; RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, "%s hardware based encryption for keyidx: %d, mac: %pM\n", cmd == SET_KEY ? "Using" : "Disabling", key->keyidx, sta ? sta->addr : bcast_addr); rtlpriv->sec.being_setkey = true; rtl_ips_nic_on(hw); mutex_lock(&rtlpriv->locks.conf_mutex); /* <1> get encryption alg */ switch (key->cipher) { case WLAN_CIPHER_SUITE_WEP40: key_type = WEP40_ENCRYPTION; RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, "alg:WEP40\n"); break; case WLAN_CIPHER_SUITE_WEP104: RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, "alg:WEP104\n"); key_type = WEP104_ENCRYPTION; break; case WLAN_CIPHER_SUITE_TKIP: key_type = TKIP_ENCRYPTION; RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, "alg:TKIP\n"); break; case WLAN_CIPHER_SUITE_CCMP: key_type = AESCCMP_ENCRYPTION; RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, "alg:CCMP\n"); break; case WLAN_CIPHER_SUITE_AES_CMAC: /*HW doesn't support CMAC encryption, use software CMAC */ key_type = AESCMAC_ENCRYPTION; RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, "alg:CMAC\n"); RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, "HW don't support CMAC encryption, use software CMAC\n"); err = -EOPNOTSUPP; goto out_unlock; default: RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "alg_err:%x!!!!\n", key->cipher); goto out_unlock; } if (key_type == WEP40_ENCRYPTION || key_type == WEP104_ENCRYPTION || mac->opmode == NL80211_IFTYPE_ADHOC) rtlpriv->sec.use_defaultkey = true; /* <2> get key_idx */ key_idx = (u8) (key->keyidx); if (key_idx > 3) goto out_unlock; /* <3> if pairwise key enable_hw_sec */ group_key = !(key->flags & IEEE80211_KEY_FLAG_PAIRWISE); /* wep always be group key, but there are two conditions: * 1) wep only: is just for wep enc, in this condition * rtlpriv->sec.pairwise_enc_algorithm == NO_ENCRYPTION * will be true & enable_hw_sec will be set when wep * key setting. * 2) wep(group) + AES(pairwise): some AP like cisco * may use it, in this condition enable_hw_sec will not * be set when wep key setting */ /* we must reset sec_info after lingked before set key, * or some flag will be wrong*/ if (vif->type == NL80211_IFTYPE_AP || vif->type == NL80211_IFTYPE_MESH_POINT) { if (!group_key || key_type == WEP40_ENCRYPTION || key_type == WEP104_ENCRYPTION) { if (group_key) wep_only = true; rtlpriv->cfg->ops->enable_hw_sec(hw); } } else { if ((!group_key) || (mac->opmode == NL80211_IFTYPE_ADHOC) || rtlpriv->sec.pairwise_enc_algorithm == NO_ENCRYPTION) { if (rtlpriv->sec.pairwise_enc_algorithm == NO_ENCRYPTION && (key_type == WEP40_ENCRYPTION || key_type == WEP104_ENCRYPTION)) wep_only = true; rtlpriv->sec.pairwise_enc_algorithm = key_type; RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, "set enable_hw_sec, key_type:%x(OPEN:0 WEP40:1 TKIP:2 AES:4 WEP104:5)\n", key_type); rtlpriv->cfg->ops->enable_hw_sec(hw); } } /* <4> set key based on cmd */ switch (cmd) { case SET_KEY: if (wep_only) { RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, "set WEP(group/pairwise) key\n"); /* Pairwise key with an assigned MAC address. */ rtlpriv->sec.pairwise_enc_algorithm = key_type; rtlpriv->sec.group_enc_algorithm = key_type; /*set local buf about wep key. */ memcpy(rtlpriv->sec.key_buf[key_idx], key->key, key->keylen); rtlpriv->sec.key_len[key_idx] = key->keylen; eth_zero_addr(mac_addr); } else if (group_key) { /* group key */ RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, "set group key\n"); /* group key */ rtlpriv->sec.group_enc_algorithm = key_type; /*set local buf about group key. */ memcpy(rtlpriv->sec.key_buf[key_idx], key->key, key->keylen); rtlpriv->sec.key_len[key_idx] = key->keylen; memcpy(mac_addr, bcast_addr, ETH_ALEN); } else { /* pairwise key */ RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, "set pairwise key\n"); if (!sta) { RT_ASSERT(false, "pairwise key without mac_addr\n"); err = -EOPNOTSUPP; goto out_unlock; } /* Pairwise key with an assigned MAC address. */ rtlpriv->sec.pairwise_enc_algorithm = key_type; /*set local buf about pairwise key. */ memcpy(rtlpriv->sec.key_buf[PAIRWISE_KEYIDX], key->key, key->keylen); rtlpriv->sec.key_len[PAIRWISE_KEYIDX] = key->keylen; rtlpriv->sec.pairwise_key = rtlpriv->sec.key_buf[PAIRWISE_KEYIDX]; memcpy(mac_addr, sta->addr, ETH_ALEN); } rtlpriv->cfg->ops->set_key(hw, key_idx, mac_addr, group_key, key_type, wep_only, false); /* <5> tell mac80211 do something: */ /*must use sw generate IV, or can not work !!!!. */ key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; key->hw_key_idx = key_idx; if (key_type == TKIP_ENCRYPTION) key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC; /*use software CCMP encryption for management frames (MFP) */ if (key_type == AESCCMP_ENCRYPTION) key->flags |= IEEE80211_KEY_FLAG_SW_MGMT_TX; break; case DISABLE_KEY: RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, "disable key delete one entry\n"); /*set local buf about wep key. */ if (vif->type == NL80211_IFTYPE_AP || vif->type == NL80211_IFTYPE_MESH_POINT) { if (sta) rtl_cam_del_entry(hw, sta->addr); } memset(rtlpriv->sec.key_buf[key_idx], 0, key->keylen); rtlpriv->sec.key_len[key_idx] = 0; eth_zero_addr(mac_addr); /* *mac80211 will delete entrys one by one, *so don't use rtl_cam_reset_all_entry *or clear all entry here. */ rtl_cam_delete_one_entry(hw, mac_addr, key_idx); rtl_cam_reset_sec_info(hw); break; default: RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "cmd_err:%x!!!!\n", cmd); } out_unlock: mutex_unlock(&rtlpriv->locks.conf_mutex); rtlpriv->sec.being_setkey = false; return err; }
static void _rtl_init_mac80211(struct ieee80211_hw *hw) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_hal *rtlhal = rtl_hal(rtlpriv); struct rtl_mac *rtlmac = rtl_mac(rtl_priv(hw)); struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); struct ieee80211_supported_band *sband; if (rtlhal->macphymode == SINGLEMAC_SINGLEPHY && rtlhal->bandset == BAND_ON_BOTH) { /* 1: 2.4 G bands */ /* <1> use mac->bands as mem for hw->wiphy->bands */ sband = &(rtlmac->bands[IEEE80211_BAND_2GHZ]); /* <2> set hw->wiphy->bands[IEEE80211_BAND_2GHZ] * to default value(1T1R) */ memcpy(&(rtlmac->bands[IEEE80211_BAND_2GHZ]), &rtl_band_2ghz, sizeof(struct ieee80211_supported_band)); /* <3> init ht cap base on ant_num */ _rtl_init_hw_ht_capab(hw, &sband->ht_cap); /* <4> set mac->sband to wiphy->sband */ hw->wiphy->bands[IEEE80211_BAND_2GHZ] = sband; /* 2: 5 G bands */ /* <1> use mac->bands as mem for hw->wiphy->bands */ sband = &(rtlmac->bands[IEEE80211_BAND_5GHZ]); /* <2> set hw->wiphy->bands[IEEE80211_BAND_5GHZ] * to default value(1T1R) */ memcpy(&(rtlmac->bands[IEEE80211_BAND_5GHZ]), &rtl_band_5ghz, sizeof(struct ieee80211_supported_band)); /* <3> init ht cap base on ant_num */ _rtl_init_hw_ht_capab(hw, &sband->ht_cap); /* <4> set mac->sband to wiphy->sband */ hw->wiphy->bands[IEEE80211_BAND_5GHZ] = sband; } else { if (rtlhal->current_bandtype == BAND_ON_2_4G) { /* <1> use mac->bands as mem for hw->wiphy->bands */ sband = &(rtlmac->bands[IEEE80211_BAND_2GHZ]); /* <2> set hw->wiphy->bands[IEEE80211_BAND_2GHZ] * to default value(1T1R) */ memcpy(&(rtlmac->bands[IEEE80211_BAND_2GHZ]), &rtl_band_2ghz, sizeof(struct ieee80211_supported_band)); /* <3> init ht cap base on ant_num */ _rtl_init_hw_ht_capab(hw, &sband->ht_cap); /* <4> set mac->sband to wiphy->sband */ hw->wiphy->bands[IEEE80211_BAND_2GHZ] = sband; } else if (rtlhal->current_bandtype == BAND_ON_5G) { /* <1> use mac->bands as mem for hw->wiphy->bands */ sband = &(rtlmac->bands[IEEE80211_BAND_5GHZ]); /* <2> set hw->wiphy->bands[IEEE80211_BAND_5GHZ] * to default value(1T1R) */ memcpy(&(rtlmac->bands[IEEE80211_BAND_5GHZ]), &rtl_band_5ghz, sizeof(struct ieee80211_supported_band)); /* <3> init ht cap base on ant_num */ _rtl_init_hw_ht_capab(hw, &sband->ht_cap); /* <4> set mac->sband to wiphy->sband */ hw->wiphy->bands[IEEE80211_BAND_5GHZ] = sband; } else { RT_TRACE(rtlpriv, COMP_INIT, DBG_EMERG, "Err BAND %d\n", rtlhal->current_bandtype); } } /* <5> set hw caps */ hw->flags = IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_RX_INCLUDES_FCS | IEEE80211_HW_AMPDU_AGGREGATION | IEEE80211_HW_CONNECTION_MONITOR | /* IEEE80211_HW_SUPPORTS_CQM_RSSI | */ IEEE80211_HW_REPORTS_TX_ACK_STATUS | 0; /* swlps or hwlps has been set in diff chip in init_sw_vars */ if (rtlpriv->psc.swctrl_lps) hw->flags |= IEEE80211_HW_SUPPORTS_PS | IEEE80211_HW_PS_NULLFUNC_STACK | /* IEEE80211_HW_SUPPORTS_DYNAMIC_PS | */ 0; hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_AP) | BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_ADHOC); hw->wiphy->rts_threshold = 2347; hw->queues = AC_MAX; hw->extra_tx_headroom = RTL_TX_HEADER_SIZE; /* TODO: Correct this value for our hw */ /* TODO: define these hard code value */ hw->channel_change_time = 100; hw->max_listen_interval = 10; hw->max_rate_tries = 4; /* hw->max_rates = 1; */ hw->sta_data_size = sizeof(struct rtl_sta_info); /* <6> mac address */ if (is_valid_ether_addr(rtlefuse->dev_addr)) { SET_IEEE80211_PERM_ADDR(hw, rtlefuse->dev_addr); } else { u8 rtlmac1[] = { 0x00, 0xe0, 0x4c, 0x81, 0x92, 0x00 }; get_random_bytes((rtlmac1 + (ETH_ALEN - 1)), 1); SET_IEEE80211_PERM_ADDR(hw, rtlmac1); } }
static int rtl_op_config(struct ieee80211_hw *hw, u32 changed) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_phy *rtlphy = &(rtlpriv->phy); struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); struct ieee80211_conf *conf = &hw->conf; if (mac->skip_scan) return 1; mutex_lock(&rtlpriv->locks.conf_mutex); if (changed & IEEE80211_CONF_CHANGE_LISTEN_INTERVAL) { /*BIT(2)*/ RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, "IEEE80211_CONF_CHANGE_LISTEN_INTERVAL\n"); } /*For IPS */ if (changed & IEEE80211_CONF_CHANGE_IDLE) { if (hw->conf.flags & IEEE80211_CONF_IDLE) rtl_ips_nic_off(hw); else rtl_ips_nic_on(hw); } else { /* *although rfoff may not cause by ips, but we will *check the reason in set_rf_power_state function */ if (unlikely(ppsc->rfpwr_state == ERFOFF)) rtl_ips_nic_on(hw); } /*For LPS */ if (changed & IEEE80211_CONF_CHANGE_PS) { cancel_delayed_work(&rtlpriv->works.ps_work); cancel_delayed_work(&rtlpriv->works.ps_rfon_wq); if (conf->flags & IEEE80211_CONF_PS) { rtlpriv->psc.sw_ps_enabled = true; /* sleep here is must, or we may recv the beacon and * cause mac80211 into wrong ps state, this will cause * power save nullfunc send fail, and further cause * pkt loss, So sleep must quickly but not immediatly * because that will cause nullfunc send by mac80211 * fail, and cause pkt loss, we have tested that 5mA * is worked very well */ if (!rtlpriv->psc.multi_buffered) queue_delayed_work(rtlpriv->works.rtl_wq, &rtlpriv->works.ps_work, MSECS(5)); } else { rtl_swlps_rf_awake(hw); rtlpriv->psc.sw_ps_enabled = false; } } if (changed & IEEE80211_CONF_CHANGE_RETRY_LIMITS) { RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, "IEEE80211_CONF_CHANGE_RETRY_LIMITS %x\n", hw->conf.long_frame_max_tx_count); mac->retry_long = hw->conf.long_frame_max_tx_count; mac->retry_short = hw->conf.long_frame_max_tx_count; rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RETRY_LIMIT, (u8 *) (&hw->conf. long_frame_max_tx_count)); } if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { struct ieee80211_channel *channel = hw->conf.chandef.chan; u8 wide_chan = (u8) channel->hw_value; if (mac->act_scanning) mac->n_channels++; if (rtlpriv->dm.supp_phymode_switch && mac->link_state < MAC80211_LINKED && !mac->act_scanning) { if (rtlpriv->cfg->ops->chk_switch_dmdp) rtlpriv->cfg->ops->chk_switch_dmdp(hw); } /* *because we should back channel to *current_network.chan in in scanning, *So if set_chan == current_network.chan *we should set it. *because mac80211 tell us wrong bw40 *info for cisco1253 bw20, so we modify *it here based on UPPER & LOWER */ switch (cfg80211_get_chandef_type(&hw->conf.chandef)) { case NL80211_CHAN_HT20: case NL80211_CHAN_NO_HT: /* SC */ mac->cur_40_prime_sc = PRIME_CHNL_OFFSET_DONT_CARE; rtlphy->current_chan_bw = HT_CHANNEL_WIDTH_20; mac->bw_40 = false; break; case NL80211_CHAN_HT40MINUS: /* SC */ mac->cur_40_prime_sc = PRIME_CHNL_OFFSET_UPPER; rtlphy->current_chan_bw = HT_CHANNEL_WIDTH_20_40; mac->bw_40 = true; /*wide channel */ wide_chan -= 2; break; case NL80211_CHAN_HT40PLUS: /* SC */ mac->cur_40_prime_sc = PRIME_CHNL_OFFSET_LOWER; rtlphy->current_chan_bw = HT_CHANNEL_WIDTH_20_40; mac->bw_40 = true; /*wide channel */ wide_chan += 2; break; default: mac->bw_40 = false; RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "switch case not processed\n"); break; } if (wide_chan <= 0) wide_chan = 1; /* In scanning, before we go offchannel we may send a ps = 1 * null to AP, and then we may send a ps = 0 null to AP quickly, * but first null may have caused AP to put lots of packet to * hw tx buffer. These packets must be tx'd before we go off * channel so we must delay more time to let AP flush these * packets before going offchannel, or dis-association or * delete BA will be caused by AP */ if (rtlpriv->mac80211.offchan_delay) { rtlpriv->mac80211.offchan_delay = false; mdelay(50); } rtlphy->current_channel = wide_chan; rtlpriv->cfg->ops->switch_channel(hw); rtlpriv->cfg->ops->set_channel_access(hw); rtlpriv->cfg->ops->set_bw_mode(hw, cfg80211_get_chandef_type(&hw->conf.chandef)); } mutex_unlock(&rtlpriv->locks.conf_mutex); return 0; }
/* Change current and default preamble mode.*/ static void rtl_lps_set_psmode(struct ieee80211_hw *hw, u8 rt_psmode) { 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 rpwm_val, fw_pwrmode; if (mac->opmode == NL80211_IFTYPE_ADHOC) return; if (mac->link_state != MAC80211_LINKED) return; if (ppsc->dot11_psmode == rt_psmode) 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 ((ppsc->fwctrl_lps) && ppsc->report_linked) { bool fw_current_inps; if (ppsc->dot11_psmode == EACTIVE) { RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, ("FW LPS leave ps_mode:%x\n", FW_PS_ACTIVE_MODE)); rpwm_val = 0x0C; /* RF on */ fw_pwrmode = FW_PS_ACTIVE_MODE; rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SET_RPWM, (u8 *) (&rpwm_val)); rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_H2C_FW_PWRMODE, (u8 *) (&fw_pwrmode)); fw_current_inps = false; rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_FW_PSMODE_STATUS, (u8 *) (&fw_current_inps)); } else { if (rtl_get_fwlps_doze(hw)) { RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, ("FW LPS enter ps_mode:%x\n", ppsc->fwctrl_psmode)); rpwm_val = 0x02; /* RF off */ fw_current_inps = true; rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_FW_PSMODE_STATUS, (u8 *) (&fw_current_inps)); rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_H2C_FW_PWRMODE, (u8 *) (&ppsc->fwctrl_psmode)); rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SET_RPWM, (u8 *) (&rpwm_val)); } else { /* Reset the power save related parameters. */ ppsc->dot11_psmode = EACTIVE; } } } }