Merge branch 'for-john' of git://git.kernel.org/pub/scm/linux/kernel/git/iwlwifi/iwlwifi-next
This commit is contained in:
@@ -71,7 +71,7 @@ enum wkp_nvm_offsets {
|
||||
/* NVM HW-Section offset (in words) definitions */
|
||||
HW_ADDR = 0x15,
|
||||
|
||||
/* NVM SW-Section offset (in words) definitions */
|
||||
/* NVM SW-Section offset (in words) definitions */
|
||||
NVM_SW_SECTION = 0x1C0,
|
||||
NVM_VERSION = 0,
|
||||
RADIO_CFG = 1,
|
||||
@@ -79,11 +79,32 @@ enum wkp_nvm_offsets {
|
||||
N_HW_ADDRS = 3,
|
||||
NVM_CHANNELS = 0x1E0 - NVM_SW_SECTION,
|
||||
|
||||
/* NVM calibration section offset (in words) definitions */
|
||||
/* NVM calibration section offset (in words) definitions */
|
||||
NVM_CALIB_SECTION = 0x2B8,
|
||||
XTAL_CALIB = 0x316 - NVM_CALIB_SECTION
|
||||
};
|
||||
|
||||
enum family_8000_nvm_offsets {
|
||||
/* NVM HW-Section offset (in words) definitions */
|
||||
HW_ADDR0_FAMILY_8000 = 0x12,
|
||||
HW_ADDR1_FAMILY_8000 = 0x16,
|
||||
MAC_ADDRESS_OVERRIDE_FAMILY_8000 = 1,
|
||||
|
||||
/* NVM SW-Section offset (in words) definitions */
|
||||
NVM_SW_SECTION_FAMILY_8000 = 0x1C0,
|
||||
NVM_VERSION_FAMILY_8000 = 0,
|
||||
RADIO_CFG_FAMILY_8000 = 2,
|
||||
SKU_FAMILY_8000 = 4,
|
||||
N_HW_ADDRS_FAMILY_8000 = 5,
|
||||
|
||||
/* NVM REGULATORY -Section offset (in words) definitions */
|
||||
NVM_CHANNELS_FAMILY_8000 = 0,
|
||||
|
||||
/* NVM calibration section offset (in words) definitions */
|
||||
NVM_CALIB_SECTION_FAMILY_8000 = 0x2B8,
|
||||
XTAL_CALIB_FAMILY_8000 = 0x316 - NVM_CALIB_SECTION_FAMILY_8000
|
||||
};
|
||||
|
||||
/* SKU Capabilities (actual values from NVM definition) */
|
||||
enum nvm_sku_bits {
|
||||
NVM_SKU_CAP_BAND_24GHZ = BIT(0),
|
||||
@@ -92,14 +113,6 @@ enum nvm_sku_bits {
|
||||
NVM_SKU_CAP_11AC_ENABLE = BIT(3),
|
||||
};
|
||||
|
||||
/* radio config bits (actual values from NVM definition) */
|
||||
#define NVM_RF_CFG_DASH_MSK(x) (x & 0x3) /* bits 0-1 */
|
||||
#define NVM_RF_CFG_STEP_MSK(x) ((x >> 2) & 0x3) /* bits 2-3 */
|
||||
#define NVM_RF_CFG_TYPE_MSK(x) ((x >> 4) & 0x3) /* bits 4-5 */
|
||||
#define NVM_RF_CFG_PNUM_MSK(x) ((x >> 6) & 0x3) /* bits 6-7 */
|
||||
#define NVM_RF_CFG_TX_ANT_MSK(x) ((x >> 8) & 0xF) /* bits 8-11 */
|
||||
#define NVM_RF_CFG_RX_ANT_MSK(x) ((x >> 12) & 0xF) /* bits 12-15 */
|
||||
|
||||
/*
|
||||
* These are the channel numbers in the order that they are stored in the NVM
|
||||
*/
|
||||
@@ -112,7 +125,17 @@ static const u8 iwl_nvm_channels[] = {
|
||||
149, 153, 157, 161, 165
|
||||
};
|
||||
|
||||
static const u8 iwl_nvm_channels_family_8000[] = {
|
||||
/* 2.4 GHz */
|
||||
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
|
||||
/* 5 GHz */
|
||||
36, 40, 44, 48, 52, 56, 60, 64, 68, 72, 76, 80, 84, 88, 92,
|
||||
96, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144,
|
||||
149, 153, 157, 161, 165, 169, 173, 177, 181
|
||||
};
|
||||
|
||||
#define IWL_NUM_CHANNELS ARRAY_SIZE(iwl_nvm_channels)
|
||||
#define IWL_NUM_CHANNELS_FAMILY_8000 ARRAY_SIZE(iwl_nvm_channels_family_8000)
|
||||
#define NUM_2GHZ_CHANNELS 14
|
||||
#define FIRST_2GHZ_HT_MINUS 5
|
||||
#define LAST_2GHZ_HT_PLUS 9
|
||||
@@ -179,8 +202,18 @@ static int iwl_init_channel_map(struct device *dev, const struct iwl_cfg *cfg,
|
||||
struct ieee80211_channel *channel;
|
||||
u16 ch_flags;
|
||||
bool is_5ghz;
|
||||
int num_of_ch;
|
||||
const u8 *nvm_chan;
|
||||
|
||||
for (ch_idx = 0; ch_idx < IWL_NUM_CHANNELS; ch_idx++) {
|
||||
if (cfg->device_family != IWL_DEVICE_FAMILY_8000) {
|
||||
num_of_ch = IWL_NUM_CHANNELS;
|
||||
nvm_chan = &iwl_nvm_channels[0];
|
||||
} else {
|
||||
num_of_ch = IWL_NUM_CHANNELS_FAMILY_8000;
|
||||
nvm_chan = &iwl_nvm_channels_family_8000[0];
|
||||
}
|
||||
|
||||
for (ch_idx = 0; ch_idx < num_of_ch; ch_idx++) {
|
||||
ch_flags = __le16_to_cpup(nvm_ch_flags + ch_idx);
|
||||
|
||||
if (ch_idx >= NUM_2GHZ_CHANNELS &&
|
||||
@@ -190,7 +223,7 @@ static int iwl_init_channel_map(struct device *dev, const struct iwl_cfg *cfg,
|
||||
if (!(ch_flags & NVM_CHANNEL_VALID)) {
|
||||
IWL_DEBUG_EEPROM(dev,
|
||||
"Ch. %d Flags %x [%sGHz] - No traffic\n",
|
||||
iwl_nvm_channels[ch_idx],
|
||||
nvm_chan[ch_idx],
|
||||
ch_flags,
|
||||
(ch_idx >= NUM_2GHZ_CHANNELS) ?
|
||||
"5.2" : "2.4");
|
||||
@@ -200,7 +233,7 @@ static int iwl_init_channel_map(struct device *dev, const struct iwl_cfg *cfg,
|
||||
channel = &data->channels[n_channels];
|
||||
n_channels++;
|
||||
|
||||
channel->hw_value = iwl_nvm_channels[ch_idx];
|
||||
channel->hw_value = nvm_chan[ch_idx];
|
||||
channel->band = (ch_idx < NUM_2GHZ_CHANNELS) ?
|
||||
IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ;
|
||||
channel->center_freq =
|
||||
@@ -211,11 +244,11 @@ static int iwl_init_channel_map(struct device *dev, const struct iwl_cfg *cfg,
|
||||
channel->flags = IEEE80211_CHAN_NO_HT40;
|
||||
if (ch_idx < NUM_2GHZ_CHANNELS &&
|
||||
(ch_flags & NVM_CHANNEL_40MHZ)) {
|
||||
if (iwl_nvm_channels[ch_idx] <= LAST_2GHZ_HT_PLUS)
|
||||
if (nvm_chan[ch_idx] <= LAST_2GHZ_HT_PLUS)
|
||||
channel->flags &= ~IEEE80211_CHAN_NO_HT40PLUS;
|
||||
if (iwl_nvm_channels[ch_idx] >= FIRST_2GHZ_HT_MINUS)
|
||||
if (nvm_chan[ch_idx] >= FIRST_2GHZ_HT_MINUS)
|
||||
channel->flags &= ~IEEE80211_CHAN_NO_HT40MINUS;
|
||||
} else if (iwl_nvm_channels[ch_idx] <= LAST_5GHZ_HT &&
|
||||
} else if (nvm_chan[ch_idx] <= LAST_5GHZ_HT &&
|
||||
(ch_flags & NVM_CHANNEL_40MHZ)) {
|
||||
if ((ch_idx - NUM_2GHZ_CHANNELS) % 2 == 0)
|
||||
channel->flags &= ~IEEE80211_CHAN_NO_HT40PLUS;
|
||||
@@ -307,14 +340,23 @@ static void iwl_init_vht_hw_capab(const struct iwl_cfg *cfg,
|
||||
}
|
||||
|
||||
static void iwl_init_sbands(struct device *dev, const struct iwl_cfg *cfg,
|
||||
struct iwl_nvm_data *data, const __le16 *nvm_sw,
|
||||
bool enable_vht, u8 tx_chains, u8 rx_chains)
|
||||
struct iwl_nvm_data *data,
|
||||
const __le16 *ch_section, bool enable_vht,
|
||||
u8 tx_chains, u8 rx_chains)
|
||||
{
|
||||
int n_channels = iwl_init_channel_map(dev, cfg, data,
|
||||
&nvm_sw[NVM_CHANNELS]);
|
||||
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]);
|
||||
else
|
||||
n_channels = iwl_init_channel_map(
|
||||
dev, cfg, data,
|
||||
&ch_section[NVM_CHANNELS_FAMILY_8000]);
|
||||
|
||||
sband = &data->bands[IEEE80211_BAND_2GHZ];
|
||||
sband->band = IEEE80211_BAND_2GHZ;
|
||||
sband->bitrates = &iwl_cfg80211_rates[RATES_24_OFFS];
|
||||
@@ -340,67 +382,150 @@ static void iwl_init_sbands(struct device *dev, const struct iwl_cfg *cfg,
|
||||
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, u8 tx_chains, u8 rx_chains)
|
||||
static int iwl_get_sku(const struct iwl_cfg *cfg,
|
||||
const __le16 *nvm_sw)
|
||||
{
|
||||
struct iwl_nvm_data *data;
|
||||
u8 hw_addr[ETH_ALEN];
|
||||
u16 radio_cfg, sku;
|
||||
if (cfg->device_family != IWL_DEVICE_FAMILY_8000)
|
||||
return le16_to_cpup(nvm_sw + SKU);
|
||||
else
|
||||
return le32_to_cpup((__le32 *)(nvm_sw + SKU_FAMILY_8000));
|
||||
}
|
||||
|
||||
data = kzalloc(sizeof(*data) +
|
||||
sizeof(struct ieee80211_channel) * IWL_NUM_CHANNELS,
|
||||
GFP_KERNEL);
|
||||
if (!data)
|
||||
return NULL;
|
||||
static int iwl_get_nvm_version(const struct iwl_cfg *cfg,
|
||||
const __le16 *nvm_sw)
|
||||
{
|
||||
if (cfg->device_family != IWL_DEVICE_FAMILY_8000)
|
||||
return le16_to_cpup(nvm_sw + NVM_VERSION);
|
||||
else
|
||||
return le32_to_cpup((__le32 *)(nvm_sw +
|
||||
NVM_VERSION_FAMILY_8000));
|
||||
}
|
||||
|
||||
data->nvm_version = le16_to_cpup(nvm_sw + NVM_VERSION);
|
||||
static int iwl_get_radio_cfg(const struct iwl_cfg *cfg,
|
||||
const __le16 *nvm_sw)
|
||||
{
|
||||
if (cfg->device_family != IWL_DEVICE_FAMILY_8000)
|
||||
return le16_to_cpup(nvm_sw + RADIO_CFG);
|
||||
else
|
||||
return le32_to_cpup((__le32 *)(nvm_sw + RADIO_CFG_FAMILY_8000));
|
||||
}
|
||||
|
||||
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);
|
||||
#define N_HW_ADDRS_MASK_FAMILY_8000 0xF
|
||||
static int iwl_get_n_hw_addrs(const struct iwl_cfg *cfg,
|
||||
const __le16 *nvm_sw)
|
||||
{
|
||||
if (cfg->device_family != IWL_DEVICE_FAMILY_8000)
|
||||
return le16_to_cpup(nvm_sw + N_HW_ADDRS);
|
||||
else
|
||||
return le32_to_cpup((__le32 *)(nvm_sw + N_HW_ADDRS_FAMILY_8000))
|
||||
& N_HW_ADDRS_MASK_FAMILY_8000;
|
||||
}
|
||||
|
||||
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;
|
||||
static void iwl_set_radio_cfg(const struct iwl_cfg *cfg,
|
||||
struct iwl_nvm_data *data,
|
||||
u32 radio_cfg)
|
||||
{
|
||||
if (cfg->device_family != IWL_DEVICE_FAMILY_8000) {
|
||||
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);
|
||||
return;
|
||||
}
|
||||
|
||||
data->n_hw_addrs = le16_to_cpup(nvm_sw + N_HW_ADDRS);
|
||||
/* set the radio configuration for family 8000 */
|
||||
data->radio_cfg_type = NVM_RF_CFG_TYPE_MSK_FAMILY_8000(radio_cfg);
|
||||
data->radio_cfg_step = NVM_RF_CFG_STEP_MSK_FAMILY_8000(radio_cfg);
|
||||
data->radio_cfg_dash = NVM_RF_CFG_DASH_MSK_FAMILY_8000(radio_cfg);
|
||||
data->radio_cfg_pnum = NVM_RF_CFG_FLAVOR_MSK_FAMILY_8000(radio_cfg);
|
||||
}
|
||||
|
||||
data->xtal_calib[0] = *(nvm_calib + XTAL_CALIB);
|
||||
data->xtal_calib[1] = *(nvm_calib + XTAL_CALIB + 1);
|
||||
static void iwl_set_hw_address(const struct iwl_cfg *cfg,
|
||||
struct iwl_nvm_data *data,
|
||||
const __le16 *nvm_sec)
|
||||
{
|
||||
u8 hw_addr[ETH_ALEN];
|
||||
|
||||
if (cfg->device_family != IWL_DEVICE_FAMILY_8000)
|
||||
memcpy(hw_addr, nvm_sec + HW_ADDR, ETH_ALEN);
|
||||
else
|
||||
memcpy(hw_addr, nvm_sec + MAC_ADDRESS_OVERRIDE_FAMILY_8000,
|
||||
ETH_ALEN);
|
||||
|
||||
/* The byte order is little endian 16 bit, meaning 214365 */
|
||||
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, sku & NVM_SKU_CAP_11AC_ENABLE,
|
||||
tx_chains, rx_chains);
|
||||
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(cfg, data, mac_override);
|
||||
|
||||
iwl_init_sbands(dev, cfg, data, regulatory,
|
||||
sku & NVM_SKU_CAP_11AC_ENABLE, tx_chains,
|
||||
rx_chains);
|
||||
}
|
||||
|
||||
data->calib_version = 255;
|
||||
|
||||
|
مرجع در شماره جدید
Block a user