/** * enum iwl_nvm_channel_flags - channel flags in NVM * @NVM_CHANNEL_VALID: channel is usable for this SKU/geo * @NVM_CHANNEL_IBSS: usable as an IBSS channel and deprecated * when %IWL_NVM_SBANDS_FLAGS_LAR enabled. * @NVM_CHANNEL_ALLOW_20MHZ_ACTIVITY: active scanning allowed and * AP allowed only in 20 MHz. Valid only * when %IWL_NVM_SBANDS_FLAGS_LAR enabled. * @NVM_CHANNEL_ACTIVE: active scanning allowed and allows IBSS * when %IWL_NVM_SBANDS_FLAGS_LAR enabled. * @NVM_CHANNEL_RADAR: radar detection required * @NVM_CHANNEL_INDOOR_ONLY: only indoor use is allowed * @NVM_CHANNEL_GO_CONCURRENT: GO operation is allowed when connected to BSS * on same channel on 2.4 or same UNII band on 5.2 * @NVM_CHANNEL_UNIFORM: uniform spreading required * @NVM_CHANNEL_20MHZ: 20 MHz channel okay * @NVM_CHANNEL_40MHZ: 40 MHz channel okay * @NVM_CHANNEL_80MHZ: 80 MHz channel okay * @NVM_CHANNEL_160MHZ: 160 MHz channel okay * @NVM_CHANNEL_DC_HIGH: DC HIGH required/allowed (?) * @NVM_CHANNEL_VLP: client support connection to UHB VLP AP * @NVM_CHANNEL_AFC: client support connection to UHB AFC AP * @NVM_CHANNEL_VLP_AP_NOT_ALLOWED: UHB VLP AP not allowed, * Valid only when %NVM_CHANNEL_VLP is enabled.
*/ enum iwl_nvm_channel_flags {
NVM_CHANNEL_VALID = BIT(0),
NVM_CHANNEL_IBSS = BIT(1),
NVM_CHANNEL_ALLOW_20MHZ_ACTIVITY = BIT(2),
NVM_CHANNEL_ACTIVE = BIT(3),
NVM_CHANNEL_RADAR = BIT(4),
NVM_CHANNEL_INDOOR_ONLY = BIT(5),
NVM_CHANNEL_GO_CONCURRENT = BIT(6),
NVM_CHANNEL_UNIFORM = BIT(7),
NVM_CHANNEL_20MHZ = BIT(8),
NVM_CHANNEL_40MHZ = BIT(9),
NVM_CHANNEL_80MHZ = BIT(10),
NVM_CHANNEL_160MHZ = BIT(11),
NVM_CHANNEL_DC_HIGH = BIT(12),
NVM_CHANNEL_VLP = BIT(13),
NVM_CHANNEL_AFC = BIT(14),
NVM_CHANNEL_VLP_AP_NOT_ALLOWED = BIT(15),
};
/** * enum iwl_reg_capa_flags_v1 - global flags applied for the whole regulatory * domain. * @REG_CAPA_V1_BF_CCD_LOW_BAND: Beam-forming or Cyclic Delay Diversity in the * 2.4Ghz band is allowed. * @REG_CAPA_V1_BF_CCD_HIGH_BAND: Beam-forming or Cyclic Delay Diversity in the * 5Ghz band is allowed. * @REG_CAPA_V1_160MHZ_ALLOWED: 11ac channel with a width of 160Mhz is allowed * for this regulatory domain (valid only in 5Ghz). * @REG_CAPA_V1_80MHZ_ALLOWED: 11ac channel with a width of 80Mhz is allowed * for this regulatory domain (valid only in 5Ghz). * @REG_CAPA_V1_MCS_8_ALLOWED: 11ac with MCS 8 is allowed. * @REG_CAPA_V1_MCS_9_ALLOWED: 11ac with MCS 9 is allowed. * @REG_CAPA_V1_40MHZ_FORBIDDEN: 11n channel with a width of 40Mhz is forbidden * for this regulatory domain (valid only in 5Ghz). * @REG_CAPA_V1_DC_HIGH_ENABLED: DC HIGH allowed. * @REG_CAPA_V1_11AX_DISABLED: 11ax is forbidden for this regulatory domain.
*/ enum iwl_reg_capa_flags_v1 {
REG_CAPA_V1_BF_CCD_LOW_BAND = BIT(0),
REG_CAPA_V1_BF_CCD_HIGH_BAND = BIT(1),
REG_CAPA_V1_160MHZ_ALLOWED = BIT(2),
REG_CAPA_V1_80MHZ_ALLOWED = BIT(3),
REG_CAPA_V1_MCS_8_ALLOWED = BIT(4),
REG_CAPA_V1_MCS_9_ALLOWED = BIT(5),
REG_CAPA_V1_40MHZ_FORBIDDEN = BIT(7),
REG_CAPA_V1_DC_HIGH_ENABLED = BIT(9),
REG_CAPA_V1_11AX_DISABLED = BIT(10),
}; /* GEO_CHANNEL_CAPABILITIES_API_S_VER_1 */
/** * enum iwl_reg_capa_flags_v2 - global flags applied for the whole regulatory * domain (version 2). * @REG_CAPA_V2_STRADDLE_DISABLED: Straddle channels (144, 142, 138) are * disabled. * @REG_CAPA_V2_BF_CCD_LOW_BAND: Beam-forming or Cyclic Delay Diversity in the * 2.4Ghz band is allowed. * @REG_CAPA_V2_BF_CCD_HIGH_BAND: Beam-forming or Cyclic Delay Diversity in the * 5Ghz band is allowed. * @REG_CAPA_V2_160MHZ_ALLOWED: 11ac channel with a width of 160Mhz is allowed * for this regulatory domain (valid only in 5Ghz). * @REG_CAPA_V2_80MHZ_ALLOWED: 11ac channel with a width of 80Mhz is allowed * for this regulatory domain (valid only in 5Ghz). * @REG_CAPA_V2_MCS_8_ALLOWED: 11ac with MCS 8 is allowed. * @REG_CAPA_V2_MCS_9_ALLOWED: 11ac with MCS 9 is allowed. * @REG_CAPA_V2_WEATHER_DISABLED: Weather radar channels (120, 124, 128, 118, * 126, 122) are disabled. * @REG_CAPA_V2_40MHZ_ALLOWED: 11n channel with a width of 40Mhz is allowed * for this regulatory domain (uvalid only in 5Ghz). * @REG_CAPA_V2_11AX_DISABLED: 11ax is forbidden for this regulatory domain.
*/ enum iwl_reg_capa_flags_v2 {
REG_CAPA_V2_STRADDLE_DISABLED = BIT(0),
REG_CAPA_V2_BF_CCD_LOW_BAND = BIT(1),
REG_CAPA_V2_BF_CCD_HIGH_BAND = BIT(2),
REG_CAPA_V2_160MHZ_ALLOWED = BIT(3),
REG_CAPA_V2_80MHZ_ALLOWED = BIT(4),
REG_CAPA_V2_MCS_8_ALLOWED = BIT(5),
REG_CAPA_V2_MCS_9_ALLOWED = BIT(6),
REG_CAPA_V2_WEATHER_DISABLED = BIT(7),
REG_CAPA_V2_40MHZ_ALLOWED = BIT(8),
REG_CAPA_V2_11AX_DISABLED = BIT(10),
}; /* GEO_CHANNEL_CAPABILITIES_API_S_VER_2 */
/** * enum iwl_reg_capa_flags_v4 - global flags applied for the whole regulatory * domain. * @REG_CAPA_V4_160MHZ_ALLOWED: 11ac channel with a width of 160Mhz is allowed * for this regulatory domain (valid only in 5Ghz). * @REG_CAPA_V4_80MHZ_ALLOWED: 11ac channel with a width of 80Mhz is allowed * for this regulatory domain (valid only in 5Ghz). * @REG_CAPA_V4_MCS_12_ALLOWED: 11ac with MCS 12 is allowed. * @REG_CAPA_V4_MCS_13_ALLOWED: 11ac with MCS 13 is allowed. * @REG_CAPA_V4_11BE_DISABLED: 11be is forbidden for this regulatory domain. * @REG_CAPA_V4_11AX_DISABLED: 11ax is forbidden for this regulatory domain. * @REG_CAPA_V4_320MHZ_ALLOWED: 11be channel with a width of 320Mhz is allowed * for this regulatory domain (valid only in 5GHz).
*/ enum iwl_reg_capa_flags_v4 {
REG_CAPA_V4_160MHZ_ALLOWED = BIT(3),
REG_CAPA_V4_80MHZ_ALLOWED = BIT(4),
REG_CAPA_V4_MCS_12_ALLOWED = BIT(5),
REG_CAPA_V4_MCS_13_ALLOWED = BIT(6),
REG_CAPA_V4_11BE_DISABLED = BIT(8),
REG_CAPA_V4_11AX_DISABLED = BIT(13),
REG_CAPA_V4_320MHZ_ALLOWED = BIT(16),
}; /* GEO_CHANNEL_CAPABILITIES_API_S_VER_4 */
/* * API v2 for reg_capa_flags is relevant from version 6 and onwards of the * MCC update command response.
*/ #define REG_CAPA_V2_RESP_VER 6
/* API v4 for reg_capa_flags is relevant from version 8 and onwards of the * MCC update command response.
*/ #define REG_CAPA_V4_RESP_VER 8
/** * struct iwl_reg_capa - struct for global regulatory capabilities, Used for * handling the different APIs of reg_capa_flags. * * @allow_40mhz: 11n channel with a width of 40Mhz is allowed * for this regulatory domain. * @allow_80mhz: 11ac channel with a width of 80Mhz is allowed * for this regulatory domain (valid only in 5 and 6 Ghz). * @allow_160mhz: 11ac channel with a width of 160Mhz is allowed * for this regulatory domain (valid only in 5 and 6 Ghz). * @allow_320mhz: 11be channel with a width of 320Mhz is allowed * for this regulatory domain (valid only in 6 Ghz). * @disable_11ax: 11ax is forbidden for this regulatory domain. * @disable_11be: 11be is forbidden for this regulatory domain.
*/ struct iwl_reg_capa { bool allow_40mhz; bool allow_80mhz; bool allow_160mhz; bool allow_320mhz; bool disable_11ax; bool disable_11be;
};
if (band == NL80211_BAND_2GHZ && (nvm_flags & NVM_CHANNEL_40MHZ)) { if (ch_num <= LAST_2GHZ_HT_PLUS)
flags &= ~IEEE80211_CHAN_NO_HT40PLUS; if (ch_num >= FIRST_2GHZ_HT_MINUS)
flags &= ~IEEE80211_CHAN_NO_HT40MINUS;
} elseif (nvm_flags & NVM_CHANNEL_40MHZ) { if ((ch_idx - NUM_2GHZ_CHANNELS) % 2 == 0)
flags &= ~IEEE80211_CHAN_NO_HT40PLUS; else
flags &= ~IEEE80211_CHAN_NO_HT40MINUS;
} if (!(nvm_flags & NVM_CHANNEL_80MHZ))
flags |= IEEE80211_CHAN_NO_80MHZ; if (!(nvm_flags & NVM_CHANNEL_160MHZ))
flags |= IEEE80211_CHAN_NO_160MHZ;
if (!(nvm_flags & NVM_CHANNEL_IBSS))
flags |= IEEE80211_CHAN_NO_IR;
if (!(nvm_flags & NVM_CHANNEL_ACTIVE))
flags |= IEEE80211_CHAN_NO_IR;
if (nvm_flags & NVM_CHANNEL_RADAR)
flags |= IEEE80211_CHAN_RADAR;
if (nvm_flags & NVM_CHANNEL_INDOOR_ONLY)
flags |= IEEE80211_CHAN_INDOOR_ONLY;
/* Set the GO concurrent flag only in case that NO_IR is set. * Otherwise it is meaningless
*/ if ((nvm_flags & NVM_CHANNEL_GO_CONCURRENT) &&
(flags & IEEE80211_CHAN_NO_IR))
flags |= IEEE80211_CHAN_IR_CONCURRENT;
/* Set the AP type for the UHB case. */ if (nvm_flags & NVM_CHANNEL_VLP)
flags |= IEEE80211_CHAN_ALLOW_6GHZ_VLP_AP; else
flags |= IEEE80211_CHAN_NO_6GHZ_VLP_CLIENT; if (!(nvm_flags & NVM_CHANNEL_AFC))
flags |= IEEE80211_CHAN_NO_6GHZ_AFC_CLIENT;
if (band == NL80211_BAND_5GHZ &&
!data->sku_cap_band_52ghz_enable) continue;
/* workaround to disable wide channels in 5GHz */ if ((sbands_flags & IWL_NVM_SBANDS_FLAGS_NO_WIDE_IN_5GHZ) &&
band == NL80211_BAND_5GHZ) {
ch_flags &= ~(NVM_CHANNEL_40MHZ |
NVM_CHANNEL_80MHZ |
NVM_CHANNEL_160MHZ);
}
if (ch_flags & NVM_CHANNEL_160MHZ)
data->vht160_supported = true;
if (!(sbands_flags & IWL_NVM_SBANDS_FLAGS_LAR) &&
!(ch_flags & NVM_CHANNEL_VALID)) { /* * Channels might become valid later if lar is * supported, hence we still want to add them to * the list of supported channels to cfg80211.
*/
iwl_nvm_print_channel_flags(dev, IWL_DL_EEPROM,
nvm_chan[ch_idx], ch_flags); continue;
}
/* * Default value - highest tx power value. max_power * is not used in mvm, and is used for backwards compatibility
*/
channel->max_power = IWL_DEFAULT_MAX_TX_POWER;
/* don't put limitations in case we're using LAR */ if (!(sbands_flags & IWL_NVM_SBANDS_FLAGS_LAR))
channel->flags = iwl_get_channel_flags(nvm_chan[ch_idx],
ch_idx, band,
ch_flags, cfg); else
channel->flags = 0;
if (fw_has_capa(&fw->ucode_capa,
IWL_UCODE_TLV_CAPA_MONITOR_PASSIVE_CHANS))
channel->flags |= IEEE80211_CHAN_CAN_MONITOR;
/* * With fips_enabled crypto is done by software, so the HW cannot * split up A-MSDUs and the real limit that was set applies. * Note that EHT doesn't honour this (HE copies the VHT value), * but EHT is also entirely disabled for fips_enabled.
*/ switch (iwlwifi_mod_params.amsdu_size) { case IWL_AMSDU_DEF: if (trans->mac_cfg->mq_rx_supported && !fips_enabled)
vht_cap->cap |=
IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454; else
vht_cap->cap |= IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_3895; break; case IWL_AMSDU_2K: if (trans->mac_cfg->mq_rx_supported && !fips_enabled)
vht_cap->cap |=
IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454; else
WARN(1, "RB size of 2K is not supported by this device\n"); break; case IWL_AMSDU_4K:
vht_cap->cap |= IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_3895; break; case IWL_AMSDU_8K:
vht_cap->cap |= IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991; break; case IWL_AMSDU_12K:
vht_cap->cap |= IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454; break; default: break;
}
/* For all MCS and bandwidth, set 2 NSS for both Tx and * Rx - note we don't set the only_20mhz, but due to this * being a union, it gets set correctly anyway.
*/
.eht_mcs_nss_supp = {
.bw._80 = {
.rx_tx_mcs9_max_nss = 0x22,
.rx_tx_mcs11_max_nss = 0x22,
.rx_tx_mcs13_max_nss = 0x22,
},
.bw._160 = {
.rx_tx_mcs9_max_nss = 0x22,
.rx_tx_mcs11_max_nss = 0x22,
.rx_tx_mcs13_max_nss = 0x22,
},
.bw._320 = {
.rx_tx_mcs9_max_nss = 0x22,
.rx_tx_mcs11_max_nss = 0x22,
.rx_tx_mcs13_max_nss = 0x22,
},
},
/* * PPE thresholds for NSS = 2, and RU index bitmap set * to 0xc. * Note: just for stating what we want, not present in * the transmitted data due to not including * IEEE80211_EHT_PHY_CAP5_PPE_THRESHOLD_PRESENT.
*/
.eht_ppe_thres = {0xc1, 0x0e, 0xe0 }
},
},
{
.types_mask = BIT(NL80211_IFTYPE_AP) |
BIT(NL80211_IFTYPE_P2P_GO),
.he_cap = {
.has_he = true,
.he_cap_elem = {
.mac_cap_info[0] =
IEEE80211_HE_MAC_CAP0_HTC_HE,
.mac_cap_info[1] =
IEEE80211_HE_MAC_CAP1_MULTI_TID_AGG_RX_QOS_8,
.mac_cap_info[3] =
IEEE80211_HE_MAC_CAP3_OMI_CONTROL,
.phy_cap_info[1] =
IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD,
.phy_cap_info[2] =
IEEE80211_HE_PHY_CAP2_STBC_RX_UNDER_80MHZ |
IEEE80211_HE_PHY_CAP2_NDP_4x_LTF_AND_3_2US,
.phy_cap_info[3] =
IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_TX_BPSK |
IEEE80211_HE_PHY_CAP3_DCM_MAX_TX_NSS_1 |
IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_RX_BPSK |
IEEE80211_HE_PHY_CAP3_DCM_MAX_RX_NSS_1,
.phy_cap_info[6] =
IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT,
.phy_cap_info[7] =
IEEE80211_HE_PHY_CAP7_HE_SU_MU_PPDU_4XLTF_AND_08_US_GI,
.phy_cap_info[8] =
IEEE80211_HE_PHY_CAP8_HE_ER_SU_PPDU_4XLTF_AND_08_US_GI |
IEEE80211_HE_PHY_CAP8_DCM_MAX_RU_242,
.phy_cap_info[9] =
IEEE80211_HE_PHY_CAP9_TX_1024_QAM_LESS_THAN_242_TONE_RU |
IEEE80211_HE_PHY_CAP9_NOMINAL_PKT_PADDING_RESERVED
<< IEEE80211_HE_PHY_CAP9_NOMINAL_PKT_PADDING_POS,
}, /* * Set default Tx/Rx HE MCS NSS Support field. * Indicate support for up to 2 spatial streams and all * MCS, without any special cases
*/
.he_mcs_nss_supp = {
.rx_mcs_80 = cpu_to_le16(0xfffa),
.tx_mcs_80 = cpu_to_le16(0xfffa),
.rx_mcs_160 = cpu_to_le16(0xfffa),
.tx_mcs_160 = cpu_to_le16(0xfffa),
.rx_mcs_80p80 = cpu_to_le16(0xffff),
.tx_mcs_80p80 = cpu_to_le16(0xffff),
}, /* * Set default PPE thresholds, with PPET16 set to 0, * PPET8 set to 7
*/
.ppe_thres = {0x61, 0x1c, 0xc7, 0x71},
},
.eht_cap = {
.has_eht = true,
.eht_cap_elem = {
.mac_cap_info[0] =
IEEE80211_EHT_MAC_CAP0_OM_CONTROL,
.phy_cap_info[0] =
IEEE80211_EHT_PHY_CAP0_242_TONE_RU_GT20MHZ |
IEEE80211_EHT_PHY_CAP0_NDP_4_EHT_LFT_32_GI,
.phy_cap_info[5] =
FIELD_PREP_CONST(IEEE80211_EHT_PHY_CAP5_COMMON_NOMINAL_PKT_PAD_MASK,
IEEE80211_EHT_PHY_CAP5_COMMON_NOMINAL_PKT_PAD_16US),
},
/* For all MCS and bandwidth, set 2 NSS for both Tx and * Rx - note we don't set the only_20mhz, but due to this * being a union, it gets set correctly anyway.
*/
.eht_mcs_nss_supp = {
.bw._80 = {
.rx_tx_mcs9_max_nss = 0x22,
.rx_tx_mcs11_max_nss = 0x22,
.rx_tx_mcs13_max_nss = 0x22,
},
.bw._160 = {
.rx_tx_mcs9_max_nss = 0x22,
.rx_tx_mcs11_max_nss = 0x22,
.rx_tx_mcs13_max_nss = 0x22,
},
.bw._320 = {
.rx_tx_mcs9_max_nss = 0x22,
.rx_tx_mcs11_max_nss = 0x22,
.rx_tx_mcs13_max_nss = 0x22,
},
},
/* * PPE thresholds for NSS = 2, and RU index bitmap set * to 0xc. * Note: just for stating what we want, not present in * the transmitted data due to not including * IEEE80211_EHT_PHY_CAP5_PPE_THRESHOLD_PRESENT.
*/
.eht_ppe_thres = {0xc1, 0x0e, 0xe0 }
},
},
};
/* we know it's writable - we set it before ourselves */
iftype_data = (void *)(uintptr_t)sband->iftype_data; for (i = 0; i < sband->n_iftype_data; i++)
iftype_data[i].he_6ghz_capa.capa = cpu_to_le16(he_6ghz_capa);
}
/* EHT needs WPA3/MFP so cannot do it for fips_enabled */ if (!data->sku_cap_11be_enable || iwlwifi_mod_params.disable_11be ||
fips_enabled)
iftype_data->eht_cap.has_eht = false;
/* Advertise an A-MPDU exponent extension based on * operating band
*/ if (sband->band == NL80211_BAND_6GHZ && iftype_data->eht_cap.has_eht)
iftype_data->he_cap.he_cap_elem.mac_cap_info[3] |=
IEEE80211_HE_MAC_CAP3_MAX_AMPDU_LEN_EXP_EXT_2; elseif (sband->band != NL80211_BAND_2GHZ)
iftype_data->he_cap.he_cap_elem.mac_cap_info[3] |=
IEEE80211_HE_MAC_CAP3_MAX_AMPDU_LEN_EXP_EXT_1; else
iftype_data->he_cap.he_cap_elem.mac_cap_info[3] |=
IEEE80211_HE_MAC_CAP3_MAX_AMPDU_LEN_EXP_EXT_3;
if (iftype_data->eht_cap.has_eht) { /* * Set the number of sounding dimensions for each * bandwidth to 1 to indicate the maximal supported * value of TXVECTOR parameter NUM_STS of 2
*/
iftype_data->eht_cap.eht_cap_elem.phy_cap_info[2] |= 0x49;
/* * Set the MAX NC to 1 to indicate sounding feedback of * 2 supported by the beamfomee.
*/
iftype_data->eht_cap.eht_cap_elem.phy_cap_info[4] |= 0x10;
}
}
if (slow_pcie) { struct ieee80211_eht_mcs_nss_supp *mcs_nss =
&iftype_data->eht_cap.eht_mcs_nss_supp;
if (iftype_data->eht_cap.has_eht) { struct ieee80211_eht_mcs_nss_supp *mcs_nss =
&iftype_data->eht_cap.eht_mcs_nss_supp;
memset(mcs_nss, 0x11, sizeof(*mcs_nss));
}
if (!is_ap) { /* If not 2x2, we need to indicate 1x1 in the * Midamble RX Max NSTS - but not for AP mode
*/
iftype_data->he_cap.he_cap_elem.phy_cap_info[1] &=
~IEEE80211_HE_PHY_CAP1_MIDAMBLE_RX_TX_MAX_NSTS;
iftype_data->he_cap.he_cap_elem.phy_cap_info[2] &=
~IEEE80211_HE_PHY_CAP2_MIDAMBLE_RX_TX_MAX_NSTS;
iftype_data->he_cap.he_cap_elem.phy_cap_info[7] |=
IEEE80211_HE_PHY_CAP7_MAX_NC_1;
}
/* prior RFs don't have HE, HR RF doesn't have this, later have it */ if (CSR_HW_RFID_TYPE(trans->info.hw_rf_id) == IWL_CFG_RF_TYPE_HR1 ||
CSR_HW_RFID_TYPE(trans->info.hw_rf_id) == IWL_CFG_RF_TYPE_HR2)
iftype_data->he_cap.he_cap_elem.phy_cap_info[9] &=
~(IEEE80211_HE_PHY_CAP9_TX_1024_QAM_LESS_THAN_242_TONE_RU |
IEEE80211_HE_PHY_CAP9_RX_1024_QAM_LESS_THAN_242_TONE_RU);
if (trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_AX210 && !is_ap)
iftype_data->he_cap.he_cap_elem.phy_cap_info[2] |=
IEEE80211_HE_PHY_CAP2_UL_MU_FULL_MU_MIMO;
if (fw_has_capa(&fw->ucode_capa, IWL_UCODE_TLV_CAPA_BROADCAST_TWT))
iftype_data->he_cap.he_cap_elem.mac_cap_info[2] |=
IEEE80211_HE_MAC_CAP2_BCAST_TWT;
if (data->sku_cap_11ax_enable && !iwlwifi_mod_params.disable_11ax)
iwl_init_he_hw_capab(trans, data, sband, tx_chains, rx_chains,
fw);
/* 6GHz band. */
sband = &data->bands[NL80211_BAND_6GHZ];
sband->band = NL80211_BAND_6GHZ; /* use the same rates as 5GHz band */
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_6GHZ);
/* * 6 GHz requires WPA3 which requires MFP, which FW cannot do * when fips_enabled, so don't advertise any 6 GHz channels to * avoid spending time on scanning those channels and perhaps * even finding APs there that cannot be used.
*/ if (!fips_enabled && data->sku_cap_11ax_enable &&
!iwlwifi_mod_params.disable_11ax)
iwl_init_he_hw_capab(trans, data, sband, tx_chains, rx_chains,
fw); else
sband->n_channels = 0;
if (n_channels != n_used)
IWL_ERR_DEV(dev, "NVM: used only %d of %d channels\n",
n_used, n_channels);
}
iwl_flip_hw_address(mac_addr0, mac_addr1, data->hw_addr); /* * If the OEM fused a valid address, use it instead of the one in the * OTP
*/ if (is_valid_ether_addr(data->hw_addr)) return;
/* * Store the MAC address from MAO section. * No byte swapping is required in MAO section
*/
memcpy(data->hw_addr, hw_addr, ETH_ALEN);
/* * 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(trans, "mac address from nvm override section is not valid\n");
}
if (nvm_hw) { /* read the mac address from WFMP registers */
__le32 mac_addr0 = cpu_to_le32(iwl_trans_read_prph(trans,
WFMP_MAC_ADDR_0));
__le32 mac_addr1 = cpu_to_le32(iwl_trans_read_prph(trans,
WFMP_MAC_ADDR_1));
/* 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];
} else {
iwl_set_hw_address_family_8000(trans, cfg, data,
mac_override, nvm_hw);
}
if (!is_valid_ether_addr(data->hw_addr)) {
IWL_ERR(trans, "no valid mac address was found\n"); return -EINVAL;
}
if (!trans->csme_own)
IWL_INFO(trans, "base HW address: %pM, OTP minor version: 0x%x\n",
data->hw_addr, iwl_read_prph(trans, REG_OTP_MINOR));
return 0;
}
staticbool
iwl_nvm_no_wide_in_5ghz(struct iwl_trans *trans, conststruct iwl_rf_cfg *cfg, const __be16 *nvm_hw)
{ /* * Workaround a bug in Indonesia SKUs where the regulatory in * some 7000-family OTPs erroneously allow wide channels in * 5GHz. To check for Indonesia, we take the SKU value from * bits 1-4 in the subsystem ID and check if it is either 5 or * 9. In those cases, we need to force-disable wide channels * in 5GHz otherwise the FW will throw a sysassert when we try * to use them.
*/ if (trans->mac_cfg->device_family == IWL_DEVICE_FAMILY_7000) { /* * Unlike the other sections in the NVM, the hw * section uses big-endian.
*/
u16 subsystem_id = be16_to_cpup(nvm_hw + SUBSYSTEM_ID);
u8 sku = (subsystem_id & 0x1e) >> 1;
if (cfg->uhb_supported)
data = kzalloc(struct_size(data, channels,
IWL_NVM_NUM_CHANNELS_UHB),
GFP_KERNEL); else
data = kzalloc(struct_size(data, channels,
IWL_NVM_NUM_CHANNELS_EXT),
GFP_KERNEL); if (!data) return NULL;
data->n_hw_addrs = mei_nvm->n_hw_addrs; /* If no valid mac address was found - bail out */ if (iwl_set_hw_address(trans, cfg, data, NULL, NULL)) {
kfree(data); return NULL;
}
if (data->lar_enabled &&
fw_has_capa(&fw->ucode_capa, IWL_UCODE_TLV_CAPA_LAR_SUPPORT))
sbands_flags |= IWL_NVM_SBANDS_FLAGS_LAR;
/* Set the GO concurrent flag only in case that NO_IR is set. * Otherwise it is meaningless
*/ if ((nvm_flags & NVM_CHANNEL_GO_CONCURRENT)) { if (flags & NL80211_RRF_NO_IR)
flags |= NL80211_RRF_GO_CONCURRENT; if (flags & NL80211_RRF_DFS) {
flags |= NL80211_RRF_DFS_CONCURRENT; /* Our device doesn't set active bit for DFS channels * however, once marked as DFS no-ir is not needed.
*/
flags &= ~NL80211_RRF_NO_IR;
}
}
/* Set the AP type for the UHB case. */ if (nvm_flags & NVM_CHANNEL_VLP) { if (!(nvm_flags & NVM_CHANNEL_VLP_AP_NOT_ALLOWED))
flags |= NL80211_RRF_ALLOW_6GHZ_VLP_AP;
} else {
flags |= NL80211_RRF_NO_6GHZ_VLP_CLIENT;
}
if (!(nvm_flags & NVM_CHANNEL_AFC))
flags |= NL80211_RRF_NO_6GHZ_AFC_CLIENT;
/* * reg_capa is per regulatory domain so apply it for every channel
*/ if (ch_idx >= NUM_2GHZ_CHANNELS) { if (!reg_capa.allow_40mhz)
flags |= NL80211_RRF_NO_HT40;
if (!reg_capa.allow_80mhz)
flags |= NL80211_RRF_NO_80MHZ;
if (!reg_capa.allow_160mhz)
flags |= NL80211_RRF_NO_160MHZ;
if (!reg_capa.allow_320mhz)
flags |= NL80211_RRF_NO_320MHZ;
}
if (reg_capa.disable_11ax)
flags |= NL80211_RRF_NO_HE;
if (reg_capa.disable_11be)
flags |= NL80211_RRF_NO_EHT;
if (num_of_ch > max_num_ch) {
IWL_DEBUG_DEV(dev, IWL_DL_LAR, "Num of channels (%d) is greater than expected. Truncating to %d\n",
num_of_ch, max_num_ch);
num_of_ch = max_num_ch;
}
if (WARN_ON_ONCE(num_of_ch > NL80211_MAX_SUPP_REG_RULES)) return ERR_PTR(-EINVAL);
IWL_DEBUG_DEV(dev, IWL_DL_LAR, "building regdom for %d channels\n",
num_of_ch);
/* build a regdomain rule for every valid channel */
regd = kzalloc(struct_size(regd, reg_rules, num_of_ch), GFP_KERNEL); if (!regd) return ERR_PTR(-ENOMEM);
/* set alpha2 from FW. */
regd->alpha2[0] = fw_mcc >> 8;
regd->alpha2[1] = fw_mcc & 0xff;
/* this doesn't matter - not used by FW */
rule->power_rule.max_antenna_gain = DBI_TO_MBI(6);
rule->power_rule.max_eirp =
DBM_TO_MBM(IWL_DEFAULT_MAX_TX_POWER);
rule->flags = reg_rule_flags;
/* rely on auto-calculation to merge BW of contiguous chans */
rule->flags |= NL80211_RRF_AUTO_BW;
rule->freq_range.max_bandwidth_khz = 0;
/* * Certain firmware versions might report no valid channels * if booted in RF-kill, i.e. not all calibrations etc. are * running. We'll get out of this situation later when the * rfkill is removed and we update the regdomain again, but * since cfg80211 doesn't accept an empty regdomain, add a * dummy (unusable) rule here in this case so we can init.
*/ if (!valid_rules) {
valid_rules = 1;
rule = ®d->reg_rules[valid_rules - 1];
rule->freq_range.start_freq_khz = MHZ_TO_KHZ(2412);
rule->freq_range.end_freq_khz = MHZ_TO_KHZ(2413);
rule->freq_range.max_bandwidth_khz = MHZ_TO_KHZ(1);
rule->power_rule.max_antenna_gain = DBI_TO_MBI(6);
rule->power_rule.max_eirp =
DBM_TO_MBM(IWL_DEFAULT_MAX_TX_POWER);
}
regd->n_reg_rules = valid_rules;
/* * Narrow down regdom for unused regulatory rules to prevent hole * between reg rules to wmm rules.
*/
copy_rd = kmemdup(regd, struct_size(regd, reg_rules, valid_rules),
GFP_KERNEL); if (!copy_rd)
copy_rd = ERR_PTR(-ENOMEM);
if (section == NVM_SECTION_TYPE_PHY_SKU &&
hw_id == IWL_4165_DEVICE_ID && data && len >= 5 &&
(data[4] & NVM_SKU_CAP_MIMO_DISABLE)) /* OTP 0x52 bug work around: it's a 1x1 device */
data[3] = ANT_B | (ANT_B << 4);
}
IWL_EXPORT_SYMBOL(iwl_nvm_fixups);
/* * Reads external NVM from a file into mvm->nvm_sections * * HOW TO CREATE THE NVM FILE FORMAT: * ------------------------------ * 1. create hex file, format: * 3800 -> header * 0000 -> header * 5a40 -> data * * rev - 6 bit (word1) * len - 10 bit (word1) * id - 4 bit (word2) * rsv - 12 bit (word2) * * 2. flip 8bits with 8 bits per line to get the right NVM file format * * 3. create binary file from the hex file * * 4. save as "iNVM_xxx.bin" under /lib/firmware
*/ int iwl_read_external_nvm(struct iwl_trans *trans, constchar *nvm_file_name, struct iwl_nvm_section *nvm_sections)
{ int ret, section_size;
u16 section_id; conststruct firmware *fw_entry; conststruct {
__le16 word1;
__le16 word2;
u8 data[];
} *file_sec; const u8 *eof;
u8 *temp; int max_section_size; const __le32 *dword_buff;
IWL_DEBUG_EEPROM(trans->dev, "Read from external NVM\n");
/* Maximal size depends on NVM version */ if (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;
/* * Obtain NVM image via request_firmware. Since we already used * request_firmware_nowait() for the firmware binary load and only * get here after that we assume the NVM request can be satisfied * synchronously.
*/
ret = request_firmware(&fw_entry, nvm_file_name, trans->dev); if (ret) {
IWL_ERR(trans, "ERROR: %s isn't available %d\n",
nvm_file_name, ret); return ret;
}
/* some NVM file will contain a header. * The header is identified by 2 dwords header as follow: * dword[0] = 0x2A504C54 * dword[1] = 0x4E564D2A * * This header must be skipped when providing the NVM data to the FW.
*/ if (fw_entry->size > NVM_HEADER_SIZE &&
dword_buff[0] == cpu_to_le32(NVM_HEADER_0) &&
dword_buff[1] == cpu_to_le32(NVM_HEADER_1)) {
file_sec = (constvoid *)(fw_entry->data + NVM_HEADER_SIZE);
IWL_INFO(trans, "NVM Version %08X\n", le32_to_cpu(dword_buff[2]));
IWL_INFO(trans, "NVM Manufacturing date %08X\n",
le32_to_cpu(dword_buff[3]));
/* nvm file validation, dword_buff[2] holds the file version */ if (trans->mac_cfg->device_family == IWL_DEVICE_FAMILY_8000 &&
trans->info.hw_rev_step == SILICON_C_STEP &&
le32_to_cpu(dword_buff[2]) < 0xE4A) {
ret = -EFAULT; goto out;
}
} else {
file_sec = (constvoid *)fw_entry->data;
}
while (true) { if (file_sec->data > eof) {
IWL_ERR(trans, "ERROR - NVM file too short for section header\n");
ret = -EINVAL; break;
}
/* check for EOF marker */ if (!file_sec->word1 && !file_sec->word2) {
ret = 0; break;
}
if (section_size > max_section_size) {
IWL_ERR(trans, "ERROR - section too large (%d)\n",
section_size);
ret = -EINVAL; break;
}
if (!section_size) {
IWL_ERR(trans, "ERROR - section empty\n");
ret = -EINVAL; break;
}
if (file_sec->data + section_size > eof) {
IWL_ERR(trans, "ERROR - NVM file too short for section (%d bytes)\n",
section_size);
ret = -EINVAL; break;
}
if (WARN(section_id >= NVM_MAX_NUM_SECTIONS, "Invalid NVM section ID %d\n", section_id)) {
ret = -EINVAL; break;
}
temp = kmemdup(file_sec->data, section_size, GFP_KERNEL); if (!temp) {
ret = -ENOMEM; break;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.