aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwlwifi/mvm
diff options
context:
space:
mode:
authorEyal Shapira <eyal@wizery.com>2013-08-11 11:43:47 -0400
committerJohannes Berg <johannes.berg@intel.com>2013-10-02 12:00:41 -0400
commitd310e4059fe39cf7669801173d25dc9da29eb05e (patch)
tree9188adc0e4762f926e0e87afc61c54205263fb9b /drivers/net/wireless/iwlwifi/mvm
parent4515f30fb6c890faba21dd2d74ff2e84ad94c01c (diff)
iwlwifi: mvm: support VHT in rs
Enable rs algorithm to use VHT rates and use 80Mhz. This enables reaching VHT rates which wasn't possible. Signed-off-by: Eyal Shapira <eyal@wizery.com> Reviewed-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'drivers/net/wireless/iwlwifi/mvm')
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/fw-api-rs.h4
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/mvm.h3
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/rs.c518
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/rs.h117
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/tx.c35
5 files changed, 431 insertions, 246 deletions
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-rs.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-rs.h
index ada130524ef8..538f1c7a5966 100644
--- a/drivers/net/wireless/iwlwifi/mvm/fw-api-rs.h
+++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-rs.h
@@ -68,6 +68,7 @@
68/* 68/*
69 * These serve as indexes into 69 * These serve as indexes into
70 * struct iwl_rate_info fw_rate_idx_to_plcp[IWL_RATE_COUNT]; 70 * struct iwl_rate_info fw_rate_idx_to_plcp[IWL_RATE_COUNT];
71 * TODO: avoid overlap between legacy and HT rates
71 */ 72 */
72enum { 73enum {
73 IWL_RATE_1M_INDEX = 0, 74 IWL_RATE_1M_INDEX = 0,
@@ -121,6 +122,7 @@ enum {
121 IWL_RATE_2M_PLCP = 20, 122 IWL_RATE_2M_PLCP = 20,
122 IWL_RATE_5M_PLCP = 55, 123 IWL_RATE_5M_PLCP = 55,
123 IWL_RATE_11M_PLCP = 110, 124 IWL_RATE_11M_PLCP = 110,
125 IWL_RATE_INVM_PLCP = -1,
124}; 126};
125 127
126/* 128/*
@@ -177,6 +179,8 @@ enum {
177 * which is the duplicate 20 MHz MCS (bit 5 set, all others zero.) 179 * which is the duplicate 20 MHz MCS (bit 5 set, all others zero.)
178 */ 180 */
179#define RATE_HT_MCS_RATE_CODE_MSK 0x7 181#define RATE_HT_MCS_RATE_CODE_MSK 0x7
182#define RATE_HT_MCS_NSS_POS 3
183#define RATE_HT_MCS_NSS_MSK (3 << RATE_HT_MCS_NSS_POS)
180 184
181/* Bit 10: (1) Use Green Field preamble */ 185/* Bit 10: (1) Use Green Field preamble */
182#define RATE_HT_MCS_GF_POS 10 186#define RATE_HT_MCS_GF_POS 10
diff --git a/drivers/net/wireless/iwlwifi/mvm/mvm.h b/drivers/net/wireless/iwlwifi/mvm/mvm.h
index dc18668b4f78..2d65fe2474e9 100644
--- a/drivers/net/wireless/iwlwifi/mvm/mvm.h
+++ b/drivers/net/wireless/iwlwifi/mvm/mvm.h
@@ -586,6 +586,9 @@ int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm);
586/* Utils */ 586/* Utils */
587int iwl_mvm_legacy_rate_to_mac80211_idx(u32 rate_n_flags, 587int iwl_mvm_legacy_rate_to_mac80211_idx(u32 rate_n_flags,
588 enum ieee80211_band band); 588 enum ieee80211_band band);
589void iwl_mvm_hwrate_to_tx_rate(u32 rate_n_flags,
590 enum ieee80211_band band,
591 struct ieee80211_tx_rate *r);
589u8 iwl_mvm_mac80211_idx_to_hwrate(int rate_idx); 592u8 iwl_mvm_mac80211_idx_to_hwrate(int rate_idx);
590void iwl_mvm_dump_nic_error_log(struct iwl_mvm *mvm); 593void iwl_mvm_dump_nic_error_log(struct iwl_mvm *mvm);
591void iwl_mvm_dump_sram(struct iwl_mvm *mvm); 594void iwl_mvm_dump_sram(struct iwl_mvm *mvm);
diff --git a/drivers/net/wireless/iwlwifi/mvm/rs.c b/drivers/net/wireless/iwlwifi/mvm/rs.c
index 8e2bd7a3ff3f..9dfb06515521 100644
--- a/drivers/net/wireless/iwlwifi/mvm/rs.c
+++ b/drivers/net/wireless/iwlwifi/mvm/rs.c
@@ -82,13 +82,24 @@ static const u8 ant_toggle_lookup[] = {
82 [ANT_ABC] = ANT_ABC, 82 [ANT_ABC] = ANT_ABC,
83}; 83};
84 84
85#define IWL_DECLARE_RATE_INFO(r, s, rp, rn) \ 85#define IWL_DECLARE_RATE_INFO(r, s, rp, rn) \
86 [IWL_RATE_##r##M_INDEX] = { IWL_RATE_##r##M_PLCP, \ 86 [IWL_RATE_##r##M_INDEX] = { IWL_RATE_##r##M_PLCP, \
87 IWL_RATE_SISO_##s##M_PLCP, \ 87 IWL_RATE_HT_SISO_MCS_##s##_PLCP, \
88 IWL_RATE_MIMO2_##s##M_PLCP,\ 88 IWL_RATE_HT_MIMO2_MCS_##s##_PLCP, \
89 IWL_RATE_##rp##M_INDEX, \ 89 IWL_RATE_VHT_SISO_MCS_##s##_PLCP, \
90 IWL_RATE_VHT_MIMO2_MCS_##s##_PLCP,\
91 IWL_RATE_##rp##M_INDEX, \
90 IWL_RATE_##rn##M_INDEX } 92 IWL_RATE_##rn##M_INDEX }
91 93
94#define IWL_DECLARE_MCS_RATE(s) \
95 [IWL_RATE_MCS_##s##_INDEX] = { IWL_RATE_INVM_PLCP, \
96 IWL_RATE_HT_SISO_MCS_##s##_PLCP, \
97 IWL_RATE_HT_MIMO2_MCS_##s##_PLCP, \
98 IWL_RATE_VHT_SISO_MCS_##s##_PLCP, \
99 IWL_RATE_VHT_MIMO2_MCS_##s##_PLCP, \
100 IWL_RATE_INVM_INDEX, \
101 IWL_RATE_INVM_INDEX }
102
92/* 103/*
93 * Parameter order: 104 * Parameter order:
94 * rate, ht rate, prev rate, next rate 105 * rate, ht rate, prev rate, next rate
@@ -102,16 +113,17 @@ static const struct iwl_rs_rate_info iwl_rates[IWL_RATE_COUNT] = {
102 IWL_DECLARE_RATE_INFO(2, INV, 1, 5), /* 2mbps */ 113 IWL_DECLARE_RATE_INFO(2, INV, 1, 5), /* 2mbps */
103 IWL_DECLARE_RATE_INFO(5, INV, 2, 11), /*5.5mbps */ 114 IWL_DECLARE_RATE_INFO(5, INV, 2, 11), /*5.5mbps */
104 IWL_DECLARE_RATE_INFO(11, INV, 9, 12), /* 11mbps */ 115 IWL_DECLARE_RATE_INFO(11, INV, 9, 12), /* 11mbps */
105 IWL_DECLARE_RATE_INFO(6, 6, 5, 11), /* 6mbps */ 116 IWL_DECLARE_RATE_INFO(6, 0, 5, 11), /* 6mbps ; MCS 0 */
106 IWL_DECLARE_RATE_INFO(9, 6, 6, 11), /* 9mbps */ 117 IWL_DECLARE_RATE_INFO(9, INV, 6, 11), /* 9mbps */
107 IWL_DECLARE_RATE_INFO(12, 12, 11, 18), /* 12mbps */ 118 IWL_DECLARE_RATE_INFO(12, 1, 11, 18), /* 12mbps ; MCS 1 */
108 IWL_DECLARE_RATE_INFO(18, 18, 12, 24), /* 18mbps */ 119 IWL_DECLARE_RATE_INFO(18, 2, 12, 24), /* 18mbps ; MCS 2 */
109 IWL_DECLARE_RATE_INFO(24, 24, 18, 36), /* 24mbps */ 120 IWL_DECLARE_RATE_INFO(24, 3, 18, 36), /* 24mbps ; MCS 3 */
110 IWL_DECLARE_RATE_INFO(36, 36, 24, 48), /* 36mbps */ 121 IWL_DECLARE_RATE_INFO(36, 4, 24, 48), /* 36mbps ; MCS 4 */
111 IWL_DECLARE_RATE_INFO(48, 48, 36, 54), /* 48mbps */ 122 IWL_DECLARE_RATE_INFO(48, 5, 36, 54), /* 48mbps ; MCS 5 */
112 IWL_DECLARE_RATE_INFO(54, 54, 48, INV), /* 54mbps */ 123 IWL_DECLARE_RATE_INFO(54, 6, 48, INV), /* 54mbps ; MCS 6 */
113 IWL_DECLARE_RATE_INFO(60, 60, 48, INV), /* 60mbps */ 124 IWL_DECLARE_MCS_RATE(7), /* MCS 7 */
114 /* FIXME:RS: ^^ should be INV (legacy) */ 125 IWL_DECLARE_MCS_RATE(8), /* MCS 8 */
126 IWL_DECLARE_MCS_RATE(9), /* MCS 9 */
115}; 127};
116 128
117static inline u8 rs_extract_rate(u32 rate_n_flags) 129static inline u8 rs_extract_rate(u32 rate_n_flags)
@@ -124,26 +136,30 @@ static int iwl_hwrate_to_plcp_idx(u32 rate_n_flags)
124{ 136{
125 int idx = 0; 137 int idx = 0;
126 138
127 /* HT rate format */
128 if (rate_n_flags & RATE_MCS_HT_MSK) { 139 if (rate_n_flags & RATE_MCS_HT_MSK) {
129 idx = rs_extract_rate(rate_n_flags); 140 idx = rate_n_flags & RATE_HT_MCS_RATE_CODE_MSK;
130 141 idx += IWL_RATE_MCS_0_INDEX;
131 WARN_ON_ONCE(idx >= IWL_RATE_MIMO3_6M_PLCP);
132 if (idx >= IWL_RATE_MIMO2_6M_PLCP)
133 idx = idx - IWL_RATE_MIMO2_6M_PLCP;
134 142
135 idx += IWL_FIRST_OFDM_RATE; 143 /* skip 9M not supported in HT*/
136 /* skip 9M not supported in ht*/
137 if (idx >= IWL_RATE_9M_INDEX) 144 if (idx >= IWL_RATE_9M_INDEX)
138 idx += 1; 145 idx += 1;
139 if ((idx >= IWL_FIRST_HT_RATE) && (idx <= IWL_LAST_HT_RATE)) 146 if ((idx >= IWL_FIRST_HT_RATE) && (idx <= IWL_LAST_HT_RATE))
140 return idx; 147 return idx;
148 } else if (rate_n_flags & RATE_MCS_VHT_MSK) {
149 idx = rate_n_flags & RATE_VHT_MCS_RATE_CODE_MSK;
150 idx += IWL_RATE_MCS_0_INDEX;
141 151
142 /* legacy rate format, search for match in table */ 152 /* skip 9M not supported in VHT*/
153 if (idx >= IWL_RATE_9M_INDEX)
154 idx++;
155 if ((idx >= IWL_FIRST_VHT_RATE) && (idx <= IWL_LAST_VHT_RATE))
156 return idx;
143 } else { 157 } else {
158 /* legacy rate format, search for match in table */
159
160 u8 legacy_rate = rs_extract_rate(rate_n_flags);
144 for (idx = 0; idx < ARRAY_SIZE(iwl_rates); idx++) 161 for (idx = 0; idx < ARRAY_SIZE(iwl_rates); idx++)
145 if (iwl_rates[idx].plcp == 162 if (iwl_rates[idx].plcp == legacy_rate)
146 rs_extract_rate(rate_n_flags))
147 return idx; 163 return idx;
148 } 164 }
149 165
@@ -200,6 +216,13 @@ static s32 expected_tpt_siso_40MHz[4][IWL_RATE_COUNT] = {
200 {0, 0, 0, 0, 112, 0, 220, 326, 429, 629, 819, 912, 1000, 1173, 1284}, 216 {0, 0, 0, 0, 112, 0, 220, 326, 429, 629, 819, 912, 1000, 1173, 1284},
201}; 217};
202 218
219static s32 expected_tpt_siso_80MHz[4][IWL_RATE_COUNT] = {
220 {0, 0, 0, 0, 130, 0, 191, 223, 244, 273, 288, 294, 298, 305, 308},
221 {0, 0, 0, 0, 138, 0, 200, 231, 251, 279, 293, 298, 302, 308, 312},
222 {0, 0, 0, 0, 217, 0, 429, 634, 834, 1220, 1585, 1760, 1931, 2258, 2466},
223 {0, 0, 0, 0, 241, 0, 475, 701, 921, 1343, 1741, 1931, 2117, 2468, 2691},
224};
225
203static s32 expected_tpt_mimo2_20MHz[4][IWL_RATE_COUNT] = { 226static s32 expected_tpt_mimo2_20MHz[4][IWL_RATE_COUNT] = {
204 {0, 0, 0, 0, 74, 0, 123, 155, 179, 213, 235, 243, 250, 261, 0}, 227 {0, 0, 0, 0, 74, 0, 123, 155, 179, 213, 235, 243, 250, 261, 0},
205 {0, 0, 0, 0, 81, 0, 131, 164, 187, 221, 242, 250, 256, 267, 0}, 228 {0, 0, 0, 0, 81, 0, 131, 164, 187, 221, 242, 250, 256, 267, 0},
@@ -214,6 +237,13 @@ static s32 expected_tpt_mimo2_40MHz[4][IWL_RATE_COUNT] = {
214 {0, 0, 0, 0, 221, 0, 430, 630, 816, 1169, 1490, 1641, 1784, 2053, 2221}, 237 {0, 0, 0, 0, 221, 0, 430, 630, 816, 1169, 1490, 1641, 1784, 2053, 2221},
215}; 238};
216 239
240static s32 expected_tpt_mimo2_80MHz[4][IWL_RATE_COUNT] = {
241 {0, 0, 0, 0, 182, 0, 240, 264, 278, 299, 308, 311, 313, 317, 319},
242 {0, 0, 0, 0, 190, 0, 247, 269, 282, 302, 310, 313, 315, 319, 320},
243 {0, 0, 0, 0, 428, 0, 833, 1215, 1577, 2254, 2863, 3147, 3418, 3913, 4219},
244 {0, 0, 0, 0, 474, 0, 920, 1338, 1732, 2464, 3116, 3418, 3705, 4225, 4545},
245};
246
217/* mbps, mcs */ 247/* mbps, mcs */
218static const struct iwl_rate_mcs_info iwl_rate_mcs[IWL_RATE_COUNT] = { 248static const struct iwl_rate_mcs_info iwl_rate_mcs[IWL_RATE_COUNT] = {
219 { "1", "BPSK DSSS"}, 249 { "1", "BPSK DSSS"},
@@ -424,42 +454,56 @@ static u32 rate_n_flags_from_tbl(struct iwl_mvm *mvm,
424{ 454{
425 u32 rate_n_flags = 0; 455 u32 rate_n_flags = 0;
426 456
457 rate_n_flags |= ((tbl->ant_type << RATE_MCS_ANT_POS) &
458 RATE_MCS_ANT_ABC_MSK);
459
427 if (is_legacy(tbl->lq_type)) { 460 if (is_legacy(tbl->lq_type)) {
428 rate_n_flags = iwl_rates[index].plcp; 461 rate_n_flags |= iwl_rates[index].plcp;
429 if (index >= IWL_FIRST_CCK_RATE && index <= IWL_LAST_CCK_RATE) 462 if (index >= IWL_FIRST_CCK_RATE && index <= IWL_LAST_CCK_RATE)
430 rate_n_flags |= RATE_MCS_CCK_MSK; 463 rate_n_flags |= RATE_MCS_CCK_MSK;
431 } else if (is_Ht(tbl->lq_type)) { 464 return rate_n_flags;
432 if (index > IWL_LAST_HT_RATE) { 465 }
466
467 if (is_ht(tbl->lq_type)) {
468 if (index < IWL_FIRST_HT_RATE || index > IWL_LAST_HT_RATE) {
433 IWL_ERR(mvm, "Invalid HT rate index %d\n", index); 469 IWL_ERR(mvm, "Invalid HT rate index %d\n", index);
434 index = IWL_LAST_HT_RATE; 470 index = IWL_LAST_HT_RATE;
435 } 471 }
436 rate_n_flags = RATE_MCS_HT_MSK; 472 rate_n_flags |= RATE_MCS_HT_MSK;
437 473
438 if (is_siso(tbl->lq_type)) 474 if (is_ht_siso(tbl->lq_type))
439 rate_n_flags |= iwl_rates[index].plcp_siso; 475 rate_n_flags |= iwl_rates[index].plcp_ht_siso;
440 else if (is_mimo2(tbl->lq_type)) 476 else if (is_ht_mimo2(tbl->lq_type))
441 rate_n_flags |= iwl_rates[index].plcp_mimo2; 477 rate_n_flags |= iwl_rates[index].plcp_ht_mimo2;
442 else 478 else
443 WARN_ON_ONCE(1); 479 WARN_ON_ONCE(1);
480 } else if (is_vht(tbl->lq_type)) {
481 if (index < IWL_FIRST_VHT_RATE || index > IWL_LAST_VHT_RATE) {
482 IWL_ERR(mvm, "Invalid VHT rate index %d\n", index);
483 index = IWL_LAST_VHT_RATE;
484 }
485 rate_n_flags |= RATE_MCS_VHT_MSK;
486 if (is_vht_siso(tbl->lq_type))
487 rate_n_flags |= iwl_rates[index].plcp_vht_siso;
488 else if (is_vht_mimo2(tbl->lq_type))
489 rate_n_flags |= iwl_rates[index].plcp_vht_mimo2;
490 else
491 WARN_ON_ONCE(1);
492
444 } else { 493 } else {
445 IWL_ERR(mvm, "Invalid tbl->lq_type %d\n", tbl->lq_type); 494 IWL_ERR(mvm, "Invalid tbl->lq_type %d\n", tbl->lq_type);
446 } 495 }
447 496
448 rate_n_flags |= ((tbl->ant_type << RATE_MCS_ANT_POS) & 497 rate_n_flags |= tbl->bw;
449 RATE_MCS_ANT_ABC_MSK); 498 if (tbl->is_SGI)
450 499 rate_n_flags |= RATE_MCS_SGI_MSK;
451 if (is_Ht(tbl->lq_type)) { 500
452 if (tbl->is_ht40) 501 /* TODO: remove GF completely ? */
453 rate_n_flags |= RATE_MCS_CHAN_WIDTH_40; 502 if (use_green) {
454 if (tbl->is_SGI) 503 rate_n_flags |= RATE_HT_MCS_GF_MSK;
455 rate_n_flags |= RATE_MCS_SGI_MSK; 504 if (is_ht_siso(tbl->lq_type) && tbl->is_SGI) {
456 505 rate_n_flags &= ~RATE_MCS_SGI_MSK;
457 if (use_green) { 506 IWL_ERR(mvm, "GF was set with SGI:SISO\n");
458 rate_n_flags |= RATE_HT_MCS_GF_MSK;
459 if (is_siso(tbl->lq_type) && tbl->is_SGI) {
460 rate_n_flags &= ~RATE_MCS_SGI_MSK;
461 IWL_ERR(mvm, "GF was set with SGI:SISO\n");
462 }
463 } 507 }
464 } 508 }
465 return rate_n_flags; 509 return rate_n_flags;
@@ -476,7 +520,7 @@ static int rs_get_tbl_info_from_mcs(const u32 rate_n_flags,
476{ 520{
477 u32 ant_msk = (rate_n_flags & RATE_MCS_ANT_ABC_MSK); 521 u32 ant_msk = (rate_n_flags & RATE_MCS_ANT_ABC_MSK);
478 u8 num_of_ant = get_num_of_ant_from_rate(rate_n_flags); 522 u8 num_of_ant = get_num_of_ant_from_rate(rate_n_flags);
479 u8 mcs; 523 u8 nss;
480 524
481 memset(tbl, 0, offsetof(struct iwl_scale_tbl_info, win)); 525 memset(tbl, 0, offsetof(struct iwl_scale_tbl_info, win));
482 *rate_idx = iwl_hwrate_to_plcp_idx(rate_n_flags); 526 *rate_idx = iwl_hwrate_to_plcp_idx(rate_n_flags);
@@ -486,41 +530,62 @@ static int rs_get_tbl_info_from_mcs(const u32 rate_n_flags,
486 return -EINVAL; 530 return -EINVAL;
487 } 531 }
488 tbl->is_SGI = 0; /* default legacy setup */ 532 tbl->is_SGI = 0; /* default legacy setup */
489 tbl->is_ht40 = 0; 533 tbl->bw = 0;
490 tbl->ant_type = (ant_msk >> RATE_MCS_ANT_POS); 534 tbl->ant_type = (ant_msk >> RATE_MCS_ANT_POS);
491 tbl->lq_type = LQ_NONE; 535 tbl->lq_type = LQ_NONE;
492 tbl->max_search = IWL_MAX_SEARCH; 536 tbl->max_search = IWL_MAX_SEARCH;
493 537
494 /* legacy rate format */ 538 /* Legacy */
495 if (!(rate_n_flags & RATE_MCS_HT_MSK)) { 539 if (!(rate_n_flags & RATE_MCS_HT_MSK) &&
540 !(rate_n_flags & RATE_MCS_VHT_MSK)) {
496 if (num_of_ant == 1) { 541 if (num_of_ant == 1) {
497 if (band == IEEE80211_BAND_5GHZ) 542 if (band == IEEE80211_BAND_5GHZ)
498 tbl->lq_type = LQ_A; 543 tbl->lq_type = LQ_LEGACY_A;
499 else 544 else
500 tbl->lq_type = LQ_G; 545 tbl->lq_type = LQ_LEGACY_G;
501 } 546 }
502 /* HT rate format */ 547
503 } else { 548 return 0;
504 if (rate_n_flags & RATE_MCS_SGI_MSK) 549 }
505 tbl->is_SGI = 1; 550
506 551 /* HT or VHT */
507 if (rate_n_flags & RATE_MCS_CHAN_WIDTH_40) /* TODO */ 552 if (rate_n_flags & RATE_MCS_SGI_MSK)
508 tbl->is_ht40 = 1; 553 tbl->is_SGI = 1;
509 554
510 mcs = rs_extract_rate(rate_n_flags); 555 tbl->bw = rate_n_flags & RATE_MCS_CHAN_WIDTH_MSK;
511 556
512 /* SISO */ 557 if (rate_n_flags & RATE_MCS_HT_MSK) {
513 if (mcs <= IWL_RATE_SISO_60M_PLCP) { 558 nss = ((rate_n_flags & RATE_HT_MCS_NSS_MSK) >>
514 if (num_of_ant == 1) 559 RATE_HT_MCS_NSS_POS) + 1;
515 tbl->lq_type = LQ_SISO; /*else NONE*/ 560
516 /* MIMO2 */ 561 if (nss == 1) {
517 } else if (mcs <= IWL_RATE_MIMO2_60M_PLCP) { 562 tbl->lq_type = LQ_HT_SISO;
518 if (num_of_ant == 2) 563 WARN_ON_ONCE(num_of_ant != 1);
519 tbl->lq_type = LQ_MIMO2; 564 } else if (nss == 2) {
565 tbl->lq_type = LQ_HT_MIMO2;
566 WARN_ON_ONCE(num_of_ant != 2);
520 } else { 567 } else {
521 WARN_ON_ONCE(num_of_ant == 3); 568 WARN_ON_ONCE(1);
569 }
570 } else if (rate_n_flags & RATE_MCS_VHT_MSK) {
571 nss = ((rate_n_flags & RATE_VHT_MCS_NSS_MSK) >>
572 RATE_VHT_MCS_NSS_POS) + 1;
573
574 if (nss == 1) {
575 tbl->lq_type = LQ_VHT_SISO;
576 WARN_ON_ONCE(num_of_ant != 1);
577 } else if (nss == 2) {
578 tbl->lq_type = LQ_VHT_MIMO2;
579 WARN_ON_ONCE(num_of_ant != 2);
580 } else {
581 WARN_ON_ONCE(1);
522 } 582 }
523 } 583 }
584
585 WARN_ON_ONCE(tbl->bw == RATE_MCS_CHAN_WIDTH_160);
586 WARN_ON_ONCE(tbl->bw == RATE_MCS_CHAN_WIDTH_80 &&
587 !is_vht(tbl->lq_type));
588
524 return 0; 589 return 0;
525} 590}
526 591
@@ -579,16 +644,15 @@ static u16 rs_get_supported_rates(struct iwl_lq_sta *lq_sta,
579 struct ieee80211_hdr *hdr, 644 struct ieee80211_hdr *hdr,
580 enum iwl_table_type rate_type) 645 enum iwl_table_type rate_type)
581{ 646{
582 if (is_legacy(rate_type)) { 647 if (is_legacy(rate_type))
583 return lq_sta->active_legacy_rate; 648 return lq_sta->active_legacy_rate;
584 } else { 649 else if (is_siso(rate_type))
585 if (is_siso(rate_type)) 650 return lq_sta->active_siso_rate;
586 return lq_sta->active_siso_rate; 651 else if (is_mimo2(rate_type))
587 else { 652 return lq_sta->active_mimo2_rate;
588 WARN_ON_ONCE(!is_mimo2(rate_type)); 653
589 return lq_sta->active_mimo2_rate; 654 WARN_ON_ONCE(1);
590 } 655 return 0;
591 }
592} 656}
593 657
594static u16 rs_get_adjacent_rate(struct iwl_mvm *mvm, u8 index, u16 rate_mask, 658static u16 rs_get_adjacent_rate(struct iwl_mvm *mvm, u8 index, u16 rate_mask,
@@ -665,15 +729,15 @@ static u32 rs_get_lower_rate(struct iwl_lq_sta *lq_sta,
665 switch_to_legacy = 1; 729 switch_to_legacy = 1;
666 scale_index = rs_ht_to_legacy[scale_index]; 730 scale_index = rs_ht_to_legacy[scale_index];
667 if (lq_sta->band == IEEE80211_BAND_5GHZ) 731 if (lq_sta->band == IEEE80211_BAND_5GHZ)
668 tbl->lq_type = LQ_A; 732 tbl->lq_type = LQ_LEGACY_A;
669 else 733 else
670 tbl->lq_type = LQ_G; 734 tbl->lq_type = LQ_LEGACY_G;
671 735
672 if (num_of_ant(tbl->ant_type) > 1) 736 if (num_of_ant(tbl->ant_type) > 1)
673 tbl->ant_type = 737 tbl->ant_type =
674 first_antenna(iwl_fw_valid_tx_ant(mvm->fw)); 738 first_antenna(iwl_fw_valid_tx_ant(mvm->fw));
675 739
676 tbl->is_ht40 = 0; 740 tbl->bw = 0;
677 tbl->is_SGI = 0; 741 tbl->is_SGI = 0;
678 tbl->max_search = IWL_MAX_SEARCH; 742 tbl->max_search = IWL_MAX_SEARCH;
679 } 743 }
@@ -717,6 +781,18 @@ static bool table_type_matches(struct iwl_scale_tbl_info *a,
717 (a->is_SGI == b->is_SGI); 781 (a->is_SGI == b->is_SGI);
718} 782}
719 783
784static u32 rs_ch_width_from_mac_flags(enum mac80211_rate_control_flags flags)
785{
786 if (flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
787 return RATE_MCS_CHAN_WIDTH_40;
788 else if (flags & IEEE80211_TX_RC_80_MHZ_WIDTH)
789 return RATE_MCS_CHAN_WIDTH_80;
790 else if (flags & IEEE80211_TX_RC_160_MHZ_WIDTH)
791 return RATE_MCS_CHAN_WIDTH_160;
792
793 return RATE_MCS_CHAN_WIDTH_20;
794}
795
720/* 796/*
721 * mac80211 sends us Tx status 797 * mac80211 sends us Tx status
722 */ 798 */
@@ -786,16 +862,23 @@ static void rs_tx_status(void *mvm_r, struct ieee80211_supported_band *sband,
786 */ 862 */
787 if (info->band == IEEE80211_BAND_2GHZ) 863 if (info->band == IEEE80211_BAND_2GHZ)
788 mac_index += IWL_FIRST_OFDM_RATE; 864 mac_index += IWL_FIRST_OFDM_RATE;
865 } else if (mac_flags & IEEE80211_TX_RC_VHT_MCS) {
866 mac_index &= RATE_VHT_MCS_RATE_CODE_MSK;
867 if (mac_index >= (IWL_RATE_9M_INDEX - IWL_FIRST_OFDM_RATE))
868 mac_index++;
789 } 869 }
870
790 /* Here we actually compare this rate to the latest LQ command */ 871 /* Here we actually compare this rate to the latest LQ command */
791 if ((mac_index < 0) || 872 if ((mac_index < 0) ||
792 (tbl_type.is_SGI != !!(mac_flags & IEEE80211_TX_RC_SHORT_GI)) || 873 (tbl_type.is_SGI != !!(mac_flags & IEEE80211_TX_RC_SHORT_GI)) ||
793 (tbl_type.is_ht40 != !!(mac_flags & IEEE80211_TX_RC_40_MHZ_WIDTH)) || 874 (tbl_type.bw != rs_ch_width_from_mac_flags(mac_flags)) ||
794 (tbl_type.ant_type != info->status.antenna) || 875 (tbl_type.ant_type != info->status.antenna) ||
795 (!!(tx_rate & RATE_MCS_HT_MSK) != 876 (!!(tx_rate & RATE_MCS_HT_MSK) !=
796 !!(mac_flags & IEEE80211_TX_RC_MCS)) || 877 !!(mac_flags & IEEE80211_TX_RC_MCS)) ||
878 (!!(tx_rate & RATE_MCS_VHT_MSK) !=
879 !!(mac_flags & IEEE80211_TX_RC_VHT_MCS)) ||
797 (!!(tx_rate & RATE_HT_MCS_GF_MSK) != 880 (!!(tx_rate & RATE_HT_MCS_GF_MSK) !=
798 !!(mac_flags & IEEE80211_TX_RC_GREEN_FIELD)) || 881 !!(mac_flags & IEEE80211_TX_RC_GREEN_FIELD)) ||
799 (rs_index != mac_index)) { 882 (rs_index != mac_index)) {
800 IWL_DEBUG_RATE(mvm, 883 IWL_DEBUG_RATE(mvm,
801 "initial rate %d does not match %d (0x%x)\n", 884 "initial rate %d does not match %d (0x%x)\n",
@@ -950,7 +1033,8 @@ static void rs_set_expected_tpt_table(struct iwl_lq_sta *lq_sta,
950 s32 (*ht_tbl_pointer)[IWL_RATE_COUNT]; 1033 s32 (*ht_tbl_pointer)[IWL_RATE_COUNT];
951 1034
952 /* Check for invalid LQ type */ 1035 /* Check for invalid LQ type */
953 if (WARN_ON_ONCE(!is_legacy(tbl->lq_type) && !is_Ht(tbl->lq_type))) { 1036 if (WARN_ON_ONCE(!is_legacy(tbl->lq_type) && !is_ht(tbl->lq_type) &&
1037 !(is_vht(tbl->lq_type)))) {
954 tbl->expected_tpt = expected_tpt_legacy; 1038 tbl->expected_tpt = expected_tpt_legacy;
955 return; 1039 return;
956 } 1040 }
@@ -961,18 +1045,40 @@ static void rs_set_expected_tpt_table(struct iwl_lq_sta *lq_sta,
961 return; 1045 return;
962 } 1046 }
963 1047
1048 ht_tbl_pointer = expected_tpt_mimo2_20MHz;
964 /* Choose among many HT tables depending on number of streams 1049 /* Choose among many HT tables depending on number of streams
965 * (SISO/MIMO2), channel width (20/40), SGI, and aggregation 1050 * (SISO/MIMO2), channel width (20/40/80), SGI, and aggregation
966 * status */ 1051 * status */
967 if (is_siso(tbl->lq_type) && !tbl->is_ht40) 1052 if (is_siso(tbl->lq_type)) {
968 ht_tbl_pointer = expected_tpt_siso_20MHz; 1053 switch (tbl->bw) {
969 else if (is_siso(tbl->lq_type)) 1054 case RATE_MCS_CHAN_WIDTH_20:
970 ht_tbl_pointer = expected_tpt_siso_40MHz; 1055 ht_tbl_pointer = expected_tpt_siso_20MHz;
971 else if (is_mimo2(tbl->lq_type) && !tbl->is_ht40) 1056 break;
972 ht_tbl_pointer = expected_tpt_mimo2_20MHz; 1057 case RATE_MCS_CHAN_WIDTH_40:
973 else { 1058 ht_tbl_pointer = expected_tpt_siso_40MHz;
974 WARN_ON_ONCE(!is_mimo2(tbl->lq_type)); 1059 break;
975 ht_tbl_pointer = expected_tpt_mimo2_40MHz; 1060 case RATE_MCS_CHAN_WIDTH_80:
1061 ht_tbl_pointer = expected_tpt_siso_80MHz;
1062 break;
1063 default:
1064 WARN_ON_ONCE(1);
1065 }
1066 } else if (is_mimo2(tbl->lq_type)) {
1067 switch (tbl->bw) {
1068 case RATE_MCS_CHAN_WIDTH_20:
1069 ht_tbl_pointer = expected_tpt_mimo2_20MHz;
1070 break;
1071 case RATE_MCS_CHAN_WIDTH_40:
1072 ht_tbl_pointer = expected_tpt_mimo2_40MHz;
1073 break;
1074 case RATE_MCS_CHAN_WIDTH_80:
1075 ht_tbl_pointer = expected_tpt_mimo2_80MHz;
1076 break;
1077 default:
1078 WARN_ON_ONCE(1);
1079 }
1080 } else {
1081 WARN_ON_ONCE(1);
976 } 1082 }
977 1083
978 if (!tbl->is_SGI && !lq_sta->is_agg) /* Normal */ 1084 if (!tbl->is_SGI && !lq_sta->is_agg) /* Normal */
@@ -1087,11 +1193,6 @@ static s32 rs_get_best_rate(struct iwl_mvm *mvm,
1087 return new_rate; 1193 return new_rate;
1088} 1194}
1089 1195
1090static bool iwl_is_ht40_tx_allowed(struct ieee80211_sta *sta)
1091{
1092 return sta->bandwidth >= IEEE80211_STA_RX_BW_40;
1093}
1094
1095/* Move to the next action and wrap around to the first action in case 1196/* Move to the next action and wrap around to the first action in case
1096 * we're at the last action. Assumes actions start at 0. 1197 * we're at the last action. Assumes actions start at 0.
1097 */ 1198 */
@@ -1105,6 +1206,36 @@ static inline void rs_move_next_action(struct iwl_scale_tbl_info *tbl,
1105 tbl->action = (tbl->action + 1) % (last_action + 1); 1206 tbl->action = (tbl->action + 1) % (last_action + 1);
1106} 1207}
1107 1208
1209static void rs_set_bw_from_sta(struct iwl_scale_tbl_info *tbl,
1210 struct ieee80211_sta *sta)
1211{
1212 if (sta->bandwidth >= IEEE80211_STA_RX_BW_80)
1213 tbl->bw = RATE_MCS_CHAN_WIDTH_80;
1214 else if (sta->bandwidth >= IEEE80211_STA_RX_BW_40)
1215 tbl->bw = RATE_MCS_CHAN_WIDTH_40;
1216 else
1217 tbl->bw = RATE_MCS_CHAN_WIDTH_20;
1218}
1219
1220static bool rs_sgi_allowed(struct iwl_scale_tbl_info *tbl,
1221 struct ieee80211_sta *sta)
1222{
1223 struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap;
1224 struct ieee80211_sta_vht_cap *vht_cap = &sta->vht_cap;
1225
1226 if (is_ht20(tbl) && (ht_cap->cap &
1227 IEEE80211_HT_CAP_SGI_20))
1228 return true;
1229 if (is_ht40(tbl) && (ht_cap->cap &
1230 IEEE80211_HT_CAP_SGI_40))
1231 return true;
1232 if (is_ht80(tbl) && (vht_cap->cap &
1233 IEEE80211_VHT_CAP_SHORT_GI_80))
1234 return true;
1235
1236 return false;
1237}
1238
1108/* 1239/*
1109 * Set up search table for MIMO2 1240 * Set up search table for MIMO2
1110 */ 1241 */
@@ -1129,16 +1260,12 @@ static int rs_switch_to_mimo2(struct iwl_mvm *mvm,
1129 1260
1130 IWL_DEBUG_RATE(mvm, "LQ: try to switch to MIMO2\n"); 1261 IWL_DEBUG_RATE(mvm, "LQ: try to switch to MIMO2\n");
1131 1262
1132 tbl->lq_type = LQ_MIMO2; 1263 tbl->lq_type = lq_sta->is_vht ? LQ_VHT_MIMO2 : LQ_HT_MIMO2;
1133 tbl->action = 0; 1264 tbl->action = 0;
1134 tbl->max_search = IWL_MAX_SEARCH; 1265 tbl->max_search = IWL_MAX_SEARCH;
1135 rate_mask = lq_sta->active_mimo2_rate; 1266 rate_mask = lq_sta->active_mimo2_rate;
1136 1267
1137 if (iwl_is_ht40_tx_allowed(sta)) 1268 rs_set_bw_from_sta(tbl, sta);
1138 tbl->is_ht40 = 1;
1139 else
1140 tbl->is_ht40 = 0;
1141
1142 rs_set_expected_tpt_table(lq_sta, tbl); 1269 rs_set_expected_tpt_table(lq_sta, tbl);
1143 1270
1144 rate = rs_get_best_rate(mvm, lq_sta, tbl, rate_mask, index); 1271 rate = rs_get_best_rate(mvm, lq_sta, tbl, rate_mask, index);
@@ -1174,19 +1301,15 @@ static int rs_switch_to_siso(struct iwl_mvm *mvm,
1174 1301
1175 IWL_DEBUG_RATE(mvm, "LQ: try to switch to SISO\n"); 1302 IWL_DEBUG_RATE(mvm, "LQ: try to switch to SISO\n");
1176 1303
1177 tbl->lq_type = LQ_SISO; 1304 tbl->lq_type = lq_sta->is_vht ? LQ_VHT_SISO : LQ_HT_SISO;
1178 tbl->action = 0; 1305 tbl->action = 0;
1179 tbl->max_search = IWL_MAX_SEARCH; 1306 tbl->max_search = IWL_MAX_SEARCH;
1180 rate_mask = lq_sta->active_siso_rate; 1307 rate_mask = lq_sta->active_siso_rate;
1181 1308
1182 if (iwl_is_ht40_tx_allowed(sta))
1183 tbl->is_ht40 = 1;
1184 else
1185 tbl->is_ht40 = 0;
1186
1187 if (is_green) 1309 if (is_green)
1188 tbl->is_SGI = 0; /*11n spec: no SGI in SISO+Greenfield*/ 1310 tbl->is_SGI = 0; /*11n spec: no SGI in SISO+Greenfield*/
1189 1311
1312 rs_set_bw_from_sta(tbl, sta);
1190 rs_set_expected_tpt_table(lq_sta, tbl); 1313 rs_set_expected_tpt_table(lq_sta, tbl);
1191 rate = rs_get_best_rate(mvm, lq_sta, tbl, rate_mask, index); 1314 rate = rs_get_best_rate(mvm, lq_sta, tbl, rate_mask, index);
1192 1315
@@ -1313,7 +1436,6 @@ static int rs_move_siso_to_other(struct iwl_mvm *mvm,
1313 struct iwl_scale_tbl_info *search_tbl = 1436 struct iwl_scale_tbl_info *search_tbl =
1314 &(lq_sta->lq_info[(1 - lq_sta->active_tbl)]); 1437 &(lq_sta->lq_info[(1 - lq_sta->active_tbl)]);
1315 struct iwl_rate_scale_data *window = &(tbl->win[index]); 1438 struct iwl_rate_scale_data *window = &(tbl->win[index]);
1316 struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap;
1317 u32 sz = (sizeof(struct iwl_scale_tbl_info) - 1439 u32 sz = (sizeof(struct iwl_scale_tbl_info) -
1318 (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT)); 1440 (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT));
1319 u8 start_action; 1441 u8 start_action;
@@ -1385,11 +1507,7 @@ static int rs_move_siso_to_other(struct iwl_mvm *mvm,
1385 goto out; 1507 goto out;
1386 break; 1508 break;
1387 case IWL_SISO_SWITCH_GI: 1509 case IWL_SISO_SWITCH_GI:
1388 if (!tbl->is_ht40 && !(ht_cap->cap & 1510 if (!rs_sgi_allowed(tbl, sta))
1389 IEEE80211_HT_CAP_SGI_20))
1390 break;
1391 if (tbl->is_ht40 && !(ht_cap->cap &
1392 IEEE80211_HT_CAP_SGI_40))
1393 break; 1511 break;
1394 1512
1395 IWL_DEBUG_RATE(mvm, "LQ: SISO toggle SGI/NGI\n"); 1513 IWL_DEBUG_RATE(mvm, "LQ: SISO toggle SGI/NGI\n");
@@ -1445,7 +1563,6 @@ static int rs_move_mimo2_to_other(struct iwl_mvm *mvm,
1445 struct iwl_scale_tbl_info *tbl = &(lq_sta->lq_info[lq_sta->active_tbl]); 1563 struct iwl_scale_tbl_info *tbl = &(lq_sta->lq_info[lq_sta->active_tbl]);
1446 struct iwl_scale_tbl_info *search_tbl = 1564 struct iwl_scale_tbl_info *search_tbl =
1447 &(lq_sta->lq_info[(1 - lq_sta->active_tbl)]); 1565 &(lq_sta->lq_info[(1 - lq_sta->active_tbl)]);
1448 struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap;
1449 u32 sz = (sizeof(struct iwl_scale_tbl_info) - 1566 u32 sz = (sizeof(struct iwl_scale_tbl_info) -
1450 (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT)); 1567 (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT));
1451 u8 start_action; 1568 u8 start_action;
@@ -1502,11 +1619,7 @@ static int rs_move_mimo2_to_other(struct iwl_mvm *mvm,
1502 break; 1619 break;
1503 1620
1504 case IWL_MIMO2_SWITCH_GI: 1621 case IWL_MIMO2_SWITCH_GI:
1505 if (!tbl->is_ht40 && !(ht_cap->cap & 1622 if (!rs_sgi_allowed(tbl, sta))
1506 IEEE80211_HT_CAP_SGI_20))
1507 break;
1508 if (tbl->is_ht40 && !(ht_cap->cap &
1509 IEEE80211_HT_CAP_SGI_40))
1510 break; 1623 break;
1511 1624
1512 IWL_DEBUG_RATE(mvm, "LQ: MIMO2 toggle SGI/NGI\n"); 1625 IWL_DEBUG_RATE(mvm, "LQ: MIMO2 toggle SGI/NGI\n");
@@ -2167,7 +2280,6 @@ static void rs_get_rate(void *mvm_r, struct ieee80211_sta *sta, void *mvm_sta,
2167 struct iwl_mvm *mvm __maybe_unused = IWL_OP_MODE_GET_MVM(op_mode); 2280 struct iwl_mvm *mvm __maybe_unused = IWL_OP_MODE_GET_MVM(op_mode);
2168 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); 2281 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
2169 struct iwl_lq_sta *lq_sta = mvm_sta; 2282 struct iwl_lq_sta *lq_sta = mvm_sta;
2170 int rate_idx;
2171 2283
2172 IWL_DEBUG_RATE_LIMIT(mvm, "rate scale calculate new rate for skb\n"); 2284 IWL_DEBUG_RATE_LIMIT(mvm, "rate scale calculate new rate for skb\n");
2173 2285
@@ -2192,36 +2304,9 @@ static void rs_get_rate(void *mvm_r, struct ieee80211_sta *sta, void *mvm_sta,
2192 if (rate_control_send_low(sta, mvm_sta, txrc)) 2304 if (rate_control_send_low(sta, mvm_sta, txrc))
2193 return; 2305 return;
2194 2306
2195 rate_idx = lq_sta->last_txrate_idx; 2307 iwl_mvm_hwrate_to_tx_rate(lq_sta->last_rate_n_flags,
2196 2308 info->band, &info->control.rates[0]);
2197 if (lq_sta->last_rate_n_flags & RATE_MCS_HT_MSK) { 2309
2198 rate_idx -= IWL_FIRST_OFDM_RATE;
2199 /* 6M and 9M shared same MCS index */
2200 rate_idx = (rate_idx > 0) ? (rate_idx - 1) : 0;
2201 WARN_ON_ONCE(rs_extract_rate(lq_sta->last_rate_n_flags) >=
2202 IWL_RATE_MIMO3_6M_PLCP);
2203 if (rs_extract_rate(lq_sta->last_rate_n_flags) >=
2204 IWL_RATE_MIMO2_6M_PLCP)
2205 rate_idx = rate_idx + MCS_INDEX_PER_STREAM;
2206 info->control.rates[0].flags = IEEE80211_TX_RC_MCS;
2207 if (lq_sta->last_rate_n_flags & RATE_MCS_SGI_MSK)
2208 info->control.rates[0].flags |= IEEE80211_TX_RC_SHORT_GI;
2209 if (lq_sta->last_rate_n_flags & RATE_MCS_CHAN_WIDTH_40) /* TODO */
2210 info->control.rates[0].flags |= IEEE80211_TX_RC_40_MHZ_WIDTH;
2211 if (lq_sta->last_rate_n_flags & RATE_HT_MCS_GF_MSK)
2212 info->control.rates[0].flags |= IEEE80211_TX_RC_GREEN_FIELD;
2213 } else {
2214 /* Check for invalid rates */
2215 if ((rate_idx < 0) || (rate_idx >= IWL_RATE_COUNT_LEGACY) ||
2216 ((sband->band == IEEE80211_BAND_5GHZ) &&
2217 (rate_idx < IWL_FIRST_OFDM_RATE)))
2218 rate_idx = rate_lowest_index(sband, sta);
2219 /* On valid 5 GHz rate, adjust index */
2220 else if (sband->band == IEEE80211_BAND_5GHZ)
2221 rate_idx -= IWL_FIRST_OFDM_RATE;
2222 info->control.rates[0].flags = 0;
2223 }
2224 info->control.rates[0].idx = rate_idx;
2225 info->control.rates[0].count = 1; 2310 info->control.rates[0].count = 1;
2226} 2311}
2227 2312
@@ -2238,6 +2323,24 @@ static void *rs_alloc_sta(void *mvm_rate, struct ieee80211_sta *sta,
2238 return &sta_priv->lq_sta; 2323 return &sta_priv->lq_sta;
2239} 2324}
2240 2325
2326static int rs_vht_highest_rx_mcs_index(struct ieee80211_sta_vht_cap *vht_cap,
2327 int nss)
2328{
2329 u16 rx_mcs = le16_to_cpu(vht_cap->vht_mcs.rx_mcs_map) &
2330 (0x3 << (2 * (nss - 1)));
2331 rx_mcs >>= (2 * (nss - 1));
2332
2333 if (rx_mcs == IEEE80211_VHT_MCS_SUPPORT_0_7)
2334 return IWL_RATE_MCS_7_INDEX;
2335 else if (rx_mcs == IEEE80211_VHT_MCS_SUPPORT_0_8)
2336 return IWL_RATE_MCS_8_INDEX;
2337 else if (rx_mcs == IEEE80211_VHT_MCS_SUPPORT_0_9)
2338 return IWL_RATE_MCS_9_INDEX;
2339
2340 WARN_ON_ONCE(rx_mcs != IEEE80211_VHT_MCS_NOT_SUPPORTED);
2341 return -1;
2342}
2343
2241/* 2344/*
2242 * Called after adding a new station to initialize rate scaling 2345 * Called after adding a new station to initialize rate scaling
2243 */ 2346 */
@@ -2247,6 +2350,7 @@ void iwl_mvm_rs_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
2247 int i, j; 2350 int i, j;
2248 struct ieee80211_hw *hw = mvm->hw; 2351 struct ieee80211_hw *hw = mvm->hw;
2249 struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap; 2352 struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap;
2353 struct ieee80211_sta_vht_cap *vht_cap = &sta->vht_cap;
2250 struct iwl_mvm_sta *sta_priv; 2354 struct iwl_mvm_sta *sta_priv;
2251 struct iwl_lq_sta *lq_sta; 2355 struct iwl_lq_sta *lq_sta;
2252 struct ieee80211_supported_band *sband; 2356 struct ieee80211_supported_band *sband;
@@ -2285,25 +2389,54 @@ void iwl_mvm_rs_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
2285 for_each_set_bit(i, &supp, BITS_PER_LONG) 2389 for_each_set_bit(i, &supp, BITS_PER_LONG)
2286 lq_sta->active_legacy_rate |= BIT(sband->bitrates[i].hw_value); 2390 lq_sta->active_legacy_rate |= BIT(sband->bitrates[i].hw_value);
2287 2391
2288 /* 2392 /* TODO: should probably account for rx_highest for both HT/VHT */
2289 * active_siso_rate mask includes 9 MBits (bit 5), and CCK (bits 0-3), 2393 if (!vht_cap || !vht_cap->vht_supported) {
2290 * supp_rates[] does not; shift to convert format, force 9 MBits off. 2394 /* active_siso_rate mask includes 9 MBits (bit 5),
2291 */ 2395 * and CCK (bits 0-3), supp_rates[] does not;
2292 lq_sta->active_siso_rate = ht_cap->mcs.rx_mask[0] << 1; 2396 * shift to convert format, force 9 MBits off.
2293 lq_sta->active_siso_rate |= ht_cap->mcs.rx_mask[0] & 0x1; 2397 */
2294 lq_sta->active_siso_rate &= ~((u16)0x2); 2398 lq_sta->active_siso_rate = ht_cap->mcs.rx_mask[0] << 1;
2295 lq_sta->active_siso_rate <<= IWL_FIRST_OFDM_RATE; 2399 lq_sta->active_siso_rate |= ht_cap->mcs.rx_mask[0] & 0x1;
2400 lq_sta->active_siso_rate &= ~((u16)0x2);
2401 lq_sta->active_siso_rate <<= IWL_FIRST_OFDM_RATE;
2402
2403 /* Same here */
2404 lq_sta->active_mimo2_rate = ht_cap->mcs.rx_mask[1] << 1;
2405 lq_sta->active_mimo2_rate |= ht_cap->mcs.rx_mask[1] & 0x1;
2406 lq_sta->active_mimo2_rate &= ~((u16)0x2);
2407 lq_sta->active_mimo2_rate <<= IWL_FIRST_OFDM_RATE;
2408
2409 lq_sta->is_vht = false;
2410 } else {
2411 int highest_mcs = rs_vht_highest_rx_mcs_index(vht_cap, 1);
2412 if (highest_mcs >= IWL_RATE_MCS_0_INDEX) {
2413 for (i = IWL_RATE_MCS_0_INDEX; i <= highest_mcs; i++) {
2414 if (i == IWL_RATE_9M_INDEX)
2415 continue;
2416
2417 lq_sta->active_siso_rate |= BIT(i);
2418 }
2419 }
2296 2420
2297 /* Same here */ 2421 highest_mcs = rs_vht_highest_rx_mcs_index(vht_cap, 2);
2298 lq_sta->active_mimo2_rate = ht_cap->mcs.rx_mask[1] << 1; 2422 if (highest_mcs >= IWL_RATE_MCS_0_INDEX) {
2299 lq_sta->active_mimo2_rate |= ht_cap->mcs.rx_mask[1] & 0x1; 2423 for (i = IWL_RATE_MCS_0_INDEX; i <= highest_mcs; i++) {
2300 lq_sta->active_mimo2_rate &= ~((u16)0x2); 2424 if (i == IWL_RATE_9M_INDEX)
2301 lq_sta->active_mimo2_rate <<= IWL_FIRST_OFDM_RATE; 2425 continue;
2426
2427 lq_sta->active_mimo2_rate |= BIT(i);
2428 }
2429 }
2430
2431 /* TODO: avoid MCS9 in 20Mhz which isn't valid for 11ac */
2432 lq_sta->is_vht = true;
2433 }
2302 2434
2303 IWL_DEBUG_RATE(mvm, 2435 IWL_DEBUG_RATE(mvm,
2304 "SISO-RATE=%X MIMO2-RATE=%X\n", 2436 "SISO-RATE=%X MIMO2-RATE=%X VHT=%d\n",
2305 lq_sta->active_siso_rate, 2437 lq_sta->active_siso_rate,
2306 lq_sta->active_mimo2_rate); 2438 lq_sta->active_mimo2_rate,
2439 lq_sta->is_vht);
2307 2440
2308 /* These values will be overridden later */ 2441 /* These values will be overridden later */
2309 lq_sta->lq.single_stream_ant_msk = 2442 lq_sta->lq.single_stream_ant_msk =
@@ -2406,7 +2539,6 @@ static void rs_fill_link_cmd(struct iwl_mvm *mvm,
2406 rs_get_tbl_info_from_mcs(new_rate, lq_sta->band, &tbl_type, 2539 rs_get_tbl_info_from_mcs(new_rate, lq_sta->band, &tbl_type,
2407 &rate_idx); 2540 &rate_idx);
2408 2541
2409
2410 /* Indicate to uCode which entries might be MIMO. 2542 /* Indicate to uCode which entries might be MIMO.
2411 * If initial rate was MIMO, this will finally end up 2543 * If initial rate was MIMO, this will finally end up
2412 * as (IWL_HT_NUMBER_TRY * 2), after 2nd pass, otherwise 0. */ 2544 * as (IWL_HT_NUMBER_TRY * 2), after 2nd pass, otherwise 0. */
@@ -2432,7 +2564,9 @@ static void rs_fill_link_cmd(struct iwl_mvm *mvm,
2432 } 2564 }
2433 2565
2434 /* Don't allow HT rates after next pass. 2566 /* Don't allow HT rates after next pass.
2435 * rs_get_lower_rate() will change type to LQ_A or LQ_G. */ 2567 * rs_get_lower_rate() will change type to LQ_LEGACY_A
2568 * or LQ_LEGACY_G.
2569 */
2436 use_ht_possible = 0; 2570 use_ht_possible = 0;
2437 2571
2438 /* Override next rate if needed for debug purposes */ 2572 /* Override next rate if needed for debug purposes */
@@ -2563,12 +2697,15 @@ static ssize_t rs_sta_dbgfs_scale_table_read(struct file *file,
2563 (iwl_fw_valid_tx_ant(mvm->fw) & ANT_B) ? "ANT_B," : "", 2697 (iwl_fw_valid_tx_ant(mvm->fw) & ANT_B) ? "ANT_B," : "",
2564 (iwl_fw_valid_tx_ant(mvm->fw) & ANT_C) ? "ANT_C" : ""); 2698 (iwl_fw_valid_tx_ant(mvm->fw) & ANT_C) ? "ANT_C" : "");
2565 desc += sprintf(buff+desc, "lq type %s\n", 2699 desc += sprintf(buff+desc, "lq type %s\n",
2566 (is_legacy(tbl->lq_type)) ? "legacy" : "HT"); 2700 (is_legacy(tbl->lq_type)) ? "legacy" :
2567 if (is_Ht(tbl->lq_type)) { 2701 is_vht(tbl->lq_type) ? "VHT" : "HT");
2702 if (is_ht(tbl->lq_type)) {
2568 desc += sprintf(buff+desc, " %s", 2703 desc += sprintf(buff+desc, " %s",
2569 (is_siso(tbl->lq_type)) ? "SISO" : "MIMO2"); 2704 (is_siso(tbl->lq_type)) ? "SISO" : "MIMO2");
2570 desc += sprintf(buff+desc, " %s", 2705 desc += sprintf(buff+desc, " %s",
2571 (tbl->is_ht40) ? "40MHz" : "20MHz"); 2706 (is_ht20(tbl)) ? "20MHz" :
2707 (is_ht40(tbl)) ? "40MHz" :
2708 (is_ht80(tbl)) ? "80Mhz" : "BAD BW");
2572 desc += sprintf(buff+desc, " %s %s %s\n", 2709 desc += sprintf(buff+desc, " %s %s %s\n",
2573 (tbl->is_SGI) ? "SGI" : "", 2710 (tbl->is_SGI) ? "SGI" : "",
2574 (lq_sta->is_green) ? "GF enabled" : "", 2711 (lq_sta->is_green) ? "GF enabled" : "",
@@ -2630,7 +2767,7 @@ static ssize_t rs_sta_dbgfs_stats_table_read(struct file *file,
2630 int desc = 0; 2767 int desc = 0;
2631 int i, j; 2768 int i, j;
2632 ssize_t ret; 2769 ssize_t ret;
2633 2770 struct iwl_scale_tbl_info *tbl;
2634 struct iwl_lq_sta *lq_sta = file->private_data; 2771 struct iwl_lq_sta *lq_sta = file->private_data;
2635 2772
2636 buff = kmalloc(1024, GFP_KERNEL); 2773 buff = kmalloc(1024, GFP_KERNEL);
@@ -2638,21 +2775,24 @@ static ssize_t rs_sta_dbgfs_stats_table_read(struct file *file,
2638 return -ENOMEM; 2775 return -ENOMEM;
2639 2776
2640 for (i = 0; i < LQ_SIZE; i++) { 2777 for (i = 0; i < LQ_SIZE; i++) {
2778 tbl = &(lq_sta->lq_info[i]);
2641 desc += sprintf(buff+desc, 2779 desc += sprintf(buff+desc,
2642 "%s type=%d SGI=%d HT40=%d DUP=0 GF=%d\n" 2780 "%s type=%d SGI=%d BW=%s DUP=0 GF=%d\n"
2643 "rate=0x%X\n", 2781 "rate=0x%X\n",
2644 lq_sta->active_tbl == i ? "*" : "x", 2782 lq_sta->active_tbl == i ? "*" : "x",
2645 lq_sta->lq_info[i].lq_type, 2783 tbl->lq_type,
2646 lq_sta->lq_info[i].is_SGI, 2784 tbl->is_SGI,
2647 lq_sta->lq_info[i].is_ht40, 2785 is_ht20(tbl) ? "20Mhz" :
2786 is_ht40(tbl) ? "40Mhz" :
2787 is_ht80(tbl) ? "80Mhz" : "ERR",
2648 lq_sta->is_green, 2788 lq_sta->is_green,
2649 lq_sta->lq_info[i].current_rate); 2789 tbl->current_rate);
2650 for (j = 0; j < IWL_RATE_COUNT; j++) { 2790 for (j = 0; j < IWL_RATE_COUNT; j++) {
2651 desc += sprintf(buff+desc, 2791 desc += sprintf(buff+desc,
2652 "counter=%d success=%d %%=%d\n", 2792 "counter=%d success=%d %%=%d\n",
2653 lq_sta->lq_info[i].win[j].counter, 2793 tbl->win[j].counter,
2654 lq_sta->lq_info[i].win[j].success_counter, 2794 tbl->win[j].success_counter,
2655 lq_sta->lq_info[i].win[j].success_ratio); 2795 tbl->win[j].success_ratio);
2656 } 2796 }
2657 } 2797 }
2658 ret = simple_read_from_buffer(user_buf, count, ppos, buff, desc); 2798 ret = simple_read_from_buffer(user_buf, count, ppos, buff, desc);
diff --git a/drivers/net/wireless/iwlwifi/mvm/rs.h b/drivers/net/wireless/iwlwifi/mvm/rs.h
index 1e47a0c19b75..4709b4395c01 100644
--- a/drivers/net/wireless/iwlwifi/mvm/rs.h
+++ b/drivers/net/wireless/iwlwifi/mvm/rs.h
@@ -35,9 +35,11 @@
35#include "iwl-trans.h" 35#include "iwl-trans.h"
36 36
37struct iwl_rs_rate_info { 37struct iwl_rs_rate_info {
38 u8 plcp; /* uCode API: IWL_RATE_6M_PLCP, etc. */ 38 u8 plcp; /* uCode API: IWL_RATE_6M_PLCP, etc. */
39 u8 plcp_siso; /* uCode API: IWL_RATE_SISO_6M_PLCP, etc. */ 39 u8 plcp_ht_siso; /* uCode API: IWL_RATE_SISO_6M_PLCP, etc. */
40 u8 plcp_mimo2; /* uCode API: IWL_RATE_MIMO2_6M_PLCP, etc. */ 40 u8 plcp_ht_mimo2; /* uCode API: IWL_RATE_MIMO2_6M_PLCP, etc. */
41 u8 plcp_vht_siso;
42 u8 plcp_vht_mimo2;
41 u8 prev_rs; /* previous rate used in rs algo */ 43 u8 prev_rs; /* previous rate used in rs algo */
42 u8 next_rs; /* next rate used in rs algo */ 44 u8 next_rs; /* next rate used in rs algo */
43}; 45};
@@ -83,35 +85,52 @@ enum {
83#define IWL_RATE_11M_MASK (1 << IWL_RATE_11M_INDEX) 85#define IWL_RATE_11M_MASK (1 << IWL_RATE_11M_INDEX)
84 86
85 87
86/* uCode API values for OFDM high-throughput (HT) bit rates */ 88/* uCode API values for HT/VHT bit rates */
87enum { 89enum {
88 IWL_RATE_SISO_6M_PLCP = 0, 90 IWL_RATE_HT_SISO_MCS_0_PLCP = 0,
89 IWL_RATE_SISO_12M_PLCP = 1, 91 IWL_RATE_HT_SISO_MCS_1_PLCP = 1,
90 IWL_RATE_SISO_18M_PLCP = 2, 92 IWL_RATE_HT_SISO_MCS_2_PLCP = 2,
91 IWL_RATE_SISO_24M_PLCP = 3, 93 IWL_RATE_HT_SISO_MCS_3_PLCP = 3,
92 IWL_RATE_SISO_36M_PLCP = 4, 94 IWL_RATE_HT_SISO_MCS_4_PLCP = 4,
93 IWL_RATE_SISO_48M_PLCP = 5, 95 IWL_RATE_HT_SISO_MCS_5_PLCP = 5,
94 IWL_RATE_SISO_54M_PLCP = 6, 96 IWL_RATE_HT_SISO_MCS_6_PLCP = 6,
95 IWL_RATE_SISO_60M_PLCP = 7, 97 IWL_RATE_HT_SISO_MCS_7_PLCP = 7,
96 IWL_RATE_MIMO2_6M_PLCP = 0x8, 98 IWL_RATE_HT_MIMO2_MCS_0_PLCP = 0x8,
97 IWL_RATE_MIMO2_12M_PLCP = 0x9, 99 IWL_RATE_HT_MIMO2_MCS_1_PLCP = 0x9,
98 IWL_RATE_MIMO2_18M_PLCP = 0xa, 100 IWL_RATE_HT_MIMO2_MCS_2_PLCP = 0xA,
99 IWL_RATE_MIMO2_24M_PLCP = 0xb, 101 IWL_RATE_HT_MIMO2_MCS_3_PLCP = 0xB,
100 IWL_RATE_MIMO2_36M_PLCP = 0xc, 102 IWL_RATE_HT_MIMO2_MCS_4_PLCP = 0xC,
101 IWL_RATE_MIMO2_48M_PLCP = 0xd, 103 IWL_RATE_HT_MIMO2_MCS_5_PLCP = 0xD,
102 IWL_RATE_MIMO2_54M_PLCP = 0xe, 104 IWL_RATE_HT_MIMO2_MCS_6_PLCP = 0xE,
103 IWL_RATE_MIMO2_60M_PLCP = 0xf, 105 IWL_RATE_HT_MIMO2_MCS_7_PLCP = 0xF,
104 IWL_RATE_MIMO3_6M_PLCP = 0x10, 106 IWL_RATE_VHT_SISO_MCS_0_PLCP = 0,
105 IWL_RATE_MIMO3_12M_PLCP = 0x11, 107 IWL_RATE_VHT_SISO_MCS_1_PLCP = 1,
106 IWL_RATE_MIMO3_18M_PLCP = 0x12, 108 IWL_RATE_VHT_SISO_MCS_2_PLCP = 2,
107 IWL_RATE_MIMO3_24M_PLCP = 0x13, 109 IWL_RATE_VHT_SISO_MCS_3_PLCP = 3,
108 IWL_RATE_MIMO3_36M_PLCP = 0x14, 110 IWL_RATE_VHT_SISO_MCS_4_PLCP = 4,
109 IWL_RATE_MIMO3_48M_PLCP = 0x15, 111 IWL_RATE_VHT_SISO_MCS_5_PLCP = 5,
110 IWL_RATE_MIMO3_54M_PLCP = 0x16, 112 IWL_RATE_VHT_SISO_MCS_6_PLCP = 6,
111 IWL_RATE_MIMO3_60M_PLCP = 0x17, 113 IWL_RATE_VHT_SISO_MCS_7_PLCP = 7,
112 IWL_RATE_SISO_INVM_PLCP, 114 IWL_RATE_VHT_SISO_MCS_8_PLCP = 8,
113 IWL_RATE_MIMO2_INVM_PLCP = IWL_RATE_SISO_INVM_PLCP, 115 IWL_RATE_VHT_SISO_MCS_9_PLCP = 9,
114 IWL_RATE_MIMO3_INVM_PLCP = IWL_RATE_SISO_INVM_PLCP, 116 IWL_RATE_VHT_MIMO2_MCS_0_PLCP = 0x10,
117 IWL_RATE_VHT_MIMO2_MCS_1_PLCP = 0x11,
118 IWL_RATE_VHT_MIMO2_MCS_2_PLCP = 0x12,
119 IWL_RATE_VHT_MIMO2_MCS_3_PLCP = 0x13,
120 IWL_RATE_VHT_MIMO2_MCS_4_PLCP = 0x14,
121 IWL_RATE_VHT_MIMO2_MCS_5_PLCP = 0x15,
122 IWL_RATE_VHT_MIMO2_MCS_6_PLCP = 0x16,
123 IWL_RATE_VHT_MIMO2_MCS_7_PLCP = 0x17,
124 IWL_RATE_VHT_MIMO2_MCS_8_PLCP = 0x18,
125 IWL_RATE_VHT_MIMO2_MCS_9_PLCP = 0x19,
126 IWL_RATE_HT_SISO_MCS_INV_PLCP,
127 IWL_RATE_HT_MIMO2_MCS_INV_PLCP = IWL_RATE_HT_SISO_MCS_INV_PLCP,
128 IWL_RATE_VHT_SISO_MCS_INV_PLCP = IWL_RATE_HT_SISO_MCS_INV_PLCP,
129 IWL_RATE_VHT_MIMO2_MCS_INV_PLCP = IWL_RATE_HT_SISO_MCS_INV_PLCP,
130 IWL_RATE_HT_SISO_MCS_8_PLCP = IWL_RATE_HT_SISO_MCS_INV_PLCP,
131 IWL_RATE_HT_SISO_MCS_9_PLCP = IWL_RATE_HT_SISO_MCS_INV_PLCP,
132 IWL_RATE_HT_MIMO2_MCS_8_PLCP = IWL_RATE_HT_SISO_MCS_INV_PLCP,
133 IWL_RATE_HT_MIMO2_MCS_9_PLCP = IWL_RATE_HT_SISO_MCS_INV_PLCP,
115}; 134};
116 135
117#define IWL_RATES_MASK ((1 << IWL_RATE_COUNT) - 1) 136#define IWL_RATES_MASK ((1 << IWL_RATE_COUNT) - 1)
@@ -196,20 +215,31 @@ enum {
196 215
197enum iwl_table_type { 216enum iwl_table_type {
198 LQ_NONE, 217 LQ_NONE,
199 LQ_G, /* legacy types */ 218 LQ_LEGACY_G, /* legacy types */
200 LQ_A, 219 LQ_LEGACY_A,
201 LQ_SISO, /* high-throughput types */ 220 LQ_HT_SISO, /* HT types */
202 LQ_MIMO2, 221 LQ_HT_MIMO2,
222 LQ_VHT_SISO, /* VHT types */
223 LQ_VHT_MIMO2,
203 LQ_MAX, 224 LQ_MAX,
204}; 225};
205 226
206#define is_legacy(tbl) (((tbl) == LQ_G) || ((tbl) == LQ_A)) 227#define is_legacy(tbl) (((tbl) == LQ_LEGACY_G) || ((tbl) == LQ_LEGACY_A))
207#define is_siso(tbl) ((tbl) == LQ_SISO) 228#define is_ht_siso(tbl) ((tbl) == LQ_HT_SISO)
208#define is_mimo2(tbl) ((tbl) == LQ_MIMO2) 229#define is_ht_mimo2(tbl) ((tbl) == LQ_HT_MIMO2)
209#define is_mimo(tbl) is_mimo2(tbl) 230#define is_vht_siso(tbl) ((tbl) == LQ_VHT_SISO)
210#define is_Ht(tbl) (is_siso(tbl) || is_mimo(tbl)) 231#define is_vht_mimo2(tbl) ((tbl) == LQ_VHT_MIMO2)
211#define is_a_band(tbl) ((tbl) == LQ_A) 232#define is_siso(tbl) (is_ht_siso(tbl) || is_vht_siso(tbl))
212#define is_g_and(tbl) ((tbl) == LQ_G) 233#define is_mimo2(tbl) (is_ht_mimo2(tbl) || is_vht_mimo2(tbl))
234#define is_mimo(tbl) (is_mimo2(tbl))
235#define is_ht(tbl) (is_ht_siso(tbl) || is_ht_mimo2(tbl))
236#define is_vht(tbl) (is_vht_siso(tbl) || is_vht_mimo2(tbl))
237#define is_a_band(tbl) ((tbl) == LQ_LEGACY_A)
238#define is_g_band(tbl) ((tbl) == LQ_LEGACY_G)
239
240#define is_ht20(tbl) (tbl->bw == RATE_MCS_CHAN_WIDTH_20)
241#define is_ht40(tbl) (tbl->bw == RATE_MCS_CHAN_WIDTH_40)
242#define is_ht80(tbl) (tbl->bw == RATE_MCS_CHAN_WIDTH_80)
213 243
214#define IWL_MAX_MCS_DISPLAY_SIZE 12 244#define IWL_MAX_MCS_DISPLAY_SIZE 12
215 245
@@ -240,7 +270,7 @@ struct iwl_scale_tbl_info {
240 enum iwl_table_type lq_type; 270 enum iwl_table_type lq_type;
241 u8 ant_type; 271 u8 ant_type;
242 u8 is_SGI; /* 1 = short guard interval */ 272 u8 is_SGI; /* 1 = short guard interval */
243 u8 is_ht40; /* 1 = 40 MHz channel width */ 273 u32 bw; /* channel bandwidth; RATE_MCS_CHAN_WIDTH_XX */
244 u8 action; /* change modulation; IWL_[LEGACY/SISO/MIMO]_SWITCH_* */ 274 u8 action; /* change modulation; IWL_[LEGACY/SISO/MIMO]_SWITCH_* */
245 u8 max_search; /* maximun number of tables we can search */ 275 u8 max_search; /* maximun number of tables we can search */
246 s32 *expected_tpt; /* throughput metrics; expected_tpt_G, etc. */ 276 s32 *expected_tpt; /* throughput metrics; expected_tpt_G, etc. */
@@ -271,6 +301,7 @@ struct iwl_lq_sta {
271 301
272 u8 action_counter; /* # mode-switch actions tried */ 302 u8 action_counter; /* # mode-switch actions tried */
273 u8 is_green; 303 u8 is_green;
304 bool is_vht;
274 enum ieee80211_band band; 305 enum ieee80211_band band;
275 306
276 /* The following are bitmaps of rates; IWL_RATE_6M_MASK, etc. */ 307 /* The following are bitmaps of rates; IWL_RATE_6M_MASK, etc. */
diff --git a/drivers/net/wireless/iwlwifi/mvm/tx.c b/drivers/net/wireless/iwlwifi/mvm/tx.c
index 1ef70d0bd9e2..1606e1da5b0c 100644
--- a/drivers/net/wireless/iwlwifi/mvm/tx.c
+++ b/drivers/net/wireless/iwlwifi/mvm/tx.c
@@ -511,16 +511,10 @@ const char *iwl_mvm_get_tx_fail_reason(u32 status)
511} 511}
512#endif /* CONFIG_IWLWIFI_DEBUG */ 512#endif /* CONFIG_IWLWIFI_DEBUG */
513 513
514/** 514void iwl_mvm_hwrate_to_tx_rate(u32 rate_n_flags,
515 * translate ucode response to mac80211 tx status control values 515 enum ieee80211_band band,
516 */ 516 struct ieee80211_tx_rate *r)
517static void iwl_mvm_hwrate_to_tx_control(u32 rate_n_flags,
518 struct ieee80211_tx_info *info)
519{ 517{
520 struct ieee80211_tx_rate *r = &info->status.rates[0];
521
522 info->status.antenna =
523 ((rate_n_flags & RATE_MCS_ANT_ABC_MSK) >> RATE_MCS_ANT_POS);
524 if (rate_n_flags & RATE_HT_MCS_GF_MSK) 518 if (rate_n_flags & RATE_HT_MCS_GF_MSK)
525 r->flags |= IEEE80211_TX_RC_GREEN_FIELD; 519 r->flags |= IEEE80211_TX_RC_GREEN_FIELD;
526 switch (rate_n_flags & RATE_MCS_CHAN_WIDTH_MSK) { 520 switch (rate_n_flags & RATE_MCS_CHAN_WIDTH_MSK) {
@@ -549,10 +543,23 @@ static void iwl_mvm_hwrate_to_tx_control(u32 rate_n_flags,
549 r->flags |= IEEE80211_TX_RC_VHT_MCS; 543 r->flags |= IEEE80211_TX_RC_VHT_MCS;
550 } else { 544 } else {
551 r->idx = iwl_mvm_legacy_rate_to_mac80211_idx(rate_n_flags, 545 r->idx = iwl_mvm_legacy_rate_to_mac80211_idx(rate_n_flags,
552 info->band); 546 band);
553 } 547 }
554} 548}
555 549
550/**
551 * translate ucode response to mac80211 tx status control values
552 */
553static void iwl_mvm_hwrate_to_tx_status(u32 rate_n_flags,
554 struct ieee80211_tx_info *info)
555{
556 struct ieee80211_tx_rate *r = &info->status.rates[0];
557
558 info->status.antenna =
559 ((rate_n_flags & RATE_MCS_ANT_ABC_MSK) >> RATE_MCS_ANT_POS);
560 iwl_mvm_hwrate_to_tx_rate(rate_n_flags, info->band, r);
561}
562
556static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm, 563static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm,
557 struct iwl_rx_packet *pkt) 564 struct iwl_rx_packet *pkt)
558{ 565{
@@ -602,8 +609,8 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm,
602 } 609 }
603 610
604 info->status.rates[0].count = tx_resp->failure_frame + 1; 611 info->status.rates[0].count = tx_resp->failure_frame + 1;
605 iwl_mvm_hwrate_to_tx_control(le32_to_cpu(tx_resp->initial_rate), 612 iwl_mvm_hwrate_to_tx_status(le32_to_cpu(tx_resp->initial_rate),
606 info); 613 info);
607 614
608 /* Single frame failure in an AMPDU queue => send BAR */ 615 /* Single frame failure in an AMPDU queue => send BAR */
609 if (txq_id >= IWL_MVM_FIRST_AGG_QUEUE && 616 if (txq_id >= IWL_MVM_FIRST_AGG_QUEUE &&
@@ -900,8 +907,8 @@ int iwl_mvm_rx_ba_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb,
900 info->flags |= IEEE80211_TX_STAT_AMPDU; 907 info->flags |= IEEE80211_TX_STAT_AMPDU;
901 info->status.ampdu_ack_len = ba_notif->txed_2_done; 908 info->status.ampdu_ack_len = ba_notif->txed_2_done;
902 info->status.ampdu_len = ba_notif->txed; 909 info->status.ampdu_len = ba_notif->txed;
903 iwl_mvm_hwrate_to_tx_control(tid_data->rate_n_flags, 910 iwl_mvm_hwrate_to_tx_status(tid_data->rate_n_flags,
904 info); 911 info);
905 } 912 }
906 } 913 }
907 914