aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGregory Greenman <gregory.greenman@intel.com>2017-11-01 03:04:38 -0400
committerLuca Coelho <luciano.coelho@intel.com>2017-12-05 14:01:41 -0500
commit110b32f065f3c66a7a1626ca57b64641ed6a578e (patch)
tree9a0c5eb3cc79744758d82b0fb1b2f57a6f6c21f9
parent9f66a397c8773167939c4eafc33725f38ec5c872 (diff)
iwlwifi: mvm: rs: add basic implementation of the new RS API handlers
This patch adds rate scaling configuration command and implements a few other handlers. Signed-off-by: Gregory Greenman <gregory.greenman@intel.com> Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/api/datapath.h5
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/api/rs.h168
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/rs-fw.c187
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/rs.c25
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/rs.h2
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/utils.c4
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
@@ -83,6 +83,11 @@ enum iwl_data_path_subcmd_ids {
83 TRIGGER_RX_QUEUES_NOTIF_CMD = 0x2, 83 TRIGGER_RX_QUEUES_NOTIF_CMD = 0x2,
84 84
85 /** 85 /**
86 * @TLC_MNG_CONFIG_CMD: &struct iwl_tlc_config_cmd
87 */
88 TLC_MNG_CONFIG_CMD = 0xF,
89
90 /**
86 * @STA_PM_NOTIF: &struct iwl_mvm_pm_state_notification 91 * @STA_PM_NOTIF: &struct iwl_mvm_pm_state_notification
87 */ 92 */
88 STA_PM_NOTIF = 0xFD, 93 STA_PM_NOTIF = 0xFD,
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 @@
62 62
63#include "mac.h" 63#include "mac.h"
64 64
65/**
66 * enum iwl_tlc_mng_cfg_flags_enum - options for TLC config flags
67 * @IWL_TLC_MNG_CFG_FLAGS_CCK_MSK: CCK support
68 * @IWL_TLC_MNG_CFG_FLAGS_DD_MSK: enable DD
69 * @IWL_TLC_MNG_CFG_FLAGS_STBC_MSK: enable STBC
70 * @IWL_TLC_MNG_CFG_FLAGS_LDPC_MSK: enable LDPC
71 * @IWL_TLC_MNG_CFG_FLAGS_BF_MSK: enable BFER
72 * @IWL_TLC_MNG_CFG_FLAGS_DCM_MSK: enable DCM
73 */
74enum iwl_tlc_mng_cfg_flags_enum {
75 IWL_TLC_MNG_CFG_FLAGS_CCK_MSK = BIT(0),
76 IWL_TLC_MNG_CFG_FLAGS_DD_MSK = BIT(1),
77 IWL_TLC_MNG_CFG_FLAGS_STBC_MSK = BIT(2),
78 IWL_TLC_MNG_CFG_FLAGS_LDPC_MSK = BIT(3),
79 IWL_TLC_MNG_CFG_FLAGS_BF_MSK = BIT(4),
80 IWL_TLC_MNG_CFG_FLAGS_DCM_MSK = BIT(5),
81};
82
83/**
84 * enum iwl_tlc_mng_cfg_cw_enum - channel width options
85 * @IWL_TLC_MNG_MAX_CH_WIDTH_20MHZ: 20MHZ channel
86 * @IWL_TLC_MNG_MAX_CH_WIDTH_40MHZ: 40MHZ channel
87 * @IWL_TLC_MNG_MAX_CH_WIDTH_80MHZ: 80MHZ channel
88 * @IWL_TLC_MNG_MAX_CH_WIDTH_160MHZ: 160MHZ channel
89 * @IWL_TLC_MNG_MAX_CH_WIDTH_LAST: maximum value
90 */
91enum iwl_tlc_mng_cfg_cw_enum {
92 IWL_TLC_MNG_MAX_CH_WIDTH_20MHZ,
93 IWL_TLC_MNG_MAX_CH_WIDTH_40MHZ,
94 IWL_TLC_MNG_MAX_CH_WIDTH_80MHZ,
95 IWL_TLC_MNG_MAX_CH_WIDTH_160MHZ,
96 IWL_TLC_MNG_MAX_CH_WIDTH_LAST = IWL_TLC_MNG_MAX_CH_WIDTH_160MHZ,
97};
98
99/**
100 * enum iwl_tlc_mng_cfg_chains_enum - possible chains
101 * @IWL_TLC_MNG_CHAIN_A_MSK: chain A
102 * @IWL_TLC_MNG_CHAIN_B_MSK: chain B
103 * @IWL_TLC_MNG_CHAIN_C_MSK: chain C
104 */
105enum iwl_tlc_mng_cfg_chains_enum {
106 IWL_TLC_MNG_CHAIN_A_MSK = BIT(0),
107 IWL_TLC_MNG_CHAIN_B_MSK = BIT(1),
108 IWL_TLC_MNG_CHAIN_C_MSK = BIT(2),
109};
110
111/**
112 * enum iwl_tlc_mng_cfg_gi_enum - guard interval options
113 * @IWL_TLC_MNG_SGI_20MHZ_MSK: enable short GI for 20MHZ
114 * @IWL_TLC_MNG_SGI_40MHZ_MSK: enable short GI for 40MHZ
115 * @IWL_TLC_MNG_SGI_80MHZ_MSK: enable short GI for 80MHZ
116 * @IWL_TLC_MNG_SGI_160MHZ_MSK: enable short GI for 160MHZ
117 */
118enum iwl_tlc_mng_cfg_gi_enum {
119 IWL_TLC_MNG_SGI_20MHZ_MSK = BIT(0),
120 IWL_TLC_MNG_SGI_40MHZ_MSK = BIT(1),
121 IWL_TLC_MNG_SGI_80MHZ_MSK = BIT(2),
122 IWL_TLC_MNG_SGI_160MHZ_MSK = BIT(3),
123};
124
125/**
126 * enum iwl_tlc_mng_cfg_mode_enum - supported modes
127 * @IWL_TLC_MNG_MODE_CCK: enable CCK
128 * @IWL_TLC_MNG_MODE_OFDM_NON_HT: enable OFDM (non HT)
129 * @IWL_TLC_MNG_MODE_NON_HT: enable non HT
130 * @IWL_TLC_MNG_MODE_HT: enable HT
131 * @IWL_TLC_MNG_MODE_VHT: enable VHT
132 * @IWL_TLC_MNG_MODE_HE: enable HE
133 * @IWL_TLC_MNG_MODE_INVALID: invalid value
134 * @IWL_TLC_MNG_MODE_NUM: a count of possible modes
135 */
136enum iwl_tlc_mng_cfg_mode_enum {
137 IWL_TLC_MNG_MODE_CCK = 0,
138 IWL_TLC_MNG_MODE_OFDM_NON_HT = IWL_TLC_MNG_MODE_CCK,
139 IWL_TLC_MNG_MODE_NON_HT = IWL_TLC_MNG_MODE_CCK,
140 IWL_TLC_MNG_MODE_HT,
141 IWL_TLC_MNG_MODE_VHT,
142 IWL_TLC_MNG_MODE_HE,
143 IWL_TLC_MNG_MODE_INVALID,
144 IWL_TLC_MNG_MODE_NUM = IWL_TLC_MNG_MODE_INVALID,
145};
146
147/**
148 * enum iwl_tlc_mng_vht_he_types_enum - VHT HE types
149 * @IWL_TLC_MNG_VALID_VHT_HE_TYPES_SU: VHT HT single user
150 * @IWL_TLC_MNG_VALID_VHT_HE_TYPES_SU_EXT: VHT HT single user extended
151 * @IWL_TLC_MNG_VALID_VHT_HE_TYPES_MU: VHT HT multiple users
152 * @IWL_TLC_MNG_VALID_VHT_HE_TYPES_TRIG_BASED: trigger based
153 * @IWL_TLC_MNG_VALID_VHT_HE_TYPES_NUM: a count of possible types
154 */
155enum iwl_tlc_mng_vht_he_types_enum {
156 IWL_TLC_MNG_VALID_VHT_HE_TYPES_SU = 0,
157 IWL_TLC_MNG_VALID_VHT_HE_TYPES_SU_EXT,
158 IWL_TLC_MNG_VALID_VHT_HE_TYPES_MU,
159 IWL_TLC_MNG_VALID_VHT_HE_TYPES_TRIG_BASED,
160 IWL_TLC_MNG_VALID_VHT_HE_TYPES_NUM =
161 IWL_TLC_MNG_VALID_VHT_HE_TYPES_TRIG_BASED,
162
163};
164
165/**
166 * enum iwl_tlc_mng_ht_rates_enum - HT/VHT rates
167 * @IWL_TLC_MNG_HT_RATE_MCS0: index of MCS0
168 * @IWL_TLC_MNG_HT_RATE_MCS1: index of MCS1
169 * @IWL_TLC_MNG_HT_RATE_MCS2: index of MCS2
170 * @IWL_TLC_MNG_HT_RATE_MCS3: index of MCS3
171 * @IWL_TLC_MNG_HT_RATE_MCS4: index of MCS4
172 * @IWL_TLC_MNG_HT_RATE_MCS5: index of MCS5
173 * @IWL_TLC_MNG_HT_RATE_MCS6: index of MCS6
174 * @IWL_TLC_MNG_HT_RATE_MCS7: index of MCS7
175 * @IWL_TLC_MNG_HT_RATE_MCS8: index of MCS8
176 * @IWL_TLC_MNG_HT_RATE_MCS9: index of MCS9
177 * @IWL_TLC_MNG_HT_RATE_MAX: maximal rate for HT/VHT
178 */
179enum iwl_tlc_mng_ht_rates_enum {
180 IWL_TLC_MNG_HT_RATE_MCS0 = 0,
181 IWL_TLC_MNG_HT_RATE_MCS1,
182 IWL_TLC_MNG_HT_RATE_MCS2,
183 IWL_TLC_MNG_HT_RATE_MCS3,
184 IWL_TLC_MNG_HT_RATE_MCS4,
185 IWL_TLC_MNG_HT_RATE_MCS5,
186 IWL_TLC_MNG_HT_RATE_MCS6,
187 IWL_TLC_MNG_HT_RATE_MCS7,
188 IWL_TLC_MNG_HT_RATE_MCS8,
189 IWL_TLC_MNG_HT_RATE_MCS9,
190 IWL_TLC_MNG_HT_RATE_MAX = IWL_TLC_MNG_HT_RATE_MCS9,
191};
192
193/* Maximum supported tx antennas number */
194#define MAX_RS_ANT_NUM 3
195
196/**
197 * struct tlc_config_cmd - TLC configuration
198 * @sta_id: station id
199 * @reserved1: reserved
200 * @max_supp_ch_width: channel width
201 * @flags: bitmask of %IWL_TLC_MNG_CONFIG_FLAGS_ENABLE_\*
202 * @chains: bitmask of %IWL_TLC_MNG_CHAIN_\*
203 * @max_supp_ss: valid values are 0-3, 0 - spatial streams are not supported
204 * @valid_vht_he_types: bitmap of %IWL_TLC_MNG_VALID_VHT_HE_TYPES_\*
205 * @non_ht_supp_rates: bitmap of supported legacy rates
206 * @ht_supp_rates: bitmap of supported HT/VHT rates, valid bits are 0-9
207 * @mode: modulation type %IWL_TLC_MNG_MODE_\*
208 * @reserved2: reserved
209 * @he_supp_rates: bitmap of supported HE rates
210 * @sgi_ch_width_supp: bitmap of SGI support per channel width
211 * @he_gi_support: 11ax HE guard interval
212 * @max_ampdu_cnt: max AMPDU size (frames count)
213 */
214struct iwl_tlc_config_cmd {
215 u8 sta_id;
216 u8 reserved1[3];
217 u8 max_supp_ch_width;
218 u8 chains;
219 u8 max_supp_ss;
220 u8 valid_vht_he_types;
221 __le16 flags;
222 __le16 non_ht_supp_rates;
223 __le16 ht_supp_rates[MAX_RS_ANT_NUM];
224 u8 mode;
225 u8 reserved2;
226 __le16 he_supp_rates;
227 u8 sgi_ch_width_supp;
228 u8 he_gi_support;
229 __le32 max_ampdu_cnt;
230} __packed; /* TLC_MNG_CONFIG_CMD_API_S_VER_1 */
231
65/* 232/*
66 * These serve as indexes into 233 * These serve as indexes into
67 * struct iwl_rate_info fw_rate_idx_to_plcp[IWL_RATE_COUNT]; 234 * struct iwl_rate_info fw_rate_idx_to_plcp[IWL_RATE_COUNT];
@@ -253,7 +420,6 @@ enum {
253#define RATE_MCS_ANT_ABC_MSK (RATE_MCS_ANT_AB_MSK | \ 420#define RATE_MCS_ANT_ABC_MSK (RATE_MCS_ANT_AB_MSK | \
254 RATE_MCS_ANT_C_MSK) 421 RATE_MCS_ANT_C_MSK)
255#define RATE_MCS_ANT_MSK RATE_MCS_ANT_ABC_MSK 422#define RATE_MCS_ANT_MSK RATE_MCS_ANT_ABC_MSK
256#define RATE_MCS_ANT_NUM 3
257 423
258/* Bit 17: (0) SS, (1) SS*2 */ 424/* Bit 17: (0) SS, (1) SS*2 */
259#define RATE_MCS_STBC_POS 17 425#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 aae55b26a397..8317b2fcc2d1 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/rs-fw.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/rs-fw.c
@@ -61,9 +61,196 @@
61#include "iwl-op-mode.h" 61#include "iwl-op-mode.h"
62#include "mvm.h" 62#include "mvm.h"
63 63
64static u8 rs_fw_bw_from_sta_bw(struct ieee80211_sta *sta)
65{
66 switch (sta->bandwidth) {
67 case IEEE80211_STA_RX_BW_160:
68 return IWL_TLC_MNG_MAX_CH_WIDTH_160MHZ;
69 case IEEE80211_STA_RX_BW_80:
70 return IWL_TLC_MNG_MAX_CH_WIDTH_80MHZ;
71 case IEEE80211_STA_RX_BW_40:
72 return IWL_TLC_MNG_MAX_CH_WIDTH_40MHZ;
73 case IEEE80211_STA_RX_BW_20:
74 default:
75 return IWL_TLC_MNG_MAX_CH_WIDTH_20MHZ;
76 }
77}
78
79static u8 rs_fw_set_active_chains(u8 chains)
80{
81 u8 fw_chains = 0;
82
83 if (chains & ANT_A)
84 fw_chains |= IWL_TLC_MNG_CHAIN_A_MSK;
85 if (chains & ANT_B)
86 fw_chains |= IWL_TLC_MNG_CHAIN_B_MSK;
87 if (chains & ANT_C)
88 fw_chains |= IWL_TLC_MNG_CHAIN_C_MSK;
89
90 return fw_chains;
91}
92
93static u8 rs_fw_sgi_cw_support(struct ieee80211_sta *sta)
94{
95 struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap;
96 struct ieee80211_sta_vht_cap *vht_cap = &sta->vht_cap;
97 u8 supp = 0;
98
99 if (ht_cap->cap & IEEE80211_HT_CAP_SGI_20)
100 supp |= IWL_TLC_MNG_SGI_20MHZ_MSK;
101 if (ht_cap->cap & IEEE80211_HT_CAP_SGI_40)
102 supp |= IWL_TLC_MNG_SGI_40MHZ_MSK;
103 if (vht_cap->cap & IEEE80211_VHT_CAP_SHORT_GI_80)
104 supp |= IWL_TLC_MNG_SGI_80MHZ_MSK;
105 if (vht_cap->cap & IEEE80211_VHT_CAP_SHORT_GI_160)
106 supp |= IWL_TLC_MNG_SGI_160MHZ_MSK;
107
108 return supp;
109}
110
111static u16 rs_fw_set_config_flags(struct iwl_mvm *mvm,
112 struct ieee80211_sta *sta)
113{
114 struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap;
115 struct ieee80211_sta_vht_cap *vht_cap = &sta->vht_cap;
116 bool vht_ena = vht_cap && vht_cap->vht_supported;
117 u16 flags = IWL_TLC_MNG_CFG_FLAGS_CCK_MSK |
118 IWL_TLC_MNG_CFG_FLAGS_DCM_MSK |
119 IWL_TLC_MNG_CFG_FLAGS_DD_MSK;
120
121 if (mvm->cfg->ht_params->stbc &&
122 (num_of_ant(iwl_mvm_get_valid_tx_ant(mvm)) > 1) &&
123 ((ht_cap && (ht_cap->cap & IEEE80211_HT_CAP_RX_STBC)) ||
124 (vht_ena && (vht_cap->cap & IEEE80211_VHT_CAP_RXSTBC_MASK))))
125 flags |= IWL_TLC_MNG_CFG_FLAGS_STBC_MSK;
126
127 if (mvm->cfg->ht_params->ldpc &&
128 ((ht_cap && (ht_cap->cap & IEEE80211_HT_CAP_LDPC_CODING)) ||
129 (vht_ena && (vht_cap->cap & IEEE80211_VHT_CAP_RXLDPC))))
130 flags |= IWL_TLC_MNG_CFG_FLAGS_LDPC_MSK;
131
132 if (fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_BEAMFORMER) &&
133 (num_of_ant(iwl_mvm_get_valid_tx_ant(mvm)) > 1) &&
134 (vht_cap->cap & IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE))
135 flags |= IWL_TLC_MNG_CFG_FLAGS_BF_MSK;
136
137 return flags;
138}
139
140static
141int rs_fw_vht_highest_rx_mcs_index(struct ieee80211_sta_vht_cap *vht_cap,
142 int nss)
143{
144 u16 rx_mcs = le16_to_cpu(vht_cap->vht_mcs.rx_mcs_map) &
145 (0x3 << (2 * (nss - 1)));
146 rx_mcs >>= (2 * (nss - 1));
147
148 switch (rx_mcs) {
149 case IEEE80211_VHT_MCS_SUPPORT_0_7:
150 return IWL_TLC_MNG_HT_RATE_MCS7;
151 case IEEE80211_VHT_MCS_SUPPORT_0_8:
152 return IWL_TLC_MNG_HT_RATE_MCS8;
153 case IEEE80211_VHT_MCS_SUPPORT_0_9:
154 return IWL_TLC_MNG_HT_RATE_MCS9;
155 default:
156 WARN_ON_ONCE(1);
157 break;
158 }
159
160 return 0;
161}
162
163static void rs_fw_vht_set_enabled_rates(struct ieee80211_sta *sta,
164 struct ieee80211_sta_vht_cap *vht_cap,
165 struct iwl_tlc_config_cmd *cmd)
166{
167 u16 supp;
168 int i, highest_mcs;
169
170 for (i = 0; i < sta->rx_nss; i++) {
171 if (i == MAX_RS_ANT_NUM)
172 break;
173
174 highest_mcs = rs_fw_vht_highest_rx_mcs_index(vht_cap, i + 1);
175 if (!highest_mcs)
176 continue;
177
178 supp = BIT(highest_mcs + 1) - 1;
179 if (sta->bandwidth == IEEE80211_STA_RX_BW_20)
180 supp &= ~BIT(IWL_TLC_MNG_HT_RATE_MCS9);
181
182 cmd->ht_supp_rates[i] = cpu_to_le16(supp);
183 }
184}
185
186static void rs_fw_set_supp_rates(struct ieee80211_sta *sta,
187 struct ieee80211_supported_band *sband,
188 struct iwl_tlc_config_cmd *cmd)
189{
190 int i;
191 unsigned long tmp;
192 unsigned long supp; /* must be unsigned long for for_each_set_bit */
193 struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap;
194 struct ieee80211_sta_vht_cap *vht_cap = &sta->vht_cap;
195
196 /* non HT rates */
197 supp = 0;
198 tmp = sta->supp_rates[sband->band];
199 for_each_set_bit(i, &tmp, BITS_PER_LONG)
200 supp |= BIT(sband->bitrates[i].hw_value);
201
202 cmd->non_ht_supp_rates = cpu_to_le16(supp);
203 cmd->mode = IWL_TLC_MNG_MODE_NON_HT;
204
205 /* HT/VHT rates */
206 if (vht_cap && vht_cap->vht_supported) {
207 cmd->mode = IWL_TLC_MNG_MODE_VHT;
208 rs_fw_vht_set_enabled_rates(sta, vht_cap, cmd);
209 } else if (ht_cap && ht_cap->ht_supported) {
210 cmd->mode = IWL_TLC_MNG_MODE_HT;
211 cmd->ht_supp_rates[0] = cpu_to_le16(ht_cap->mcs.rx_mask[0]);
212 cmd->ht_supp_rates[1] = cpu_to_le16(ht_cap->mcs.rx_mask[1]);
213 }
214}
215
64void rs_fw_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta, 216void rs_fw_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
65 enum nl80211_band band) 217 enum nl80211_band band)
66{ 218{
219 struct ieee80211_hw *hw = mvm->hw;
220 struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
221 struct iwl_lq_sta_rs_fw *lq_sta = &mvmsta->lq_sta.rs_fw;
222 u32 cmd_id = iwl_cmd_id(TLC_MNG_CONFIG_CMD, DATA_PATH_GROUP, 0);
223 struct ieee80211_supported_band *sband;
224 struct iwl_tlc_config_cmd cfg_cmd = {
225 .sta_id = mvmsta->sta_id,
226 .max_supp_ch_width = rs_fw_bw_from_sta_bw(sta),
227 .flags = cpu_to_le16(rs_fw_set_config_flags(mvm, sta)),
228 .chains = rs_fw_set_active_chains(iwl_mvm_get_valid_tx_ant(mvm)),
229 .max_supp_ss = sta->rx_nss,
230 .max_ampdu_cnt = cpu_to_le32(mvmsta->max_agg_bufsize),
231 .sgi_ch_width_supp = rs_fw_sgi_cw_support(sta),
232 };
233 int ret;
234
235 memset(lq_sta, 0, offsetof(typeof(*lq_sta), pers));
236
237#ifdef CONFIG_IWLWIFI_DEBUGFS
238 iwl_mvm_reset_frame_stats(mvm);
239#endif
240 sband = hw->wiphy->bands[band];
241 rs_fw_set_supp_rates(sta, sband, &cfg_cmd);
242
243 ret = iwl_mvm_send_cmd_pdu(mvm, cmd_id, 0, sizeof(cfg_cmd), &cfg_cmd);
244 if (ret)
245 IWL_ERR(mvm, "Failed to send rate scale config (%d)\n", ret);
246}
247
248int rs_fw_tx_protection(struct iwl_mvm *mvm, struct iwl_mvm_sta *mvmsta,
249 bool enable)
250{
251 /* TODO: need to introduce a new FW cmd since LQ cmd is not relevant */
252 IWL_DEBUG_RATE(mvm, "tx protection - not implemented yet.\n");
253 return 0;
67} 254}
68 255
69void iwl_mvm_rs_add_sta(struct iwl_mvm *mvm, struct iwl_mvm_sta *mvmsta) 256void iwl_mvm_rs_add_sta(struct iwl_mvm *mvm, struct iwl_mvm_sta *mvmsta)
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)
4061 ieee80211_rate_control_unregister(&rs_mvm_ops_drv); 4061 ieee80211_rate_control_unregister(&rs_mvm_ops_drv);
4062} 4062}
4063 4063
4064/** 4064static int rs_drv_tx_protection(struct iwl_mvm *mvm, struct iwl_mvm_sta *mvmsta,
4065 * iwl_mvm_tx_protection - Gets LQ command, change it to enable/disable 4065 bool enable)
4066 * Tx protection, according to this request and previous requests,
4067 * and send the LQ command.
4068 * @mvmsta: The station
4069 * @enable: Enable Tx protection?
4070 */
4071int iwl_mvm_tx_protection(struct iwl_mvm *mvm, struct iwl_mvm_sta *mvmsta,
4072 bool enable)
4073{ 4066{
4074 struct iwl_lq_cmd *lq = &mvmsta->lq_sta.rs_drv.lq; 4067 struct iwl_lq_cmd *lq = &mvmsta->lq_sta.rs_drv.lq;
4075 4068
@@ -4087,3 +4080,17 @@ int iwl_mvm_tx_protection(struct iwl_mvm *mvm, struct iwl_mvm_sta *mvmsta,
4087 4080
4088 return iwl_mvm_send_lq_cmd(mvm, lq, false); 4081 return iwl_mvm_send_lq_cmd(mvm, lq, false);
4089} 4082}
4083
4084/**
4085 * iwl_mvm_tx_protection - ask FW to enable RTS/CTS protection
4086 * @mvmsta: The station
4087 * @enable: Enable Tx protection?
4088 */
4089int iwl_mvm_tx_protection(struct iwl_mvm *mvm, struct iwl_mvm_sta *mvmsta,
4090 bool enable)
4091{
4092 if (fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_TLC_OFFLOAD))
4093 return rs_fw_tx_protection(mvm, mvmsta, enable);
4094 else
4095 return rs_drv_tx_protection(mvm, mvmsta, enable);
4096}
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);
452void iwl_mvm_rs_add_sta(struct iwl_mvm *mvm, struct iwl_mvm_sta *mvmsta); 452void iwl_mvm_rs_add_sta(struct iwl_mvm *mvm, struct iwl_mvm_sta *mvmsta);
453void rs_fw_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta, 453void rs_fw_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
454 enum nl80211_band band); 454 enum nl80211_band band);
455int rs_fw_tx_protection(struct iwl_mvm *mvm, struct iwl_mvm_sta *mvmsta,
456 bool enable);
455#endif /* __rs__ */ 457#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)
278 u8 ind = last_idx; 278 u8 ind = last_idx;
279 int i; 279 int i;
280 280
281 for (i = 0; i < RATE_MCS_ANT_NUM; i++) { 281 for (i = 0; i < MAX_RS_ANT_NUM; i++) {
282 ind = (ind + 1) % RATE_MCS_ANT_NUM; 282 ind = (ind + 1) % MAX_RS_ANT_NUM;
283 if (valid & BIT(ind)) 283 if (valid & BIT(ind))
284 return ind; 284 return ind;
285 } 285 }