diff options
author | Gregory Greenman <gregory.greenman@intel.com> | 2017-11-01 03:04:38 -0400 |
---|---|---|
committer | Luca Coelho <luciano.coelho@intel.com> | 2017-12-05 14:01:41 -0500 |
commit | 110b32f065f3c66a7a1626ca57b64641ed6a578e (patch) | |
tree | 9a0c5eb3cc79744758d82b0fb1b2f57a6f6c21f9 | |
parent | 9f66a397c8773167939c4eafc33725f38ec5c872 (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.h | 5 | ||||
-rw-r--r-- | drivers/net/wireless/intel/iwlwifi/fw/api/rs.h | 168 | ||||
-rw-r--r-- | drivers/net/wireless/intel/iwlwifi/mvm/rs-fw.c | 187 | ||||
-rw-r--r-- | drivers/net/wireless/intel/iwlwifi/mvm/rs.c | 25 | ||||
-rw-r--r-- | drivers/net/wireless/intel/iwlwifi/mvm/rs.h | 2 | ||||
-rw-r--r-- | 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 | |||
@@ -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 | */ | ||
74 | enum 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 | */ | ||
91 | enum 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 | */ | ||
105 | enum 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 | */ | ||
118 | enum 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 | */ | ||
136 | enum 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 | */ | ||
155 | enum 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 | */ | ||
179 | enum 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 | */ | ||
214 | struct 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 | ||
64 | static 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 | |||
79 | static 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 | |||
93 | static 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 | |||
111 | static 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 | |||
140 | static | ||
141 | int 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 | |||
163 | static 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 | |||
186 | static 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 | |||
64 | void rs_fw_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta, | 216 | void 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 | |||
248 | int 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 | ||
69 | void iwl_mvm_rs_add_sta(struct iwl_mvm *mvm, struct iwl_mvm_sta *mvmsta) | 256 | void 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 | /** | 4064 | static 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 | */ | ||
4071 | int 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 | */ | ||
4089 | int 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); | |||
452 | void iwl_mvm_rs_add_sta(struct iwl_mvm *mvm, struct iwl_mvm_sta *mvmsta); | 452 | void iwl_mvm_rs_add_sta(struct iwl_mvm *mvm, struct iwl_mvm_sta *mvmsta); |
453 | void rs_fw_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta, | 453 | void rs_fw_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta, |
454 | enum nl80211_band band); | 454 | enum nl80211_band band); |
455 | int 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 | } |