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); }
int rtl92su_hw_init(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_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); int err = 0; bool rtstatus = true; u8 i; int wdcapra_add[] = { REG_EDCA_BE_PARAM, REG_EDCA_BK_PARAM, REG_EDCA_VI_PARAM, REG_EDCA_VO_PARAM}; u8 secr_value = 0x0; /* 1. MAC Initialize */ /* Before FW download, we have to set some MAC register */ err = _rtl92su_macconfig_before_fwdownload(hw); if (err) { RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, "Failed to get the device ready for the firmware (%d)\n", err); return err; } rtlhal->version = (enum version_8192s)((rtl_read_dword(rtlpriv, REG_PMC_FSM) >> 16) & 0xF); /* 2. download firmware */ rtstatus = rtl92s_download_fw(hw); if (!rtstatus) { RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, "Failed to download FW. Init HW without FW now... Please copy FW into /lib/firmware/rtlwifi\n"); return -ENOENT; } /* After FW download, we have to reset MAC register */ _rtl92su_macconfig_after_fwdownload(hw); /*Retrieve default FW Cmd IO map. */ rtlhal->fwcmd_iomap = rtl_read_word(rtlpriv, REG_LBUS_MON_ADDR); rtlhal->fwcmd_ioparam = rtl_read_dword(rtlpriv, REG_LBUS_ADDR_MASK); /* 3. Initialize MAC/PHY Config by MACPHY_reg.txt */ rtstatus = rtl92s_phy_mac_config(hw); if (!rtstatus) { RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "MAC Config failed\n"); return -EINVAL; } /* because last function modify RCR, so we update * rcr var here, or TP will unstable for receive_config * is wrong, RX RCR_ACRC32 will cause TP unstabel & Rx * RCR_APP_ICV will cause mac80211 unassoc for cisco 1252 */ /* Make sure BB/RF write OK. We should prevent enter IPS. radio off. */ /* We must set flag avoid BB/RF config period later!! */ rtl_write_word(rtlpriv, CMDR, 0x37FC); /* 4. Initialize BB After MAC Config PHY_reg.txt, AGC_Tab.txt */ rtstatus = rtl92s_phy_bb_config(hw); if (!rtstatus) { RT_TRACE(rtlpriv, COMP_INIT, DBG_EMERG, "BB Config failed\n"); return -ENODEV; } /* 5. Initiailze RF RAIO_A.txt RF RAIO_B.txt */ /* Before initalizing RF. We can not use FW to do RF-R/W. */ rtlphy->rf_mode = RF_OP_BY_SW_3WIRE; /* Before RF-R/W we must execute the IO from Scott's suggestion. */ rtl_write_byte(rtlpriv, REG_AFE_XTAL_CTRL + 1, 0xDB); if (rtlhal->version == VERSION_8192S_ACUT) rtl_write_byte(rtlpriv, REG_SPS1_CTRL + 3, 0x07); else rtl_write_byte(rtlpriv, REG_RF_CTRL, 0x07); rtstatus = rtl92s_phy_rf_config(hw); if (!rtstatus) { RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "RF Config failed\n"); return -EOPNOTSUPP; } /* After read predefined TXT, we must set BB/MAC/RF * register as our requirement */ rtlphy->rfreg_chnlval[0] = rtl92s_phy_query_rf_reg(hw, (enum radio_path)0, RF_CHNLBW, RFREG_OFFSET_MASK); rtlphy->rfreg_chnlval[1] = rtl92s_phy_query_rf_reg(hw, (enum radio_path)1, RF_CHNLBW, RFREG_OFFSET_MASK); /*---- Set CCK and OFDM Block "ON"----*/ rtl_set_bbreg(hw, REG_RFPGA0_RFMOD, BCCKEN, 0x1); rtl_set_bbreg(hw, REG_RFPGA0_RFMOD, BOFDMEN, 0x1); /*3 Set Hardware(Do nothing now) */ _rtl92su_hw_configure(hw); /* Read EEPROM TX power index and PHY_REG_PG.txt to capture correct */ /* TX power index for different rate set. */ /* Get original hw reg values */ rtl92s_phy_get_hw_reg_originalvalue(hw); /* Write correct tx power index */ rtl92s_phy_set_txpower(hw, rtlphy->current_channel); /* We must set MAC address after firmware download. */ for (i = 0; i < 6; i++) rtl_write_byte(rtlpriv, MACIDR0 + i, rtlefuse->dev_addr[i]); /* We enable high power and RA related mechanism after NIC * initialized. */ if (hal_get_firmwareversion(rtlpriv) >= 0x35) { /* Fw v.53 and later. */ rtl92s_phy_set_fw_cmd(hw, FW_CMD_RA_INIT); } else if (hal_get_firmwareversion(rtlpriv) == 0x34) { /* Fw v.52. */ rtl_write_dword(rtlpriv, REG_WFM5, FW_RA_INIT); rtl92s_phy_chk_fwcmd_iodone(hw); } else { /* Compatible earlier FW version. */ rtl_write_dword(rtlpriv, REG_WFM5, FW_RA_RESET); rtl92s_phy_chk_fwcmd_iodone(hw); rtl_write_dword(rtlpriv, REG_WFM5, FW_RA_ACTIVE); rtl92s_phy_chk_fwcmd_iodone(hw); rtl_write_dword(rtlpriv, REG_WFM5, FW_RA_REFRESH); rtl92s_phy_chk_fwcmd_iodone(hw); } /* Security related * 1. Clear all H/W keys. * 2. Enable H/W encryption/decryption. */ rtl_cam_reset_all_entry(hw); secr_value |= SCR_TXENCENABLE; secr_value |= SCR_RXENCENABLE; secr_value |= SCR_NOSKMC; rtl_write_byte(rtlpriv, REG_SECR, secr_value); for (i = 0; i < 4; i++) rtl_write_dword(rtlpriv, wdcapra_add[i], 0x5e4322); if (rtlphy->rf_type == RF_1T2R) { bool mrc2set = true; /* Turn on B-Path */ rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_MRC, (u8 *)&mrc2set); } rtlpriv->cfg->ops->led_control(hw, LED_CTL_POWER_ON); rtl92s_dm_init(hw); return err; }