diff options
author | Eyal Shapira <eyal@wizery.com> | 2013-08-11 11:43:47 -0400 |
---|---|---|
committer | Johannes Berg <johannes.berg@intel.com> | 2013-10-02 12:00:41 -0400 |
commit | d310e4059fe39cf7669801173d25dc9da29eb05e (patch) | |
tree | 9188adc0e4762f926e0e87afc61c54205263fb9b | |
parent | 4515f30fb6c890faba21dd2d74ff2e84ad94c01c (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>
-rw-r--r-- | drivers/net/wireless/iwlwifi/mvm/fw-api-rs.h | 4 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/mvm/mvm.h | 3 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/mvm/rs.c | 518 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/mvm/rs.h | 117 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/mvm/tx.c | 35 |
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 | */ |
72 | enum { | 73 | enum { |
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 */ |
587 | int iwl_mvm_legacy_rate_to_mac80211_idx(u32 rate_n_flags, | 587 | int iwl_mvm_legacy_rate_to_mac80211_idx(u32 rate_n_flags, |
588 | enum ieee80211_band band); | 588 | enum ieee80211_band band); |
589 | void iwl_mvm_hwrate_to_tx_rate(u32 rate_n_flags, | ||
590 | enum ieee80211_band band, | ||
591 | struct ieee80211_tx_rate *r); | ||
589 | u8 iwl_mvm_mac80211_idx_to_hwrate(int rate_idx); | 592 | u8 iwl_mvm_mac80211_idx_to_hwrate(int rate_idx); |
590 | void iwl_mvm_dump_nic_error_log(struct iwl_mvm *mvm); | 593 | void iwl_mvm_dump_nic_error_log(struct iwl_mvm *mvm); |
591 | void iwl_mvm_dump_sram(struct iwl_mvm *mvm); | 594 | void 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 | ||
117 | static inline u8 rs_extract_rate(u32 rate_n_flags) | 129 | static 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 | ||
219 | static 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 | |||
203 | static s32 expected_tpt_mimo2_20MHz[4][IWL_RATE_COUNT] = { | 226 | static 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 | ||
240 | static 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 */ |
218 | static const struct iwl_rate_mcs_info iwl_rate_mcs[IWL_RATE_COUNT] = { | 248 | static 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 | ||
594 | static u16 rs_get_adjacent_rate(struct iwl_mvm *mvm, u8 index, u16 rate_mask, | 658 | static 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 | ||
784 | static 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 | ||
1090 | static 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 | ||
1209 | static 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 | |||
1220 | static 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 | ||
2326 | static 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 | ||
37 | struct iwl_rs_rate_info { | 37 | struct 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 */ |
87 | enum { | 89 | enum { |
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 | ||
197 | enum iwl_table_type { | 216 | enum 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 | /** | 514 | void 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) |
517 | static 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 | */ | ||
553 | static 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 | |||
556 | static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm, | 563 | static 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 | ||