Skip to content

Commit

Permalink
iwlwifi: nvm: set the correct offsets to 3168 series
Browse files Browse the repository at this point in the history
The driver currently handles two NVM formats,
one for 7000 family and below, and one for 8000 family and above.
The 3168 series uses something in between,
so currently the driver uses incorrect offsets for it.
Fix the incorrect offsets.

Fixes: c4836b0 ("iwlwifi: Add PCI IDs for the new 3168 series")
Signed-off-by: Chaya Rachel Ivgi <chaya.rachel.ivgi@intel.com>
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
  • Loading branch information
Chaya Rachel Ivgi authored and Luca Coelho committed Oct 6, 2017
1 parent d8c73e4 commit 44fd09d
Show file tree
Hide file tree
Showing 9 changed files with 59 additions and 28 deletions.
1 change: 1 addition & 0 deletions drivers/net/wireless/intel/iwlwifi/cfg/7000.c
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,7 @@ const struct iwl_cfg iwl3168_2ac_cfg = {
.nvm_calib_ver = IWL3168_TX_POWER_VERSION,
.pwr_tx_backoffs = iwl7265_pwr_tx_backoffs,
.dccm_len = IWL7265_DCCM_LEN,
.nvm_type = IWL_NVM_SDP,
};

const struct iwl_cfg iwl7265_2ac_cfg = {
Expand Down
2 changes: 1 addition & 1 deletion drivers/net/wireless/intel/iwlwifi/cfg/8000.c
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ static const struct iwl_tt_params iwl8000_tt_params = {
.default_nvm_file_C_step = DEFAULT_NVM_FILE_FAMILY_8000C, \
.thermal_params = &iwl8000_tt_params, \
.apmg_not_supported = true, \
.ext_nvm = true, \
.nvm_type = IWL_NVM_EXT, \
.dbgc_supported = true

#define IWL_DEVICE_8000 \
Expand Down
2 changes: 1 addition & 1 deletion drivers/net/wireless/intel/iwlwifi/cfg/9000.c
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ static const struct iwl_tt_params iwl9000_tt_params = {
.vht_mu_mimo_supported = true, \
.mac_addr_from_csr = true, \
.rf_id = true, \
.ext_nvm = true, \
.nvm_type = IWL_NVM_EXT, \
.dbgc_supported = true

const struct iwl_cfg iwl9160_2ac_cfg = {
Expand Down
2 changes: 1 addition & 1 deletion drivers/net/wireless/intel/iwlwifi/cfg/a000.c
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ static const struct iwl_ht_params iwl_a000_ht_params = {
.use_tfh = true, \
.rf_id = true, \
.gen2 = true, \
.ext_nvm = true, \
.nvm_type = IWL_NVM_EXT, \
.dbgc_supported = true

const struct iwl_cfg iwla000_2ac_cfg_hr = {
Expand Down
2 changes: 2 additions & 0 deletions drivers/net/wireless/intel/iwlwifi/fw/api/nvm-reg.h
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ enum iwl_nvm_access_target {
* @NVM_SECTION_TYPE_REGULATORY: regulatory section
* @NVM_SECTION_TYPE_CALIBRATION: calibration section
* @NVM_SECTION_TYPE_PRODUCTION: production section
* @NVM_SECTION_TYPE_REGULATORY_SDP: regulatory section used by 3168 series
* @NVM_SECTION_TYPE_MAC_OVERRIDE: MAC override section
* @NVM_SECTION_TYPE_PHY_SKU: PHY SKU section
* @NVM_MAX_NUM_SECTIONS: number of sections
Expand All @@ -117,6 +118,7 @@ enum iwl_nvm_section_type {
NVM_SECTION_TYPE_REGULATORY = 3,
NVM_SECTION_TYPE_CALIBRATION = 4,
NVM_SECTION_TYPE_PRODUCTION = 5,
NVM_SECTION_TYPE_REGULATORY_SDP = 8,
NVM_SECTION_TYPE_MAC_OVERRIDE = 11,
NVM_SECTION_TYPE_PHY_SKU = 12,
NVM_MAX_NUM_SECTIONS = 13,
Expand Down
16 changes: 14 additions & 2 deletions drivers/net/wireless/intel/iwlwifi/iwl-config.h
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,18 @@ enum iwl_led_mode {
IWL_LED_DISABLE,
};

/**
* enum iwl_nvm_type - nvm formats
* @IWL_NVM: the regular format
* @IWL_NVM_EXT: extended NVM format
* @IWL_NVM_SDP: NVM format used by 3168 series
*/
enum iwl_nvm_type {
IWL_NVM,
IWL_NVM_EXT,
IWL_NVM_SDP,
};

/*
* This is the threshold value of plcp error rate per 100mSecs. It is
* used to set and check for the validity of plcp_delta.
Expand Down Expand Up @@ -320,7 +332,7 @@ struct iwl_pwr_tx_backoff {
* @integrated: discrete or integrated
* @gen2: a000 and on transport operation
* @cdb: CDB support
* @ext_nvm: extended NVM format
* @nvm_type: see &enum iwl_nvm_type
*
* We enable the driver to be backward compatible wrt. hardware features.
* API differences in uCode shouldn't be handled here but through TLVs
Expand All @@ -342,6 +354,7 @@ struct iwl_cfg {
const struct iwl_tt_params *thermal_params;
enum iwl_device_family device_family;
enum iwl_led_mode led_mode;
enum iwl_nvm_type nvm_type;
u32 max_data_size;
u32 max_inst_size;
netdev_features_t features;
Expand Down Expand Up @@ -369,7 +382,6 @@ struct iwl_cfg {
use_tfh:1,
gen2:1,
cdb:1,
ext_nvm:1,
dbgc_supported:1;
u8 valid_tx_ant;
u8 valid_rx_ant;
Expand Down
39 changes: 23 additions & 16 deletions drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@
#include "iwl-csr.h"

/* NVM offsets (in words) definitions */
enum wkp_nvm_offsets {
enum nvm_offsets {
/* NVM HW-Section offset (in words) definitions */
SUBSYSTEM_ID = 0x0A,
HW_ADDR = 0x15,
Expand All @@ -92,7 +92,10 @@ enum wkp_nvm_offsets {

/* NVM calibration section offset (in words) definitions */
NVM_CALIB_SECTION = 0x2B8,
XTAL_CALIB = 0x316 - NVM_CALIB_SECTION
XTAL_CALIB = 0x316 - NVM_CALIB_SECTION,

/* NVM REGULATORY -Section offset (in words) definitions */
NVM_CHANNELS_SDP = 0,
};

enum ext_nvm_offsets {
Expand Down Expand Up @@ -243,7 +246,7 @@ static u32 iwl_get_channel_flags(u8 ch_num, int ch_idx, bool is_5ghz,
u32 flags = IEEE80211_CHAN_NO_HT40;
u32 last_5ghz_ht = LAST_5GHZ_HT;

if (cfg->ext_nvm)
if (cfg->nvm_type == IWL_NVM_EXT)
last_5ghz_ht = LAST_5GHZ_HT_FAMILY_8000;

if (!is_5ghz && (nvm_flags & NVM_CHANNEL_40MHZ)) {
Expand Down Expand Up @@ -296,7 +299,7 @@ static int iwl_init_channel_map(struct device *dev, const struct iwl_cfg *cfg,
int num_of_ch, num_2ghz_channels;
const u8 *nvm_chan;

if (!cfg->ext_nvm) {
if (cfg->nvm_type != IWL_NVM_EXT) {
num_of_ch = IWL_NUM_CHANNELS;
nvm_chan = &iwl_nvm_channels[0];
num_2ghz_channels = NUM_2GHZ_CHANNELS;
Expand Down Expand Up @@ -491,15 +494,15 @@ IWL_EXPORT_SYMBOL(iwl_init_sbands);
static int iwl_get_sku(const struct iwl_cfg *cfg, const __le16 *nvm_sw,
const __le16 *phy_sku)
{
if (!cfg->ext_nvm)
if (cfg->nvm_type != IWL_NVM_EXT)
return le16_to_cpup(nvm_sw + SKU);

return le32_to_cpup((__le32 *)(phy_sku + SKU_FAMILY_8000));
}

static int iwl_get_nvm_version(const struct iwl_cfg *cfg, const __le16 *nvm_sw)
{
if (!cfg->ext_nvm)
if (cfg->nvm_type != IWL_NVM_EXT)
return le16_to_cpup(nvm_sw + NVM_VERSION);
else
return le32_to_cpup((__le32 *)(nvm_sw +
Expand All @@ -509,7 +512,7 @@ static int iwl_get_nvm_version(const struct iwl_cfg *cfg, const __le16 *nvm_sw)
static int iwl_get_radio_cfg(const struct iwl_cfg *cfg, const __le16 *nvm_sw,
const __le16 *phy_sku)
{
if (!cfg->ext_nvm)
if (cfg->nvm_type != IWL_NVM_EXT)
return le16_to_cpup(nvm_sw + RADIO_CFG);

return le32_to_cpup((__le32 *)(phy_sku + RADIO_CFG_FAMILY_EXT_NVM));
Expand All @@ -520,7 +523,7 @@ static int iwl_get_n_hw_addrs(const struct iwl_cfg *cfg, const __le16 *nvm_sw)
{
int n_hw_addr;

if (!cfg->ext_nvm)
if (cfg->nvm_type != IWL_NVM_EXT)
return le16_to_cpup(nvm_sw + N_HW_ADDRS);

n_hw_addr = le32_to_cpup((__le32 *)(nvm_sw + N_HW_ADDRS_FAMILY_8000));
Expand All @@ -532,7 +535,7 @@ static void iwl_set_radio_cfg(const struct iwl_cfg *cfg,
struct iwl_nvm_data *data,
u32 radio_cfg)
{
if (!cfg->ext_nvm) {
if (cfg->nvm_type != IWL_NVM_EXT) {
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);
Expand Down Expand Up @@ -641,7 +644,7 @@ static int iwl_set_hw_address(struct iwl_trans *trans,
{
if (cfg->mac_addr_from_csr) {
iwl_set_hw_address_from_csr(trans, data);
} else if (!cfg->ext_nvm) {
} else if (cfg->nvm_type != IWL_NVM_EXT) {
const u8 *hw_addr = (const u8 *)(nvm_hw + HW_ADDR);

/* The byte order is little endian 16 bit, meaning 214365 */
Expand Down Expand Up @@ -713,7 +716,7 @@ iwl_parse_nvm_data(struct iwl_trans *trans, const struct iwl_cfg *cfg,
u16 lar_config;
const __le16 *ch_section;

if (!cfg->ext_nvm)
if (cfg->nvm_type != IWL_NVM_EXT)
data = kzalloc(sizeof(*data) +
sizeof(struct ieee80211_channel) *
IWL_NUM_CHANNELS,
Expand Down Expand Up @@ -747,19 +750,23 @@ iwl_parse_nvm_data(struct iwl_trans *trans, const struct iwl_cfg *cfg,

data->n_hw_addrs = iwl_get_n_hw_addrs(cfg, nvm_sw);

if (!cfg->ext_nvm) {
if (cfg->nvm_type != IWL_NVM_EXT) {
/* Checking for required sections */
if (!nvm_calib) {
IWL_ERR(trans,
"Can't parse empty Calib NVM sections\n");
kfree(data);
return NULL;
}

ch_section = cfg->nvm_type == IWL_NVM_SDP ?
&regulatory[NVM_CHANNELS_SDP] :
&nvm_sw[NVM_CHANNELS];

/* 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);
lar_enabled = true;
ch_section = &nvm_sw[NVM_CHANNELS];
} else {
u16 lar_offset = data->nvm_version < 0xE39 ?
NVM_LAR_OFFSET_OLD :
Expand Down Expand Up @@ -793,7 +800,7 @@ static u32 iwl_nvm_get_regdom_bw_flags(const u8 *nvm_chan,
u32 flags = NL80211_RRF_NO_HT40;
u32 last_5ghz_ht = LAST_5GHZ_HT;

if (cfg->ext_nvm)
if (cfg->nvm_type == IWL_NVM_EXT)
last_5ghz_ht = LAST_5GHZ_HT_FAMILY_8000;

if (ch_idx < NUM_2GHZ_CHANNELS &&
Expand Down Expand Up @@ -841,7 +848,7 @@ iwl_parse_nvm_mcc_info(struct device *dev, const struct iwl_cfg *cfg,
int ch_idx;
u16 ch_flags;
u32 reg_rule_flags, prev_reg_rule_flags = 0;
const u8 *nvm_chan = cfg->ext_nvm ?
const u8 *nvm_chan = cfg->nvm_type == IWL_NVM_EXT ?
iwl_ext_nvm_channels : iwl_nvm_channels;
struct ieee80211_regdomain *regd;
int size_of_regd;
Expand All @@ -850,7 +857,7 @@ iwl_parse_nvm_mcc_info(struct device *dev, const struct iwl_cfg *cfg,
int center_freq, prev_center_freq = 0;
int valid_rules = 0;
bool new_rule;
int max_num_ch = cfg->ext_nvm ?
int max_num_ch = cfg->nvm_type == IWL_NVM_EXT ?
IWL_NUM_CHANNELS_EXT : IWL_NUM_CHANNELS;

if (WARN_ON_ONCE(num_of_ch > NL80211_MAX_SUPP_REG_RULES))
Expand Down
2 changes: 1 addition & 1 deletion drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
Original file line number Diff line number Diff line change
Expand Up @@ -1162,7 +1162,7 @@ static inline bool iwl_mvm_is_lar_supported(struct iwl_mvm *mvm)
* Enable LAR only if it is supported by the FW (TLV) &&
* enabled in the NVM
*/
if (mvm->cfg->ext_nvm)
if (mvm->cfg->nvm_type == IWL_NVM_EXT)
return nvm_lar && tlv_lar;
else
return tlv_lar;
Expand Down
21 changes: 15 additions & 6 deletions drivers/net/wireless/intel/iwlwifi/mvm/nvm.c
Original file line number Diff line number Diff line change
Expand Up @@ -295,18 +295,24 @@ iwl_parse_nvm_sections(struct iwl_mvm *mvm)
const __be16 *hw;
const __le16 *sw, *calib, *regulatory, *mac_override, *phy_sku;
bool lar_enabled;
int regulatory_type;

/* Checking for required sections */
if (!mvm->trans->cfg->ext_nvm) {
if (mvm->trans->cfg->nvm_type != IWL_NVM_EXT) {
if (!mvm->nvm_sections[NVM_SECTION_TYPE_SW].data ||
!mvm->nvm_sections[mvm->cfg->nvm_hw_section_num].data) {
IWL_ERR(mvm, "Can't parse empty OTP/NVM sections\n");
return NULL;
}
} else {
if (mvm->trans->cfg->nvm_type == IWL_NVM_SDP)
regulatory_type = NVM_SECTION_TYPE_REGULATORY_SDP;
else
regulatory_type = NVM_SECTION_TYPE_REGULATORY;

/* SW and REGULATORY sections are mandatory */
if (!mvm->nvm_sections[NVM_SECTION_TYPE_SW].data ||
!mvm->nvm_sections[NVM_SECTION_TYPE_REGULATORY].data) {
!mvm->nvm_sections[regulatory_type].data) {
IWL_ERR(mvm,
"Can't parse empty family 8000 OTP/NVM sections\n");
return NULL;
Expand All @@ -330,11 +336,14 @@ iwl_parse_nvm_sections(struct iwl_mvm *mvm)
hw = (const __be16 *)sections[mvm->cfg->nvm_hw_section_num].data;
sw = (const __le16 *)sections[NVM_SECTION_TYPE_SW].data;
calib = (const __le16 *)sections[NVM_SECTION_TYPE_CALIBRATION].data;
regulatory = (const __le16 *)sections[NVM_SECTION_TYPE_REGULATORY].data;
mac_override =
(const __le16 *)sections[NVM_SECTION_TYPE_MAC_OVERRIDE].data;
phy_sku = (const __le16 *)sections[NVM_SECTION_TYPE_PHY_SKU].data;

regulatory = mvm->trans->cfg->nvm_type == IWL_NVM_SDP ?
(const __le16 *)sections[NVM_SECTION_TYPE_REGULATORY_SDP].data :
(const __le16 *)sections[NVM_SECTION_TYPE_REGULATORY].data;

lar_enabled = !iwlwifi_mod_params.lar_disable &&
fw_has_capa(&mvm->fw->ucode_capa,
IWL_UCODE_TLV_CAPA_LAR_SUPPORT);
Expand Down Expand Up @@ -394,7 +403,7 @@ int iwl_mvm_read_external_nvm(struct iwl_mvm *mvm)
IWL_DEBUG_EEPROM(mvm->trans->dev, "Read from external NVM\n");

/* Maximal size depends on NVM version */
if (!mvm->trans->cfg->ext_nvm)
if (mvm->trans->cfg->nvm_type != IWL_NVM_EXT)
max_section_size = IWL_MAX_NVM_SECTION_SIZE;
else
max_section_size = IWL_MAX_EXT_NVM_SECTION_SIZE;
Expand Down Expand Up @@ -465,7 +474,7 @@ int iwl_mvm_read_external_nvm(struct iwl_mvm *mvm)
break;
}

if (!mvm->trans->cfg->ext_nvm) {
if (mvm->trans->cfg->nvm_type != IWL_NVM_EXT) {
section_size =
2 * NVM_WORD1_LEN(le16_to_cpu(file_sec->word1));
section_id = NVM_WORD2_ID(le16_to_cpu(file_sec->word2));
Expand Down Expand Up @@ -740,7 +749,7 @@ int iwl_mvm_init_mcc(struct iwl_mvm *mvm)
struct ieee80211_regdomain *regd;
char mcc[3];

if (mvm->cfg->ext_nvm) {
if (mvm->cfg->nvm_type == IWL_NVM_EXT) {
tlv_lar = fw_has_capa(&mvm->fw->ucode_capa,
IWL_UCODE_TLV_CAPA_LAR_SUPPORT);
nvm_lar = mvm->nvm_data->lar_enabled;
Expand Down

0 comments on commit 44fd09d

Please sign in to comment.