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) { /* 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, 6); if (rtlpriv->cfg->ops->linked_set_reg) rtlpriv->cfg->ops->linked_set_reg(hw); if (mac->opmode == NL80211_IFTYPE_STATION && sta) rtlpriv->cfg->ops->update_rate_tbl(hw, sta, 0); RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG, ("BSS_CHANGED_ASSOC\n")); } else { if (mac->link_state == MAC80211_LINKED) rtl_lps_leave(hw); mac->link_state = MAC80211_NOLINK; memset(mac->bssid, 0, 6); mac->vendor = PEER_UNKNOWN; 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, (u8 *) (&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, (u8 *) (&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, (u8 *)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, (u8 *) (&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, (MAC_FMT "\n", MAC_ARG(bss_conf->bssid))); mac->vendor = PEER_UNKNOWN; memcpy(mac->bssid, bss_conf->bssid, 6); rtlpriv->cfg->ops->set_network_type(hw, vif->type); rcu_read_lock(); sta = get_sta(hw, vif, (u8 *)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; rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_H2C_FW_JOINBSSRPT, (u8 *) (&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, (u8 *)(&mstatus)); ppsc->report_linked = false; } } } out: mutex_unlock(&rtlpriv->locks.conf_mutex); }
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); u32 low_rssi_thresh = 0; u32 middle_rssi_thresh = 0; u32 high_rssi_thresh = 0; u8 rssi_level; struct ieee80211_sta *sta = NULL; if (is_hal_stop(rtlhal)) return; if (!rtlpriv->dm.useramask) return; if (!rtlpriv->dm.inform_fw_driverctrldm) { rtl92s_phy_set_fw_cmd(hw, FW_CMD_CTRL_DM_BY_DRIVER); rtlpriv->dm.inform_fw_driverctrldm = true; } rcu_read_lock(); if (mac->opmode == NL80211_IFTYPE_STATION) sta = get_sta(hw, mac->vif, mac->bssid); 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.undecorated_smoothed_pwdb > (long)high_rssi_thresh) { ra->ratr_state = DM_RATR_STA_HIGH; rssi_level = 1; } else if (rtlpriv->dm.undecorated_smoothed_pwdb > (long)middle_rssi_thresh) { ra->ratr_state = DM_RATR_STA_LOW; rssi_level = 3; } else if (rtlpriv->dm.undecorated_smoothed_pwdb > (long)low_rssi_thresh) { ra->ratr_state = DM_RATR_STA_LOW; rssi_level = 5; } else { ra->ratr_state = DM_RATR_STA_ULTRALOW; rssi_level = 6; } 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.undecorated_smoothed_pwdb, ra->ratr_state, ra->pre_ratr_state, ra->ratr_state)); rtlpriv->cfg->ops->update_rate_tbl(hw, sta, ra->ratr_state); ra->pre_ratr_state = ra->ratr_state; } } rcu_read_unlock(); }