hc
2024-01-03 2f7c68cb55ecb7331f2381deb497c27155f32faf
kernel/drivers/net/wireless/intel/iwlwifi/mvm/rs-fw.c
....@@ -6,7 +6,7 @@
66 * GPL LICENSE SUMMARY
77 *
88 * Copyright(c) 2017 Intel Deutschland GmbH
9
- * Copyright(c) 2018 Intel Corporation
9
+ * Copyright(c) 2018 - 2020 Intel Corporation
1010 *
1111 * This program is free software; you can redistribute it and/or modify
1212 * it under the terms of version 2 of the GNU General Public License as
....@@ -27,7 +27,7 @@
2727 * BSD LICENSE
2828 *
2929 * Copyright(c) 2017 Intel Deutschland GmbH
30
- * Copyright(c) 2018 Intel Corporation
30
+ * Copyright(c) 2018 - 2020 Intel Corporation
3131 * All rights reserved.
3232 *
3333 * Redistribution and use in source and binary forms, with or without
....@@ -101,7 +101,7 @@
101101 struct ieee80211_sta_he_cap *he_cap = &sta->he_cap;
102102 u8 supp = 0;
103103
104
- if (he_cap && he_cap->has_he)
104
+ if (he_cap->has_he)
105105 return 0;
106106
107107 if (ht_cap->cap & IEEE80211_HT_CAP_SGI_20)
....@@ -116,24 +116,51 @@
116116 return supp;
117117 }
118118
119
-static u16 rs_fw_set_config_flags(struct iwl_mvm *mvm,
120
- struct ieee80211_sta *sta)
119
+static u16 rs_fw_get_config_flags(struct iwl_mvm *mvm,
120
+ struct ieee80211_sta *sta,
121
+ struct ieee80211_supported_band *sband)
121122 {
122123 struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap;
123124 struct ieee80211_sta_vht_cap *vht_cap = &sta->vht_cap;
124
- bool vht_ena = vht_cap && vht_cap->vht_supported;
125
+ struct ieee80211_sta_he_cap *he_cap = &sta->he_cap;
126
+ bool vht_ena = vht_cap->vht_supported;
125127 u16 flags = 0;
126128
127129 if (mvm->cfg->ht_params->stbc &&
128
- (num_of_ant(iwl_mvm_get_valid_tx_ant(mvm)) > 1) &&
129
- ((ht_cap && (ht_cap->cap & IEEE80211_HT_CAP_RX_STBC)) ||
130
- (vht_ena && (vht_cap->cap & IEEE80211_VHT_CAP_RXSTBC_MASK))))
131
- flags |= IWL_TLC_MNG_CFG_FLAGS_STBC_MSK;
130
+ (num_of_ant(iwl_mvm_get_valid_tx_ant(mvm)) > 1)) {
131
+ if (he_cap->has_he) {
132
+ if (he_cap->he_cap_elem.phy_cap_info[2] &
133
+ IEEE80211_HE_PHY_CAP2_STBC_RX_UNDER_80MHZ)
134
+ flags |= IWL_TLC_MNG_CFG_FLAGS_STBC_MSK;
135
+
136
+ if (he_cap->he_cap_elem.phy_cap_info[7] &
137
+ IEEE80211_HE_PHY_CAP7_STBC_RX_ABOVE_80MHZ)
138
+ flags |= IWL_TLC_MNG_CFG_FLAGS_HE_STBC_160MHZ_MSK;
139
+ } else if ((ht_cap->cap & IEEE80211_HT_CAP_RX_STBC) ||
140
+ (vht_ena &&
141
+ (vht_cap->cap & IEEE80211_VHT_CAP_RXSTBC_MASK)))
142
+ flags |= IWL_TLC_MNG_CFG_FLAGS_STBC_MSK;
143
+ }
132144
133145 if (mvm->cfg->ht_params->ldpc &&
134
- ((ht_cap && (ht_cap->cap & IEEE80211_HT_CAP_LDPC_CODING)) ||
146
+ ((ht_cap->cap & IEEE80211_HT_CAP_LDPC_CODING) ||
135147 (vht_ena && (vht_cap->cap & IEEE80211_VHT_CAP_RXLDPC))))
136148 flags |= IWL_TLC_MNG_CFG_FLAGS_LDPC_MSK;
149
+
150
+ /* consider LDPC support in case of HE */
151
+ if (he_cap->has_he && (he_cap->he_cap_elem.phy_cap_info[1] &
152
+ IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD))
153
+ flags |= IWL_TLC_MNG_CFG_FLAGS_LDPC_MSK;
154
+
155
+ if (sband->iftype_data && sband->iftype_data->he_cap.has_he &&
156
+ !(sband->iftype_data->he_cap.he_cap_elem.phy_cap_info[1] &
157
+ IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD))
158
+ flags &= ~IWL_TLC_MNG_CFG_FLAGS_LDPC_MSK;
159
+
160
+ if (he_cap->has_he &&
161
+ (he_cap->he_cap_elem.phy_cap_info[3] &
162
+ IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_RX_MASK))
163
+ flags |= IWL_TLC_MNG_CFG_FLAGS_HE_DCM_NSS_1_MSK;
137164
138165 return flags;
139166 }
....@@ -168,12 +195,20 @@
168195 {
169196 u16 supp;
170197 int i, highest_mcs;
198
+ u8 max_nss = sta->rx_nss;
199
+ struct ieee80211_vht_cap ieee_vht_cap = {
200
+ .vht_cap_info = cpu_to_le32(vht_cap->cap),
201
+ .supp_mcs = vht_cap->vht_mcs,
202
+ };
171203
172
- for (i = 0; i < sta->rx_nss; i++) {
173
- if (i == MAX_NSS)
174
- break;
204
+ /* the station support only a single receive chain */
205
+ if (sta->smps_mode == IEEE80211_SMPS_STATIC)
206
+ max_nss = 1;
175207
176
- highest_mcs = rs_fw_vht_highest_rx_mcs_index(vht_cap, i + 1);
208
+ for (i = 0; i < max_nss && i < IWL_TLC_NSS_MAX; i++) {
209
+ int nss = i + 1;
210
+
211
+ highest_mcs = rs_fw_vht_highest_rx_mcs_index(vht_cap, nss);
177212 if (!highest_mcs)
178213 continue;
179214
....@@ -181,9 +216,18 @@
181216 if (sta->bandwidth == IEEE80211_STA_RX_BW_20)
182217 supp &= ~BIT(IWL_TLC_MNG_HT_RATE_MCS9);
183218
184
- cmd->ht_rates[i][0] = cpu_to_le16(supp);
185
- if (sta->bandwidth == IEEE80211_STA_RX_BW_160)
186
- cmd->ht_rates[i][1] = cmd->ht_rates[i][0];
219
+ cmd->ht_rates[i][IWL_TLC_HT_BW_NONE_160] = cpu_to_le16(supp);
220
+ /*
221
+ * Check if VHT extended NSS indicates that the bandwidth/NSS
222
+ * configuration is supported - only for MCS 0 since we already
223
+ * decoded the MCS bits anyway ourselves.
224
+ */
225
+ if (sta->bandwidth == IEEE80211_STA_RX_BW_160 &&
226
+ ieee80211_get_vht_max_nss(&ieee_vht_cap,
227
+ IEEE80211_VHT_CHANWIDTH_160MHZ,
228
+ 0, true, nss) >= nss)
229
+ cmd->ht_rates[i][IWL_TLC_HT_BW_160] =
230
+ cmd->ht_rates[i][IWL_TLC_HT_BW_NONE_160];
187231 }
188232 }
189233
....@@ -206,20 +250,49 @@
206250
207251 static void
208252 rs_fw_he_set_enabled_rates(const struct ieee80211_sta *sta,
209
- const struct ieee80211_sta_he_cap *he_cap,
253
+ struct ieee80211_supported_band *sband,
210254 struct iwl_tlc_config_cmd *cmd)
211255 {
212
- u16 mcs_160 = le16_to_cpu(sta->he_cap.he_mcs_nss_supp.rx_mcs_160);
213
- u16 mcs_80 = le16_to_cpu(sta->he_cap.he_mcs_nss_supp.rx_mcs_80);
256
+ const struct ieee80211_sta_he_cap *he_cap = &sta->he_cap;
257
+ u16 mcs_160 = le16_to_cpu(he_cap->he_mcs_nss_supp.rx_mcs_160);
258
+ u16 mcs_80 = le16_to_cpu(he_cap->he_mcs_nss_supp.rx_mcs_80);
259
+ u16 tx_mcs_80 =
260
+ le16_to_cpu(sband->iftype_data->he_cap.he_mcs_nss_supp.tx_mcs_80);
261
+ u16 tx_mcs_160 =
262
+ le16_to_cpu(sband->iftype_data->he_cap.he_mcs_nss_supp.tx_mcs_160);
214263 int i;
264
+ u8 nss = sta->rx_nss;
215265
216
- for (i = 0; i < sta->rx_nss && i < MAX_NSS; i++) {
266
+ /* the station support only a single receive chain */
267
+ if (sta->smps_mode == IEEE80211_SMPS_STATIC)
268
+ nss = 1;
269
+
270
+ for (i = 0; i < nss && i < IWL_TLC_NSS_MAX; i++) {
217271 u16 _mcs_160 = (mcs_160 >> (2 * i)) & 0x3;
218272 u16 _mcs_80 = (mcs_80 >> (2 * i)) & 0x3;
273
+ u16 _tx_mcs_160 = (tx_mcs_160 >> (2 * i)) & 0x3;
274
+ u16 _tx_mcs_80 = (tx_mcs_80 >> (2 * i)) & 0x3;
219275
220
- cmd->ht_rates[i][0] =
276
+ /* If one side doesn't support - mark both as not supporting */
277
+ if (_mcs_80 == IEEE80211_HE_MCS_NOT_SUPPORTED ||
278
+ _tx_mcs_80 == IEEE80211_HE_MCS_NOT_SUPPORTED) {
279
+ _mcs_80 = IEEE80211_HE_MCS_NOT_SUPPORTED;
280
+ _tx_mcs_80 = IEEE80211_HE_MCS_NOT_SUPPORTED;
281
+ }
282
+ if (_mcs_80 > _tx_mcs_80)
283
+ _mcs_80 = _tx_mcs_80;
284
+ cmd->ht_rates[i][IWL_TLC_HT_BW_NONE_160] =
221285 cpu_to_le16(rs_fw_he_ieee80211_mcs_to_rs_mcs(_mcs_80));
222
- cmd->ht_rates[i][1] =
286
+
287
+ /* If one side doesn't support - mark both as not supporting */
288
+ if (_mcs_160 == IEEE80211_HE_MCS_NOT_SUPPORTED ||
289
+ _tx_mcs_160 == IEEE80211_HE_MCS_NOT_SUPPORTED) {
290
+ _mcs_160 = IEEE80211_HE_MCS_NOT_SUPPORTED;
291
+ _tx_mcs_160 = IEEE80211_HE_MCS_NOT_SUPPORTED;
292
+ }
293
+ if (_mcs_160 > _tx_mcs_160)
294
+ _mcs_160 = _tx_mcs_160;
295
+ cmd->ht_rates[i][IWL_TLC_HT_BW_160] =
223296 cpu_to_le16(rs_fw_he_ieee80211_mcs_to_rs_mcs(_mcs_160));
224297 }
225298 }
....@@ -245,16 +318,24 @@
245318 cmd->mode = IWL_TLC_MNG_MODE_NON_HT;
246319
247320 /* HT/VHT rates */
248
- if (he_cap && he_cap->has_he) {
321
+ if (he_cap->has_he) {
249322 cmd->mode = IWL_TLC_MNG_MODE_HE;
250
- rs_fw_he_set_enabled_rates(sta, he_cap, cmd);
251
- } else if (vht_cap && vht_cap->vht_supported) {
323
+ rs_fw_he_set_enabled_rates(sta, sband, cmd);
324
+ } else if (vht_cap->vht_supported) {
252325 cmd->mode = IWL_TLC_MNG_MODE_VHT;
253326 rs_fw_vht_set_enabled_rates(sta, vht_cap, cmd);
254
- } else if (ht_cap && ht_cap->ht_supported) {
327
+ } else if (ht_cap->ht_supported) {
255328 cmd->mode = IWL_TLC_MNG_MODE_HT;
256
- cmd->ht_rates[0][0] = cpu_to_le16(ht_cap->mcs.rx_mask[0]);
257
- cmd->ht_rates[1][0] = cpu_to_le16(ht_cap->mcs.rx_mask[1]);
329
+ cmd->ht_rates[IWL_TLC_NSS_1][IWL_TLC_HT_BW_NONE_160] =
330
+ cpu_to_le16(ht_cap->mcs.rx_mask[0]);
331
+
332
+ /* the station support only a single receive chain */
333
+ if (sta->smps_mode == IEEE80211_SMPS_STATIC)
334
+ cmd->ht_rates[IWL_TLC_NSS_2][IWL_TLC_HT_BW_NONE_160] =
335
+ 0;
336
+ else
337
+ cmd->ht_rates[IWL_TLC_NSS_2][IWL_TLC_HT_BW_NONE_160] =
338
+ cpu_to_le16(ht_cap->mcs.rx_mask[1]);
258339 }
259340 }
260341
....@@ -291,19 +372,42 @@
291372 lq_sta = &mvmsta->lq_sta.rs_fw;
292373
293374 if (flags & IWL_TLC_NOTIF_FLAG_RATE) {
375
+ char pretty_rate[100];
294376 lq_sta->last_rate_n_flags = le32_to_cpu(notif->rate);
295
- IWL_DEBUG_RATE(mvm, "new rate_n_flags: 0x%X\n",
296
- lq_sta->last_rate_n_flags);
377
+ rs_pretty_print_rate(pretty_rate, sizeof(pretty_rate),
378
+ lq_sta->last_rate_n_flags);
379
+ IWL_DEBUG_RATE(mvm, "new rate: %s\n", pretty_rate);
297380 }
298381
299
- if (flags & IWL_TLC_NOTIF_FLAG_AMSDU) {
382
+ if (flags & IWL_TLC_NOTIF_FLAG_AMSDU && !mvmsta->orig_amsdu_len) {
300383 u16 size = le32_to_cpu(notif->amsdu_size);
384
+ int i;
301385
302
- if (WARN_ON(sta->max_amsdu_len < size))
386
+ if (sta->max_amsdu_len < size) {
387
+ /*
388
+ * In debug sta->max_amsdu_len < size
389
+ * so also check with orig_amsdu_len which holds the
390
+ * original data before debugfs changed the value
391
+ */
392
+ WARN_ON(mvmsta->orig_amsdu_len < size);
303393 goto out;
394
+ }
304395
305396 mvmsta->amsdu_enabled = le32_to_cpu(notif->amsdu_enabled);
306397 mvmsta->max_amsdu_len = size;
398
+ sta->max_rc_amsdu_len = mvmsta->max_amsdu_len;
399
+
400
+ for (i = 0; i < IWL_MAX_TID_COUNT; i++) {
401
+ if (mvmsta->amsdu_enabled & BIT(i))
402
+ sta->max_tid_amsdu_len[i] =
403
+ iwl_mvm_max_amsdu_size(mvm, sta, i);
404
+ else
405
+ /*
406
+ * Not so elegant, but this will effectively
407
+ * prevent AMSDU on this TID
408
+ */
409
+ sta->max_tid_amsdu_len[i] = 1;
410
+ }
307411
308412 IWL_DEBUG_RATE(mvm,
309413 "AMSDU update. AMSDU size: %d, AMSDU selected size: %d, AMSDU TID bitmap 0x%X\n",
....@@ -314,6 +418,36 @@
314418 rcu_read_unlock();
315419 }
316420
421
+u16 rs_fw_get_max_amsdu_len(struct ieee80211_sta *sta)
422
+{
423
+ const struct ieee80211_sta_vht_cap *vht_cap = &sta->vht_cap;
424
+ const struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap;
425
+
426
+ if (vht_cap->vht_supported) {
427
+ switch (vht_cap->cap & IEEE80211_VHT_CAP_MAX_MPDU_MASK) {
428
+ case IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454:
429
+ return IEEE80211_MAX_MPDU_LEN_VHT_11454;
430
+ case IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991:
431
+ return IEEE80211_MAX_MPDU_LEN_VHT_7991;
432
+ default:
433
+ return IEEE80211_MAX_MPDU_LEN_VHT_3895;
434
+ }
435
+ } else if (ht_cap->ht_supported) {
436
+ if (ht_cap->cap & IEEE80211_HT_CAP_MAX_AMSDU)
437
+ /*
438
+ * agg is offloaded so we need to assume that agg
439
+ * are enabled and max mpdu in ampdu is 4095
440
+ * (spec 802.11-2016 9.3.2.1)
441
+ */
442
+ return IEEE80211_MAX_MPDU_LEN_HT_BA;
443
+ else
444
+ return IEEE80211_MAX_MPDU_LEN_HT_3839;
445
+ }
446
+
447
+ /* in legacy mode no amsdu is enabled so return zero */
448
+ return 0;
449
+}
450
+
317451 void rs_fw_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
318452 enum nl80211_band band, bool update)
319453 {
....@@ -321,28 +455,41 @@
321455 struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
322456 struct iwl_lq_sta_rs_fw *lq_sta = &mvmsta->lq_sta.rs_fw;
323457 u32 cmd_id = iwl_cmd_id(TLC_MNG_CONFIG_CMD, DATA_PATH_GROUP, 0);
324
- struct ieee80211_supported_band *sband;
458
+ struct ieee80211_supported_band *sband = hw->wiphy->bands[band];
459
+ u16 max_amsdu_len = rs_fw_get_max_amsdu_len(sta);
325460 struct iwl_tlc_config_cmd cfg_cmd = {
326461 .sta_id = mvmsta->sta_id,
327462 .max_ch_width = update ?
328463 rs_fw_bw_from_sta_bw(sta) : RATE_MCS_CHAN_WIDTH_20,
329
- .flags = cpu_to_le16(rs_fw_set_config_flags(mvm, sta)),
464
+ .flags = cpu_to_le16(rs_fw_get_config_flags(mvm, sta, sband)),
330465 .chains = rs_fw_set_active_chains(iwl_mvm_get_valid_tx_ant(mvm)),
331
- .max_mpdu_len = cpu_to_le16(sta->max_amsdu_len),
332466 .sgi_ch_width_supp = rs_fw_sgi_cw_support(sta),
467
+ .max_mpdu_len = cpu_to_le16(max_amsdu_len),
333468 .amsdu = iwl_mvm_is_csum_supported(mvm),
334469 };
335470 int ret;
471
+ u16 cmd_size = sizeof(cfg_cmd);
472
+
473
+ /* In old versions of the API the struct is 4 bytes smaller */
474
+ if (iwl_fw_lookup_cmd_ver(mvm->fw, DATA_PATH_GROUP,
475
+ TLC_MNG_CONFIG_CMD, 0) < 3)
476
+ cmd_size -= 4;
336477
337478 memset(lq_sta, 0, offsetof(typeof(*lq_sta), pers));
338479
339480 #ifdef CONFIG_IWLWIFI_DEBUGFS
340481 iwl_mvm_reset_frame_stats(mvm);
341482 #endif
342
- sband = hw->wiphy->bands[band];
343483 rs_fw_set_supp_rates(sta, sband, &cfg_cmd);
344484
345
- ret = iwl_mvm_send_cmd_pdu(mvm, cmd_id, 0, sizeof(cfg_cmd), &cfg_cmd);
485
+ /*
486
+ * since TLC offload works with one mode we can assume
487
+ * that only vht/ht is used and also set it as station max amsdu
488
+ */
489
+ sta->max_amsdu_len = max_amsdu_len;
490
+
491
+ ret = iwl_mvm_send_cmd_pdu(mvm, cmd_id, CMD_ASYNC, cmd_size,
492
+ &cfg_cmd);
346493 if (ret)
347494 IWL_ERR(mvm, "Failed to send rate scale config (%d)\n", ret);
348495 }