1 // SPDX-License-Identifier: ISC
2 /* Copyright (C) 2020 MediaTek Inc. */
8 mt7921_fw_debug_set(void *data, u64 val)
10 struct mt7921_dev *dev = data;
12 mt7921_mutex_acquire(dev);
14 dev->fw_debug = (u8)val;
15 mt7921_mcu_fw_log_2_host(dev, dev->fw_debug);
17 mt7921_mutex_release(dev);
23 mt7921_fw_debug_get(void *data, u64 *val)
25 struct mt7921_dev *dev = data;
32 DEFINE_DEBUGFS_ATTRIBUTE(fops_fw_debug, mt7921_fw_debug_get,
33 mt7921_fw_debug_set, "%lld\n");
36 mt7921_ampdu_stat_read_phy(struct mt7921_phy *phy,
37 struct seq_file *file)
39 struct mt7921_dev *dev = file->private;
40 int bound[15], range[4], i;
46 for (i = 0; i < ARRAY_SIZE(range); i++)
47 range[i] = mt76_rr(dev, MT_MIB_ARNG(0, i));
49 for (i = 0; i < ARRAY_SIZE(bound); i++)
50 bound[i] = MT_MIB_ARNCR_RANGE(range[i / 4], i % 4) + 1;
52 seq_printf(file, "\nPhy0\n");
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]);
58 seq_puts(file, "\nCount: ");
59 for (i = 0; i < ARRAY_SIZE(bound); i++)
60 seq_printf(file, "%8d | ", dev->mt76.aggr_stats[i]);
63 seq_printf(file, "BA miss count: %d\n", phy->mib.ba_miss_cnt);
67 mt7921_tx_stats_show(struct seq_file *file, void *data)
69 struct mt7921_dev *dev = file->private;
72 mt7921_ampdu_stat_read_phy(&dev->phy, file);
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));
81 for (i = 0; i < ARRAY_SIZE(stat); i++) {
82 seq_printf(file, "AMSDU pack count of %d MSDU in TXD: 0x%x ",
85 seq_printf(file, "(%d%%)\n", stat[i] * 100 / n);
93 DEFINE_SHOW_ATTRIBUTE(mt7921_tx_stats);
96 mt7921_queues_acq(struct seq_file *s, void *data)
98 struct mt7921_dev *dev = dev_get_drvdata(s->private);
101 for (i = 0; i < 16; i++) {
102 int j, acs = i / 4, index = i % 4;
103 u32 ctrl, val, qlen = 0;
105 val = mt76_rr(dev, MT_PLE_AC_QEMPTY(acs, index));
106 ctrl = BIT(31) | BIT(15) | (acs << 8);
108 for (j = 0; j < 32; j++) {
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,
117 seq_printf(s, "AC%d%d: queued=%d\n", acs, index, qlen);
124 mt7921_queues_read(struct seq_file *s, void *data)
126 struct mt7921_dev *dev = dev_get_drvdata(s->private);
128 struct mt76_queue *q;
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" },
137 for (i = 0; i < ARRAY_SIZE(queue_map); i++) {
138 struct mt76_queue *q = queue_map[i].q;
144 "%s: queued=%d head=%d tail=%d\n",
145 queue_map[i].queue, q->queued, q->head,
153 mt7921_seq_puts_array(struct seq_file *file, const char *str,
158 seq_printf(file, "%-16s:", str);
159 for (i = 0; i < len; i++)
161 seq_printf(file, " %6s", "N.A");
163 seq_printf(file, " %6d", val[i]);
164 seq_puts(file, "\n");
167 #define mt7921_print_txpwr_entry(prefix, rate) \
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)); \
181 mt7921_txpwr(struct seq_file *s, void *data)
183 struct mt7921_dev *dev = dev_get_drvdata(s->private);
184 struct mt7921_txpwr txpwr;
187 ret = mt7921_get_txpwr_info(dev, &txpwr);
191 seq_printf(s, "Tx power table (channel %d)\n", txpwr.ch);
192 seq_printf(s, "%-16s %6s %6s %6s %6s\n",
193 " ", "1m", "2m", "5m", "11m");
194 mt7921_print_txpwr_entry(CCK, cck);
196 seq_printf(s, "%-16s %6s %6s %6s %6s %6s %6s %6s %6s\n",
197 " ", "6m", "9m", "12m", "18m", "24m", "36m",
199 mt7921_print_txpwr_entry(OFDM, ofdm);
201 seq_printf(s, "%-16s %6s %6s %6s %6s %6s %6s %6s %6s\n",
202 " ", "mcs0", "mcs1", "mcs2", "mcs3", "mcs4", "mcs5",
204 mt7921_print_txpwr_entry(HT20, ht20);
206 seq_printf(s, "%-16s %6s %6s %6s %6s %6s %6s %6s %6s %6s\n",
207 " ", "mcs0", "mcs1", "mcs2", "mcs3", "mcs4", "mcs5",
208 "mcs6", "mcs7", "mcs32");
209 mt7921_print_txpwr_entry(HT40, ht40);
211 seq_printf(s, "%-16s %6s %6s %6s %6s %6s %6s %6s %6s %6s %6s %6s %6s\n",
212 " ", "mcs0", "mcs1", "mcs2", "mcs3", "mcs4", "mcs5",
213 "mcs6", "mcs7", "mcs8", "mcs9", "mcs10", "mcs11");
214 mt7921_print_txpwr_entry(VHT20, vht20);
215 mt7921_print_txpwr_entry(VHT40, vht40);
216 mt7921_print_txpwr_entry(VHT80, vht80);
217 mt7921_print_txpwr_entry(VHT160, vht160);
218 mt7921_print_txpwr_entry(HE26, he26);
219 mt7921_print_txpwr_entry(HE52, he52);
220 mt7921_print_txpwr_entry(HE106, he106);
221 mt7921_print_txpwr_entry(HE242, he242);
222 mt7921_print_txpwr_entry(HE484, he484);
223 mt7921_print_txpwr_entry(HE996, he996);
224 mt7921_print_txpwr_entry(HE996x2, he996x2);
230 mt7921_pm_set(void *data, u64 val)
232 struct mt7921_dev *dev = data;
233 struct mt76_connac_pm *pm = &dev->pm;
234 struct mt76_phy *mphy = dev->phy.mt76;
236 if (val == pm->enable)
239 mt7921_mutex_acquire(dev);
242 pm->stats.last_wake_event = jiffies;
243 pm->stats.last_doze_event = jiffies;
247 ieee80211_iterate_active_interfaces(mphy->hw,
248 IEEE80211_IFACE_ITER_RESUME_ALL,
249 mt7921_pm_interface_iter, mphy->priv);
250 mt7921_mutex_release(dev);
256 mt7921_pm_get(void *data, u64 *val)
258 struct mt7921_dev *dev = data;
260 *val = dev->pm.enable;
265 DEFINE_DEBUGFS_ATTRIBUTE(fops_pm, mt7921_pm_get, mt7921_pm_set, "%lld\n");
268 mt7921_pm_stats(struct seq_file *s, void *data)
270 struct mt7921_dev *dev = dev_get_drvdata(s->private);
271 struct mt76_connac_pm *pm = &dev->pm;
273 unsigned long awake_time = pm->stats.awake_time;
274 unsigned long doze_time = pm->stats.doze_time;
276 if (!test_bit(MT76_STATE_PM, &dev->mphy.state))
277 awake_time += jiffies - pm->stats.last_wake_event;
279 doze_time += jiffies - pm->stats.last_doze_event;
281 seq_printf(s, "awake time: %14u\ndoze time: %15u\n",
282 jiffies_to_msecs(awake_time),
283 jiffies_to_msecs(doze_time));
285 seq_printf(s, "low power wakes: %9d\n", pm->stats.lp_wake);
291 mt7921_pm_idle_timeout_set(void *data, u64 val)
293 struct mt7921_dev *dev = data;
295 dev->pm.idle_timeout = msecs_to_jiffies(val);
301 mt7921_pm_idle_timeout_get(void *data, u64 *val)
303 struct mt7921_dev *dev = data;
305 *val = jiffies_to_msecs(dev->pm.idle_timeout);
310 DEFINE_DEBUGFS_ATTRIBUTE(fops_pm_idle_timeout, mt7921_pm_idle_timeout_get,
311 mt7921_pm_idle_timeout_set, "%lld\n");
313 static int mt7921_chip_reset(void *data, u64 val)
315 struct mt7921_dev *dev = data;
320 /* Reset wifisys directly. */
321 mt7921_reset(&dev->mt76);
324 /* Collect the core dump before reset wifisys. */
325 mt7921_mutex_acquire(dev);
326 ret = mt76_connac_mcu_chip_config(&dev->mt76);
327 mt7921_mutex_release(dev);
334 DEFINE_DEBUGFS_ATTRIBUTE(fops_reset, NULL, mt7921_chip_reset, "%lld\n");
336 int mt7921_init_debugfs(struct mt7921_dev *dev)
340 dir = mt76_register_debugfs(&dev->mt76);
344 debugfs_create_devm_seqfile(dev->mt76.dev, "queues", dir,
346 debugfs_create_devm_seqfile(dev->mt76.dev, "acq", dir,
348 debugfs_create_devm_seqfile(dev->mt76.dev, "txpower_sku", dir,
350 debugfs_create_file("tx_stats", 0400, dir, dev, &mt7921_tx_stats_fops);
351 debugfs_create_file("fw_debug", 0600, dir, dev, &fops_fw_debug);
352 debugfs_create_file("runtime-pm", 0600, dir, dev, &fops_pm);
353 debugfs_create_file("idle-timeout", 0600, dir, dev,
354 &fops_pm_idle_timeout);
355 debugfs_create_file("chip_reset", 0600, dir, dev, &fops_reset);
356 debugfs_create_devm_seqfile(dev->mt76.dev, "runtime_pm_stats", dir,