fc9aa3b971cee9feaf42b29ee02bc61101ade98f
[openwrt/openwrt.git] /
1 From 0f98a59596579b34932c06aec7d52c1e835fa1f0 Mon Sep 17 00:00:00 2001
2 From: Bitterblue Smith <rtl8821cerfe2@gmail.com>
3 Date: Tue, 4 Feb 2025 20:41:43 +0200
4 Subject: [PATCH] wifi: rtw88: Extend TX power stuff for 3-4 spatial streams
5
6 Although the RTL8814AU only has 3 spatial streams, maybe some other chip
7 has 4.
8
9 Correct the TX power index and TX power limit calculations for 3SS and
10 4SS HT/VHT rates.
11
12 With this the RTL8814AU can set the TX power correctly.
13
14 Signed-off-by: Bitterblue Smith <rtl8821cerfe2@gmail.com>
15 Acked-by: Ping-Ke Shih <pkshih@realtek.com>
16 Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
17 Link: https://patch.msgid.link/d0c0e126-0794-4c4e-9203-ea39a707b673@gmail.com
18 ---
19 drivers/net/wireless/realtek/rtw88/main.h | 5 +
20 drivers/net/wireless/realtek/rtw88/phy.c | 145 ++++++++++++------
21 drivers/net/wireless/realtek/rtw88/phy.h | 4 +
22 drivers/net/wireless/realtek/rtw88/rtw8821c.c | 2 +-
23 drivers/net/wireless/realtek/rtw88/rtw8822b.c | 2 +-
24 drivers/net/wireless/realtek/rtw88/rtw8822c.c | 2 +-
25 drivers/net/wireless/realtek/rtw88/rtw88xxa.c | 2 +-
26 7 files changed, 111 insertions(+), 51 deletions(-)
27
28 --- a/drivers/net/wireless/realtek/rtw88/main.h
29 +++ b/drivers/net/wireless/realtek/rtw88/main.h
30 @@ -166,6 +166,11 @@ enum rtw_rate_section {
31 RTW_RATE_SECTION_HT_2S,
32 RTW_RATE_SECTION_VHT_1S,
33 RTW_RATE_SECTION_VHT_2S,
34 + __RTW_RATE_SECTION_2SS_MAX = RTW_RATE_SECTION_VHT_2S,
35 + RTW_RATE_SECTION_HT_3S,
36 + RTW_RATE_SECTION_HT_4S,
37 + RTW_RATE_SECTION_VHT_3S,
38 + RTW_RATE_SECTION_VHT_4S,
39
40 /* keep last */
41 RTW_RATE_SECTION_NUM,
42 --- a/drivers/net/wireless/realtek/rtw88/phy.c
43 +++ b/drivers/net/wireless/realtek/rtw88/phy.c
44 @@ -88,10 +88,40 @@ const u8 rtw_vht_2s_rates[] = {
45 DESC_RATEVHT2SS_MCS8, DESC_RATEVHT2SS_MCS9
46 };
47
48 +const u8 rtw_ht_3s_rates[] = {
49 + DESC_RATEMCS16, DESC_RATEMCS17, DESC_RATEMCS18,
50 + DESC_RATEMCS19, DESC_RATEMCS20, DESC_RATEMCS21,
51 + DESC_RATEMCS22, DESC_RATEMCS23
52 +};
53 +
54 +const u8 rtw_ht_4s_rates[] = {
55 + DESC_RATEMCS24, DESC_RATEMCS25, DESC_RATEMCS26,
56 + DESC_RATEMCS27, DESC_RATEMCS28, DESC_RATEMCS29,
57 + DESC_RATEMCS30, DESC_RATEMCS31
58 +};
59 +
60 +const u8 rtw_vht_3s_rates[] = {
61 + DESC_RATEVHT3SS_MCS0, DESC_RATEVHT3SS_MCS1,
62 + DESC_RATEVHT3SS_MCS2, DESC_RATEVHT3SS_MCS3,
63 + DESC_RATEVHT3SS_MCS4, DESC_RATEVHT3SS_MCS5,
64 + DESC_RATEVHT3SS_MCS6, DESC_RATEVHT3SS_MCS7,
65 + DESC_RATEVHT3SS_MCS8, DESC_RATEVHT3SS_MCS9
66 +};
67 +
68 +const u8 rtw_vht_4s_rates[] = {
69 + DESC_RATEVHT4SS_MCS0, DESC_RATEVHT4SS_MCS1,
70 + DESC_RATEVHT4SS_MCS2, DESC_RATEVHT4SS_MCS3,
71 + DESC_RATEVHT4SS_MCS4, DESC_RATEVHT4SS_MCS5,
72 + DESC_RATEVHT4SS_MCS6, DESC_RATEVHT4SS_MCS7,
73 + DESC_RATEVHT4SS_MCS8, DESC_RATEVHT4SS_MCS9
74 +};
75 +
76 const u8 * const rtw_rate_section[RTW_RATE_SECTION_NUM] = {
77 rtw_cck_rates, rtw_ofdm_rates,
78 rtw_ht_1s_rates, rtw_ht_2s_rates,
79 - rtw_vht_1s_rates, rtw_vht_2s_rates
80 + rtw_vht_1s_rates, rtw_vht_2s_rates,
81 + rtw_ht_3s_rates, rtw_ht_4s_rates,
82 + rtw_vht_3s_rates, rtw_vht_4s_rates
83 };
84 EXPORT_SYMBOL(rtw_rate_section);
85
86 @@ -101,17 +131,14 @@ const u8 rtw_rate_size[RTW_RATE_SECTION_
87 ARRAY_SIZE(rtw_ht_1s_rates),
88 ARRAY_SIZE(rtw_ht_2s_rates),
89 ARRAY_SIZE(rtw_vht_1s_rates),
90 - ARRAY_SIZE(rtw_vht_2s_rates)
91 + ARRAY_SIZE(rtw_vht_2s_rates),
92 + ARRAY_SIZE(rtw_ht_3s_rates),
93 + ARRAY_SIZE(rtw_ht_4s_rates),
94 + ARRAY_SIZE(rtw_vht_3s_rates),
95 + ARRAY_SIZE(rtw_vht_4s_rates)
96 };
97 EXPORT_SYMBOL(rtw_rate_size);
98
99 -static const u8 rtw_cck_size = ARRAY_SIZE(rtw_cck_rates);
100 -static const u8 rtw_ofdm_size = ARRAY_SIZE(rtw_ofdm_rates);
101 -static const u8 rtw_ht_1s_size = ARRAY_SIZE(rtw_ht_1s_rates);
102 -static const u8 rtw_ht_2s_size = ARRAY_SIZE(rtw_ht_2s_rates);
103 -static const u8 rtw_vht_1s_size = ARRAY_SIZE(rtw_vht_1s_rates);
104 -static const u8 rtw_vht_2s_size = ARRAY_SIZE(rtw_vht_2s_rates);
105 -
106 enum rtw_phy_band_type {
107 PHY_BAND_2G = 0,
108 PHY_BAND_5G = 1,
109 @@ -1640,11 +1667,15 @@ rtw_xref_5g_txpwr_lmt(struct rtw_dev *rt
110 static void
111 rtw_xref_txpwr_lmt_by_rs(struct rtw_dev *rtwdev, u8 regd, u8 bw, u8 ch_idx)
112 {
113 + static const u8 rs_cmp[4][2] = {
114 + {RTW_RATE_SECTION_HT_1S, RTW_RATE_SECTION_VHT_1S},
115 + {RTW_RATE_SECTION_HT_2S, RTW_RATE_SECTION_VHT_2S},
116 + {RTW_RATE_SECTION_HT_3S, RTW_RATE_SECTION_VHT_3S},
117 + {RTW_RATE_SECTION_HT_4S, RTW_RATE_SECTION_VHT_4S}
118 + };
119 u8 rs_idx, rs_ht, rs_vht;
120 - u8 rs_cmp[2][2] = {{RTW_RATE_SECTION_HT_1S, RTW_RATE_SECTION_VHT_1S},
121 - {RTW_RATE_SECTION_HT_2S, RTW_RATE_SECTION_VHT_2S} };
122
123 - for (rs_idx = 0; rs_idx < 2; rs_idx++) {
124 + for (rs_idx = 0; rs_idx < 4; rs_idx++) {
125 rs_ht = rs_cmp[rs_idx][0];
126 rs_vht = rs_cmp[rs_idx][1];
127
128 @@ -1965,10 +1996,10 @@ static u8 rtw_phy_get_2g_tx_power_index(
129 u8 rate, u8 group)
130 {
131 const struct rtw_chip_info *chip = rtwdev->chip;
132 - u8 tx_power;
133 - bool mcs_rate;
134 - bool above_2ss;
135 + bool above_2ss, above_3ss, above_4ss;
136 u8 factor = chip->txgi_factor;
137 + bool mcs_rate;
138 + u8 tx_power;
139
140 if (rate <= DESC_RATE11M)
141 tx_power = pwr_idx_2g->cck_base[group];
142 @@ -1978,11 +2009,15 @@ static u8 rtw_phy_get_2g_tx_power_index(
143 if (rate >= DESC_RATE6M && rate <= DESC_RATE54M)
144 tx_power += pwr_idx_2g->ht_1s_diff.ofdm * factor;
145
146 - mcs_rate = (rate >= DESC_RATEMCS0 && rate <= DESC_RATEMCS15) ||
147 + mcs_rate = (rate >= DESC_RATEMCS0 && rate <= DESC_RATEMCS31) ||
148 (rate >= DESC_RATEVHT1SS_MCS0 &&
149 - rate <= DESC_RATEVHT2SS_MCS9);
150 - above_2ss = (rate >= DESC_RATEMCS8 && rate <= DESC_RATEMCS15) ||
151 + rate <= DESC_RATEVHT4SS_MCS9);
152 + above_2ss = (rate >= DESC_RATEMCS8 && rate <= DESC_RATEMCS31) ||
153 (rate >= DESC_RATEVHT2SS_MCS0);
154 + above_3ss = (rate >= DESC_RATEMCS16 && rate <= DESC_RATEMCS31) ||
155 + (rate >= DESC_RATEVHT3SS_MCS0);
156 + above_4ss = (rate >= DESC_RATEMCS24 && rate <= DESC_RATEMCS31) ||
157 + (rate >= DESC_RATEVHT4SS_MCS0);
158
159 if (!mcs_rate)
160 return tx_power;
161 @@ -1995,11 +2030,19 @@ static u8 rtw_phy_get_2g_tx_power_index(
162 tx_power += pwr_idx_2g->ht_1s_diff.bw20 * factor;
163 if (above_2ss)
164 tx_power += pwr_idx_2g->ht_2s_diff.bw20 * factor;
165 + if (above_3ss)
166 + tx_power += pwr_idx_2g->ht_3s_diff.bw20 * factor;
167 + if (above_4ss)
168 + tx_power += pwr_idx_2g->ht_4s_diff.bw20 * factor;
169 break;
170 case RTW_CHANNEL_WIDTH_40:
171 /* bw40 is the base power */
172 if (above_2ss)
173 tx_power += pwr_idx_2g->ht_2s_diff.bw40 * factor;
174 + if (above_3ss)
175 + tx_power += pwr_idx_2g->ht_3s_diff.bw40 * factor;
176 + if (above_4ss)
177 + tx_power += pwr_idx_2g->ht_4s_diff.bw40 * factor;
178 break;
179 }
180
181 @@ -2012,19 +2055,23 @@ static u8 rtw_phy_get_5g_tx_power_index(
182 u8 rate, u8 group)
183 {
184 const struct rtw_chip_info *chip = rtwdev->chip;
185 - u8 tx_power;
186 + bool above_2ss, above_3ss, above_4ss;
187 + u8 factor = chip->txgi_factor;
188 u8 upper, lower;
189 bool mcs_rate;
190 - bool above_2ss;
191 - u8 factor = chip->txgi_factor;
192 + u8 tx_power;
193
194 tx_power = pwr_idx_5g->bw40_base[group];
195
196 - mcs_rate = (rate >= DESC_RATEMCS0 && rate <= DESC_RATEMCS15) ||
197 + mcs_rate = (rate >= DESC_RATEMCS0 && rate <= DESC_RATEMCS31) ||
198 (rate >= DESC_RATEVHT1SS_MCS0 &&
199 - rate <= DESC_RATEVHT2SS_MCS9);
200 - above_2ss = (rate >= DESC_RATEMCS8 && rate <= DESC_RATEMCS15) ||
201 + rate <= DESC_RATEVHT4SS_MCS9);
202 + above_2ss = (rate >= DESC_RATEMCS8 && rate <= DESC_RATEMCS31) ||
203 (rate >= DESC_RATEVHT2SS_MCS0);
204 + above_3ss = (rate >= DESC_RATEMCS16 && rate <= DESC_RATEMCS31) ||
205 + (rate >= DESC_RATEVHT3SS_MCS0);
206 + above_4ss = (rate >= DESC_RATEMCS24 && rate <= DESC_RATEMCS31) ||
207 + (rate >= DESC_RATEVHT4SS_MCS0);
208
209 if (!mcs_rate) {
210 tx_power += pwr_idx_5g->ht_1s_diff.ofdm * factor;
211 @@ -2039,11 +2086,19 @@ static u8 rtw_phy_get_5g_tx_power_index(
212 tx_power += pwr_idx_5g->ht_1s_diff.bw20 * factor;
213 if (above_2ss)
214 tx_power += pwr_idx_5g->ht_2s_diff.bw20 * factor;
215 + if (above_3ss)
216 + tx_power += pwr_idx_5g->ht_3s_diff.bw20 * factor;
217 + if (above_4ss)
218 + tx_power += pwr_idx_5g->ht_4s_diff.bw20 * factor;
219 break;
220 case RTW_CHANNEL_WIDTH_40:
221 /* bw40 is the base power */
222 if (above_2ss)
223 tx_power += pwr_idx_5g->ht_2s_diff.bw40 * factor;
224 + if (above_3ss)
225 + tx_power += pwr_idx_5g->ht_3s_diff.bw40 * factor;
226 + if (above_4ss)
227 + tx_power += pwr_idx_5g->ht_4s_diff.bw40 * factor;
228 break;
229 case RTW_CHANNEL_WIDTH_80:
230 /* the base idx of bw80 is the average of bw40+/bw40- */
231 @@ -2054,6 +2109,10 @@ static u8 rtw_phy_get_5g_tx_power_index(
232 tx_power += pwr_idx_5g->vht_1s_diff.bw80 * factor;
233 if (above_2ss)
234 tx_power += pwr_idx_5g->vht_2s_diff.bw80 * factor;
235 + if (above_3ss)
236 + tx_power += pwr_idx_5g->vht_3s_diff.bw80 * factor;
237 + if (above_4ss)
238 + tx_power += pwr_idx_5g->vht_4s_diff.bw80 * factor;
239 break;
240 }
241
242 @@ -2071,10 +2130,18 @@ static u8 rtw_phy_rate_to_rate_section(u
243 return RTW_RATE_SECTION_HT_1S;
244 else if (rate >= DESC_RATEMCS8 && rate <= DESC_RATEMCS15)
245 return RTW_RATE_SECTION_HT_2S;
246 + else if (rate >= DESC_RATEMCS16 && rate <= DESC_RATEMCS23)
247 + return RTW_RATE_SECTION_HT_3S;
248 + else if (rate >= DESC_RATEMCS24 && rate <= DESC_RATEMCS31)
249 + return RTW_RATE_SECTION_HT_4S;
250 else if (rate >= DESC_RATEVHT1SS_MCS0 && rate <= DESC_RATEVHT1SS_MCS9)
251 return RTW_RATE_SECTION_VHT_1S;
252 else if (rate >= DESC_RATEVHT2SS_MCS0 && rate <= DESC_RATEVHT2SS_MCS9)
253 return RTW_RATE_SECTION_VHT_2S;
254 + else if (rate >= DESC_RATEVHT3SS_MCS0 && rate <= DESC_RATEVHT3SS_MCS9)
255 + return RTW_RATE_SECTION_VHT_3S;
256 + else if (rate >= DESC_RATEVHT4SS_MCS0 && rate <= DESC_RATEVHT4SS_MCS9)
257 + return RTW_RATE_SECTION_VHT_4S;
258 else
259 return RTW_RATE_SECTION_NUM;
260 }
261 @@ -2102,7 +2169,7 @@ static s8 rtw_phy_get_tx_power_limit(str
262 bw = RTW_CHANNEL_WIDTH_20;
263
264 /* only 20/40M BW with ht */
265 - if (rs == RTW_RATE_SECTION_HT_1S || rs == RTW_RATE_SECTION_HT_2S)
266 + if (rate >= DESC_RATEMCS0 && rate <= DESC_RATEMCS31)
267 bw = min_t(u8, bw, RTW_CHANNEL_WIDTH_40);
268
269 /* select min power limit among [20M BW ~ current BW] */
270 @@ -2286,7 +2353,7 @@ rtw_phy_tx_power_by_rate_config_by_path(
271 u8 base_idx, rate_idx;
272 s8 base_2g, base_5g;
273
274 - if (rs >= RTW_RATE_SECTION_VHT_1S)
275 + if (size == 10) /* VHT rates */
276 base_idx = rates[size - 3];
277 else
278 base_idx = rates[size - 1];
279 @@ -2303,28 +2370,12 @@ rtw_phy_tx_power_by_rate_config_by_path(
280
281 void rtw_phy_tx_power_by_rate_config(struct rtw_hal *hal)
282 {
283 - u8 path;
284 + u8 path, rs;
285
286 - for (path = 0; path < RTW_RF_PATH_MAX; path++) {
287 - rtw_phy_tx_power_by_rate_config_by_path(hal, path,
288 - RTW_RATE_SECTION_CCK,
289 - rtw_cck_size, rtw_cck_rates);
290 - rtw_phy_tx_power_by_rate_config_by_path(hal, path,
291 - RTW_RATE_SECTION_OFDM,
292 - rtw_ofdm_size, rtw_ofdm_rates);
293 - rtw_phy_tx_power_by_rate_config_by_path(hal, path,
294 - RTW_RATE_SECTION_HT_1S,
295 - rtw_ht_1s_size, rtw_ht_1s_rates);
296 - rtw_phy_tx_power_by_rate_config_by_path(hal, path,
297 - RTW_RATE_SECTION_HT_2S,
298 - rtw_ht_2s_size, rtw_ht_2s_rates);
299 - rtw_phy_tx_power_by_rate_config_by_path(hal, path,
300 - RTW_RATE_SECTION_VHT_1S,
301 - rtw_vht_1s_size, rtw_vht_1s_rates);
302 - rtw_phy_tx_power_by_rate_config_by_path(hal, path,
303 - RTW_RATE_SECTION_VHT_2S,
304 - rtw_vht_2s_size, rtw_vht_2s_rates);
305 - }
306 + for (path = 0; path < RTW_RF_PATH_MAX; path++)
307 + for (rs = 0; rs < RTW_RATE_SECTION_NUM; rs++)
308 + rtw_phy_tx_power_by_rate_config_by_path(hal, path, rs,
309 + rtw_rate_size[rs], rtw_rate_section[rs]);
310 }
311
312 static void
313 --- a/drivers/net/wireless/realtek/rtw88/phy.h
314 +++ b/drivers/net/wireless/realtek/rtw88/phy.h
315 @@ -13,6 +13,10 @@ extern const u8 rtw_ht_1s_rates[];
316 extern const u8 rtw_ht_2s_rates[];
317 extern const u8 rtw_vht_1s_rates[];
318 extern const u8 rtw_vht_2s_rates[];
319 +extern const u8 rtw_ht_3s_rates[];
320 +extern const u8 rtw_ht_4s_rates[];
321 +extern const u8 rtw_vht_3s_rates[];
322 +extern const u8 rtw_vht_4s_rates[];
323 extern const u8 * const rtw_rate_section[];
324 extern const u8 rtw_rate_size[];
325
326 --- a/drivers/net/wireless/realtek/rtw88/rtw8821c.c
327 +++ b/drivers/net/wireless/realtek/rtw88/rtw8821c.c
328 @@ -709,7 +709,7 @@ static void rtw8821c_set_tx_power_index(
329 int rs, path;
330
331 for (path = 0; path < hal->rf_path_num; path++) {
332 - for (rs = 0; rs < RTW_RATE_SECTION_NUM; rs++) {
333 + for (rs = 0; rs <= __RTW_RATE_SECTION_2SS_MAX; rs++) {
334 if (rs == RTW_RATE_SECTION_HT_2S ||
335 rs == RTW_RATE_SECTION_VHT_2S)
336 continue;
337 --- a/drivers/net/wireless/realtek/rtw88/rtw8822b.c
338 +++ b/drivers/net/wireless/realtek/rtw88/rtw8822b.c
339 @@ -964,7 +964,7 @@ static void rtw8822b_set_tx_power_index(
340 int rs, path;
341
342 for (path = 0; path < hal->rf_path_num; path++) {
343 - for (rs = 0; rs < RTW_RATE_SECTION_NUM; rs++)
344 + for (rs = 0; rs <= __RTW_RATE_SECTION_2SS_MAX; rs++)
345 rtw8822b_set_tx_power_index_by_rate(rtwdev, path, rs,
346 &phy_pwr_idx);
347 }
348 --- a/drivers/net/wireless/realtek/rtw88/rtw8822c.c
349 +++ b/drivers/net/wireless/realtek/rtw88/rtw8822c.c
350 @@ -2746,7 +2746,7 @@ static void rtw8822c_set_tx_power_index(
351 s8 diff_idx[4];
352
353 rtw8822c_set_write_tx_power_ref(rtwdev, pwr_ref_cck, pwr_ref_ofdm);
354 - for (rs = 0; rs < RTW_RATE_SECTION_NUM; rs++) {
355 + for (rs = 0; rs <= __RTW_RATE_SECTION_2SS_MAX; rs++) {
356 for (j = 0; j < rtw_rate_size[rs]; j++) {
357 rate = rtw_rate_section[rs][j];
358 pwr_a = hal->tx_pwr_tbl[RF_PATH_A][rate];
359 --- a/drivers/net/wireless/realtek/rtw88/rtw88xxa.c
360 +++ b/drivers/net/wireless/realtek/rtw88/rtw88xxa.c
361 @@ -1637,7 +1637,7 @@ void rtw88xxa_set_tx_power_index(struct
362 int rs, path;
363
364 for (path = 0; path < hal->rf_path_num; path++) {
365 - for (rs = 0; rs < RTW_RATE_SECTION_NUM; rs++) {
366 + for (rs = 0; rs <= __RTW_RATE_SECTION_2SS_MAX; rs++) {
367 if (hal->rf_path_num == 1 &&
368 (rs == RTW_RATE_SECTION_HT_2S ||
369 rs == RTW_RATE_SECTION_VHT_2S))