summaryrefslogtreecommitdiff
path: root/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c')
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c71
1 files changed, 71 insertions, 0 deletions
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c
index 6f3aca19a254..41a79da878ef 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c
@@ -166,6 +166,7 @@ static const u16 iwl_uhb_nvm_channels[] = {
#define IWL_NVM_NUM_CHANNELS_EXT ARRAY_SIZE(iwl_ext_nvm_channels)
#define IWL_NVM_NUM_CHANNELS_UHB ARRAY_SIZE(iwl_uhb_nvm_channels)
#define NUM_2GHZ_CHANNELS 14
+#define NUM_5GHZ_CHANNELS 37
#define FIRST_2GHZ_HT_MINUS 5
#define LAST_2GHZ_HT_PLUS 9
#define N_HW_ADDR_MASK 0xF
@@ -389,6 +390,10 @@ static u32 iwl_get_channel_flags(u8 ch_num, int ch_idx, enum nl80211_band band,
static enum nl80211_band iwl_nl80211_band_from_channel_idx(int ch_idx)
{
+ if (ch_idx >= NUM_2GHZ_CHANNELS + NUM_5GHZ_CHANNELS) {
+ return NL80211_BAND_6GHZ;
+ }
+
if (ch_idx >= NUM_2GHZ_CHANNELS)
return NL80211_BAND_5GHZ;
return NL80211_BAND_2GHZ;
@@ -480,6 +485,11 @@ static int iwl_init_channel_map(struct device *dev, const struct iwl_cfg *cfg,
else
channel->flags = 0;
+ /* TODO: Don't put limitations on UHB devices as we still don't
+ * have NVM for them
+ */
+ if (cfg->uhb_supported)
+ channel->flags = 0;
iwl_nvm_print_channel_flags(dev, IWL_DL_EEPROM,
channel->hw_value, ch_flags);
IWL_DEBUG_EEPROM(dev, "Ch. %d: %ddBm\n",
@@ -743,6 +753,52 @@ static const struct ieee80211_sband_iftype_data iwl_he_capa[] = {
},
};
+static void iwl_init_he_6ghz_capa(struct iwl_trans *trans,
+ struct iwl_nvm_data *data,
+ struct ieee80211_supported_band *sband,
+ u8 tx_chains, u8 rx_chains)
+{
+ struct ieee80211_sta_ht_cap ht_cap;
+ struct ieee80211_sta_vht_cap vht_cap = {};
+ struct ieee80211_sband_iftype_data *iftype_data;
+ u16 he_6ghz_capa = 0;
+ u32 exp;
+ int i;
+
+ if (sband->band != NL80211_BAND_6GHZ)
+ return;
+
+ /* grab HT/VHT capabilities and calculate HE 6 GHz capabilities */
+ iwl_init_ht_hw_capab(trans, data, &ht_cap, NL80211_BAND_5GHZ,
+ tx_chains, rx_chains);
+ WARN_ON(!ht_cap.ht_supported);
+ iwl_init_vht_hw_capab(trans, data, &vht_cap, tx_chains, rx_chains);
+ WARN_ON(!vht_cap.vht_supported);
+
+ he_6ghz_capa |=
+ u16_encode_bits(ht_cap.ampdu_density,
+ IEEE80211_HE_6GHZ_CAP_MIN_MPDU_START);
+ exp = u32_get_bits(vht_cap.cap,
+ IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK);
+ he_6ghz_capa |=
+ u16_encode_bits(exp, IEEE80211_HE_6GHZ_CAP_MAX_AMPDU_LEN_EXP);
+ exp = u32_get_bits(vht_cap.cap, IEEE80211_VHT_CAP_MAX_MPDU_MASK);
+ he_6ghz_capa |=
+ u16_encode_bits(exp, IEEE80211_HE_6GHZ_CAP_MAX_MPDU_LEN);
+ /* we don't support extended_ht_cap_info anywhere, so no RD_RESPONDER */
+ if (vht_cap.cap & IEEE80211_VHT_CAP_TX_ANTENNA_PATTERN)
+ he_6ghz_capa |= IEEE80211_HE_6GHZ_CAP_TX_ANTPAT_CONS;
+ if (vht_cap.cap & IEEE80211_VHT_CAP_RX_ANTENNA_PATTERN)
+ he_6ghz_capa |= IEEE80211_HE_6GHZ_CAP_RX_ANTPAT_CONS;
+
+ IWL_DEBUG_EEPROM(trans->dev, "he_6ghz_capa=0x%x\n", he_6ghz_capa);
+
+ /* we know it's writable - we set it before ourselves */
+ iftype_data = (void *)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);
+}
+
static void iwl_init_he_hw_capab(struct iwl_trans *trans,
struct iwl_nvm_data *data,
struct ieee80211_supported_band *sband,
@@ -762,6 +818,7 @@ static void iwl_init_he_hw_capab(struct iwl_trans *trans,
iftype_data = data->iftd.low;
break;
case NL80211_BAND_5GHZ:
+ case NL80211_BAND_6GHZ:
iftype_data = data->iftd.high;
break;
default:
@@ -787,6 +844,7 @@ static void iwl_init_he_hw_capab(struct iwl_trans *trans,
~IEEE80211_HE_PHY_CAP7_MAX_NC_MASK;
}
}
+ iwl_init_he_6ghz_capa(trans, data, sband, tx_chains, rx_chains);
}
static void iwl_init_sbands(struct iwl_trans *trans,
@@ -829,6 +887,19 @@ static void iwl_init_sbands(struct iwl_trans *trans,
if (data->sku_cap_11ax_enable && !iwlwifi_mod_params.disable_11ax)
iwl_init_he_hw_capab(trans, data, sband, tx_chains, rx_chains);
+ /* 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);
+
+ if (data->sku_cap_11ax_enable && !iwlwifi_mod_params.disable_11ax)
+ iwl_init_he_hw_capab(trans, data, sband, tx_chains, rx_chains);
+ 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);