Example #1
0
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);
}
Example #3
0
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);
}
Example #4
0
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");
}