From patchwork Sat Dec 2 16:28:50 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Luca Coelho X-Patchwork-Id: 10088917 X-Patchwork-Delegate: luca@coelho.fi Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 98A8160380 for ; Sat, 2 Dec 2017 16:29:15 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 8B3BF29C4A for ; Sat, 2 Dec 2017 16:29:15 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 8043129CA4; Sat, 2 Dec 2017 16:29:15 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.9 required=2.0 tests=BAYES_00,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 810F429C4A for ; Sat, 2 Dec 2017 16:29:14 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752472AbdLBQ3N (ORCPT ); Sat, 2 Dec 2017 11:29:13 -0500 Received: from paleale.coelho.fi ([176.9.41.70]:48580 "EHLO farmhouse.coelho.fi" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1751978AbdLBQ3L (ORCPT ); Sat, 2 Dec 2017 11:29:11 -0500 Received: from a91-156-4-241.elisa-laajakaista.fi ([91.156.4.241] helo=redipa.ger.corp.intel.com) by farmhouse.coelho.fi with esmtpsa (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.89) (envelope-from ) id 1eLAf6-0000Eu-UH; Sat, 02 Dec 2017 18:29:09 +0200 From: Luca Coelho To: kvalo@codeaurora.org Cc: linux-wireless@vger.kernel.org, Gregory Greenman , Luca Coelho Date: Sat, 2 Dec 2017 18:28:50 +0200 Message-Id: <20171202162858.4167-8-luca@coelho.fi> X-Mailer: git-send-email 2.15.0 In-Reply-To: <20171202162858.4167-1-luca@coelho.fi> References: <20171202162858.4167-1-luca@coelho.fi> X-SA-Exim-Connect-IP: 91.156.4.241 X-SA-Exim-Mail-From: luca@coelho.fi Subject: [PATCH 07/15] iwlwifi: mvm: rs: add basic implementation of the new RS API handlers X-SA-Exim-Version: 4.2.1 (built Tue, 02 Aug 2016 21:08:31 +0000) X-SA-Exim-Scanned: Yes (on farmhouse.coelho.fi) Sender: linux-wireless-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Gregory Greenman This patch adds rate scaling configuration command and implements a few other handlers. Signed-off-by: Gregory Greenman Signed-off-by: Luca Coelho --- .../net/wireless/intel/iwlwifi/fw/api/datapath.h | 5 + drivers/net/wireless/intel/iwlwifi/fw/api/rs.h | 168 +++++++++++++++++- drivers/net/wireless/intel/iwlwifi/mvm/rs-fw.c | 187 +++++++++++++++++++++ drivers/net/wireless/intel/iwlwifi/mvm/rs.c | 25 ++- drivers/net/wireless/intel/iwlwifi/mvm/rs.h | 2 + drivers/net/wireless/intel/iwlwifi/mvm/utils.c | 4 +- 6 files changed, 379 insertions(+), 12 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/datapath.h b/drivers/net/wireless/intel/iwlwifi/fw/api/datapath.h index aa76dcc148bd..8ec1a7fe62ea 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/datapath.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/datapath.h @@ -82,6 +82,11 @@ enum iwl_data_path_subcmd_ids { */ TRIGGER_RX_QUEUES_NOTIF_CMD = 0x2, + /** + * @TLC_MNG_CONFIG_CMD: &struct iwl_tlc_config_cmd + */ + TLC_MNG_CONFIG_CMD = 0xF, + /** * @STA_PM_NOTIF: &struct iwl_mvm_pm_state_notification */ diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/rs.h b/drivers/net/wireless/intel/iwlwifi/fw/api/rs.h index a13fd8a1be62..ba88b0ea9a60 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/rs.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/rs.h @@ -62,6 +62,173 @@ #include "mac.h" +/** + * enum iwl_tlc_mng_cfg_flags_enum - options for TLC config flags + * @IWL_TLC_MNG_CFG_FLAGS_CCK_MSK: CCK support + * @IWL_TLC_MNG_CFG_FLAGS_DD_MSK: enable DD + * @IWL_TLC_MNG_CFG_FLAGS_STBC_MSK: enable STBC + * @IWL_TLC_MNG_CFG_FLAGS_LDPC_MSK: enable LDPC + * @IWL_TLC_MNG_CFG_FLAGS_BF_MSK: enable BFER + * @IWL_TLC_MNG_CFG_FLAGS_DCM_MSK: enable DCM + */ +enum iwl_tlc_mng_cfg_flags_enum { + IWL_TLC_MNG_CFG_FLAGS_CCK_MSK = BIT(0), + IWL_TLC_MNG_CFG_FLAGS_DD_MSK = BIT(1), + IWL_TLC_MNG_CFG_FLAGS_STBC_MSK = BIT(2), + IWL_TLC_MNG_CFG_FLAGS_LDPC_MSK = BIT(3), + IWL_TLC_MNG_CFG_FLAGS_BF_MSK = BIT(4), + IWL_TLC_MNG_CFG_FLAGS_DCM_MSK = BIT(5), +}; + +/** + * enum iwl_tlc_mng_cfg_cw_enum - channel width options + * @IWL_TLC_MNG_MAX_CH_WIDTH_20MHZ: 20MHZ channel + * @IWL_TLC_MNG_MAX_CH_WIDTH_40MHZ: 40MHZ channel + * @IWL_TLC_MNG_MAX_CH_WIDTH_80MHZ: 80MHZ channel + * @IWL_TLC_MNG_MAX_CH_WIDTH_160MHZ: 160MHZ channel + * @IWL_TLC_MNG_MAX_CH_WIDTH_LAST: maximum value + */ +enum iwl_tlc_mng_cfg_cw_enum { + IWL_TLC_MNG_MAX_CH_WIDTH_20MHZ, + IWL_TLC_MNG_MAX_CH_WIDTH_40MHZ, + IWL_TLC_MNG_MAX_CH_WIDTH_80MHZ, + IWL_TLC_MNG_MAX_CH_WIDTH_160MHZ, + IWL_TLC_MNG_MAX_CH_WIDTH_LAST = IWL_TLC_MNG_MAX_CH_WIDTH_160MHZ, +}; + +/** + * enum iwl_tlc_mng_cfg_chains_enum - possible chains + * @IWL_TLC_MNG_CHAIN_A_MSK: chain A + * @IWL_TLC_MNG_CHAIN_B_MSK: chain B + * @IWL_TLC_MNG_CHAIN_C_MSK: chain C + */ +enum iwl_tlc_mng_cfg_chains_enum { + IWL_TLC_MNG_CHAIN_A_MSK = BIT(0), + IWL_TLC_MNG_CHAIN_B_MSK = BIT(1), + IWL_TLC_MNG_CHAIN_C_MSK = BIT(2), +}; + +/** + * enum iwl_tlc_mng_cfg_gi_enum - guard interval options + * @IWL_TLC_MNG_SGI_20MHZ_MSK: enable short GI for 20MHZ + * @IWL_TLC_MNG_SGI_40MHZ_MSK: enable short GI for 40MHZ + * @IWL_TLC_MNG_SGI_80MHZ_MSK: enable short GI for 80MHZ + * @IWL_TLC_MNG_SGI_160MHZ_MSK: enable short GI for 160MHZ + */ +enum iwl_tlc_mng_cfg_gi_enum { + IWL_TLC_MNG_SGI_20MHZ_MSK = BIT(0), + IWL_TLC_MNG_SGI_40MHZ_MSK = BIT(1), + IWL_TLC_MNG_SGI_80MHZ_MSK = BIT(2), + IWL_TLC_MNG_SGI_160MHZ_MSK = BIT(3), +}; + +/** + * enum iwl_tlc_mng_cfg_mode_enum - supported modes + * @IWL_TLC_MNG_MODE_CCK: enable CCK + * @IWL_TLC_MNG_MODE_OFDM_NON_HT: enable OFDM (non HT) + * @IWL_TLC_MNG_MODE_NON_HT: enable non HT + * @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 + */ +enum iwl_tlc_mng_cfg_mode_enum { + IWL_TLC_MNG_MODE_CCK = 0, + IWL_TLC_MNG_MODE_OFDM_NON_HT = IWL_TLC_MNG_MODE_CCK, + IWL_TLC_MNG_MODE_NON_HT = IWL_TLC_MNG_MODE_CCK, + 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, +}; + +/** + * enum iwl_tlc_mng_vht_he_types_enum - VHT HE types + * @IWL_TLC_MNG_VALID_VHT_HE_TYPES_SU: VHT HT single user + * @IWL_TLC_MNG_VALID_VHT_HE_TYPES_SU_EXT: VHT HT single user extended + * @IWL_TLC_MNG_VALID_VHT_HE_TYPES_MU: VHT HT multiple users + * @IWL_TLC_MNG_VALID_VHT_HE_TYPES_TRIG_BASED: trigger based + * @IWL_TLC_MNG_VALID_VHT_HE_TYPES_NUM: a count of possible types + */ +enum iwl_tlc_mng_vht_he_types_enum { + IWL_TLC_MNG_VALID_VHT_HE_TYPES_SU = 0, + IWL_TLC_MNG_VALID_VHT_HE_TYPES_SU_EXT, + IWL_TLC_MNG_VALID_VHT_HE_TYPES_MU, + IWL_TLC_MNG_VALID_VHT_HE_TYPES_TRIG_BASED, + IWL_TLC_MNG_VALID_VHT_HE_TYPES_NUM = + IWL_TLC_MNG_VALID_VHT_HE_TYPES_TRIG_BASED, + +}; + +/** + * enum iwl_tlc_mng_ht_rates_enum - HT/VHT rates + * @IWL_TLC_MNG_HT_RATE_MCS0: index of MCS0 + * @IWL_TLC_MNG_HT_RATE_MCS1: index of MCS1 + * @IWL_TLC_MNG_HT_RATE_MCS2: index of MCS2 + * @IWL_TLC_MNG_HT_RATE_MCS3: index of MCS3 + * @IWL_TLC_MNG_HT_RATE_MCS4: index of MCS4 + * @IWL_TLC_MNG_HT_RATE_MCS5: index of MCS5 + * @IWL_TLC_MNG_HT_RATE_MCS6: index of MCS6 + * @IWL_TLC_MNG_HT_RATE_MCS7: index of MCS7 + * @IWL_TLC_MNG_HT_RATE_MCS8: index of MCS8 + * @IWL_TLC_MNG_HT_RATE_MCS9: index of MCS9 + * @IWL_TLC_MNG_HT_RATE_MAX: maximal rate for HT/VHT + */ +enum iwl_tlc_mng_ht_rates_enum { + IWL_TLC_MNG_HT_RATE_MCS0 = 0, + IWL_TLC_MNG_HT_RATE_MCS1, + IWL_TLC_MNG_HT_RATE_MCS2, + IWL_TLC_MNG_HT_RATE_MCS3, + IWL_TLC_MNG_HT_RATE_MCS4, + IWL_TLC_MNG_HT_RATE_MCS5, + IWL_TLC_MNG_HT_RATE_MCS6, + IWL_TLC_MNG_HT_RATE_MCS7, + IWL_TLC_MNG_HT_RATE_MCS8, + IWL_TLC_MNG_HT_RATE_MCS9, + IWL_TLC_MNG_HT_RATE_MAX = IWL_TLC_MNG_HT_RATE_MCS9, +}; + +/* Maximum supported tx antennas number */ +#define MAX_RS_ANT_NUM 3 + +/** + * struct tlc_config_cmd - TLC configuration + * @sta_id: station id + * @reserved1: reserved + * @max_supp_ch_width: channel width + * @flags: bitmask of %IWL_TLC_MNG_CONFIG_FLAGS_ENABLE_\* + * @chains: bitmask of %IWL_TLC_MNG_CHAIN_\* + * @max_supp_ss: valid values are 0-3, 0 - spatial streams are not supported + * @valid_vht_he_types: bitmap of %IWL_TLC_MNG_VALID_VHT_HE_TYPES_\* + * @non_ht_supp_rates: bitmap of supported legacy rates + * @ht_supp_rates: bitmap of supported HT/VHT rates, valid bits are 0-9 + * @mode: modulation type %IWL_TLC_MNG_MODE_\* + * @reserved2: reserved + * @he_supp_rates: bitmap of supported HE rates + * @sgi_ch_width_supp: bitmap of SGI support per channel width + * @he_gi_support: 11ax HE guard interval + * @max_ampdu_cnt: max AMPDU size (frames count) + */ +struct iwl_tlc_config_cmd { + u8 sta_id; + u8 reserved1[3]; + u8 max_supp_ch_width; + u8 chains; + u8 max_supp_ss; + u8 valid_vht_he_types; + __le16 flags; + __le16 non_ht_supp_rates; + __le16 ht_supp_rates[MAX_RS_ANT_NUM]; + u8 mode; + u8 reserved2; + __le16 he_supp_rates; + u8 sgi_ch_width_supp; + u8 he_gi_support; + __le32 max_ampdu_cnt; +} __packed; /* TLC_MNG_CONFIG_CMD_API_S_VER_1 */ + /* * These serve as indexes into * struct iwl_rate_info fw_rate_idx_to_plcp[IWL_RATE_COUNT]; @@ -253,7 +420,6 @@ enum { #define RATE_MCS_ANT_ABC_MSK (RATE_MCS_ANT_AB_MSK | \ RATE_MCS_ANT_C_MSK) #define RATE_MCS_ANT_MSK RATE_MCS_ANT_ABC_MSK -#define RATE_MCS_ANT_NUM 3 /* Bit 17: (0) SS, (1) SS*2 */ #define RATE_MCS_STBC_POS 17 diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rs-fw.c b/drivers/net/wireless/intel/iwlwifi/mvm/rs-fw.c index 1e4b6f1685d9..e11788253803 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/rs-fw.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/rs-fw.c @@ -61,7 +61,194 @@ #include "iwl-op-mode.h" #include "mvm.h" +static u8 rs_fw_bw_from_sta_bw(struct ieee80211_sta *sta) +{ + switch (sta->bandwidth) { + case IEEE80211_STA_RX_BW_160: + return IWL_TLC_MNG_MAX_CH_WIDTH_160MHZ; + case IEEE80211_STA_RX_BW_80: + return IWL_TLC_MNG_MAX_CH_WIDTH_80MHZ; + case IEEE80211_STA_RX_BW_40: + return IWL_TLC_MNG_MAX_CH_WIDTH_40MHZ; + case IEEE80211_STA_RX_BW_20: + default: + return IWL_TLC_MNG_MAX_CH_WIDTH_20MHZ; + } +} + +static u8 rs_fw_set_active_chains(u8 chains) +{ + u8 fw_chains = 0; + + if (chains & ANT_A) + fw_chains |= IWL_TLC_MNG_CHAIN_A_MSK; + if (chains & ANT_B) + fw_chains |= IWL_TLC_MNG_CHAIN_B_MSK; + if (chains & ANT_C) + fw_chains |= IWL_TLC_MNG_CHAIN_C_MSK; + + return fw_chains; +} + +static u8 rs_fw_sgi_cw_support(struct ieee80211_sta *sta) +{ + struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap; + struct ieee80211_sta_vht_cap *vht_cap = &sta->vht_cap; + u8 supp = 0; + + if (ht_cap->cap & IEEE80211_HT_CAP_SGI_20) + supp |= IWL_TLC_MNG_SGI_20MHZ_MSK; + if (ht_cap->cap & IEEE80211_HT_CAP_SGI_40) + supp |= IWL_TLC_MNG_SGI_40MHZ_MSK; + if (vht_cap->cap & IEEE80211_VHT_CAP_SHORT_GI_80) + supp |= IWL_TLC_MNG_SGI_80MHZ_MSK; + if (vht_cap->cap & IEEE80211_VHT_CAP_SHORT_GI_160) + supp |= IWL_TLC_MNG_SGI_160MHZ_MSK; + + return supp; +} + +static u16 rs_fw_set_config_flags(struct iwl_mvm *mvm, + struct ieee80211_sta *sta) +{ + struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap; + struct ieee80211_sta_vht_cap *vht_cap = &sta->vht_cap; + bool vht_ena = vht_cap && vht_cap->vht_supported; + u16 flags = IWL_TLC_MNG_CFG_FLAGS_CCK_MSK | + IWL_TLC_MNG_CFG_FLAGS_DCM_MSK | + IWL_TLC_MNG_CFG_FLAGS_DD_MSK; + + if (mvm->cfg->ht_params->stbc && + (num_of_ant(iwl_mvm_get_valid_tx_ant(mvm)) > 1) && + ((ht_cap && (ht_cap->cap & IEEE80211_HT_CAP_RX_STBC)) || + (vht_ena && (vht_cap->cap & IEEE80211_VHT_CAP_RXSTBC_MASK)))) + flags |= IWL_TLC_MNG_CFG_FLAGS_STBC_MSK; + + if (mvm->cfg->ht_params->ldpc && + ((ht_cap && (ht_cap->cap & IEEE80211_HT_CAP_LDPC_CODING)) || + (vht_ena && (vht_cap->cap & IEEE80211_VHT_CAP_RXLDPC)))) + flags |= IWL_TLC_MNG_CFG_FLAGS_LDPC_MSK; + + if (fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_BEAMFORMER) && + (num_of_ant(iwl_mvm_get_valid_tx_ant(mvm)) > 1) && + (vht_cap->cap & IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE)) + flags |= IWL_TLC_MNG_CFG_FLAGS_BF_MSK; + + return flags; +} + +static +int rs_fw_vht_highest_rx_mcs_index(struct ieee80211_sta_vht_cap *vht_cap, + int nss) +{ + u16 rx_mcs = le16_to_cpu(vht_cap->vht_mcs.rx_mcs_map) & + (0x3 << (2 * (nss - 1))); + rx_mcs >>= (2 * (nss - 1)); + + switch (rx_mcs) { + case IEEE80211_VHT_MCS_SUPPORT_0_7: + return IWL_TLC_MNG_HT_RATE_MCS7; + case IEEE80211_VHT_MCS_SUPPORT_0_8: + return IWL_TLC_MNG_HT_RATE_MCS8; + case IEEE80211_VHT_MCS_SUPPORT_0_9: + return IWL_TLC_MNG_HT_RATE_MCS9; + default: + WARN_ON_ONCE(1); + break; + } + + return 0; +} + +static void rs_fw_vht_set_enabled_rates(struct ieee80211_sta *sta, + struct ieee80211_sta_vht_cap *vht_cap, + struct iwl_tlc_config_cmd *cmd) +{ + u16 supp; + int i, highest_mcs; + + for (i = 0; i < sta->rx_nss; i++) { + if (i == MAX_RS_ANT_NUM) + break; + + highest_mcs = rs_fw_vht_highest_rx_mcs_index(vht_cap, i + 1); + if (!highest_mcs) + continue; + + supp = BIT(highest_mcs + 1) - 1; + if (sta->bandwidth == IEEE80211_STA_RX_BW_20) + supp &= ~BIT(IWL_TLC_MNG_HT_RATE_MCS9); + + cmd->ht_supp_rates[i] = cpu_to_le16(supp); + } +} + +static void rs_fw_set_supp_rates(struct ieee80211_sta *sta, + struct ieee80211_supported_band *sband, + struct iwl_tlc_config_cmd *cmd) +{ + int i; + unsigned long tmp; + unsigned long supp; /* must be unsigned long for for_each_set_bit */ + struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap; + struct ieee80211_sta_vht_cap *vht_cap = &sta->vht_cap; + + /* non HT rates */ + supp = 0; + tmp = sta->supp_rates[sband->band]; + for_each_set_bit(i, &tmp, BITS_PER_LONG) + supp |= BIT(sband->bitrates[i].hw_value); + + cmd->non_ht_supp_rates = cpu_to_le16(supp); + cmd->mode = IWL_TLC_MNG_MODE_NON_HT; + + /* HT/VHT rates */ + if (vht_cap && vht_cap->vht_supported) { + cmd->mode = IWL_TLC_MNG_MODE_VHT; + rs_fw_vht_set_enabled_rates(sta, vht_cap, cmd); + } else if (ht_cap && ht_cap->ht_supported) { + cmd->mode = IWL_TLC_MNG_MODE_HT; + cmd->ht_supp_rates[0] = cpu_to_le16(ht_cap->mcs.rx_mask[0]); + cmd->ht_supp_rates[1] = cpu_to_le16(ht_cap->mcs.rx_mask[1]); + } +} + void rs_fw_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta, enum nl80211_band band) { + struct ieee80211_hw *hw = mvm->hw; + struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta); + struct iwl_lq_sta_rs_fw *lq_sta = &mvmsta->lq_sta.rs_fw; + u32 cmd_id = iwl_cmd_id(TLC_MNG_CONFIG_CMD, DATA_PATH_GROUP, 0); + struct ieee80211_supported_band *sband; + struct iwl_tlc_config_cmd cfg_cmd = { + .sta_id = mvmsta->sta_id, + .max_supp_ch_width = rs_fw_bw_from_sta_bw(sta), + .flags = cpu_to_le16(rs_fw_set_config_flags(mvm, sta)), + .chains = rs_fw_set_active_chains(iwl_mvm_get_valid_tx_ant(mvm)), + .max_supp_ss = sta->rx_nss, + .max_ampdu_cnt = cpu_to_le32(mvmsta->max_agg_bufsize), + .sgi_ch_width_supp = rs_fw_sgi_cw_support(sta), + }; + int ret; + + memset(lq_sta, 0, offsetof(typeof(*lq_sta), pers)); + +#ifdef CONFIG_IWLWIFI_DEBUGFS + iwl_mvm_reset_frame_stats(mvm); +#endif + sband = hw->wiphy->bands[band]; + rs_fw_set_supp_rates(sta, sband, &cfg_cmd); + + ret = iwl_mvm_send_cmd_pdu(mvm, cmd_id, 0, sizeof(cfg_cmd), &cfg_cmd); + if (ret) + IWL_ERR(mvm, "Failed to send rate scale config (%d)\n", ret); +} + +int rs_fw_tx_protection(struct iwl_mvm *mvm, struct iwl_mvm_sta *mvmsta, + bool enable) +{ + /* TODO: need to introduce a new FW cmd since LQ cmd is not relevant */ + IWL_DEBUG_RATE(mvm, "tx protection - not implemented yet.\n"); + return 0; } diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rs.c b/drivers/net/wireless/intel/iwlwifi/mvm/rs.c index 3dd6535ed922..428d34cb6683 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/rs.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/rs.c @@ -4061,15 +4061,8 @@ void iwl_mvm_rate_control_unregister(void) ieee80211_rate_control_unregister(&rs_mvm_ops_drv); } -/** - * iwl_mvm_tx_protection - Gets LQ command, change it to enable/disable - * Tx protection, according to this request and previous requests, - * and send the LQ command. - * @mvmsta: The station - * @enable: Enable Tx protection? - */ -int iwl_mvm_tx_protection(struct iwl_mvm *mvm, struct iwl_mvm_sta *mvmsta, - bool enable) +static int rs_drv_tx_protection(struct iwl_mvm *mvm, struct iwl_mvm_sta *mvmsta, + bool enable) { struct iwl_lq_cmd *lq = &mvmsta->lq_sta.rs_drv.lq; @@ -4087,3 +4080,17 @@ int iwl_mvm_tx_protection(struct iwl_mvm *mvm, struct iwl_mvm_sta *mvmsta, return iwl_mvm_send_lq_cmd(mvm, lq, false); } + +/** + * iwl_mvm_tx_protection - ask FW to enable RTS/CTS protection + * @mvmsta: The station + * @enable: Enable Tx protection? + */ +int iwl_mvm_tx_protection(struct iwl_mvm *mvm, struct iwl_mvm_sta *mvmsta, + bool enable) +{ + if (fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_TLC_OFFLOAD)) + return rs_fw_tx_protection(mvm, mvmsta, enable); + else + return rs_drv_tx_protection(mvm, mvmsta, enable); +} diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rs.h b/drivers/net/wireless/intel/iwlwifi/mvm/rs.h index eb92ded8a4dc..5b58e2d9bfbc 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/rs.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/rs.h @@ -452,4 +452,6 @@ void rs_remove_sta_debugfs(void *mvm, void *mvm_sta); void iwl_mvm_rs_add_sta(struct iwl_mvm *mvm, struct iwl_mvm_sta *mvmsta); void rs_fw_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta, enum nl80211_band band); +int rs_fw_tx_protection(struct iwl_mvm *mvm, struct iwl_mvm_sta *mvmsta, + bool enable); #endif /* __rs__ */ diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/utils.c b/drivers/net/wireless/intel/iwlwifi/mvm/utils.c index 79acb13f203a..280edf89e5eb 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/utils.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/utils.c @@ -278,8 +278,8 @@ u8 iwl_mvm_next_antenna(struct iwl_mvm *mvm, u8 valid, u8 last_idx) u8 ind = last_idx; int i; - for (i = 0; i < RATE_MCS_ANT_NUM; i++) { - ind = (ind + 1) % RATE_MCS_ANT_NUM; + for (i = 0; i < MAX_RS_ANT_NUM; i++) { + ind = (ind + 1) % MAX_RS_ANT_NUM; if (valid & BIT(ind)) return ind; }