blob: 66708ea5efda2a39056e2c559dc2d815ede999bb [file] [log] [blame]
developer8f0d89b2023-07-28 07:16:44 +08001From 485b78e6495b46b5f9adbabf99069f63217b37cd Mon Sep 17 00:00:00 2001
developerfe7be7f2022-12-13 21:40:24 +08002From: Shayne Chen <shayne.chen@mediatek.com>
3Date: Mon, 5 Dec 2022 18:21:51 +0800
developer8f0d89b2023-07-28 07:16:44 +08004Subject: [PATCH 1025/1034] wifi: mt76: mt7915: add bf backoff limit table
developerc9233442023-04-04 06:06:17 +08005 support
developerfe7be7f2022-12-13 21:40:24 +08006
7Signed-off-by: Shayne Chen <shayne.chen@mediatek.com>
8---
developer2594fb72023-07-20 14:56:49 +08009 debugfs.c | 2 +-
10 eeprom.c | 38 ++++++++++++--
11 mac80211.c | 2 +-
developerfe7be7f2022-12-13 21:40:24 +080012 mt76.h | 8 +++
developer2594fb72023-07-20 14:56:49 +080013 mt7915/debugfs.c | 121 +++++++++++++++++++++++++++++++++----------
14 mt7915/init.c | 2 +-
15 mt7915/main.c | 3 +-
developerf520c8d2023-06-19 10:33:45 +080016 mt7915/mcu.c | 132 ++++++++++++++++++++++++++++++++++++-----------
developer2594fb72023-07-20 14:56:49 +080017 mt7915/mcu.h | 8 ++-
developerfe7be7f2022-12-13 21:40:24 +080018 mt7915/mt7915.h | 4 +-
developer2594fb72023-07-20 14:56:49 +080019 10 files changed, 253 insertions(+), 67 deletions(-)
developerfe7be7f2022-12-13 21:40:24 +080020
developer2594fb72023-07-20 14:56:49 +080021diff --git a/debugfs.c b/debugfs.c
22index 4a8e186..4bb4679 100644
23--- a/debugfs.c
24+++ b/debugfs.c
25@@ -95,7 +95,7 @@ void mt76_seq_puts_array(struct seq_file *file, const char *str,
26 {
27 int i;
28
29- seq_printf(file, "%10s:", str);
30+ seq_printf(file, "%16s:", str);
31 for (i = 0; i < len; i++)
32 seq_printf(file, " %2d", val[i]);
33 seq_puts(file, "\n");
developerfe7be7f2022-12-13 21:40:24 +080034diff --git a/eeprom.c b/eeprom.c
developer2594fb72023-07-20 14:56:49 +080035index 412740f..5cbd56f 100644
developerfe7be7f2022-12-13 21:40:24 +080036--- a/eeprom.c
37+++ b/eeprom.c
developerf520c8d2023-06-19 10:33:45 +080038@@ -311,13 +311,17 @@ s8 mt76_get_rate_power_limits(struct mt76_phy *phy,
39 u32 ru_rates = ARRAY_SIZE(dest->ru[0]);
40 char band;
41 size_t len;
42- s8 max_power = 0;
43+ s8 max_power = -127;
44+ s8 max_power_backoff = -127;
45 s8 txs_delta;
developer2594fb72023-07-20 14:56:49 +080046+ int n_chains = hweight16(phy->chainmask);
developerf520c8d2023-06-19 10:33:45 +080047+ s8 target_power_combine = target_power + mt76_tx_power_nss_delta(n_chains);
48
developerfe7be7f2022-12-13 21:40:24 +080049 if (!mcs_rates)
50 mcs_rates = 10;
51
52- memset(dest, target_power, sizeof(*dest));
53+ memset(dest, target_power, sizeof(*dest) - sizeof(dest->path));
54+ memset(&dest->path, 0, sizeof(dest->path));
55
56 if (!IS_ENABLED(CONFIG_OF))
57 return target_power;
developer2594fb72023-07-20 14:56:49 +080058@@ -349,7 +353,7 @@ s8 mt76_get_rate_power_limits(struct mt76_phy *phy,
59 if (!np)
60 return target_power;
61
62- txs_delta = mt76_get_txs_delta(np, hweight8(phy->antenna_mask));
63+ txs_delta = mt76_get_txs_delta(np, hweight16(phy->chainmask));
64
65 val = mt76_get_of_array(np, "rates-cck", &len, ARRAY_SIZE(dest->cck));
66 mt76_apply_array_limit(dest->cck, ARRAY_SIZE(dest->cck), val,
developerf520c8d2023-06-19 10:33:45 +080067@@ -370,7 +374,33 @@ s8 mt76_get_rate_power_limits(struct mt76_phy *phy,
developerfe7be7f2022-12-13 21:40:24 +080068 ARRAY_SIZE(dest->ru), val, len,
69 target_power, txs_delta, &max_power);
70
developerf520c8d2023-06-19 10:33:45 +080071- return max_power;
72+ max_power_backoff = max_power;
developerfe7be7f2022-12-13 21:40:24 +080073+ val = mt76_get_of_array(np, "paths-cck", &len, ARRAY_SIZE(dest->path.cck));
74+ mt76_apply_array_limit(dest->path.cck, ARRAY_SIZE(dest->path.cck), val,
developerf520c8d2023-06-19 10:33:45 +080075+ target_power_combine, txs_delta, &max_power_backoff);
developerfe7be7f2022-12-13 21:40:24 +080076+
77+ val = mt76_get_of_array(np, "paths-ofdm", &len, ARRAY_SIZE(dest->path.ofdm));
78+ mt76_apply_array_limit(dest->path.ofdm, ARRAY_SIZE(dest->path.ofdm), val,
developerf520c8d2023-06-19 10:33:45 +080079+ target_power_combine, txs_delta, &max_power_backoff);
developerfe7be7f2022-12-13 21:40:24 +080080+
81+ val = mt76_get_of_array(np, "paths-ofdm-bf", &len, ARRAY_SIZE(dest->path.ofdm_bf));
82+ mt76_apply_array_limit(dest->path.ofdm_bf, ARRAY_SIZE(dest->path.ofdm_bf), val,
developerf520c8d2023-06-19 10:33:45 +080083+ target_power_combine, txs_delta, &max_power_backoff);
developerfe7be7f2022-12-13 21:40:24 +080084+
85+ val = mt76_get_of_array(np, "paths-ru", &len, ARRAY_SIZE(dest->path.ru[0]) + 1);
86+ mt76_apply_multi_array_limit(dest->path.ru[0], ARRAY_SIZE(dest->path.ru[0]),
87+ ARRAY_SIZE(dest->path.ru), val, len,
developerf520c8d2023-06-19 10:33:45 +080088+ target_power_combine, txs_delta, &max_power_backoff);
developerfe7be7f2022-12-13 21:40:24 +080089+
90+ val = mt76_get_of_array(np, "paths-ru-bf", &len, ARRAY_SIZE(dest->path.ru_bf[0]) + 1);
91+ mt76_apply_multi_array_limit(dest->path.ru_bf[0], ARRAY_SIZE(dest->path.ru_bf[0]),
92+ ARRAY_SIZE(dest->path.ru_bf), val, len,
developerf520c8d2023-06-19 10:33:45 +080093+ target_power_combine, txs_delta, &max_power_backoff);
developerfe7be7f2022-12-13 21:40:24 +080094+
developerf520c8d2023-06-19 10:33:45 +080095+ if (max_power_backoff == target_power_combine)
96+ return max_power;
97+
98+ return max_power_backoff;
developerfe7be7f2022-12-13 21:40:24 +080099 }
100 EXPORT_SYMBOL_GPL(mt76_get_rate_power_limits);
developerf520c8d2023-06-19 10:33:45 +0800101
developer2594fb72023-07-20 14:56:49 +0800102diff --git a/mac80211.c b/mac80211.c
103index ddc13dd..25ec433 100644
104--- a/mac80211.c
105+++ b/mac80211.c
106@@ -1456,7 +1456,7 @@ int mt76_get_txpower(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
107 int *dbm)
108 {
109 struct mt76_phy *phy = hw->priv;
110- int n_chains = hweight8(phy->antenna_mask);
111+ int n_chains = hweight16(phy->chainmask);
112 int delta = mt76_tx_power_nss_delta(n_chains);
113
114 *dbm = DIV_ROUND_UP(phy->txpower_cur + delta, 2);
developerfe7be7f2022-12-13 21:40:24 +0800115diff --git a/mt76.h b/mt76.h
developer2157bf82023-06-26 02:27:49 +0800116index b4e3429..2f801de 100644
developerfe7be7f2022-12-13 21:40:24 +0800117--- a/mt76.h
118+++ b/mt76.h
developer2157bf82023-06-26 02:27:49 +0800119@@ -1030,6 +1030,14 @@ struct mt76_power_limits {
developerfe7be7f2022-12-13 21:40:24 +0800120 s8 ofdm[8];
121 s8 mcs[4][10];
122 s8 ru[7][12];
123+
124+ struct {
125+ s8 cck[4];
126+ s8 ofdm[4];
127+ s8 ofdm_bf[4];
128+ s8 ru[7][10];
129+ s8 ru_bf[7][10];
130+ } path;
131 };
132
133 struct mt76_ethtool_worker_info {
134diff --git a/mt7915/debugfs.c b/mt7915/debugfs.c
developer2594fb72023-07-20 14:56:49 +0800135index d66d104..19a37b5 100644
developerfe7be7f2022-12-13 21:40:24 +0800136--- a/mt7915/debugfs.c
137+++ b/mt7915/debugfs.c
developer2594fb72023-07-20 14:56:49 +0800138@@ -983,9 +983,9 @@ mt7915_xmit_queues_show(struct seq_file *file, void *data)
139
140 DEFINE_SHOW_ATTRIBUTE(mt7915_xmit_queues);
141
142-#define mt7915_txpower_puts(rate) \
143+#define mt7915_txpower_puts(rate, _len) \
144 ({ \
145- len += scnprintf(buf + len, sz - len, "%-16s:", #rate " (TMAC)"); \
146+ len += scnprintf(buf + len, sz - len, "%-*s:", _len, #rate " (TMAC)"); \
147 for (i = 0; i < mt7915_sku_group_len[SKU_##rate]; i++, offs++) \
148 len += scnprintf(buf + len, sz - len, " %6d", txpwr[offs]); \
149 len += scnprintf(buf + len, sz - len, "\n"); \
developer2157bf82023-06-26 02:27:49 +0800150@@ -1019,7 +1019,7 @@ mt7915_rate_txpower_get(struct file *file, char __user *user_buf,
developerfe7be7f2022-12-13 21:40:24 +0800151 if (!buf)
152 return -ENOMEM;
153
154- ret = mt7915_mcu_get_txpower_sku(phy, txpwr, sizeof(txpwr));
155+ ret = mt7915_mcu_get_txpower_sku(phy, txpwr, sizeof(txpwr), TX_POWER_INFO_RATE);
156 if (ret)
157 goto out;
158
developer2594fb72023-07-20 14:56:49 +0800159@@ -1027,43 +1027,47 @@ mt7915_rate_txpower_get(struct file *file, char __user *user_buf,
160 len += scnprintf(buf + len, sz - len,
161 "\nPhy%d Tx power table (channel %d)\n",
162 phy != &dev->phy, phy->mt76->chandef.chan->hw_value);
163- len += scnprintf(buf + len, sz - len, "%-16s %6s %6s %6s %6s\n",
164+ len += scnprintf(buf + len, sz - len, "%-23s %6s %6s %6s %6s\n",
165 " ", "1m", "2m", "5m", "11m");
166- mt7915_txpower_puts(CCK);
167+ mt7915_txpower_puts(CCK, 23);
168
169 len += scnprintf(buf + len, sz - len,
170- "%-16s %6s %6s %6s %6s %6s %6s %6s %6s\n",
171+ "%-23s %6s %6s %6s %6s %6s %6s %6s %6s\n",
172 " ", "6m", "9m", "12m", "18m", "24m", "36m", "48m",
173 "54m");
174- mt7915_txpower_puts(OFDM);
175+ mt7915_txpower_puts(OFDM, 23);
176
177 len += scnprintf(buf + len, sz - len,
178- "%-16s %6s %6s %6s %6s %6s %6s %6s %6s\n",
179+ "%-23s %6s %6s %6s %6s %6s %6s %6s %6s\n",
180 " ", "mcs0", "mcs1", "mcs2", "mcs3", "mcs4",
181 "mcs5", "mcs6", "mcs7");
182- mt7915_txpower_puts(HT_BW20);
183+ mt7915_txpower_puts(HT_BW20, 23);
184
185 len += scnprintf(buf + len, sz - len,
186- "%-16s %6s %6s %6s %6s %6s %6s %6s %6s %6s\n",
187+ "%-23s %6s %6s %6s %6s %6s %6s %6s %6s %6s\n",
188 " ", "mcs0", "mcs1", "mcs2", "mcs3", "mcs4", "mcs5",
189 "mcs6", "mcs7", "mcs32");
190- mt7915_txpower_puts(HT_BW40);
191+ mt7915_txpower_puts(HT_BW40, 23);
192
193 len += scnprintf(buf + len, sz - len,
194- "%-16s %6s %6s %6s %6s %6s %6s %6s %6s %6s %6s %6s %6s\n",
195+ "%-23s %6s %6s %6s %6s %6s %6s %6s %6s %6s %6s %6s %6s\n",
196 " ", "mcs0", "mcs1", "mcs2", "mcs3", "mcs4", "mcs5",
197 "mcs6", "mcs7", "mcs8", "mcs9", "mcs10", "mcs11");
198- mt7915_txpower_puts(VHT_BW20);
199- mt7915_txpower_puts(VHT_BW40);
200- mt7915_txpower_puts(VHT_BW80);
201- mt7915_txpower_puts(VHT_BW160);
202- mt7915_txpower_puts(HE_RU26);
203- mt7915_txpower_puts(HE_RU52);
204- mt7915_txpower_puts(HE_RU106);
205- mt7915_txpower_puts(HE_RU242);
206- mt7915_txpower_puts(HE_RU484);
207- mt7915_txpower_puts(HE_RU996);
208- mt7915_txpower_puts(HE_RU2x996);
209+ mt7915_txpower_puts(VHT_BW20, 23);
210+ mt7915_txpower_puts(VHT_BW40, 23);
211+ mt7915_txpower_puts(VHT_BW80, 23);
212+ mt7915_txpower_puts(VHT_BW160, 23);
213+ mt7915_txpower_puts(HE_RU26, 23);
214+ mt7915_txpower_puts(HE_RU52, 23);
215+ mt7915_txpower_puts(HE_RU106, 23);
216+ len += scnprintf(buf + len, sz - len, "BW20/");
217+ mt7915_txpower_puts(HE_RU242, 18);
218+ len += scnprintf(buf + len, sz - len, "BW40/");
219+ mt7915_txpower_puts(HE_RU484, 18);
220+ len += scnprintf(buf + len, sz - len, "BW80/");
221+ mt7915_txpower_puts(HE_RU996, 18);
222+ len += scnprintf(buf + len, sz - len, "BW160/");
223+ mt7915_txpower_puts(HE_RU2x996, 17);
224
225 reg = is_mt7915(&dev->mt76) ? MT_WF_PHY_TPC_CTRL_STAT(band) :
226 MT_WF_PHY_TPC_CTRL_STAT_MT7916(band);
227@@ -1129,7 +1133,7 @@ mt7915_rate_txpower_set(struct file *file, const char __user *user_buf,
developerfe7be7f2022-12-13 21:40:24 +0800228
229 mutex_lock(&dev->mt76.mutex);
230 ret = mt7915_mcu_get_txpower_sku(phy, req.txpower_sku,
231- sizeof(req.txpower_sku));
232+ sizeof(req.txpower_sku), TX_POWER_INFO_RATE);
233 if (ret)
234 goto out;
235
developer2594fb72023-07-20 14:56:49 +0800236@@ -1171,7 +1175,7 @@ out:
developerfe7be7f2022-12-13 21:40:24 +0800237 return ret ? ret : count;
238 }
239
240-static const struct file_operations mt7915_rate_txpower_fops = {
241+static const struct file_operations mt7915_txpower_fops = {
242 .write = mt7915_rate_txpower_set,
243 .read = mt7915_rate_txpower_get,
244 .open = simple_open,
developer2594fb72023-07-20 14:56:49 +0800245@@ -1179,6 +1183,69 @@ static const struct file_operations mt7915_rate_txpower_fops = {
developerfe7be7f2022-12-13 21:40:24 +0800246 .llseek = default_llseek,
247 };
248
249+static int
250+mt7915_path_txpower_show(struct seq_file *file)
251+{
252+ struct mt7915_phy *phy = file->private;
253+ s8 txpower[MT7915_SKU_PATH_NUM], *buf = txpower;
254+ int ret;
255+
256+#define PATH_POWER_SHOW(_name, _len, _skip) do { \
257+ if (_skip) { \
258+ buf -= 1; \
259+ *buf = 0; \
260+ } \
261+ mt76_seq_puts_array(file, _name, buf, _len); \
262+ buf += _len; \
263+ } while(0)
264+
developer2594fb72023-07-20 14:56:49 +0800265+ seq_printf(file, "\n%*c", 17, ' ');
developerfe7be7f2022-12-13 21:40:24 +0800266+ seq_printf(file, "1T1S/2T1S/3T1S/4T1S/2T2S/3T2S/4T2S/3T3S/4T3S/4T4S\n");
267+ ret = mt7915_mcu_get_txpower_sku(phy, txpower, sizeof(txpower),
268+ TX_POWER_INFO_PATH);
269+ if (ret)
270+ return ret;
271+
272+ PATH_POWER_SHOW("CCK", 4, 0);
273+ PATH_POWER_SHOW("OFDM", 4, 0);
274+ PATH_POWER_SHOW("BF-OFDM", 4, 1);
275+
developer2594fb72023-07-20 14:56:49 +0800276+ PATH_POWER_SHOW("HT/VHT20", 10, 0);
277+ PATH_POWER_SHOW("BF-HT/VHT20", 10, 1);
278+ PATH_POWER_SHOW("HT/VHT40", 10, 0);
279+ PATH_POWER_SHOW("BF-HT/VHT40", 10, 1);
developerfe7be7f2022-12-13 21:40:24 +0800280+
developer2594fb72023-07-20 14:56:49 +0800281+ PATH_POWER_SHOW("BW20/RU242", 10, 0);
282+ PATH_POWER_SHOW("BF-BW20/RU242", 10, 1);
283+ PATH_POWER_SHOW("BW40/RU484", 10, 0);
284+ PATH_POWER_SHOW("BF-BW40/RU484", 10, 1);
285+ PATH_POWER_SHOW("BW80/RU996", 10, 0);
286+ PATH_POWER_SHOW("BF-BW80/RU996", 10, 1);
287+ PATH_POWER_SHOW("BW160/RU2x996", 10, 0);
288+ PATH_POWER_SHOW("BF-BW160/RU2x996", 10, 1);
developerfe7be7f2022-12-13 21:40:24 +0800289+ PATH_POWER_SHOW("RU26", 10, 0);
290+ PATH_POWER_SHOW("BF-RU26", 10, 0);
291+ PATH_POWER_SHOW("RU52", 10, 0);
292+ PATH_POWER_SHOW("BF-RU52", 10, 0);
293+ PATH_POWER_SHOW("RU106", 10, 0);
294+ PATH_POWER_SHOW("BF-RU106", 10, 0);
295+#undef PATH_POWER_SHOW
296+
297+ return 0;
298+}
299+
300+static int
301+mt7915_txpower_path_show(struct seq_file *file, void *data)
302+{
303+ struct mt7915_phy *phy = file->private;
304+
305+ seq_printf(file, "\nBand %d\n", phy != &phy->dev->phy);
306+
307+ return mt7915_path_txpower_show(file);
308+}
309+
310+DEFINE_SHOW_ATTRIBUTE(mt7915_txpower_path);
311+
312 static int
313 mt7915_twt_stats(struct seq_file *s, void *data)
314 {
developer2594fb72023-07-20 14:56:49 +0800315@@ -1265,7 +1332,9 @@ int mt7915_init_debugfs(struct mt7915_phy *phy)
developerfe7be7f2022-12-13 21:40:24 +0800316 debugfs_create_file("implicit_txbf", 0600, dir, dev,
317 &fops_implicit_txbf);
318 debugfs_create_file("txpower_sku", 0400, dir, phy,
319- &mt7915_rate_txpower_fops);
320+ &mt7915_txpower_fops);
321+ debugfs_create_file("txpower_path", 0400, dir, phy,
322+ &mt7915_txpower_path_fops);
323 debugfs_create_devm_seqfile(dev->mt76.dev, "twt_stats", dir,
324 mt7915_twt_stats);
325 debugfs_create_file("rf_regval", 0600, dir, dev, &fops_rf_regval);
developer2594fb72023-07-20 14:56:49 +0800326diff --git a/mt7915/init.c b/mt7915/init.c
327index 63c0ecb..2415f1b 100644
328--- a/mt7915/init.c
329+++ b/mt7915/init.c
330@@ -281,7 +281,7 @@ static void mt7915_led_set_brightness(struct led_classdev *led_cdev,
331 void mt7915_init_txpower(struct mt7915_dev *dev,
332 struct ieee80211_supported_band *sband)
333 {
334- int i, n_chains = hweight8(dev->mphy.antenna_mask);
335+ int i, n_chains = hweight16(dev->mphy.chainmask);
336 int nss_delta = mt76_tx_power_nss_delta(n_chains);
337 int pwr_delta = mt7915_eeprom_get_power_delta(dev, sband->band);
338 struct mt76_power_limits limits;
developerf520c8d2023-06-19 10:33:45 +0800339diff --git a/mt7915/main.c b/mt7915/main.c
developer2594fb72023-07-20 14:56:49 +0800340index fcd69ea..4833f64 100644
developerf520c8d2023-06-19 10:33:45 +0800341--- a/mt7915/main.c
342+++ b/mt7915/main.c
developer2594fb72023-07-20 14:56:49 +0800343@@ -488,7 +488,7 @@ static int mt7915_config(struct ieee80211_hw *hw, u32 changed)
344 ieee80211_wake_queues(hw);
345 }
346
347- if (changed & IEEE80211_CONF_CHANGE_POWER) {
348+ if (changed & (IEEE80211_CONF_CHANGE_POWER | IEEE80211_CONF_CHANGE_CHANNEL)) {
349 ret = mt7915_mcu_set_txpower_sku(phy);
350 if (ret)
351 return ret;
developerf520c8d2023-06-19 10:33:45 +0800352@@ -1097,6 +1097,7 @@ mt7915_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant)
353 mt76_set_stream_caps(phy->mt76, true);
354 mt7915_set_stream_vht_txbf_caps(phy);
355 mt7915_set_stream_he_caps(phy);
356+ mt7915_mcu_set_txpower_sku(phy);
357
358 mutex_unlock(&dev->mt76.mutex);
359
developerfe7be7f2022-12-13 21:40:24 +0800360diff --git a/mt7915/mcu.c b/mt7915/mcu.c
developer8f0d89b2023-07-28 07:16:44 +0800361index 4aee126..10fade2 100644
developerfe7be7f2022-12-13 21:40:24 +0800362--- a/mt7915/mcu.c
363+++ b/mt7915/mcu.c
developer2594fb72023-07-20 14:56:49 +0800364@@ -3302,7 +3302,8 @@ int mt7915_mcu_set_txpower_frame(struct mt7915_phy *phy,
developerfe7be7f2022-12-13 21:40:24 +0800365 int ret;
366 s8 txpower_sku[MT7915_SKU_RATE_NUM];
367
368- ret = mt7915_mcu_get_txpower_sku(phy, txpower_sku, sizeof(txpower_sku));
369+ ret = mt7915_mcu_get_txpower_sku(phy, txpower_sku, sizeof(txpower_sku),
370+ TX_POWER_INFO_RATE);
371 if (ret)
372 return ret;
373
developer2594fb72023-07-20 14:56:49 +0800374@@ -3344,51 +3345,106 @@ int mt7915_mcu_set_txpower_frame(struct mt7915_phy *phy,
developerfe7be7f2022-12-13 21:40:24 +0800375
376 int mt7915_mcu_set_txpower_sku(struct mt7915_phy *phy)
377 {
378+#define TX_POWER_LIMIT_TABLE_RATE 0
379+#define TX_POWER_LIMIT_TABLE_PATH 1
380 struct mt7915_dev *dev = phy->dev;
381 struct mt76_phy *mphy = phy->mt76;
382 struct ieee80211_hw *hw = mphy->hw;
383- struct mt7915_mcu_txpower_sku req = {
384+ struct mt7915_sku_val {
385+ u8 format_id;
386+ u8 limit_type;
387+ u8 band_idx;
388+ } __packed hdr = {
389 .format_id = TX_POWER_LIMIT_TABLE,
390+ .limit_type = TX_POWER_LIMIT_TABLE_RATE,
391 .band_idx = phy->mt76->band_idx,
392 };
393- struct mt76_power_limits limits_array;
394- s8 *la = (s8 *)&limits_array;
395- int i, idx;
396- int tx_power;
397+ int i, ret, tx_power;
398+ const u8 *len = mt7915_sku_group_len;
399+ struct mt76_power_limits la = {};
400+ struct sk_buff *skb;
401
402 tx_power = mt7915_get_power_bound(phy, hw->conf.power_level);
403 tx_power = mt76_get_rate_power_limits(mphy, mphy->chandef.chan,
404- &limits_array, tx_power);
405+ &la, tx_power);
406 mphy->txpower_cur = tx_power;
407
408- for (i = 0, idx = 0; i < ARRAY_SIZE(mt7915_sku_group_len); i++) {
409- u8 mcs_num, len = mt7915_sku_group_len[i];
410- int j;
411+ skb = mt76_mcu_msg_alloc(&dev->mt76, NULL,
412+ sizeof(hdr) + MT7915_SKU_RATE_NUM);
413+ if (!skb)
414+ return -ENOMEM;
415
416- if (i >= SKU_HT_BW20 && i <= SKU_VHT_BW160) {
417- mcs_num = 10;
418+ skb_put_data(skb, &hdr, sizeof(hdr));
419+ skb_put_data(skb, &la.cck, len[SKU_CCK] + len[SKU_OFDM]);
420+ skb_put_data(skb, &la.mcs[0], len[SKU_HT_BW20]);
421+ skb_put_data(skb, &la.mcs[1], len[SKU_HT_BW40]);
422
423- if (i == SKU_HT_BW20 || i == SKU_VHT_BW20)
424- la = (s8 *)&limits_array + 12;
425- } else {
426- mcs_num = len;
427- }
428+ /* vht */
429+ for (i = 0; i < 4; i++) {
430+ skb_put_data(skb, &la.mcs[i], sizeof(la.mcs[i]));
431+ skb_put_zero(skb, 2); /* padding */
432+ }
developerf520c8d2023-06-19 10:33:45 +0800433+
developerfe7be7f2022-12-13 21:40:24 +0800434+ /* he */
435+ skb_put_data(skb, &la.ru[0], sizeof(la.ru));
developer30d39c22022-12-16 10:29:49 +0800436
developerf520c8d2023-06-19 10:33:45 +0800437- for (j = 0; j < min_t(u8, mcs_num, len); j++)
438- req.txpower_sku[idx + j] = la[j];
developerfe7be7f2022-12-13 21:40:24 +0800439+ ret = mt76_mcu_skb_send_msg(&dev->mt76, skb,
440+ MCU_EXT_CMD(TX_POWER_FEATURE_CTRL), true);
441+ if (ret)
442+ return ret;
443+
444+ /* only set per-path power table when it's configured */
445+ if (!la.path.ofdm[0])
446+ return 0;
developerf520c8d2023-06-19 10:33:45 +0800447
448- la += mcs_num;
449- idx += len;
developerfe7be7f2022-12-13 21:40:24 +0800450+ skb = mt76_mcu_msg_alloc(&dev->mt76, NULL,
451+ sizeof(hdr) + MT7915_SKU_PATH_NUM);
452+ if (!skb)
453+ return -ENOMEM;
developer30d39c22022-12-16 10:29:49 +0800454+
developerfe7be7f2022-12-13 21:40:24 +0800455+ hdr.limit_type = TX_POWER_LIMIT_TABLE_PATH;
456+ skb_put_data(skb, &hdr, sizeof(hdr));
457+ skb_put_data(skb, &la.path.cck, sizeof(la.path.cck));
458+ skb_put_data(skb, &la.path.ofdm, sizeof(la.path.ofdm));
459+ skb_put_data(skb, &la.path.ofdm_bf[1], sizeof(la.path.ofdm_bf) - 1);
460+
461+ /* HT20 and HT40 */
developerf520c8d2023-06-19 10:33:45 +0800462+ skb_put_data(skb, &la.path.ru[3], sizeof(la.path.ru[3]));
463+ skb_put_data(skb, &la.path.ru_bf[3][1], sizeof(la.path.ru_bf[3]) - 1);
464+ skb_put_data(skb, &la.path.ru[4], sizeof(la.path.ru[4]));
465+ skb_put_data(skb, &la.path.ru_bf[4][1], sizeof(la.path.ru_bf[4]) - 1);
developerfe7be7f2022-12-13 21:40:24 +0800466+
467+ /* start from non-bf and bf fields of
468+ * BW20/RU242, BW40/RU484, BW80/RU996, BW160/RU2x996,
469+ * RU26, RU52, and RU106
470+ */
developerfe7be7f2022-12-13 21:40:24 +0800471+
developerf520c8d2023-06-19 10:33:45 +0800472+ for (i = 0; i < 8; i++) {
473+ bool bf = i % 2;
474+ u8 idx = (i + 6) / 2;
475+ s8 *buf = bf ? la.path.ru_bf[idx] : la.path.ru[idx];
developerfe7be7f2022-12-13 21:40:24 +0800476+ /* The non-bf fields of RU26 to RU106 are special cases */
developerf520c8d2023-06-19 10:33:45 +0800477+ if (bf)
developerfe7be7f2022-12-13 21:40:24 +0800478+ skb_put_data(skb, buf + 1, 9);
479+ else
480+ skb_put_data(skb, buf, 10);
481 }
482
483- return mt76_mcu_send_msg(&dev->mt76,
484- MCU_EXT_CMD(TX_POWER_FEATURE_CTRL), &req,
485- sizeof(req), true);
developerf520c8d2023-06-19 10:33:45 +0800486+ for (i = 0; i < 6; i++) {
487+ bool bf = i % 2;
488+ u8 idx = i / 2;
489+ s8 *buf = bf ? la.path.ru_bf[idx] : la.path.ru[idx];
490+
491+ skb_put_data(skb, buf, 10);
492+ }
493+
developerfe7be7f2022-12-13 21:40:24 +0800494+ return mt76_mcu_skb_send_msg(&dev->mt76, skb,
developer30d39c22022-12-16 10:29:49 +0800495+ MCU_EXT_CMD(TX_POWER_FEATURE_CTRL), true);
developerfe7be7f2022-12-13 21:40:24 +0800496 }
497
498-int mt7915_mcu_get_txpower_sku(struct mt7915_phy *phy, s8 *txpower, int len)
499+int mt7915_mcu_get_txpower_sku(struct mt7915_phy *phy, s8 *txpower, int len,
500+ u8 category)
501 {
502-#define RATE_POWER_INFO 2
503 struct mt7915_dev *dev = phy->dev;
504 struct {
505 u8 format_id;
developer2594fb72023-07-20 14:56:49 +0800506@@ -3397,10 +3453,9 @@ int mt7915_mcu_get_txpower_sku(struct mt7915_phy *phy, s8 *txpower, int len)
developerfe7be7f2022-12-13 21:40:24 +0800507 u8 _rsv;
508 } __packed req = {
509 .format_id = TX_POWER_LIMIT_INFO,
510- .category = RATE_POWER_INFO,
511+ .category = category,
512 .band_idx = phy->mt76->band_idx,
513 };
514- s8 txpower_sku[MT7915_SKU_RATE_NUM][2];
515 struct sk_buff *skb;
516 int ret, i;
517
developer2594fb72023-07-20 14:56:49 +0800518@@ -3410,9 +3465,15 @@ int mt7915_mcu_get_txpower_sku(struct mt7915_phy *phy, s8 *txpower, int len)
developerfe7be7f2022-12-13 21:40:24 +0800519 if (ret)
520 return ret;
521
522- memcpy(txpower_sku, skb->data + 4, sizeof(txpower_sku));
523- for (i = 0; i < len; i++)
524- txpower[i] = txpower_sku[i][req.band_idx];
525+ if (category == TX_POWER_INFO_RATE) {
526+ s8 res[MT7915_SKU_RATE_NUM][2];
527+
528+ memcpy(res, skb->data + 4, sizeof(res));
529+ for (i = 0; i < len; i++)
530+ txpower[i] = res[i][req.band_idx];
531+ } else if (category == TX_POWER_INFO_PATH) {
532+ memcpy(txpower, skb->data + 4, len);
533+ }
534
535 dev_kfree_skb(skb);
536
developer2594fb72023-07-20 14:56:49 +0800537@@ -3454,9 +3515,18 @@ int mt7915_mcu_set_sku_en(struct mt7915_phy *phy, bool enable)
developerfe7be7f2022-12-13 21:40:24 +0800538 .band_idx = phy->mt76->band_idx,
539 .sku_enable = enable,
540 };
541+ int ret;
542+
543+ ret = mt76_mcu_send_msg(&dev->mt76,
544+ MCU_EXT_CMD(TX_POWER_FEATURE_CTRL), &req,
545+ sizeof(req), true);
546+ if (ret)
547+ return ret;
548
549 pr_info("%s: enable = %d\n", __func__, enable);
550
551+ req.format_id = TX_POWER_LIMIT_PATH_ENABLE;
developer30d39c22022-12-16 10:29:49 +0800552+
developerfe7be7f2022-12-13 21:40:24 +0800553 return mt76_mcu_send_msg(&dev->mt76,
554 MCU_EXT_CMD(TX_POWER_FEATURE_CTRL), &req,
555 sizeof(req), true);
556diff --git a/mt7915/mcu.h b/mt7915/mcu.h
developer2594fb72023-07-20 14:56:49 +0800557index 3da650c..142bfc1 100644
developerfe7be7f2022-12-13 21:40:24 +0800558--- a/mt7915/mcu.h
559+++ b/mt7915/mcu.h
developerbbd45e12023-05-19 08:22:06 +0800560@@ -502,12 +502,18 @@ enum {
developerfe7be7f2022-12-13 21:40:24 +0800561
562 enum {
563 TX_POWER_LIMIT_ENABLE,
564+ TX_POWER_LIMIT_PATH_ENABLE = 0x3,
565 TX_POWER_LIMIT_TABLE = 0x4,
566 TX_POWER_LIMIT_INFO = 0x7,
567 TX_POWER_LIMIT_FRAME = 0x11,
568 TX_POWER_LIMIT_FRAME_MIN = 0x12,
569 };
570
571+enum {
572+ TX_POWER_INFO_PATH = 1,
573+ TX_POWER_INFO_RATE,
574+};
575+
576 enum {
577 SPR_ENABLE = 0x1,
578 SPR_ENABLE_SD = 0x3,
developer2594fb72023-07-20 14:56:49 +0800579@@ -770,7 +776,7 @@ static inline s8
580 mt7915_get_power_bound(struct mt7915_phy *phy, s8 txpower)
581 {
582 struct mt76_phy *mphy = phy->mt76;
583- int n_chains = hweight8(mphy->antenna_mask);
584+ int n_chains = hweight16(mphy->chainmask);
585
586 txpower = mt76_get_sar_power(mphy, mphy->chandef.chan, txpower * 2);
587 txpower -= mt76_tx_power_nss_delta(n_chains);
developerfe7be7f2022-12-13 21:40:24 +0800588diff --git a/mt7915/mt7915.h b/mt7915/mt7915.h
developerf520c8d2023-06-19 10:33:45 +0800589index bbcdd93..b80c607 100644
developerfe7be7f2022-12-13 21:40:24 +0800590--- a/mt7915/mt7915.h
591+++ b/mt7915/mt7915.h
developerbbd45e12023-05-19 08:22:06 +0800592@@ -72,6 +72,7 @@
developerfe7be7f2022-12-13 21:40:24 +0800593 #define MT7915_CDEV_THROTTLE_MAX 99
594
595 #define MT7915_SKU_RATE_NUM 161
596+#define MT7915_SKU_PATH_NUM 185
597
598 #define MT7915_MAX_TWT_AGRT 16
599 #define MT7915_MAX_STA_TWT_AGRT 8
developerf520c8d2023-06-19 10:33:45 +0800600@@ -570,7 +571,8 @@ int mt7915_mcu_set_test_param(struct mt7915_dev *dev, u8 param, bool test_mode,
developerfe7be7f2022-12-13 21:40:24 +0800601 int mt7915_mcu_set_ser(struct mt7915_dev *dev, u8 action, u8 set, u8 band);
602 int mt7915_mcu_set_sku_en(struct mt7915_phy *phy, bool enable);
603 int mt7915_mcu_set_txpower_sku(struct mt7915_phy *phy);
604-int mt7915_mcu_get_txpower_sku(struct mt7915_phy *phy, s8 *txpower, int len);
605+int mt7915_mcu_get_txpower_sku(struct mt7915_phy *phy, s8 *txpower, int len,
606+ u8 category);
607 int mt7915_mcu_set_txpower_frame_min(struct mt7915_phy *phy, s8 txpower);
608 int mt7915_mcu_set_txpower_frame(struct mt7915_phy *phy,
609 struct ieee80211_vif *vif,
610--
developer2324aa22023-04-12 11:30:15 +08006112.18.0
developerfe7be7f2022-12-13 21:40:24 +0800612