Skip to content

Commit eae94cf

Browse files
committed
iwlwifi: mvm: add support for 6GHz
Add support to the 6GHz band (aka. Ultra High Band or UHB). This allows us to scan and connect to channels in that band, including all the relevant features, such as preferred scan channels, colocated channels etc. Co-developed-by: Haim Dreyfuss <[email protected]> Signed-off-by: Haim Dreyfuss <[email protected]> Co-developed-by: Ilan Peer <[email protected]> Signed-off-by: Ilan Peer <[email protected]> Co-developed-by: Tova Mussai <[email protected]> Signed-off-by: Tova Mussai <[email protected]> Co-developed-by: Andrei Otcheretianski <[email protected]> Signed-off-by: Andrei Otcheretianski <[email protected]> Co-developed-by: Tali Levi Rovinsky <[email protected]> Signed-off-by: Tali Levi Rovinsky <[email protected]> Co-developed-by: Avraham Stern <[email protected]> Signed-off-by: Avraham Stern <[email protected]> Co-developed-by: Ayala Beker <[email protected]> Signed-off-by: Ayala Beker <[email protected]> Signed-off-by: Luca Coelho <[email protected]> Link: https://lore.kernel.org/r/iwlwifi.20201210000657.0fdbfc3d7352.Idb648536faf21716e2ab2c6d6890d3e49f719cd3@changeid Signed-off-by: Luca Coelho <[email protected]>
1 parent d43ab29 commit eae94cf

File tree

14 files changed

+430
-5
lines changed

14 files changed

+430
-5
lines changed

drivers/net/wireless/intel/iwlwifi/cfg/22000.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,8 @@ static const struct iwl_base_params iwl_ax210_base_params = {
155155
static const struct iwl_ht_params iwl_22000_ht_params = {
156156
.stbc = true,
157157
.ldpc = true,
158-
.ht40_bands = BIT(NL80211_BAND_2GHZ) | BIT(NL80211_BAND_5GHZ),
158+
.ht40_bands = BIT(NL80211_BAND_2GHZ) | BIT(NL80211_BAND_5GHZ) |
159+
BIT(NL80211_BAND_6GHZ),
159160
};
160161

161162
#define IWL_DEVICE_22000_COMMON \

drivers/net/wireless/intel/iwlwifi/fw/api/phy-ctxt.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@
6666
/* Supported bands */
6767
#define PHY_BAND_5 (0)
6868
#define PHY_BAND_24 (1)
69+
#define PHY_BAND_6 (2)
6970

7071
/* Supported channel width, vary if there is VHT support */
7172
#define PHY_VHT_CHANNEL_MODE20 (0x0)

drivers/net/wireless/intel/iwlwifi/fw/api/scan.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -530,6 +530,11 @@ enum iwl_channel_flags {
530530
IWL_CHANNEL_FLAG_PRE_SCAN_PASSIVE2ACTIVE = BIT(3),
531531
};
532532

533+
enum iwl_uhb_chan_cfg_flags {
534+
IWL_UHB_CHAN_CFG_FLAG_UNSOLICITED_PROBE_RES = BIT(24),
535+
IWL_UHB_CHAN_CFG_FLAG_PSC_CHAN_NO_LISTEN = BIT(25),
536+
IWL_UHB_CHAN_CFG_FLAG_FORCE_PASSIVE = BIT(26),
537+
};
533538
/**
534539
* struct iwl_scan_dwell
535540
* @active: default dwell time for active scan

drivers/net/wireless/intel/iwlwifi/fw/file.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -486,6 +486,11 @@ enum iwl_ucode_tlv_capa {
486486
/* set 3 */
487487
IWL_UCODE_TLV_CAPA_MLME_OFFLOAD = (__force iwl_ucode_tlv_capa_t)96,
488488

489+
/*
490+
* @IWL_UCODE_TLV_CAPA_PSC_CHAN_SUPPORT: supports PSC channels
491+
*/
492+
IWL_UCODE_TLV_CAPA_PSC_CHAN_SUPPORT = (__force iwl_ucode_tlv_capa_t)98,
493+
489494
NUM_IWL_UCODE_TLV_CAPA
490495
#ifdef __CHECKER__
491496
/* sparse says it cannot increment the previous enum member */

drivers/net/wireless/intel/iwlwifi/iwl-eeprom-parse.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,11 @@ struct iwl_nvm_data {
100100
bool vht160_supported;
101101
struct ieee80211_supported_band bands[NUM_NL80211_BANDS];
102102

103+
/*
104+
* iftype data for low (2.4 GHz) and high (5 and 6 GHz) bands,
105+
* we can use the same for 5 and 6 GHz bands because they have
106+
* the same data
107+
*/
103108
struct {
104109
struct ieee80211_sband_iftype_data low[2];
105110
struct ieee80211_sband_iftype_data high[2];

drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,7 @@ static const u16 iwl_uhb_nvm_channels[] = {
166166
#define IWL_NVM_NUM_CHANNELS_EXT ARRAY_SIZE(iwl_ext_nvm_channels)
167167
#define IWL_NVM_NUM_CHANNELS_UHB ARRAY_SIZE(iwl_uhb_nvm_channels)
168168
#define NUM_2GHZ_CHANNELS 14
169+
#define NUM_5GHZ_CHANNELS 37
169170
#define FIRST_2GHZ_HT_MINUS 5
170171
#define LAST_2GHZ_HT_PLUS 9
171172
#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,
389390

390391
static enum nl80211_band iwl_nl80211_band_from_channel_idx(int ch_idx)
391392
{
393+
if (ch_idx >= NUM_2GHZ_CHANNELS + NUM_5GHZ_CHANNELS) {
394+
return NL80211_BAND_6GHZ;
395+
}
396+
392397
if (ch_idx >= NUM_2GHZ_CHANNELS)
393398
return NL80211_BAND_5GHZ;
394399
return NL80211_BAND_2GHZ;
@@ -480,6 +485,11 @@ static int iwl_init_channel_map(struct device *dev, const struct iwl_cfg *cfg,
480485
else
481486
channel->flags = 0;
482487

488+
/* TODO: Don't put limitations on UHB devices as we still don't
489+
* have NVM for them
490+
*/
491+
if (cfg->uhb_supported)
492+
channel->flags = 0;
483493
iwl_nvm_print_channel_flags(dev, IWL_DL_EEPROM,
484494
channel->hw_value, ch_flags);
485495
IWL_DEBUG_EEPROM(dev, "Ch. %d: %ddBm\n",
@@ -743,6 +753,52 @@ static const struct ieee80211_sband_iftype_data iwl_he_capa[] = {
743753
},
744754
};
745755

756+
static void iwl_init_he_6ghz_capa(struct iwl_trans *trans,
757+
struct iwl_nvm_data *data,
758+
struct ieee80211_supported_band *sband,
759+
u8 tx_chains, u8 rx_chains)
760+
{
761+
struct ieee80211_sta_ht_cap ht_cap;
762+
struct ieee80211_sta_vht_cap vht_cap = {};
763+
struct ieee80211_sband_iftype_data *iftype_data;
764+
u16 he_6ghz_capa = 0;
765+
u32 exp;
766+
int i;
767+
768+
if (sband->band != NL80211_BAND_6GHZ)
769+
return;
770+
771+
/* grab HT/VHT capabilities and calculate HE 6 GHz capabilities */
772+
iwl_init_ht_hw_capab(trans, data, &ht_cap, NL80211_BAND_5GHZ,
773+
tx_chains, rx_chains);
774+
WARN_ON(!ht_cap.ht_supported);
775+
iwl_init_vht_hw_capab(trans, data, &vht_cap, tx_chains, rx_chains);
776+
WARN_ON(!vht_cap.vht_supported);
777+
778+
he_6ghz_capa |=
779+
u16_encode_bits(ht_cap.ampdu_density,
780+
IEEE80211_HE_6GHZ_CAP_MIN_MPDU_START);
781+
exp = u32_get_bits(vht_cap.cap,
782+
IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK);
783+
he_6ghz_capa |=
784+
u16_encode_bits(exp, IEEE80211_HE_6GHZ_CAP_MAX_AMPDU_LEN_EXP);
785+
exp = u32_get_bits(vht_cap.cap, IEEE80211_VHT_CAP_MAX_MPDU_MASK);
786+
he_6ghz_capa |=
787+
u16_encode_bits(exp, IEEE80211_HE_6GHZ_CAP_MAX_MPDU_LEN);
788+
/* we don't support extended_ht_cap_info anywhere, so no RD_RESPONDER */
789+
if (vht_cap.cap & IEEE80211_VHT_CAP_TX_ANTENNA_PATTERN)
790+
he_6ghz_capa |= IEEE80211_HE_6GHZ_CAP_TX_ANTPAT_CONS;
791+
if (vht_cap.cap & IEEE80211_VHT_CAP_RX_ANTENNA_PATTERN)
792+
he_6ghz_capa |= IEEE80211_HE_6GHZ_CAP_RX_ANTPAT_CONS;
793+
794+
IWL_DEBUG_EEPROM(trans->dev, "he_6ghz_capa=0x%x\n", he_6ghz_capa);
795+
796+
/* we know it's writable - we set it before ourselves */
797+
iftype_data = (void *)sband->iftype_data;
798+
for (i = 0; i < sband->n_iftype_data; i++)
799+
iftype_data[i].he_6ghz_capa.capa = cpu_to_le16(he_6ghz_capa);
800+
}
801+
746802
static void iwl_init_he_hw_capab(struct iwl_trans *trans,
747803
struct iwl_nvm_data *data,
748804
struct ieee80211_supported_band *sband,
@@ -762,6 +818,7 @@ static void iwl_init_he_hw_capab(struct iwl_trans *trans,
762818
iftype_data = data->iftd.low;
763819
break;
764820
case NL80211_BAND_5GHZ:
821+
case NL80211_BAND_6GHZ:
765822
iftype_data = data->iftd.high;
766823
break;
767824
default:
@@ -787,6 +844,7 @@ static void iwl_init_he_hw_capab(struct iwl_trans *trans,
787844
~IEEE80211_HE_PHY_CAP7_MAX_NC_MASK;
788845
}
789846
}
847+
iwl_init_he_6ghz_capa(trans, data, sband, tx_chains, rx_chains);
790848
}
791849

792850
static void iwl_init_sbands(struct iwl_trans *trans,
@@ -829,6 +887,19 @@ static void iwl_init_sbands(struct iwl_trans *trans,
829887
if (data->sku_cap_11ax_enable && !iwlwifi_mod_params.disable_11ax)
830888
iwl_init_he_hw_capab(trans, data, sband, tx_chains, rx_chains);
831889

890+
/* 6GHz band. */
891+
sband = &data->bands[NL80211_BAND_6GHZ];
892+
sband->band = NL80211_BAND_6GHZ;
893+
/* use the same rates as 5GHz band */
894+
sband->bitrates = &iwl_cfg80211_rates[RATES_52_OFFS];
895+
sband->n_bitrates = N_RATES_52;
896+
n_used += iwl_init_sband_channels(data, sband, n_channels,
897+
NL80211_BAND_6GHZ);
898+
899+
if (data->sku_cap_11ax_enable && !iwlwifi_mod_params.disable_11ax)
900+
iwl_init_he_hw_capab(trans, data, sband, tx_chains, rx_chains);
901+
else
902+
sband->n_channels = 0;
832903
if (n_channels != n_used)
833904
IWL_ERR_DEV(dev, "NVM: used only %d of %d channels\n",
834905
n_used, n_channels);

drivers/net/wireless/intel/iwlwifi/mvm/constants.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,5 +165,6 @@
165165
#define IWL_MVM_FTM_INITIATOR_SMOOTH_UNDERSHOOT 20016
166166
#define IWL_MVM_FTM_INITIATOR_SMOOTH_OVERSHOOT 20016
167167
#define IWL_MVM_FTM_INITIATOR_SMOOTH_AGE_SEC 2
168+
#define IWL_MVM_DISABLE_AP_FILS false
168169

169170
#endif /* __MVM_CONSTANTS_H */

drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@
6161
*****************************************************************************/
6262

6363
#include <linux/etherdevice.h>
64+
#include <linux/crc32.h>
6465
#include <net/mac80211.h>
6566
#include "iwl-io.h"
6667
#include "iwl-prph.h"
@@ -980,12 +981,28 @@ static int iwl_mvm_mac_ctxt_send_beacon_v9(struct iwl_mvm *mvm,
980981
struct iwl_mac_beacon_cmd beacon_cmd = {};
981982
u8 rate = iwl_mvm_mac_ctxt_get_lowest_rate(info, vif);
982983
u16 flags;
984+
struct ieee80211_chanctx_conf *ctx;
985+
int channel;
983986

984987
flags = iwl_mvm_mac80211_idx_to_hwrate(rate);
985988

986989
if (rate == IWL_FIRST_CCK_RATE)
987990
flags |= IWL_MAC_BEACON_CCK;
988991

992+
/* Enable FILS on PSC channels only */
993+
rcu_read_lock();
994+
ctx = rcu_dereference(vif->chanctx_conf);
995+
channel = ieee80211_frequency_to_channel(ctx->def.chan->center_freq);
996+
WARN_ON(channel == 0);
997+
if (cfg80211_channel_is_psc(ctx->def.chan) &&
998+
!IWL_MVM_DISABLE_AP_FILS) {
999+
flags |= IWL_MAC_BEACON_FILS;
1000+
beacon_cmd.short_ssid =
1001+
cpu_to_le32(~crc32_le(~0, vif->bss_conf.ssid,
1002+
vif->bss_conf.ssid_len));
1003+
}
1004+
rcu_read_unlock();
1005+
9891006
beacon_cmd.flags = cpu_to_le16(flags);
9901007
beacon_cmd.byte_cnt = cpu_to_le16((u16)beacon->len);
9911008
beacon_cmd.template_id = cpu_to_le32((u32)mvmvif->id);

drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -566,6 +566,7 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
566566

567567
hw->wiphy->flags |= WIPHY_FLAG_AP_UAPSD;
568568
hw->wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH;
569+
hw->wiphy->flags |= WIPHY_FLAG_SPLIT_SCAN_6GHZ;
569570

570571
hw->wiphy->iface_combinations = iwl_mvm_iface_combinations;
571572
hw->wiphy->n_iface_combinations =
@@ -619,6 +620,11 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
619620
hw->wiphy->bands[NL80211_BAND_5GHZ]->vht_cap.cap |=
620621
IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE;
621622
}
623+
if (fw_has_capa(&mvm->fw->ucode_capa,
624+
IWL_UCODE_TLV_CAPA_PSC_CHAN_SUPPORT) &&
625+
mvm->nvm_data->bands[NL80211_BAND_6GHZ].n_channels)
626+
hw->wiphy->bands[NL80211_BAND_6GHZ] =
627+
&mvm->nvm_data->bands[NL80211_BAND_6GHZ];
622628

623629
hw->wiphy->hw_version = mvm->trans->hw_id;
624630

drivers/net/wireless/intel/iwlwifi/mvm/mvm.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2100,6 +2100,8 @@ static inline u8 iwl_mvm_phy_band_from_nl80211(enum nl80211_band band)
21002100
return PHY_BAND_24;
21012101
case NL80211_BAND_5GHZ:
21022102
return PHY_BAND_5;
2103+
case NL80211_BAND_6GHZ:
2104+
return PHY_BAND_6;
21032105
default:
21042106
WARN_ONCE(1, "Unsupported band (%u)\n", band);
21052107
return PHY_BAND_5;

drivers/net/wireless/intel/iwlwifi/mvm/rs-fw.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -420,9 +420,21 @@ void iwl_mvm_tlc_update_notif(struct iwl_mvm *mvm,
420420

421421
u16 rs_fw_get_max_amsdu_len(struct ieee80211_sta *sta)
422422
{
423+
struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
423424
const struct ieee80211_sta_vht_cap *vht_cap = &sta->vht_cap;
424425
const struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap;
425426

427+
if (mvmsta->vif->bss_conf.chandef.chan->band == NL80211_BAND_6GHZ) {
428+
switch (le16_get_bits(sta->he_6ghz_capa.capa,
429+
IEEE80211_HE_6GHZ_CAP_MAX_MPDU_LEN)) {
430+
case IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454:
431+
return IEEE80211_MAX_MPDU_LEN_VHT_11454;
432+
case IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991:
433+
return IEEE80211_MAX_MPDU_LEN_VHT_7991;
434+
default:
435+
return IEEE80211_MAX_MPDU_LEN_VHT_3895;
436+
}
437+
} else
426438
if (vht_cap->vht_supported) {
427439
switch (vht_cap->cap & IEEE80211_VHT_CAP_MAX_MPDU_MASK) {
428440
case IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454:

drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1591,6 +1591,8 @@ static inline u8 iwl_mvm_nl80211_band_from_rx_msdu(u8 phy_band)
15911591
return NL80211_BAND_2GHZ;
15921592
case PHY_BAND_5:
15931593
return NL80211_BAND_5GHZ;
1594+
case PHY_BAND_6:
1595+
return NL80211_BAND_6GHZ;
15941596
default:
15951597
WARN_ONCE(1, "Unsupported phy band (%u)\n", phy_band);
15961598
return NL80211_BAND_5GHZ;

0 commit comments

Comments
 (0)