1
2
3
4#include "mt7921.h"
5#include "eeprom.h"
6
7static int
8mt7921_fw_debug_set(void *data, u64 val)
9{
10 struct mt7921_dev *dev = data;
11
12 mt7921_mutex_acquire(dev);
13
14 dev->fw_debug = (u8)val;
15 mt7921_mcu_fw_log_2_host(dev, dev->fw_debug);
16
17 mt7921_mutex_release(dev);
18
19 return 0;
20}
21
22static int
23mt7921_fw_debug_get(void *data, u64 *val)
24{
25 struct mt7921_dev *dev = data;
26
27 *val = dev->fw_debug;
28
29 return 0;
30}
31
32DEFINE_DEBUGFS_ATTRIBUTE(fops_fw_debug, mt7921_fw_debug_get,
33 mt7921_fw_debug_set, "%lld\n");
34
35static void
36mt7921_ampdu_stat_read_phy(struct mt7921_phy *phy,
37 struct seq_file *file)
38{
39 struct mt7921_dev *dev = file->private;
40 int bound[15], range[4], i;
41
42 if (!phy)
43 return;
44
45
46 for (i = 0; i < ARRAY_SIZE(range); i++)
47 range[i] = mt76_rr(dev, MT_MIB_ARNG(0, i));
48
49 for (i = 0; i < ARRAY_SIZE(bound); i++)
50 bound[i] = MT_MIB_ARNCR_RANGE(range[i / 4], i % 4) + 1;
51
52 seq_printf(file, "\nPhy0\n");
53
54 seq_printf(file, "Length: %8d | ", bound[0]);
55 for (i = 0; i < ARRAY_SIZE(bound) - 1; i++)
56 seq_printf(file, "%3d %3d | ", bound[i] + 1, bound[i + 1]);
57
58 seq_puts(file, "\nCount: ");
59 for (i = 0; i < ARRAY_SIZE(bound); i++)
60 seq_printf(file, "%8d | ", dev->mt76.aggr_stats[i]);
61 seq_puts(file, "\n");
62
63 seq_printf(file, "BA miss count: %d\n", phy->mib.ba_miss_cnt);
64}
65
66static int
67mt7921_tx_stats_show(struct seq_file *file, void *data)
68{
69 struct mt7921_dev *dev = file->private;
70 int stat[8], i, n;
71
72 mt7921_ampdu_stat_read_phy(&dev->phy, file);
73
74
75 seq_puts(file, "Tx MSDU stat:\n");
76 for (i = 0, n = 0; i < ARRAY_SIZE(stat); i++) {
77 stat[i] = mt76_rr(dev, MT_PLE_AMSDU_PACK_MSDU_CNT(i));
78 n += stat[i];
79 }
80
81 for (i = 0; i < ARRAY_SIZE(stat); i++) {
82 seq_printf(file, "AMSDU pack count of %d MSDU in TXD: 0x%x ",
83 i + 1, stat[i]);
84 if (n != 0)
85 seq_printf(file, "(%d%%)\n", stat[i] * 100 / n);
86 else
87 seq_puts(file, "\n");
88 }
89
90 return 0;
91}
92
93DEFINE_SHOW_ATTRIBUTE(mt7921_tx_stats);
94
95static int
96mt7921_queues_acq(struct seq_file *s, void *data)
97{
98 struct mt7921_dev *dev = dev_get_drvdata(s->private);
99 int i;
100
101 for (i = 0; i < 16; i++) {
102 int j, acs = i / 4, index = i % 4;
103 u32 ctrl, val, qlen = 0;
104
105 val = mt76_rr(dev, MT_PLE_AC_QEMPTY(acs, index));
106 ctrl = BIT(31) | BIT(15) | (acs << 8);
107
108 for (j = 0; j < 32; j++) {
109 if (val & BIT(j))
110 continue;
111
112 mt76_wr(dev, MT_PLE_FL_Q0_CTRL,
113 ctrl | (j + (index << 5)));
114 qlen += mt76_get_field(dev, MT_PLE_FL_Q3_CTRL,
115 GENMASK(11, 0));
116 }
117 seq_printf(s, "AC%d%d: queued=%d\n", acs, index, qlen);
118 }
119
120 return 0;
121}
122
123static int
124mt7921_queues_read(struct seq_file *s, void *data)
125{
126 struct mt7921_dev *dev = dev_get_drvdata(s->private);
127 struct {
128 struct mt76_queue *q;
129 char *queue;
130 } queue_map[] = {
131 { dev->mphy.q_tx[MT_TXQ_BE], "WFDMA0" },
132 { dev->mt76.q_mcu[MT_MCUQ_WM], "MCUWM" },
133 { dev->mt76.q_mcu[MT_MCUQ_FWDL], "MCUFWQ" },
134 };
135 int i;
136
137 for (i = 0; i < ARRAY_SIZE(queue_map); i++) {
138 struct mt76_queue *q = queue_map[i].q;
139
140 if (!q)
141 continue;
142
143 seq_printf(s,
144 "%s: queued=%d head=%d tail=%d\n",
145 queue_map[i].queue, q->queued, q->head,
146 q->tail);
147 }
148
149 return 0;
150}
151
152static void
153mt7921_seq_puts_array(struct seq_file *file, const char *str,
154 s8 *val, int len)
155{
156 int i;
157
158 seq_printf(file, "%-16s:", str);
159 for (i = 0; i < len; i++)
160 if (val[i] == 127)
161 seq_printf(file, " %6s", "N.A");
162 else
163 seq_printf(file, " %6d", val[i]);
164 seq_puts(file, "\n");
165}
166
167#define mt7921_print_txpwr_entry(prefix, rate) \
168({ \
169 mt7921_seq_puts_array(s, #prefix " (user)", \
170 txpwr.data[TXPWR_USER].rate, \
171 ARRAY_SIZE(txpwr.data[TXPWR_USER].rate)); \
172 mt7921_seq_puts_array(s, #prefix " (eeprom)", \
173 txpwr.data[TXPWR_EEPROM].rate, \
174 ARRAY_SIZE(txpwr.data[TXPWR_EEPROM].rate)); \
175 mt7921_seq_puts_array(s, #prefix " (tmac)", \
176 txpwr.data[TXPWR_MAC].rate, \
177 ARRAY_SIZE(txpwr.data[TXPWR_MAC].rate)); \
178})
179
180static int
181mt7921_txpwr(struct seq_file *s, void *data)
182{
183 struct mt7921_dev *dev = dev_get_drvdata(s->private);
184 struct mt7921_txpwr txpwr;
185 int ret;
186
187 mt7921_mutex_acquire(dev);
188 ret = mt7921_get_txpwr_info(dev, &txpwr);
189 mt7921_mutex_release(dev);
190
191 if (ret)
192 return ret;
193
194 seq_printf(s, "Tx power table (channel %d)\n", txpwr.ch);
195 seq_printf(s, "%-16s %6s %6s %6s %6s\n",
196 " ", "1m", "2m", "5m", "11m");
197 mt7921_print_txpwr_entry(CCK, cck);
198
199 seq_printf(s, "%-16s %6s %6s %6s %6s %6s %6s %6s %6s\n",
200 " ", "6m", "9m", "12m", "18m", "24m", "36m",
201 "48m", "54m");
202 mt7921_print_txpwr_entry(OFDM, ofdm);
203
204 seq_printf(s, "%-16s %6s %6s %6s %6s %6s %6s %6s %6s\n",
205 " ", "mcs0", "mcs1", "mcs2", "mcs3", "mcs4", "mcs5",
206 "mcs6", "mcs7");
207 mt7921_print_txpwr_entry(HT20, ht20);
208
209 seq_printf(s, "%-16s %6s %6s %6s %6s %6s %6s %6s %6s %6s\n",
210 " ", "mcs0", "mcs1", "mcs2", "mcs3", "mcs4", "mcs5",
211 "mcs6", "mcs7", "mcs32");
212 mt7921_print_txpwr_entry(HT40, ht40);
213
214 seq_printf(s, "%-16s %6s %6s %6s %6s %6s %6s %6s %6s %6s %6s %6s %6s\n",
215 " ", "mcs0", "mcs1", "mcs2", "mcs3", "mcs4", "mcs5",
216 "mcs6", "mcs7", "mcs8", "mcs9", "mcs10", "mcs11");
217 mt7921_print_txpwr_entry(VHT20, vht20);
218 mt7921_print_txpwr_entry(VHT40, vht40);
219 mt7921_print_txpwr_entry(VHT80, vht80);
220 mt7921_print_txpwr_entry(VHT160, vht160);
221 mt7921_print_txpwr_entry(HE26, he26);
222 mt7921_print_txpwr_entry(HE52, he52);
223 mt7921_print_txpwr_entry(HE106, he106);
224 mt7921_print_txpwr_entry(HE242, he242);
225 mt7921_print_txpwr_entry(HE484, he484);
226 mt7921_print_txpwr_entry(HE996, he996);
227 mt7921_print_txpwr_entry(HE996x2, he996x2);
228
229 return 0;
230}
231
232static int
233mt7921_pm_set(void *data, u64 val)
234{
235 struct mt7921_dev *dev = data;
236 struct mt76_connac_pm *pm = &dev->pm;
237 struct mt76_phy *mphy = dev->phy.mt76;
238
239 if (val == pm->enable)
240 return 0;
241
242 mt7921_mutex_acquire(dev);
243
244 if (!pm->enable) {
245 pm->stats.last_wake_event = jiffies;
246 pm->stats.last_doze_event = jiffies;
247 }
248 pm->enable = val;
249
250 ieee80211_iterate_active_interfaces(mphy->hw,
251 IEEE80211_IFACE_ITER_RESUME_ALL,
252 mt7921_pm_interface_iter, mphy->priv);
253
254 mt76_connac_mcu_set_deep_sleep(&dev->mt76, pm->ds_enable);
255
256 mt7921_mutex_release(dev);
257
258 return 0;
259}
260
261static int
262mt7921_pm_get(void *data, u64 *val)
263{
264 struct mt7921_dev *dev = data;
265
266 *val = dev->pm.enable;
267
268 return 0;
269}
270
271DEFINE_DEBUGFS_ATTRIBUTE(fops_pm, mt7921_pm_get, mt7921_pm_set, "%lld\n");
272
273static int
274mt7921_deep_sleep_set(void *data, u64 val)
275{
276 struct mt7921_dev *dev = data;
277 struct mt76_connac_pm *pm = &dev->pm;
278 bool enable = !!val;
279
280 mt7921_mutex_acquire(dev);
281 if (pm->ds_enable != enable) {
282 mt76_connac_mcu_set_deep_sleep(&dev->mt76, enable);
283 pm->ds_enable = enable;
284 }
285 mt7921_mutex_release(dev);
286
287 return 0;
288}
289
290static int
291mt7921_deep_sleep_get(void *data, u64 *val)
292{
293 struct mt7921_dev *dev = data;
294
295 *val = dev->pm.ds_enable;
296
297 return 0;
298}
299
300DEFINE_DEBUGFS_ATTRIBUTE(fops_ds, mt7921_deep_sleep_get,
301 mt7921_deep_sleep_set, "%lld\n");
302
303static int
304mt7921_pm_stats(struct seq_file *s, void *data)
305{
306 struct mt7921_dev *dev = dev_get_drvdata(s->private);
307 struct mt76_connac_pm *pm = &dev->pm;
308
309 unsigned long awake_time = pm->stats.awake_time;
310 unsigned long doze_time = pm->stats.doze_time;
311
312 if (!test_bit(MT76_STATE_PM, &dev->mphy.state))
313 awake_time += jiffies - pm->stats.last_wake_event;
314 else
315 doze_time += jiffies - pm->stats.last_doze_event;
316
317 seq_printf(s, "awake time: %14u\ndoze time: %15u\n",
318 jiffies_to_msecs(awake_time),
319 jiffies_to_msecs(doze_time));
320
321 seq_printf(s, "low power wakes: %9d\n", pm->stats.lp_wake);
322
323 return 0;
324}
325
326static int
327mt7921_pm_idle_timeout_set(void *data, u64 val)
328{
329 struct mt7921_dev *dev = data;
330
331 dev->pm.idle_timeout = msecs_to_jiffies(val);
332
333 return 0;
334}
335
336static int
337mt7921_pm_idle_timeout_get(void *data, u64 *val)
338{
339 struct mt7921_dev *dev = data;
340
341 *val = jiffies_to_msecs(dev->pm.idle_timeout);
342
343 return 0;
344}
345
346DEFINE_DEBUGFS_ATTRIBUTE(fops_pm_idle_timeout, mt7921_pm_idle_timeout_get,
347 mt7921_pm_idle_timeout_set, "%lld\n");
348
349static int mt7921_chip_reset(void *data, u64 val)
350{
351 struct mt7921_dev *dev = data;
352 int ret = 0;
353
354 switch (val) {
355 case 1:
356
357 mt7921_reset(&dev->mt76);
358 break;
359 default:
360
361 mt7921_mutex_acquire(dev);
362 ret = mt76_connac_mcu_chip_config(&dev->mt76);
363 mt7921_mutex_release(dev);
364 break;
365 }
366
367 return ret;
368}
369
370DEFINE_DEBUGFS_ATTRIBUTE(fops_reset, NULL, mt7921_chip_reset, "%lld\n");
371
372int mt7921_init_debugfs(struct mt7921_dev *dev)
373{
374 struct dentry *dir;
375
376 dir = mt76_register_debugfs(&dev->mt76);
377 if (!dir)
378 return -ENOMEM;
379
380 debugfs_create_devm_seqfile(dev->mt76.dev, "queues", dir,
381 mt7921_queues_read);
382 debugfs_create_devm_seqfile(dev->mt76.dev, "acq", dir,
383 mt7921_queues_acq);
384 debugfs_create_devm_seqfile(dev->mt76.dev, "txpower_sku", dir,
385 mt7921_txpwr);
386 debugfs_create_file("tx_stats", 0400, dir, dev, &mt7921_tx_stats_fops);
387 debugfs_create_file("fw_debug", 0600, dir, dev, &fops_fw_debug);
388 debugfs_create_file("runtime-pm", 0600, dir, dev, &fops_pm);
389 debugfs_create_file("idle-timeout", 0600, dir, dev,
390 &fops_pm_idle_timeout);
391 debugfs_create_file("chip_reset", 0600, dir, dev, &fops_reset);
392 debugfs_create_devm_seqfile(dev->mt76.dev, "runtime_pm_stats", dir,
393 mt7921_pm_stats);
394 debugfs_create_file("deep-sleep", 0600, dir, dev, &fops_ds);
395
396 return 0;
397}
398