2022-11-22 20:12:59

by Greenman, Gregory

[permalink] [raw]
Subject: [PATCH v2 0/9] wifi: iwlwifi: updates intended for v6.2 2022-11-22

From: Gregory Greenman <[email protected]>

Hi,

Here's the third set of patches intended for v6.2, with the fixes.
Resending all the patches since I think it'll make the review easier.
The fixes are only for two patches (1 and 4), the rest are unchanged.

It contains EHT adjustments for iwlwifi. It contains only iwlwifi
changes, all the required mac80211/cfg80211 changes are already merged
upstream.

As usual, I'm pushing this to a pending branch, for kbuild bot,
and will send a pull-request later.

Please review.

Thanks,
Gregory.

Abhishek Naik (1):
wifi: iwlwifi: nvm: Update EHT capabilities for GL device

Ilan Peer (1):
wifi: iwlwifi: mvm: Advertise EHT capabilities

Johannes Berg (4):
wifi: iwlwifi: mvm: support 320 MHz PHY configuration
wifi: iwlwifi: mvm: set HE PHY bandwidth according to band
wifi: iwlwifi: mvm: advertise 320 MHz in 6 GHz only conditionally
wifi: iwlwifi: nvm-parse: support A-MPDU in EHT 2.4 GHz

Miri Korenblit (1):
wifi: iwlwifi: mvm: support PPE Thresholds for EHT

Mordechay Goodstein (2):
wifi: iwlwifi: rs: add support for parsing max MCS per NSS/BW in 11be
wifi: iwlwifi: mvm: add support for EHT 1K aggregation size

.../net/wireless/intel/iwlwifi/fw/api/mac.h | 6 +-
.../wireless/intel/iwlwifi/fw/api/phy-ctxt.h | 33 ++-
.../net/wireless/intel/iwlwifi/fw/api/rs.h | 10 +-
drivers/net/wireless/intel/iwlwifi/fw/rs.c | 2 +
drivers/net/wireless/intel/iwlwifi/iwl-drv.c | 3 +
.../wireless/intel/iwlwifi/iwl-eeprom-parse.h | 3 +-
.../wireless/intel/iwlwifi/iwl-modparams.h | 1 +
.../wireless/intel/iwlwifi/iwl-nvm-parse.c | 235 ++++++++++++++++--
.../net/wireless/intel/iwlwifi/mvm/mac80211.c | 179 ++++++++++---
drivers/net/wireless/intel/iwlwifi/mvm/ops.c | 10 +-
.../net/wireless/intel/iwlwifi/mvm/phy-ctxt.c | 54 ++--
.../net/wireless/intel/iwlwifi/mvm/rs-fw.c | 125 +++++++++-
12 files changed, 548 insertions(+), 113 deletions(-)

--
2.35.3


2022-11-22 20:12:59

by Greenman, Gregory

[permalink] [raw]
Subject: [PATCH v2 1/9] wifi: iwlwifi: mvm: Advertise EHT capabilities

From: Ilan Peer <[email protected]>

Add support for advertising EHT capabilities if supported by
device SKU and not disabled by module parameters.

Signed-off-by: Ilan Peer <[email protected]>
Signed-off-by: Gregory Greenman <[email protected]>
---
drivers/net/wireless/intel/iwlwifi/iwl-drv.c | 3 +
.../wireless/intel/iwlwifi/iwl-eeprom-parse.h | 3 +-
.../wireless/intel/iwlwifi/iwl-modparams.h | 1 +
.../wireless/intel/iwlwifi/iwl-nvm-parse.c | 178 ++++++++++++++++--
4 files changed, 167 insertions(+), 18 deletions(-)

diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-drv.c b/drivers/net/wireless/intel/iwlwifi/iwl-drv.c
index a2203f661321..ab7065c93826 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-drv.c
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-drv.c
@@ -1971,3 +1971,6 @@ MODULE_PARM_DESC(remove_when_gone,
module_param_named(disable_11ax, iwlwifi_mod_params.disable_11ax, bool,
S_IRUGO);
MODULE_PARM_DESC(disable_11ax, "Disable HE capabilities (default: false)");
+
+module_param_named(disable_11be, iwlwifi_mod_params.disable_11be, bool, 0444);
+MODULE_PARM_DESC(disable_11be, "Disable EHT capabilities (default: false)");
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-eeprom-parse.h b/drivers/net/wireless/intel/iwlwifi/iwl-eeprom-parse.h
index 0efffb6eeb1e..baa643386018 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-eeprom-parse.h
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-eeprom-parse.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
- * Copyright (C) 2005-2014, 2018 Intel Corporation
+ * Copyright (C) 2005-2014, 2018, 2020-2022 Intel Corporation
* Copyright (C) 2015 Intel Mobile Communications GmbH
*/
#ifndef __iwl_eeprom_parse_h__
@@ -31,6 +31,7 @@ struct iwl_nvm_data {
bool sku_cap_amt_enable;
bool sku_cap_ipan_enable;
bool sku_cap_mimo_disabled;
+ bool sku_cap_11be_enable;

u16 radio_cfg_type;
u8 radio_cfg_step;
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-modparams.h b/drivers/net/wireless/intel/iwlwifi/iwl-modparams.h
index d0b4d02bdab9..1cf26ab4f488 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-modparams.h
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-modparams.h
@@ -62,6 +62,7 @@ enum iwl_uapsd_disable {
* @disable_11ac: disable VHT capabilities, default = false.
* @remove_when_gone: remove an inaccessible device from the PCIe bus.
* @enable_ini: enable new FW debug infratructure (INI TLVs)
+ * @disable_11be: disable EHT capabilities, default = false.
*/
struct iwl_mod_params {
int swcrypto;
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c
index 9040da3dcce3..2b43fff4d3f9 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c
@@ -546,7 +546,7 @@ static const u8 iwl_vendor_caps[] = {
0x00
};

-static const struct ieee80211_sband_iftype_data iwl_he_capa[] = {
+static const struct ieee80211_sband_iftype_data iwl_he_eht_capa[] = {
{
.types_mask = BIT(NL80211_IFTYPE_STATION),
.he_cap = {
@@ -631,6 +631,78 @@ static const struct ieee80211_sband_iftype_data iwl_he_capa[] = {
*/
.ppe_thres = {0x61, 0x1c, 0xc7, 0x71},
},
+ .eht_cap = {
+ .has_eht = true,
+ .eht_cap_elem = {
+ .mac_cap_info[0] =
+ IEEE80211_EHT_MAC_CAP0_EPCS_PRIO_ACCESS |
+ IEEE80211_EHT_MAC_CAP0_OM_CONTROL |
+ IEEE80211_EHT_MAC_CAP0_TRIG_TXOP_SHARING_MODE1 |
+ IEEE80211_EHT_MAC_CAP0_TRIG_TXOP_SHARING_MODE2,
+ .phy_cap_info[0] =
+ IEEE80211_EHT_PHY_CAP0_242_TONE_RU_GT20MHZ |
+ IEEE80211_EHT_PHY_CAP0_NDP_4_EHT_LFT_32_GI |
+ IEEE80211_EHT_PHY_CAP0_PARTIAL_BW_UL_MU_MIMO |
+ IEEE80211_EHT_PHY_CAP0_SU_BEAMFORMEE |
+ IEEE80211_EHT_PHY_CAP0_BEAMFORMEE_SS_80MHZ_MASK,
+ .phy_cap_info[1] =
+ IEEE80211_EHT_PHY_CAP1_BEAMFORMEE_SS_80MHZ_MASK |
+ IEEE80211_EHT_PHY_CAP1_BEAMFORMEE_SS_160MHZ_MASK |
+ IEEE80211_EHT_PHY_CAP1_BEAMFORMEE_SS_320MHZ_MASK,
+ .phy_cap_info[3] =
+ IEEE80211_EHT_PHY_CAP3_NG_16_SU_FEEDBACK |
+ IEEE80211_EHT_PHY_CAP3_NG_16_MU_FEEDBACK |
+ IEEE80211_EHT_PHY_CAP3_CODEBOOK_4_2_SU_FDBK |
+ IEEE80211_EHT_PHY_CAP3_CODEBOOK_7_5_MU_FDBK |
+ IEEE80211_EHT_PHY_CAP3_TRIG_SU_BF_FDBK |
+ IEEE80211_EHT_PHY_CAP3_TRIG_MU_BF_PART_BW_FDBK |
+ IEEE80211_EHT_PHY_CAP3_TRIG_CQI_FDBK,
+
+ .phy_cap_info[4] =
+ IEEE80211_EHT_PHY_CAP4_PART_BW_DL_MU_MIMO |
+ IEEE80211_EHT_PHY_CAP4_POWER_BOOST_FACT_SUPP |
+ IEEE80211_EHT_PHY_CAP4_EHT_MU_PPDU_4_EHT_LTF_08_GI,
+ .phy_cap_info[5] =
+ IEEE80211_EHT_PHY_CAP5_NON_TRIG_CQI_FEEDBACK |
+ IEEE80211_EHT_PHY_CAP5_TX_LESS_242_TONE_RU_SUPP |
+ IEEE80211_EHT_PHY_CAP5_RX_LESS_242_TONE_RU_SUPP |
+ IEEE80211_EHT_PHY_CAP5_PPE_THRESHOLD_PRESENT,
+ .phy_cap_info[6] =
+ IEEE80211_EHT_PHY_CAP6_MCS15_SUPP_MASK |
+ IEEE80211_EHT_PHY_CAP6_EHT_DUP_6GHZ_SUPP,
+ .phy_cap_info[8] =
+ IEEE80211_EHT_PHY_CAP8_RX_1024QAM_WIDER_BW_DL_OFDMA |
+ IEEE80211_EHT_PHY_CAP8_RX_4096QAM_WIDER_BW_DL_OFDMA,
+ },
+
+ /* 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.
+ */
+ .eht_ppe_thres = {0xc1, 0x0e, 0xe0 }
+ },
},
{
.types_mask = BIT(NL80211_IFTYPE_AP),
@@ -687,6 +759,49 @@ static const struct ieee80211_sband_iftype_data iwl_he_capa[] = {
*/
.ppe_thres = {0x61, 0x1c, 0xc7, 0x71},
},
+ .eht_cap = {
+ .has_eht = true,
+ .eht_cap_elem = {
+ .mac_cap_info[0] =
+ IEEE80211_EHT_MAC_CAP0_EPCS_PRIO_ACCESS |
+ IEEE80211_EHT_MAC_CAP0_OM_CONTROL |
+ IEEE80211_EHT_MAC_CAP0_TRIG_TXOP_SHARING_MODE1 |
+ IEEE80211_EHT_MAC_CAP0_TRIG_TXOP_SHARING_MODE2,
+ .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] =
+ IEEE80211_EHT_PHY_CAP5_PPE_THRESHOLD_PRESENT,
+ },
+
+ /* 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.
+ */
+ .eht_ppe_thres = {0xc1, 0x0e, 0xe0 }
+ },
},
};

@@ -738,6 +853,7 @@ static void iwl_init_he_6ghz_capa(struct iwl_trans *trans,

static void
iwl_nvm_fixup_sband_iftd(struct iwl_trans *trans,
+ struct iwl_nvm_data *data,
struct ieee80211_supported_band *sband,
struct ieee80211_sband_iftype_data *iftype_data,
u8 tx_chains, u8 rx_chains,
@@ -745,6 +861,9 @@ iwl_nvm_fixup_sband_iftd(struct iwl_trans *trans,
{
bool is_ap = iftype_data->types_mask & BIT(NL80211_IFTYPE_AP);

+ if (!data->sku_cap_11be_enable || iwlwifi_mod_params.disable_11be)
+ iftype_data->eht_cap.has_eht = false;
+
/* Advertise an A-MPDU exponent extension based on
* operating band
*/
@@ -765,19 +884,44 @@ iwl_nvm_fixup_sband_iftd(struct iwl_trans *trans,
iftype_data->he_cap.he_cap_elem.phy_cap_info[5] |=
IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_UNDER_80MHZ_2 |
IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_ABOVE_80MHZ_2;
- if (!is_ap)
+ if (!is_ap) {
iftype_data->he_cap.he_cap_elem.phy_cap_info[7] |=
IEEE80211_HE_PHY_CAP7_MAX_NC_2;
- } else 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;
+
+ 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;
+ }
+ }
+ } else {
+ 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;
+ }
}

switch (CSR_HW_RFID_TYPE(trans->hw_rf_id)) {
@@ -816,8 +960,8 @@ static void iwl_init_he_hw_capab(struct iwl_trans *trans,
if (WARN_ON(sband->iftype_data))
return;

- BUILD_BUG_ON(sizeof(data->iftd.low) != sizeof(iwl_he_capa));
- BUILD_BUG_ON(sizeof(data->iftd.high) != sizeof(iwl_he_capa));
+ BUILD_BUG_ON(sizeof(data->iftd.low) != sizeof(iwl_he_eht_capa));
+ BUILD_BUG_ON(sizeof(data->iftd.high) != sizeof(iwl_he_eht_capa));

switch (sband->band) {
case NL80211_BAND_2GHZ:
@@ -832,13 +976,13 @@ static void iwl_init_he_hw_capab(struct iwl_trans *trans,
return;
}

- memcpy(iftype_data, iwl_he_capa, sizeof(iwl_he_capa));
+ memcpy(iftype_data, iwl_he_eht_capa, sizeof(iwl_he_eht_capa));

sband->iftype_data = iftype_data;
- sband->n_iftype_data = ARRAY_SIZE(iwl_he_capa);
+ sband->n_iftype_data = ARRAY_SIZE(iwl_he_eht_capa);

for (i = 0; i < sband->n_iftype_data; i++)
- iwl_nvm_fixup_sband_iftd(trans, sband, &iftype_data[i],
+ iwl_nvm_fixup_sband_iftd(trans, data, sband, &iftype_data[i],
tx_chains, rx_chains, fw);

iwl_init_he_6ghz_capa(trans, data, sband, tx_chains, rx_chains);
--
2.35.3

2022-11-22 20:13:10

by Greenman, Gregory

[permalink] [raw]
Subject: [PATCH v2 2/9] wifi: iwlwifi: mvm: support 320 MHz PHY configuration

From: Johannes Berg <[email protected]>

Support 320 MHz PHY configuration and while doing so rewrite
the code since we'd otherwise double the number of cases in
the switch statement.

Signed-off-by: Johannes Berg <[email protected]>
Signed-off-by: Gregory Greenman <[email protected]>
---
.../wireless/intel/iwlwifi/fw/api/phy-ctxt.h | 33 ++++++------
.../net/wireless/intel/iwlwifi/mvm/mac80211.c | 2 +-
.../net/wireless/intel/iwlwifi/mvm/phy-ctxt.c | 54 +++++++++----------
3 files changed, 44 insertions(+), 45 deletions(-)

diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/phy-ctxt.h b/drivers/net/wireless/intel/iwlwifi/fw/api/phy-ctxt.h
index e66f77924f83..2f7d8558becd 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/api/phy-ctxt.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/api/phy-ctxt.h
@@ -13,10 +13,12 @@
#define PHY_BAND_6 (2)

/* Supported channel width, vary if there is VHT support */
-#define PHY_VHT_CHANNEL_MODE20 (0x0)
-#define PHY_VHT_CHANNEL_MODE40 (0x1)
-#define PHY_VHT_CHANNEL_MODE80 (0x2)
-#define PHY_VHT_CHANNEL_MODE160 (0x3)
+#define IWL_PHY_CHANNEL_MODE20 0x0
+#define IWL_PHY_CHANNEL_MODE40 0x1
+#define IWL_PHY_CHANNEL_MODE80 0x2
+#define IWL_PHY_CHANNEL_MODE160 0x3
+/* and 320 MHz for EHT */
+#define IWL_PHY_CHANNEL_MODE320 0x4

/*
* Control channel position:
@@ -24,20 +26,17 @@
* For VHT - bit-2 marks if the control is lower/upper relative to center-freq
* bits-1:0 mark the distance from the center freq. for 20Mhz, offset is 0.
* center_freq
- * |
- * 40Mhz |_______|_______|
- * 80Mhz |_______|_______|_______|_______|
- * 160Mhz |_______|_______|_______|_______|_______|_______|_______|_______|
- * code 011 010 001 000 | 100 101 110 111
+ * For EHT - bit-3 is used for extended distance
+ * |
+ * 40Mhz |____|____|
+ * 80Mhz |____|____|____|____|
+ * 160Mhz |____|____|____|____|____|____|____|____|
+ * 320MHz |____|____|____|____|____|____|____|____|____|____|____|____|____|____|____|____|
+ * code 1011 1010 1001 1000 0011 0010 0001 0000 0100 0101 0110 0111 1100 1101 1110 1111
*/
-#define PHY_VHT_CTRL_POS_1_BELOW (0x0)
-#define PHY_VHT_CTRL_POS_2_BELOW (0x1)
-#define PHY_VHT_CTRL_POS_3_BELOW (0x2)
-#define PHY_VHT_CTRL_POS_4_BELOW (0x3)
-#define PHY_VHT_CTRL_POS_1_ABOVE (0x4)
-#define PHY_VHT_CTRL_POS_2_ABOVE (0x5)
-#define PHY_VHT_CTRL_POS_3_ABOVE (0x6)
-#define PHY_VHT_CTRL_POS_4_ABOVE (0x7)
+#define IWL_PHY_CTRL_POS_ABOVE 0x4
+#define IWL_PHY_CTRL_POS_OFFS_EXT 0x8
+#define IWL_PHY_CTRL_POS_OFFS_MSK 0x3

/*
* struct iwl_fw_channel_info_v1 - channel information
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
index a81dd488caa8..57aa10466637 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
@@ -3777,7 +3777,7 @@ static int iwl_mvm_send_aux_roc_cmd(struct iwl_mvm *mvm,
/* Set the channel info data */
iwl_mvm_set_chan_info(mvm, &aux_roc_req.channel_info, channel->hw_value,
iwl_mvm_phy_band_from_nl80211(channel->band),
- PHY_VHT_CHANNEL_MODE20,
+ IWL_PHY_CHANNEL_MODE20,
0);

/* Set the time and duration */
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/phy-ctxt.c b/drivers/net/wireless/intel/iwlwifi/mvm/phy-ctxt.c
index a3cefbc43e80..06f4203fb989 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/phy-ctxt.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/phy-ctxt.c
@@ -14,16 +14,18 @@ u8 iwl_mvm_get_channel_width(struct cfg80211_chan_def *chandef)
switch (chandef->width) {
case NL80211_CHAN_WIDTH_20_NOHT:
case NL80211_CHAN_WIDTH_20:
- return PHY_VHT_CHANNEL_MODE20;
+ return IWL_PHY_CHANNEL_MODE20;
case NL80211_CHAN_WIDTH_40:
- return PHY_VHT_CHANNEL_MODE40;
+ return IWL_PHY_CHANNEL_MODE40;
case NL80211_CHAN_WIDTH_80:
- return PHY_VHT_CHANNEL_MODE80;
+ return IWL_PHY_CHANNEL_MODE80;
case NL80211_CHAN_WIDTH_160:
- return PHY_VHT_CHANNEL_MODE160;
+ return IWL_PHY_CHANNEL_MODE160;
+ case NL80211_CHAN_WIDTH_320:
+ return IWL_PHY_CHANNEL_MODE320;
default:
WARN(1, "Invalid channel width=%u", chandef->width);
- return PHY_VHT_CHANNEL_MODE20;
+ return IWL_PHY_CHANNEL_MODE20;
}
}

@@ -33,34 +35,32 @@ u8 iwl_mvm_get_channel_width(struct cfg80211_chan_def *chandef)
*/
u8 iwl_mvm_get_ctrl_pos(struct cfg80211_chan_def *chandef)
{
- switch (chandef->chan->center_freq - chandef->center_freq1) {
- case -70:
- return PHY_VHT_CTRL_POS_4_BELOW;
- case -50:
- return PHY_VHT_CTRL_POS_3_BELOW;
- case -30:
- return PHY_VHT_CTRL_POS_2_BELOW;
- case -10:
- return PHY_VHT_CTRL_POS_1_BELOW;
- case 10:
- return PHY_VHT_CTRL_POS_1_ABOVE;
- case 30:
- return PHY_VHT_CTRL_POS_2_ABOVE;
- case 50:
- return PHY_VHT_CTRL_POS_3_ABOVE;
- case 70:
- return PHY_VHT_CTRL_POS_4_ABOVE;
- default:
- WARN(1, "Invalid channel definition");
- fallthrough;
- case 0:
+ int offs = chandef->chan->center_freq - chandef->center_freq1;
+ int abs_offs = abs(offs);
+ u8 ret;
+
+ if (offs == 0) {
/*
* The FW is expected to check the control channel position only
* when in HT/VHT and the channel width is not 20MHz. Return
* this value as the default one.
*/
- return PHY_VHT_CTRL_POS_1_BELOW;
+ return 0;
}
+
+ /* this results in a value 0-7, i.e. fitting into 0b0111 */
+ ret = (abs_offs - 10) / 20;
+ /*
+ * But we need the value to be in 0b1011 because 0b0100 is
+ * IWL_PHY_CTRL_POS_ABOVE, so shift bit 2 up to land in
+ * IWL_PHY_CTRL_POS_OFFS_EXT (0b1000)
+ */
+ ret = (ret & IWL_PHY_CTRL_POS_OFFS_MSK) |
+ ((ret & BIT(2)) << 1);
+ /* and add the above bit */
+ ret |= (offs > 0) * IWL_PHY_CTRL_POS_ABOVE;
+
+ return ret;
}

/*
--
2.35.3

2022-11-22 20:13:12

by Greenman, Gregory

[permalink] [raw]
Subject: [PATCH v2 3/9] wifi: iwlwifi: rs: add support for parsing max MCS per NSS/BW in 11be

From: Mordechay Goodstein <[email protected]>

Rate scale needs to be configured to what MCS it can use per BW and NSS,
this is done by parsing our capabilities of TX and peer's capabilities of
RX and setting the minimum for rate scale usage.

Also do some cleanup removing redundant enum defines not used by
FW/Driver.

Signed-off-by: Mordechay Goodstein <[email protected]>
Signed-off-by: Gregory Greenman <[email protected]>
---
.../net/wireless/intel/iwlwifi/fw/api/rs.h | 10 +-
drivers/net/wireless/intel/iwlwifi/fw/rs.c | 2 +
.../net/wireless/intel/iwlwifi/mvm/rs-fw.c | 125 +++++++++++++++++-
3 files changed, 129 insertions(+), 8 deletions(-)

diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/rs.h b/drivers/net/wireless/intel/iwlwifi/fw/api/rs.h
index 687f804c46b7..ddacd5b45aea 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/api/rs.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/api/rs.h
@@ -36,14 +36,14 @@ enum iwl_tlc_mng_cfg_flags {
* @IWL_TLC_MNG_CH_WIDTH_40MHZ: 40MHZ channel
* @IWL_TLC_MNG_CH_WIDTH_80MHZ: 80MHZ channel
* @IWL_TLC_MNG_CH_WIDTH_160MHZ: 160MHZ channel
- * @IWL_TLC_MNG_CH_WIDTH_LAST: maximum value
+ * @IWL_TLC_MNG_CH_WIDTH_320MHZ: 320MHZ channel
*/
enum iwl_tlc_mng_cfg_cw {
IWL_TLC_MNG_CH_WIDTH_20MHZ,
IWL_TLC_MNG_CH_WIDTH_40MHZ,
IWL_TLC_MNG_CH_WIDTH_80MHZ,
IWL_TLC_MNG_CH_WIDTH_160MHZ,
- IWL_TLC_MNG_CH_WIDTH_LAST = IWL_TLC_MNG_CH_WIDTH_160MHZ,
+ IWL_TLC_MNG_CH_WIDTH_320MHZ,
};

/**
@@ -64,8 +64,7 @@ enum iwl_tlc_mng_cfg_chains {
* @IWL_TLC_MNG_MODE_HT: enable HT
* @IWL_TLC_MNG_MODE_VHT: enable VHT
* @IWL_TLC_MNG_MODE_HE: enable HE
- * @IWL_TLC_MNG_MODE_INVALID: invalid value
- * @IWL_TLC_MNG_MODE_NUM: a count of possible modes
+ * @IWL_TLC_MNG_MODE_EHT: enable EHT
*/
enum iwl_tlc_mng_cfg_mode {
IWL_TLC_MNG_MODE_CCK = 0,
@@ -74,8 +73,7 @@ enum iwl_tlc_mng_cfg_mode {
IWL_TLC_MNG_MODE_HT,
IWL_TLC_MNG_MODE_VHT,
IWL_TLC_MNG_MODE_HE,
- IWL_TLC_MNG_MODE_INVALID,
- IWL_TLC_MNG_MODE_NUM = IWL_TLC_MNG_MODE_INVALID,
+ IWL_TLC_MNG_MODE_EHT,
};

/**
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/rs.c b/drivers/net/wireless/intel/iwlwifi/fw/rs.c
index a835214611ce..e128d2e07f38 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/rs.c
+++ b/drivers/net/wireless/intel/iwlwifi/fw/rs.c
@@ -218,6 +218,8 @@ int rs_pretty_print_rate(char *buf, int bufsz, const u32 rate)
type = "HT";
else if (format == RATE_MCS_HE_MSK)
type = "HE";
+ else if (format == RATE_MCS_EHT_MSK)
+ type = "EHT";
else
type = "Unknown"; /* shouldn't happen */

diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rs-fw.c b/drivers/net/wireless/intel/iwlwifi/mvm/rs-fw.c
index 2e9081cb6627..f30eeab5505b 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/rs-fw.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/rs-fw.c
@@ -9,9 +9,11 @@
#include "iwl-op-mode.h"
#include "mvm.h"

-static u8 rs_fw_bw_from_sta_bw(struct ieee80211_sta *sta)
+static u8 rs_fw_bw_from_sta_bw(const struct ieee80211_sta *sta)
{
switch (sta->deflink.bandwidth) {
+ case IEEE80211_STA_RX_BW_320:
+ return IWL_TLC_MNG_CH_WIDTH_320MHZ;
case IEEE80211_STA_RX_BW_160:
return IWL_TLC_MNG_CH_WIDTH_160MHZ;
case IEEE80211_STA_RX_BW_80:
@@ -238,6 +240,122 @@ rs_fw_he_set_enabled_rates(const struct ieee80211_sta *sta,
}
}

+static u8 rs_fw_eht_max_nss(u8 rx_nss, u8 tx_nss)
+{
+ u8 tx = u8_get_bits(tx_nss, IEEE80211_EHT_MCS_NSS_TX);
+ u8 rx = u8_get_bits(rx_nss, IEEE80211_EHT_MCS_NSS_RX);
+ /* the max nss that can be used,
+ * is the min with our tx capa and the peer rx capa.
+ */
+ return min(tx, rx);
+}
+
+#define MAX_NSS_MCS(mcs_num, rx, tx) \
+ rs_fw_eht_max_nss((rx)->rx_tx_mcs ##mcs_num## _max_nss, \
+ (tx)->rx_tx_mcs ##mcs_num## _max_nss)
+
+static void rs_fw_set_eht_mcs_nss(__le16 ht_rates[][3],
+ enum IWL_TLC_MCS_PER_BW bw,
+ u8 max_nss, u16 mcs_msk)
+{
+ if (max_nss >= 2)
+ ht_rates[IWL_TLC_NSS_2][bw] |= cpu_to_le16(mcs_msk);
+
+ if (max_nss >= 1)
+ ht_rates[IWL_TLC_NSS_1][bw] |= cpu_to_le16(mcs_msk);
+}
+
+static const
+struct ieee80211_eht_mcs_nss_supp_bw *
+rs_fw_rs_mcs2eht_mcs(enum IWL_TLC_MCS_PER_BW bw,
+ const struct ieee80211_eht_mcs_nss_supp *eht_mcs)
+{
+ switch (bw) {
+ case IWL_TLC_MCS_PER_BW_80:
+ return &eht_mcs->bw._80;
+ case IWL_TLC_MCS_PER_BW_160:
+ return &eht_mcs->bw._160;
+ case IWL_TLC_MCS_PER_BW_320:
+ return &eht_mcs->bw._320;
+ default:
+ return NULL;
+ }
+}
+
+static void rs_fw_eht_set_enabled_rates(const struct ieee80211_sta *sta,
+ struct ieee80211_supported_band *sband,
+ struct iwl_tlc_config_cmd_v4 *cmd)
+{
+ /* peer RX mcs capa */
+ const struct ieee80211_eht_mcs_nss_supp *eht_rx_mcs =
+ &sta->deflink.eht_cap.eht_mcs_nss_supp;
+ /* our TX mcs capa */
+ const struct ieee80211_eht_mcs_nss_supp *eht_tx_mcs =
+ &sband->iftype_data->eht_cap.eht_mcs_nss_supp;
+
+ enum IWL_TLC_MCS_PER_BW bw;
+ struct ieee80211_eht_mcs_nss_supp_20mhz_only mcs_rx_20;
+ struct ieee80211_eht_mcs_nss_supp_20mhz_only mcs_tx_20;
+
+ /* peer is 20Mhz only */
+ if (!(sta->deflink.he_cap.he_cap_elem.phy_cap_info[0] &
+ IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_MASK_ALL)) {
+ mcs_rx_20 = eht_rx_mcs->only_20mhz;
+ } else {
+ mcs_rx_20.rx_tx_mcs7_max_nss = eht_rx_mcs->bw._80.rx_tx_mcs9_max_nss;
+ mcs_rx_20.rx_tx_mcs9_max_nss = eht_rx_mcs->bw._80.rx_tx_mcs9_max_nss;
+ mcs_rx_20.rx_tx_mcs11_max_nss = eht_rx_mcs->bw._80.rx_tx_mcs11_max_nss;
+ mcs_rx_20.rx_tx_mcs13_max_nss = eht_rx_mcs->bw._80.rx_tx_mcs13_max_nss;
+ }
+
+ /* nic is 20Mhz only */
+ if (!(sband->iftype_data->he_cap.he_cap_elem.phy_cap_info[0] &
+ IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_MASK_ALL)) {
+ mcs_tx_20 = eht_tx_mcs->only_20mhz;
+ } else {
+ mcs_tx_20.rx_tx_mcs7_max_nss = eht_tx_mcs->bw._80.rx_tx_mcs9_max_nss;
+ mcs_tx_20.rx_tx_mcs9_max_nss = eht_tx_mcs->bw._80.rx_tx_mcs9_max_nss;
+ mcs_tx_20.rx_tx_mcs11_max_nss = eht_tx_mcs->bw._80.rx_tx_mcs11_max_nss;
+ mcs_tx_20.rx_tx_mcs13_max_nss = eht_tx_mcs->bw._80.rx_tx_mcs13_max_nss;
+ }
+
+ /* rates for 20/40/80 bw */
+ bw = IWL_TLC_MCS_PER_BW_80;
+ rs_fw_set_eht_mcs_nss(cmd->ht_rates, bw,
+ MAX_NSS_MCS(7, &mcs_rx_20, &mcs_tx_20), GENMASK(7, 0));
+ rs_fw_set_eht_mcs_nss(cmd->ht_rates, bw,
+ MAX_NSS_MCS(9, &mcs_rx_20, &mcs_tx_20), GENMASK(9, 8));
+ rs_fw_set_eht_mcs_nss(cmd->ht_rates, bw,
+ MAX_NSS_MCS(11, &mcs_rx_20, &mcs_tx_20), GENMASK(11, 10));
+ rs_fw_set_eht_mcs_nss(cmd->ht_rates, bw,
+ MAX_NSS_MCS(13, &mcs_rx_20, &mcs_tx_20), GENMASK(13, 12));
+
+ /* rate for 160/320 bw */
+ for (bw = IWL_TLC_MCS_PER_BW_160; bw <= IWL_TLC_MCS_PER_BW_320; bw++) {
+ const struct ieee80211_eht_mcs_nss_supp_bw *mcs_rx =
+ rs_fw_rs_mcs2eht_mcs(bw, eht_rx_mcs);
+ const struct ieee80211_eht_mcs_nss_supp_bw *mcs_tx =
+ rs_fw_rs_mcs2eht_mcs(bw, eht_tx_mcs);
+
+ /* got unsuppored index for bw */
+ if (!mcs_rx || !mcs_tx)
+ continue;
+
+ rs_fw_set_eht_mcs_nss(cmd->ht_rates, bw,
+ MAX_NSS_MCS(9, mcs_rx, mcs_tx), GENMASK(9, 0));
+ rs_fw_set_eht_mcs_nss(cmd->ht_rates, bw,
+ MAX_NSS_MCS(11, mcs_rx, mcs_tx), GENMASK(11, 10));
+ rs_fw_set_eht_mcs_nss(cmd->ht_rates, bw,
+ MAX_NSS_MCS(13, mcs_rx, mcs_tx), GENMASK(13, 12));
+ }
+
+ /* the station support only a single receive chain */
+ if (sta->deflink.smps_mode == IEEE80211_SMPS_STATIC ||
+ sta->deflink.rx_nss < 2)
+ memset(cmd->ht_rates[IWL_TLC_NSS_2], 0,
+ sizeof(cmd->ht_rates[IWL_TLC_NSS_2]));
+}
+
static void rs_fw_set_supp_rates(struct ieee80211_sta *sta,
struct ieee80211_supported_band *sband,
struct iwl_tlc_config_cmd_v4 *cmd)
@@ -258,7 +376,10 @@ static void rs_fw_set_supp_rates(struct ieee80211_sta *sta,
cmd->mode = IWL_TLC_MNG_MODE_NON_HT;

/* HT/VHT rates */
- if (he_cap->has_he) {
+ if (sta->deflink.eht_cap.has_eht) {
+ cmd->mode = IWL_TLC_MNG_MODE_EHT;
+ rs_fw_eht_set_enabled_rates(sta, sband, cmd);
+ } else if (he_cap->has_he) {
cmd->mode = IWL_TLC_MNG_MODE_HE;
rs_fw_he_set_enabled_rates(sta, sband, cmd);
} else if (vht_cap->vht_supported) {
--
2.35.3

2022-11-22 20:13:13

by Greenman, Gregory

[permalink] [raw]
Subject: [PATCH v2 4/9] wifi: iwlwifi: mvm: add support for EHT 1K aggregation size

From: Mordechay Goodstein <[email protected]>

In 11be we can receive 1K aggregation size so update our max HW rx
aggregation for mac80211 usage.

Signed-off-by: Mordechay Goodstein <[email protected]>
Signed-off-by: Gregory Greenman <[email protected]>
---
drivers/net/wireless/intel/iwlwifi/mvm/ops.c | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c
index 9699433137bc..2a4db13c9dcf 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c
@@ -1077,6 +1077,7 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
static const u8 no_reclaim_cmds[] = {
TX_CMD,
};
+ u32 max_agg;
size_t scan_size;
u32 min_backoff;
struct iwl_mvm_csme_conn_info *csme_conn_info __maybe_unused;
@@ -1098,12 +1099,17 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
if (!hw)
return NULL;

- hw->max_rx_aggregation_subframes = IEEE80211_MAX_AMPDU_BUF_HE;
+ if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_BZ)
+ max_agg = IEEE80211_MAX_AMPDU_BUF_EHT;
+ else
+ max_agg = IEEE80211_MAX_AMPDU_BUF_HE;
+
+ hw->max_rx_aggregation_subframes = max_agg;

if (cfg->max_tx_agg_size)
hw->max_tx_aggregation_subframes = cfg->max_tx_agg_size;
else
- hw->max_tx_aggregation_subframes = IEEE80211_MAX_AMPDU_BUF_HE;
+ hw->max_tx_aggregation_subframes = max_agg;

op_mode = hw->priv;

--
2.35.3

2022-11-22 20:13:14

by Greenman, Gregory

[permalink] [raw]
Subject: [PATCH v2 5/9] wifi: iwlwifi: mvm: support PPE Thresholds for EHT

From: Miri Korenblit <[email protected]>

In an EHT connection fill in the HE context command
with PPE Thresholds field from EHT Capabilities IE.
If PPE Thresholds field presents only in HE Capabilities IE,
take the thresholds from there.
If it's not present in both - set the Common Nominal Packet Padding
field from EHT Capabilities IE.

Signed-off-by: Miri Korenblit <[email protected]>
Signed-off-by: Gregory Greenman <[email protected]>
---
.../net/wireless/intel/iwlwifi/fw/api/mac.h | 6 +-
.../net/wireless/intel/iwlwifi/mvm/mac80211.c | 177 +++++++++++++++---
2 files changed, 153 insertions(+), 30 deletions(-)

diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/mac.h b/drivers/net/wireless/intel/iwlwifi/fw/api/mac.h
index 9b7caf968346..e3eda251c728 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/api/mac.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/api/mac.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
- * Copyright (C) 2012-2014, 2018-2021 Intel Corporation
+ * Copyright (C) 2012-2014, 2018-2022 Intel Corporation
* Copyright (C) 2017 Intel Deutschland GmbH
*/
#ifndef __iwl_fw_api_mac_h__
@@ -398,7 +398,7 @@ struct iwl_he_backoff_conf {
* @IWL_HE_PKT_EXT_64QAM: 64-QAM
* @IWL_HE_PKT_EXT_256QAM: 256-QAM
* @IWL_HE_PKT_EXT_1024QAM: 1024-QAM
- * @IWL_HE_PKT_EXT_RESERVED: reserved value
+ * @IWL_HE_PKT_EXT_4096QAM: 4096-QAM, for EHT only
* @IWL_HE_PKT_EXT_NONE: not defined
*/
enum iwl_he_pkt_ext_constellations {
@@ -408,7 +408,7 @@ enum iwl_he_pkt_ext_constellations {
IWL_HE_PKT_EXT_64QAM,
IWL_HE_PKT_EXT_256QAM,
IWL_HE_PKT_EXT_1024QAM,
- IWL_HE_PKT_EXT_RESERVED,
+ IWL_HE_PKT_EXT_4096QAM,
IWL_HE_PKT_EXT_NONE,
};

diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
index 57aa10466637..3fba69554f83 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
@@ -1825,7 +1825,8 @@ static u8 iwl_mvm_he_get_ppe_val(u8 *ppe, u8 ppe_pos_bit)

static void iwl_mvm_parse_ppe(struct iwl_mvm *mvm,
struct iwl_he_pkt_ext_v2 *pkt_ext, u8 nss,
- u8 ru_index_bitmap, u8 *ppe, u8 ppe_pos_bit)
+ u8 ru_index_bitmap, u8 *ppe, u8 ppe_pos_bit,
+ bool inheritance)
{
int i;

@@ -1851,14 +1852,25 @@ static void iwl_mvm_parse_ppe(struct iwl_mvm *mvm,
bw++) {
ru_index_tmp >>= 1;

- if (!(ru_index_tmp & 1))
- continue;
+ /*
+ * According to the 11be spec, if for a specific BW the PPE Thresholds
+ * isn't present - it should inherit the thresholds from the last
+ * BW for which we had PPE Thresholds. In 11ax though, we don't have
+ * this inheritance - continue in this case
+ */
+ if (!(ru_index_tmp & 1)) {
+ if (inheritance)
+ goto set_thresholds;
+ else
+ continue;
+ }

high_th = iwl_mvm_he_get_ppe_val(ppe, ppe_pos_bit);
ppe_pos_bit += IEEE80211_PPE_THRES_INFO_PPET_SIZE;
low_th = iwl_mvm_he_get_ppe_val(ppe, ppe_pos_bit);
ppe_pos_bit += IEEE80211_PPE_THRES_INFO_PPET_SIZE;

+set_thresholds:
pkt_ext->pkt_ext_qam_th[i][bw][0] = low_th;
pkt_ext->pkt_ext_qam_th[i][bw][1] = high_th;
}
@@ -1867,7 +1879,8 @@ static void iwl_mvm_parse_ppe(struct iwl_mvm *mvm,

static void iwl_mvm_set_pkt_ext_from_he_ppe(struct iwl_mvm *mvm,
struct ieee80211_sta *sta,
- struct iwl_he_pkt_ext_v2 *pkt_ext)
+ struct iwl_he_pkt_ext_v2 *pkt_ext,
+ bool inheritance)
{
u8 nss = (sta->deflink.he_cap.ppe_thres[0] & IEEE80211_PPE_THRES_NSS_MASK) + 1;
u8 *ppe = &sta->deflink.he_cap.ppe_thres[0];
@@ -1877,7 +1890,8 @@ static void iwl_mvm_set_pkt_ext_from_he_ppe(struct iwl_mvm *mvm,
/* Starting after PPE header */
u8 ppe_pos_bit = IEEE80211_HE_PPE_THRES_INFO_HEADER_SIZE;

- iwl_mvm_parse_ppe(mvm, pkt_ext, nss, ru_index_bitmap, ppe, ppe_pos_bit);
+ iwl_mvm_parse_ppe(mvm, pkt_ext, nss, ru_index_bitmap, ppe, ppe_pos_bit,
+ inheritance);
}

static void iwl_mvm_set_pkt_ext_from_nominal_padding(struct iwl_he_pkt_ext_v2 *pkt_ext,
@@ -1888,16 +1902,18 @@ static void iwl_mvm_set_pkt_ext_from_nominal_padding(struct iwl_he_pkt_ext_v2 *p
int high_th = -1;
int i;

+ /* all the macros are the same for EHT and HE */
switch (nominal_padding) {
- case IEEE80211_HE_PHY_CAP9_NOMINAL_PKT_PADDING_0US:
+ case IEEE80211_EHT_PHY_CAP5_COMMON_NOMINAL_PKT_PAD_0US:
low_th = IWL_HE_PKT_EXT_NONE;
high_th = IWL_HE_PKT_EXT_NONE;
break;
- case IEEE80211_HE_PHY_CAP9_NOMINAL_PKT_PADDING_8US:
+ case IEEE80211_EHT_PHY_CAP5_COMMON_NOMINAL_PKT_PAD_8US:
low_th = IWL_HE_PKT_EXT_BPSK;
high_th = IWL_HE_PKT_EXT_NONE;
break;
- case IEEE80211_HE_PHY_CAP9_NOMINAL_PKT_PADDING_16US:
+ case IEEE80211_EHT_PHY_CAP5_COMMON_NOMINAL_PKT_PAD_16US:
+ case IEEE80211_EHT_PHY_CAP5_COMMON_NOMINAL_PKT_PAD_20US:
low_th = IWL_HE_PKT_EXT_NONE;
high_th = IWL_HE_PKT_EXT_BPSK;
break;
@@ -1920,6 +1936,31 @@ static void iwl_mvm_set_pkt_ext_from_nominal_padding(struct iwl_he_pkt_ext_v2 *p
}
}

+static void iwl_mvm_get_optimal_ppe_info(struct iwl_he_pkt_ext_v2 *pkt_ext,
+ u8 nominal_padding)
+{
+ int i;
+
+ for (i = 0; i < MAX_HE_SUPP_NSS; i++) {
+ u8 bw;
+
+ for (bw = 0; bw < ARRAY_SIZE(pkt_ext->pkt_ext_qam_th[i]);
+ bw++) {
+ u8 *qam_th = &pkt_ext->pkt_ext_qam_th[i][bw][0];
+
+ if (nominal_padding >
+ IEEE80211_EHT_PHY_CAP5_COMMON_NOMINAL_PKT_PAD_8US &&
+ qam_th[1] == IWL_HE_PKT_EXT_NONE)
+ qam_th[1] = IWL_HE_PKT_EXT_4096QAM;
+ else if (nominal_padding ==
+ IEEE80211_EHT_PHY_CAP5_COMMON_NOMINAL_PKT_PAD_8US &&
+ qam_th[0] == IWL_HE_PKT_EXT_NONE &&
+ qam_th[1] == IWL_HE_PKT_EXT_NONE)
+ qam_th[0] = IWL_HE_PKT_EXT_4096QAM;
+ }
+ }
+}
+
static void iwl_mvm_cfg_he_sta(struct iwl_mvm *mvm,
struct ieee80211_vif *vif, u8 sta_id)
{
@@ -1943,6 +1984,7 @@ static void iwl_mvm_cfg_he_sta(struct iwl_mvm *mvm,
struct ieee80211_chanctx_conf *chanctx_conf;
const struct ieee80211_supported_band *sband;
void *cmd;
+ u8 nominal_padding;

if (!fw_has_api(&mvm->fw->ucode_capa, IWL_UCODE_TLV_API_MBSSID_HE))
ver = 1;
@@ -2032,22 +2074,96 @@ static void iwl_mvm_cfg_he_sta(struct iwl_mvm *mvm,
memset(&sta_ctxt_cmd.pkt_ext, IWL_HE_PKT_EXT_NONE,
sizeof(sta_ctxt_cmd.pkt_ext));

- /* If PPE Thresholds exist, parse them into a FW-familiar format. */
- if (sta->deflink.he_cap.he_cap_elem.phy_cap_info[6] &
- IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT) {
- iwl_mvm_set_pkt_ext_from_he_ppe(mvm, sta,
- &sta_ctxt_cmd.pkt_ext);
- flags |= STA_CTXT_HE_PACKET_EXT;
- /* PPE Thresholds doesn't exist - set the API PPE values
- * according to Common Nominal Packet Padding fiels. */
- } else {
- u8 nominal_padding =
- u8_get_bits(sta->deflink.he_cap.he_cap_elem.phy_cap_info[9],
- IEEE80211_HE_PHY_CAP9_NOMINAL_PKT_PADDING_MASK);
- if (nominal_padding != IEEE80211_HE_PHY_CAP9_NOMINAL_PKT_PADDING_RESERVED)
+ if (sta->deflink.eht_cap.has_eht) {
+ nominal_padding =
+ u8_get_bits(sta->deflink.eht_cap.eht_cap_elem.phy_cap_info[5],
+ IEEE80211_EHT_PHY_CAP5_COMMON_NOMINAL_PKT_PAD_MASK);
+
+ /* If PPE Thresholds exists, parse them into a FW-familiar format. */
+ if (sta->deflink.eht_cap.eht_cap_elem.phy_cap_info[5] &
+ IEEE80211_EHT_PHY_CAP5_PPE_THRESHOLD_PRESENT) {
+ u8 nss = (sta->deflink.eht_cap.eht_ppe_thres[0] &
+ IEEE80211_EHT_PPE_THRES_NSS_MASK) + 1;
+ u8 *ppe = &sta->deflink.eht_cap.eht_ppe_thres[0];
+ u8 ru_index_bitmap =
+ u16_get_bits(*ppe,
+ IEEE80211_EHT_PPE_THRES_RU_INDEX_BITMASK_MASK);
+ /* Starting after PPE header */
+ u8 ppe_pos_bit = IEEE80211_EHT_PPE_THRES_INFO_HEADER_SIZE;
+
+ iwl_mvm_parse_ppe(mvm,
+ &sta_ctxt_cmd.pkt_ext,
+ nss, ru_index_bitmap, ppe,
+ ppe_pos_bit, true);
+ flags |= STA_CTXT_HE_PACKET_EXT;
+ /* EHT PPE Thresholds doesn't exist - set the API according to HE PPE Tresholds*/
+ } else if (sta->deflink.he_cap.he_cap_elem.phy_cap_info[6] &
+ IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT) {
+ struct iwl_he_pkt_ext_v2 *pkt_ext =
+ &sta_ctxt_cmd.pkt_ext;
+
+ /*
+ * Even though HE Capabilities IE doesn't contain PPE
+ * Thresholds for BW 320Mhz, thresholds for this BW will
+ * be filled in with the same values as 160Mhz, due to
+ * the inheritance, as required.
+ */
+ iwl_mvm_set_pkt_ext_from_he_ppe(mvm, sta, pkt_ext,
+ true);
+
+ /*
+ * According to the requirements, for MCSs 12-13 the maximum value between
+ * HE PPE Threshold and Common Nominal Packet Padding needs to be taken
+ */
+ iwl_mvm_get_optimal_ppe_info(pkt_ext, nominal_padding);
+
+ flags |= STA_CTXT_HE_PACKET_EXT;
+
+ /*
+ * if PPE Thresholds doesn't present in both EHT IE and HE IE -
+ * take the Thresholds from Common Nominal Packet Padding field
+ */
+ } else {
iwl_mvm_set_pkt_ext_from_nominal_padding(&sta_ctxt_cmd.pkt_ext,
nominal_padding,
&flags);
+ }
+ } else if (sta->deflink.he_cap.has_he) {
+ /* If PPE Thresholds exist, parse them into a FW-familiar format. */
+ if (sta->deflink.he_cap.he_cap_elem.phy_cap_info[6] &
+ IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT) {
+ iwl_mvm_set_pkt_ext_from_he_ppe(mvm, sta,
+ &sta_ctxt_cmd.pkt_ext,
+ false);
+ flags |= STA_CTXT_HE_PACKET_EXT;
+ /*
+ * PPE Thresholds doesn't exist - set the API PPE values
+ * according to Common Nominal Packet Padding field.
+ */
+ } else {
+ nominal_padding =
+ u8_get_bits(sta->deflink.he_cap.he_cap_elem.phy_cap_info[9],
+ IEEE80211_HE_PHY_CAP9_NOMINAL_PKT_PADDING_MASK);
+ if (nominal_padding != IEEE80211_HE_PHY_CAP9_NOMINAL_PKT_PADDING_RESERVED)
+ iwl_mvm_set_pkt_ext_from_nominal_padding(&sta_ctxt_cmd.pkt_ext,
+ nominal_padding,
+ &flags);
+ }
+ }
+
+ for (i = 0; i < MAX_HE_SUPP_NSS; i++) {
+ int bw;
+
+ for (bw = 0;
+ bw < ARRAY_SIZE(sta_ctxt_cmd.pkt_ext.pkt_ext_qam_th[i]);
+ bw++) {
+ u8 *qam_th =
+ &sta_ctxt_cmd.pkt_ext.pkt_ext_qam_th[i][bw][0];
+
+ IWL_DEBUG_HT(mvm,
+ "PPE table: nss[%d] bw[%d] PPET8 = %d, PPET16 = %d\n",
+ i, bw, qam_th[0], qam_th[1]);
+ }
}

if (sta->deflink.he_cap.he_cap_elem.mac_cap_info[2] &
@@ -2195,8 +2311,10 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm,
* interface was added.
*/
if (changes & BSS_CHANGED_ASSOC && vif->cfg.assoc) {
- if (vif->bss_conf.he_support &&
- !iwlwifi_mod_params.disable_11ax)
+ if ((vif->bss_conf.he_support &&
+ !iwlwifi_mod_params.disable_11ax) ||
+ (vif->bss_conf.eht_support &&
+ !iwlwifi_mod_params.disable_11be))
iwl_mvm_cfg_he_sta(mvm, vif, mvmvif->ap_sta_id);

iwl_mvm_mac_ctxt_recalc_tsf_id(mvm, vif);
@@ -2204,8 +2322,11 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm,

/* Update MU EDCA params */
if (changes & BSS_CHANGED_QOS && mvmvif->associated &&
- vif->cfg.assoc && vif->bss_conf.he_support &&
- !iwlwifi_mod_params.disable_11ax)
+ vif->cfg.assoc &&
+ ((vif->bss_conf.he_support &&
+ !iwlwifi_mod_params.disable_11ax) ||
+ (vif->bss_conf.eht_support &&
+ !iwlwifi_mod_params.disable_11be)))
iwl_mvm_cfg_he_sta(mvm, vif, mvmvif->ap_sta_id);

/*
@@ -3218,8 +3339,10 @@ static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw,
vif->bss_conf.he_support = sta->deflink.he_cap.has_he;
mvmvif->ap_assoc_sta_count++;
iwl_mvm_mac_ctxt_changed(mvm, vif, false, NULL);
- if (vif->bss_conf.he_support &&
- !iwlwifi_mod_params.disable_11ax)
+ if ((vif->bss_conf.he_support &&
+ !iwlwifi_mod_params.disable_11ax) ||
+ (vif->bss_conf.eht_support &&
+ !iwlwifi_mod_params.disable_11be))
iwl_mvm_cfg_he_sta(mvm, vif, mvm_sta->sta_id);
} else if (vif->type == NL80211_IFTYPE_STATION) {
vif->bss_conf.he_support = sta->deflink.he_cap.has_he;
--
2.35.3

2022-11-22 20:13:18

by Greenman, Gregory

[permalink] [raw]
Subject: [PATCH v2 7/9] wifi: iwlwifi: mvm: advertise 320 MHz in 6 GHz only conditionally

From: Johannes Berg <[email protected]>

We can't have it in AP mode unless for debug, since we don't have
160 MHz in HE PHY capabilities, and also set it only in 6 GHz even
if (unlike in HE) it's always defined.

Signed-off-by: Johannes Berg <[email protected]>
Signed-off-by: Gregory Greenman <[email protected]>
---
drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c | 4 ++++
1 file changed, 4 insertions(+)

diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c
index e83382ded8af..b59e61a76b70 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c
@@ -873,6 +873,10 @@ iwl_nvm_fixup_sband_iftd(struct iwl_trans *trans,
IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_IN_2G;
break;
case NL80211_BAND_6GHZ:
+ if (!is_ap || iwlwifi_mod_params.nvm_file)
+ iftype_data->eht_cap.eht_cap_elem.phy_cap_info[0] |=
+ IEEE80211_EHT_PHY_CAP0_320MHZ_IN_6GHZ;
+ fallthrough;
case NL80211_BAND_5GHZ:
iftype_data->he_cap.he_cap_elem.phy_cap_info[0] |=
IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G;
--
2.35.3

2022-11-22 20:13:43

by Greenman, Gregory

[permalink] [raw]
Subject: [PATCH v2 6/9] wifi: iwlwifi: mvm: set HE PHY bandwidth according to band

From: Johannes Berg <[email protected]>

The bits are reserved on the opposite bands, so we shouldn't
always send them, only the 2G bit on 2.4 GHz and the 5G bits
on 5/6GHz. Fix that.

Signed-off-by: Johannes Berg <[email protected]>
Signed-off-by: Gregory Greenman <[email protected]>
---
.../wireless/intel/iwlwifi/iwl-nvm-parse.c | 27 ++++++++++++-------
1 file changed, 17 insertions(+), 10 deletions(-)

diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c
index 2b43fff4d3f9..e83382ded8af 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
- * Copyright (C) 2005-2014, 2018-2021 Intel Corporation
+ * Copyright (C) 2005-2014, 2018-2022 Intel Corporation
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
* Copyright (C) 2016-2017 Intel Deutschland GmbH
*/
@@ -571,10 +571,6 @@ static const struct ieee80211_sband_iftype_data iwl_he_eht_capa[] = {
IEEE80211_HE_MAC_CAP5_UL_2x996_TONE_RU |
IEEE80211_HE_MAC_CAP5_HE_DYNAMIC_SM_PS |
IEEE80211_HE_MAC_CAP5_HT_VHT_TRIG_FRAME_RX,
- .phy_cap_info[0] =
- IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_IN_2G |
- IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G |
- IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G,
.phy_cap_info[1] =
IEEE80211_HE_PHY_CAP1_PREAMBLE_PUNC_RX_MASK |
IEEE80211_HE_PHY_CAP1_DEVICE_CLASS_A |
@@ -716,9 +712,6 @@ static const struct ieee80211_sband_iftype_data iwl_he_eht_capa[] = {
IEEE80211_HE_MAC_CAP1_MULTI_TID_AGG_RX_QOS_8,
.mac_cap_info[3] =
IEEE80211_HE_MAC_CAP3_OMI_CONTROL,
- .phy_cap_info[0] =
- IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_IN_2G |
- IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G,
.phy_cap_info[1] =
IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD,
.phy_cap_info[2] =
@@ -874,9 +867,23 @@ iwl_nvm_fixup_sband_iftd(struct iwl_trans *trans,
iftype_data->he_cap.he_cap_elem.mac_cap_info[3] |=
IEEE80211_HE_MAC_CAP3_MAX_AMPDU_LEN_EXP_EXT_3;

- if (is_ap && iwlwifi_mod_params.nvm_file)
+ switch (sband->band) {
+ case NL80211_BAND_2GHZ:
iftype_data->he_cap.he_cap_elem.phy_cap_info[0] |=
- IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G;
+ IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_IN_2G;
+ break;
+ case NL80211_BAND_6GHZ:
+ case NL80211_BAND_5GHZ:
+ iftype_data->he_cap.he_cap_elem.phy_cap_info[0] |=
+ IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G;
+ if (!is_ap || iwlwifi_mod_params.nvm_file)
+ iftype_data->he_cap.he_cap_elem.phy_cap_info[0] |=
+ IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G;
+ break;
+ default:
+ WARN_ON(1);
+ break;
+ }

if ((tx_chains & rx_chains) == ANT_AB) {
iftype_data->he_cap.he_cap_elem.phy_cap_info[2] |=
--
2.35.3

2022-11-22 20:13:47

by Greenman, Gregory

[permalink] [raw]
Subject: [PATCH v2 8/9] wifi: iwlwifi: nvm-parse: support A-MPDU in EHT 2.4 GHz

From: Johannes Berg <[email protected]>

We support large A-MPDU in EHT in 2.4 GHz, so add the right
bits for that in the EHT capabilities.

Signed-off-by: Johannes Berg <[email protected]>
Signed-off-by: Gregory Greenman <[email protected]>
---
drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c | 3 +++
1 file changed, 3 insertions(+)

diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c
index b59e61a76b70..3a646bce7b42 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c
@@ -871,6 +871,9 @@ iwl_nvm_fixup_sband_iftd(struct iwl_trans *trans,
case NL80211_BAND_2GHZ:
iftype_data->he_cap.he_cap_elem.phy_cap_info[0] |=
IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_IN_2G;
+ iftype_data->eht_cap.eht_cap_elem.mac_cap_info[0] |=
+ u8_encode_bits(IEEE80211_EHT_MAC_CAP0_MAX_MPDU_LEN_11454,
+ IEEE80211_EHT_MAC_CAP0_MAX_MPDU_LEN_MASK);
break;
case NL80211_BAND_6GHZ:
if (!is_ap || iwlwifi_mod_params.nvm_file)
--
2.35.3

2022-11-22 20:14:11

by Greenman, Gregory

[permalink] [raw]
Subject: [PATCH v2 9/9] wifi: iwlwifi: nvm: Update EHT capabilities for GL device

From: Abhishek Naik <[email protected]>

Update EHT MAC and PHY capabilities for GL device
for station and softap interface.
Add relevant code in nvm_fixup_sband_iftd.

Signed-off-by: Abhishek Naik <[email protected]>
Signed-off-by: Greenman, Gregory <[email protected]>
---
.../wireless/intel/iwlwifi/iwl-nvm-parse.c | 23 +++++++++++++++++++
1 file changed, 23 insertions(+)

diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c
index 3a646bce7b42..476b90f32626 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c
@@ -950,6 +950,29 @@ iwl_nvm_fixup_sband_iftd(struct iwl_trans *trans,
break;
}

+ if (CSR_HW_REV_TYPE(trans->hw_rev) == IWL_CFG_MAC_TYPE_GL &&
+ iftype_data->eht_cap.has_eht) {
+ iftype_data->eht_cap.eht_cap_elem.mac_cap_info[0] &=
+ ~(IEEE80211_EHT_MAC_CAP0_EPCS_PRIO_ACCESS |
+ IEEE80211_EHT_MAC_CAP0_TRIG_TXOP_SHARING_MODE1 |
+ IEEE80211_EHT_MAC_CAP0_TRIG_TXOP_SHARING_MODE2);
+ iftype_data->eht_cap.eht_cap_elem.phy_cap_info[3] &=
+ ~(IEEE80211_EHT_PHY_CAP0_PARTIAL_BW_UL_MU_MIMO |
+ IEEE80211_EHT_PHY_CAP3_NG_16_SU_FEEDBACK |
+ IEEE80211_EHT_PHY_CAP3_NG_16_MU_FEEDBACK |
+ IEEE80211_EHT_PHY_CAP3_CODEBOOK_4_2_SU_FDBK |
+ IEEE80211_EHT_PHY_CAP3_CODEBOOK_7_5_MU_FDBK |
+ IEEE80211_EHT_PHY_CAP3_TRIG_MU_BF_PART_BW_FDBK);
+ iftype_data->eht_cap.eht_cap_elem.phy_cap_info[4] &=
+ ~(IEEE80211_EHT_PHY_CAP4_PART_BW_DL_MU_MIMO |
+ IEEE80211_EHT_PHY_CAP4_POWER_BOOST_FACT_SUPP);
+ iftype_data->eht_cap.eht_cap_elem.phy_cap_info[5] &=
+ ~IEEE80211_EHT_PHY_CAP5_NON_TRIG_CQI_FEEDBACK;
+ iftype_data->eht_cap.eht_cap_elem.phy_cap_info[6] &=
+ ~(IEEE80211_EHT_PHY_CAP6_MCS15_SUPP_MASK |
+ IEEE80211_EHT_PHY_CAP6_EHT_DUP_6GHZ_SUPP);
+ }
+
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;
--
2.35.3

2022-11-23 07:50:12

by Kalle Valo

[permalink] [raw]
Subject: Re: [PATCH v2 0/9] wifi: iwlwifi: updates intended for v6.2 2022-11-22

[email protected] writes:

> From: Gregory Greenman <[email protected]>
>
> Hi,
>
> Here's the third set of patches intended for v6.2, with the fixes.
> Resending all the patches since I think it'll make the review easier.
> The fixes are only for two patches (1 and 4), the rest are unchanged.
>
> It contains EHT adjustments for iwlwifi. It contains only iwlwifi
> changes, all the required mac80211/cfg80211 changes are already merged
> upstream.
>
> As usual, I'm pushing this to a pending branch, for kbuild bot,
> and will send a pull-request later.
>
> Please review.

No need to resend because of this but there's no changelog to list the
changes since v1. Usually we do something like this (I'm making up the
content, I don't know what you actually changed):

v2

* patch 1: fix a typo in the commit log

* patch 5: add missing mutex_unlock() in error handling


--
https://patchwork.kernel.org/project/linux-wireless/list/

https://wireless.wiki.kernel.org/en/developers/documentation/submittingpatches