static void iwl_set_hw_address_family_8000(struct device *dev, const struct iwl_cfg *cfg, struct iwl_nvm_data *data, const __le16 *mac_override, const __le16 *nvm_hw, u32 mac_addr0, u32 mac_addr1) { const u8 *hw_addr; if (mac_override) { static const u8 reserved_mac[] = { 0x02, 0xcc, 0xaa, 0xff, 0xee, 0x00 }; hw_addr = (const u8 *)(mac_override + MAC_ADDRESS_OVERRIDE_FAMILY_8000); /* The byte order is little endian 16 bit, meaning 214365 */ data->hw_addr[0] = hw_addr[1]; data->hw_addr[1] = hw_addr[0]; data->hw_addr[2] = hw_addr[3]; data->hw_addr[3] = hw_addr[2]; data->hw_addr[4] = hw_addr[5]; data->hw_addr[5] = hw_addr[4]; /* * Force the use of the OTP MAC address in case of reserved MAC * address in the NVM, or if address is given but invalid. */ if (is_valid_ether_addr(data->hw_addr) && memcmp(reserved_mac, hw_addr, ETH_ALEN) != 0) return; IWL_ERR_DEV(dev, "mac address from nvm override section is not valid\n"); } if (nvm_hw) { /* read the MAC address from HW resisters */ hw_addr = (const u8 *)&mac_addr0; data->hw_addr[0] = hw_addr[3]; data->hw_addr[1] = hw_addr[2]; data->hw_addr[2] = hw_addr[1]; data->hw_addr[3] = hw_addr[0]; hw_addr = (const u8 *)&mac_addr1; data->hw_addr[4] = hw_addr[1]; data->hw_addr[5] = hw_addr[0]; if (!is_valid_ether_addr(data->hw_addr)) IWL_ERR_DEV(dev, "mac address from hw section is not valid\n"); return; } IWL_ERR_DEV(dev, "mac address is not found\n"); }
static void iwl_init_sbands(struct device *dev, const struct iwl_cfg *cfg, struct iwl_nvm_data *data, const __le16 *nvm_sw) { int n_channels = iwl_init_channel_map(dev, cfg, data, &nvm_sw[NVM_CHANNELS]); int n_used = 0; struct ieee80211_supported_band *sband; sband = &data->bands[IEEE80211_BAND_2GHZ]; sband->band = IEEE80211_BAND_2GHZ; sband->bitrates = &iwl_cfg80211_rates[RATES_24_OFFS]; sband->n_bitrates = N_RATES_24; n_used += iwl_init_sband_channels(data, sband, n_channels, IEEE80211_BAND_2GHZ); iwl_init_ht_hw_capab(cfg, data, &sband->ht_cap, IEEE80211_BAND_2GHZ); sband = &data->bands[IEEE80211_BAND_5GHZ]; sband->band = IEEE80211_BAND_5GHZ; sband->bitrates = &iwl_cfg80211_rates[RATES_52_OFFS]; sband->n_bitrates = N_RATES_52; n_used += iwl_init_sband_channels(data, sband, n_channels, IEEE80211_BAND_5GHZ); iwl_init_ht_hw_capab(cfg, data, &sband->ht_cap, IEEE80211_BAND_5GHZ); iwl_init_vht_hw_capab(cfg, data, &sband->vht_cap); if (n_channels != n_used) IWL_ERR_DEV(dev, "NVM: used only %d of %d channels\n", n_used, n_channels); }
static void iwl_init_sbands(struct device *dev, const struct iwl_cfg *cfg, struct iwl_nvm_data *data, const __le16 *ch_section, u8 tx_chains, u8 rx_chains, bool lar_supported) { int n_channels; int n_used = 0; struct ieee80211_supported_band *sband; if (cfg->device_family != IWL_DEVICE_FAMILY_8000) n_channels = iwl_init_channel_map( dev, cfg, data, &ch_section[NVM_CHANNELS], lar_supported); else n_channels = iwl_init_channel_map( dev, cfg, data, &ch_section[NVM_CHANNELS_FAMILY_8000], lar_supported); sband = &data->bands[NL80211_BAND_2GHZ]; sband->band = NL80211_BAND_2GHZ; sband->bitrates = &iwl_cfg80211_rates[RATES_24_OFFS]; sband->n_bitrates = N_RATES_24; n_used += iwl_init_sband_channels(data, sband, n_channels, NL80211_BAND_2GHZ); iwl_init_ht_hw_capab(cfg, data, &sband->ht_cap, NL80211_BAND_2GHZ, tx_chains, rx_chains); sband = &data->bands[NL80211_BAND_5GHZ]; sband->band = NL80211_BAND_5GHZ; sband->bitrates = &iwl_cfg80211_rates[RATES_52_OFFS]; sband->n_bitrates = N_RATES_52; n_used += iwl_init_sband_channels(data, sband, n_channels, NL80211_BAND_5GHZ); iwl_init_ht_hw_capab(cfg, data, &sband->ht_cap, NL80211_BAND_5GHZ, tx_chains, rx_chains); if (data->sku_cap_11ac_enable && !iwlwifi_mod_params.disable_11ac) iwl_init_vht_hw_capab(cfg, data, &sband->vht_cap, tx_chains, rx_chains); if (n_channels != n_used) IWL_ERR_DEV(dev, "NVM: used only %d of %d channels\n", n_used, n_channels); }
static void iwl_init_sbands(struct device *dev, const struct iwl_cfg *cfg, struct iwl_nvm_data *data, const void *nvm_ch_flags, u8 tx_chains, u8 rx_chains, u32 sbands_flags, bool v4) { int n_channels; int n_used = 0; struct ieee80211_supported_band *sband; n_channels = iwl_init_channel_map(dev, cfg, data, nvm_ch_flags, sbands_flags, v4); sband = &data->bands[NL80211_BAND_2GHZ]; sband->band = NL80211_BAND_2GHZ; sband->bitrates = &iwl_cfg80211_rates[RATES_24_OFFS]; sband->n_bitrates = N_RATES_24; n_used += iwl_init_sband_channels(data, sband, n_channels, NL80211_BAND_2GHZ); iwl_init_ht_hw_capab(cfg, data, &sband->ht_cap, NL80211_BAND_2GHZ, tx_chains, rx_chains); if (data->sku_cap_11ax_enable && !iwlwifi_mod_params.disable_11ax) iwl_init_he_hw_capab(sband, tx_chains, rx_chains); sband = &data->bands[NL80211_BAND_5GHZ]; sband->band = NL80211_BAND_5GHZ; sband->bitrates = &iwl_cfg80211_rates[RATES_52_OFFS]; sband->n_bitrates = N_RATES_52; n_used += iwl_init_sband_channels(data, sband, n_channels, NL80211_BAND_5GHZ); iwl_init_ht_hw_capab(cfg, data, &sband->ht_cap, NL80211_BAND_5GHZ, tx_chains, rx_chains); if (data->sku_cap_11ac_enable && !iwlwifi_mod_params.disable_11ac) iwl_init_vht_hw_capab(cfg, data, &sband->vht_cap, tx_chains, rx_chains); if (data->sku_cap_11ax_enable && !iwlwifi_mod_params.disable_11ax) iwl_init_he_hw_capab(sband, tx_chains, rx_chains); if (n_channels != n_used) IWL_ERR_DEV(dev, "NVM: used only %d of %d channels\n", n_used, n_channels); }
struct iwl_nvm_data * iwl_parse_nvm_data(struct device *dev, const struct iwl_cfg *cfg, const __le16 *nvm_hw, const __le16 *nvm_sw, const __le16 *nvm_calib, const __le16 *regulatory, const __le16 *mac_override, u8 tx_chains, u8 rx_chains) { struct iwl_nvm_data *data; u32 sku; u32 radio_cfg; if (cfg->device_family != IWL_DEVICE_FAMILY_8000) data = kzalloc(sizeof(*data) + sizeof(struct ieee80211_channel) * IWL_NUM_CHANNELS, GFP_KERNEL); else data = kzalloc(sizeof(*data) + sizeof(struct ieee80211_channel) * IWL_NUM_CHANNELS_FAMILY_8000, GFP_KERNEL); if (!data) return NULL; data->nvm_version = iwl_get_nvm_version(cfg, nvm_sw); radio_cfg = iwl_get_radio_cfg(cfg, nvm_sw); iwl_set_radio_cfg(cfg, data, radio_cfg); sku = iwl_get_sku(cfg, nvm_sw); data->sku_cap_band_24GHz_enable = sku & NVM_SKU_CAP_BAND_24GHZ; data->sku_cap_band_52GHz_enable = sku & NVM_SKU_CAP_BAND_52GHZ; data->sku_cap_11n_enable = sku & NVM_SKU_CAP_11N_ENABLE; data->sku_cap_11ac_enable = sku & NVM_SKU_CAP_11AC_ENABLE; if (iwlwifi_mod_params.disable_11n & IWL_DISABLE_HT_ALL) data->sku_cap_11n_enable = false; data->n_hw_addrs = iwl_get_n_hw_addrs(cfg, nvm_sw); if (cfg->device_family != IWL_DEVICE_FAMILY_8000) { /* Checking for required sections */ if (!nvm_calib) { IWL_ERR_DEV(dev, "Can't parse empty Calib NVM sections\n"); kfree(data); return NULL; } /* in family 8000 Xtal calibration values moved to OTP */ data->xtal_calib[0] = *(nvm_calib + XTAL_CALIB); data->xtal_calib[1] = *(nvm_calib + XTAL_CALIB + 1); } if (cfg->device_family != IWL_DEVICE_FAMILY_8000) { iwl_set_hw_address(cfg, data, nvm_hw); iwl_init_sbands(dev, cfg, data, nvm_sw, sku & NVM_SKU_CAP_11AC_ENABLE, tx_chains, rx_chains); } else { /* MAC address in family 8000 */ iwl_set_hw_address_family_8000(cfg, data, mac_override, nvm_hw); iwl_init_sbands(dev, cfg, data, regulatory, sku & NVM_SKU_CAP_11AC_ENABLE, tx_chains, rx_chains); } data->calib_version = 255; return data; }
struct iwl_nvm_data * iwl_parse_nvm_data(struct device *dev, const struct iwl_cfg *cfg, const __le16 *nvm_hw, const __le16 *nvm_sw, const __le16 *nvm_calib) { struct iwl_nvm_data *data; u8 hw_addr[ETH_ALEN]; u16 radio_cfg, sku; data = kzalloc(sizeof(*data) + sizeof(struct ieee80211_channel) * IWL_NUM_CHANNELS, GFP_KERNEL); if (!data) return NULL; data->nvm_version = le16_to_cpup(nvm_sw + NVM_VERSION); radio_cfg = le16_to_cpup(nvm_sw + RADIO_CFG); data->radio_cfg_type = NVM_RF_CFG_TYPE_MSK(radio_cfg); data->radio_cfg_step = NVM_RF_CFG_STEP_MSK(radio_cfg); data->radio_cfg_dash = NVM_RF_CFG_DASH_MSK(radio_cfg); data->radio_cfg_pnum = NVM_RF_CFG_PNUM_MSK(radio_cfg); data->valid_tx_ant = NVM_RF_CFG_TX_ANT_MSK(radio_cfg); data->valid_rx_ant = NVM_RF_CFG_RX_ANT_MSK(radio_cfg); sku = le16_to_cpup(nvm_sw + SKU); data->sku_cap_band_24GHz_enable = sku & NVM_SKU_CAP_BAND_24GHZ; data->sku_cap_band_52GHz_enable = sku & NVM_SKU_CAP_BAND_52GHZ; data->sku_cap_11n_enable = sku & NVM_SKU_CAP_11N_ENABLE; if (iwlwifi_mod_params.disable_11n & IWL_DISABLE_HT_ALL) data->sku_cap_11n_enable = false; /* check overrides (some devices have wrong NVM) */ if (cfg->valid_tx_ant) data->valid_tx_ant = cfg->valid_tx_ant; if (cfg->valid_rx_ant) data->valid_rx_ant = cfg->valid_rx_ant; if (!data->valid_tx_ant || !data->valid_rx_ant) { IWL_ERR_DEV(dev, "invalid antennas (0x%x, 0x%x)\n", data->valid_tx_ant, data->valid_rx_ant); kfree(data); return NULL; } data->n_hw_addrs = le16_to_cpup(nvm_sw + N_HW_ADDRS); data->xtal_calib[0] = *(nvm_calib + XTAL_CALIB); data->xtal_calib[1] = *(nvm_calib + XTAL_CALIB + 1); memcpy(hw_addr, nvm_hw + HW_ADDR, ETH_ALEN); data->hw_addr[0] = hw_addr[1]; data->hw_addr[1] = hw_addr[0]; data->hw_addr[2] = hw_addr[3]; data->hw_addr[3] = hw_addr[2]; data->hw_addr[4] = hw_addr[5]; data->hw_addr[5] = hw_addr[4]; iwl_init_sbands(dev, cfg, data, nvm_sw); data->calib_version = 255; /* TODO: this value will prevent some checks from failing, we need to check if this field is still needed, and if it does, where is it in the NVM*/ return data; }
struct iwl_nvm_data * iwl_parse_nvm_data(struct device *dev, const struct iwl_cfg *cfg, const __le16 *nvm_hw, const __le16 *nvm_sw, const __le16 *nvm_calib, const __le16 *regulatory, const __le16 *mac_override, const __le16 *phy_sku, u8 tx_chains, u8 rx_chains, bool lar_fw_supported, u32 mac_addr0, u32 mac_addr1, u32 hw_id) { struct iwl_nvm_data *data; u32 sku; u32 radio_cfg; u16 lar_config; if (cfg->device_family != IWL_DEVICE_FAMILY_8000) data = kzalloc(sizeof(*data) + sizeof(struct ieee80211_channel) * IWL_NUM_CHANNELS, GFP_KERNEL); else data = kzalloc(sizeof(*data) + sizeof(struct ieee80211_channel) * IWL_NUM_CHANNELS_FAMILY_8000, GFP_KERNEL); if (!data) return NULL; data->nvm_version = iwl_get_nvm_version(cfg, nvm_sw); radio_cfg = iwl_get_radio_cfg(cfg, nvm_sw, phy_sku); iwl_set_radio_cfg(cfg, data, radio_cfg); if (data->valid_tx_ant) tx_chains &= data->valid_tx_ant; if (data->valid_rx_ant) rx_chains &= data->valid_rx_ant; sku = iwl_get_sku(cfg, nvm_sw, phy_sku); data->sku_cap_band_24GHz_enable = sku & NVM_SKU_CAP_BAND_24GHZ; data->sku_cap_band_52GHz_enable = sku & NVM_SKU_CAP_BAND_52GHZ; data->sku_cap_11n_enable = sku & NVM_SKU_CAP_11N_ENABLE; if (iwlwifi_mod_params.disable_11n & IWL_DISABLE_HT_ALL) data->sku_cap_11n_enable = false; data->sku_cap_11ac_enable = data->sku_cap_11n_enable && (sku & NVM_SKU_CAP_11AC_ENABLE); data->sku_cap_mimo_disabled = sku & NVM_SKU_CAP_MIMO_DISABLE; /* * OTP 0x52 bug work around * define antenna 1x1 according to MIMO disabled */ if (hw_id == IWL_4165_DEVICE_ID && data->sku_cap_mimo_disabled) { data->valid_tx_ant = ANT_B; data->valid_rx_ant = ANT_B; tx_chains = ANT_B; rx_chains = ANT_B; } data->n_hw_addrs = iwl_get_n_hw_addrs(cfg, nvm_sw); if (cfg->device_family != IWL_DEVICE_FAMILY_8000) { /* Checking for required sections */ if (!nvm_calib) { IWL_ERR_DEV(dev, "Can't parse empty Calib NVM sections\n"); kfree(data); return NULL; } /* in family 8000 Xtal calibration values moved to OTP */ data->xtal_calib[0] = *(nvm_calib + XTAL_CALIB); data->xtal_calib[1] = *(nvm_calib + XTAL_CALIB + 1); } if (cfg->device_family != IWL_DEVICE_FAMILY_8000) { iwl_set_hw_address(cfg, data, nvm_hw); iwl_init_sbands(dev, cfg, data, nvm_sw, tx_chains, rx_chains, lar_fw_supported); } else { u16 lar_offset = data->nvm_version < 0xE39 ? NVM_LAR_OFFSET_FAMILY_8000_OLD : NVM_LAR_OFFSET_FAMILY_8000; lar_config = le16_to_cpup(regulatory + lar_offset); data->lar_enabled = !!(lar_config & NVM_LAR_ENABLED_FAMILY_8000); /* MAC address in family 8000 */ iwl_set_hw_address_family_8000(dev, cfg, data, mac_override, nvm_hw, mac_addr0, mac_addr1); iwl_init_sbands(dev, cfg, data, regulatory, tx_chains, rx_chains, lar_fw_supported && data->lar_enabled); } data->calib_version = 255; return data; }
static void iwl_set_hw_address_family_8000(struct device *dev, const struct iwl_cfg *cfg, struct iwl_nvm_data *data, const __le16 *mac_override, const __le16 *nvm_hw) { const u8 *hw_addr; if (mac_override) { hw_addr = (const u8 *)(mac_override + MAC_ADDRESS_OVERRIDE_FAMILY_8000); /* The byte order is little endian 16 bit, meaning 214365 */ data->hw_addr[0] = hw_addr[1]; data->hw_addr[1] = hw_addr[0]; data->hw_addr[2] = hw_addr[3]; data->hw_addr[3] = hw_addr[2]; data->hw_addr[4] = hw_addr[5]; data->hw_addr[5] = hw_addr[4]; if (is_valid_ether_addr(data->hw_addr)) return; IWL_ERR_DEV(dev, "mac address from nvm override section is not valid\n"); } if (nvm_hw) { /* read the MAC address from OTP */ if (!dev_is_pci(dev) || (data->nvm_version < 0xE08)) { /* read the mac address from the WFPM location */ hw_addr = (const u8 *)(nvm_hw + HW_ADDR0_WFPM_FAMILY_8000); data->hw_addr[0] = hw_addr[3]; data->hw_addr[1] = hw_addr[2]; data->hw_addr[2] = hw_addr[1]; data->hw_addr[3] = hw_addr[0]; hw_addr = (const u8 *)(nvm_hw + HW_ADDR1_WFPM_FAMILY_8000); data->hw_addr[4] = hw_addr[1]; data->hw_addr[5] = hw_addr[0]; } else if ((data->nvm_version >= 0xE08) && (data->nvm_version < 0xE0B)) { /* read "reverse order" from the PCIe location */ hw_addr = (const u8 *)(nvm_hw + HW_ADDR0_PCIE_FAMILY_8000); data->hw_addr[5] = hw_addr[2]; data->hw_addr[4] = hw_addr[1]; data->hw_addr[3] = hw_addr[0]; hw_addr = (const u8 *)(nvm_hw + HW_ADDR1_PCIE_FAMILY_8000); data->hw_addr[2] = hw_addr[3]; data->hw_addr[1] = hw_addr[2]; data->hw_addr[0] = hw_addr[1]; } else { /* read from the PCIe location */ hw_addr = (const u8 *)(nvm_hw + HW_ADDR0_PCIE_FAMILY_8000); data->hw_addr[5] = hw_addr[0]; data->hw_addr[4] = hw_addr[1]; data->hw_addr[3] = hw_addr[2]; hw_addr = (const u8 *)(nvm_hw + HW_ADDR1_PCIE_FAMILY_8000); data->hw_addr[2] = hw_addr[1]; data->hw_addr[1] = hw_addr[2]; data->hw_addr[0] = hw_addr[3]; } if (!is_valid_ether_addr(data->hw_addr)) IWL_ERR_DEV(dev, "mac address from hw section is not valid\n"); return; } IWL_ERR_DEV(dev, "mac address is not found\n"); }