xref: /linux/drivers/net/wireless/mediatek/mt76/mt7925/debugfs.c (revision e7d759f31ca295d589f7420719c311870bb3166f)
1 // SPDX-License-Identifier: ISC
2 /* Copyright (C) 2023 MediaTek Inc. */
3 
4 #include "mt7925.h"
5 #include "mcu.h"
6 
7 static int
8 mt7925_reg_set(void *data, u64 val)
9 {
10 	struct mt792x_dev *dev = data;
11 	u32 regval = val;
12 
13 	mt792x_mutex_acquire(dev);
14 	mt7925_mcu_regval(dev, dev->mt76.debugfs_reg, &regval, true);
15 	mt792x_mutex_release(dev);
16 
17 	return 0;
18 }
19 
20 static int
21 mt7925_reg_get(void *data, u64 *val)
22 {
23 	struct mt792x_dev *dev = data;
24 	u32 regval;
25 	int ret;
26 
27 	mt792x_mutex_acquire(dev);
28 	ret = mt7925_mcu_regval(dev, dev->mt76.debugfs_reg, &regval, false);
29 	mt792x_mutex_release(dev);
30 	if (!ret)
31 		*val = regval;
32 
33 	return 0;
34 }
35 
36 DEFINE_DEBUGFS_ATTRIBUTE(fops_regval, mt7925_reg_get, mt7925_reg_set,
37 			 "0x%08llx\n");
38 static int
39 mt7925_fw_debug_set(void *data, u64 val)
40 {
41 	struct mt792x_dev *dev = data;
42 
43 	mt792x_mutex_acquire(dev);
44 
45 	dev->fw_debug = (u8)val;
46 	mt7925_mcu_fw_log_2_host(dev, dev->fw_debug);
47 
48 	mt792x_mutex_release(dev);
49 
50 	return 0;
51 }
52 
53 static int
54 mt7925_fw_debug_get(void *data, u64 *val)
55 {
56 	struct mt792x_dev *dev = data;
57 
58 	*val = dev->fw_debug;
59 
60 	return 0;
61 }
62 
63 DEFINE_DEBUGFS_ATTRIBUTE(fops_fw_debug, mt7925_fw_debug_get,
64 			 mt7925_fw_debug_set, "%lld\n");
65 
66 DEFINE_SHOW_ATTRIBUTE(mt792x_tx_stats);
67 
68 static void
69 mt7925_seq_puts_array(struct seq_file *file, const char *str,
70 		      s8 val[][2], int len, u8 band_idx)
71 {
72 	int i;
73 
74 	seq_printf(file, "%-22s:", str);
75 	for (i = 0; i < len; i++)
76 		if (val[i][band_idx] == 127)
77 			seq_printf(file, " %6s", "N.A");
78 		else
79 			seq_printf(file, " %6d", val[i][band_idx]);
80 	seq_puts(file, "\n");
81 }
82 
83 #define mt7925_print_txpwr_entry(prefix, rate, idx)	\
84 ({							\
85 	mt7925_seq_puts_array(s, #prefix " (tmac)",	\
86 			      txpwr->rate,		\
87 			      ARRAY_SIZE(txpwr->rate),	\
88 			      idx);			\
89 })
90 
91 static inline void
92 mt7925_eht_txpwr(struct seq_file *s, struct mt7925_txpwr *txpwr, u8 band_idx)
93 {
94 	seq_printf(s, "%-22s  %6s %6s %6s %6s %6s %6s %6s %6s %6s %6s %6s %6s %6s %6s %6s %6s\n",
95 		   " ", "mcs0", "mcs1", "mcs2", "mcs3", "mcs4", "mcs5",
96 		   "mcs6", "mcs7", "mcs8", "mcs9", "mcs10", "mcs11",
97 		   "mcs12", "mcs13", "mcs14", "mcs15");
98 	mt7925_print_txpwr_entry(EHT26, eht26, band_idx);
99 	mt7925_print_txpwr_entry(EHT52, eht52, band_idx);
100 	mt7925_print_txpwr_entry(EHT106, eht106, band_idx);
101 	mt7925_print_txpwr_entry(EHT242, eht242, band_idx);
102 	mt7925_print_txpwr_entry(EHT484, eht484, band_idx);
103 
104 	mt7925_print_txpwr_entry(EHT996, eht996, band_idx);
105 	mt7925_print_txpwr_entry(EHT996x2, eht996x2, band_idx);
106 	mt7925_print_txpwr_entry(EHT996x4, eht996x4, band_idx);
107 	mt7925_print_txpwr_entry(EHT26_52, eht26_52, band_idx);
108 	mt7925_print_txpwr_entry(EHT26_106, eht26_106, band_idx);
109 	mt7925_print_txpwr_entry(EHT484_242, eht484_242, band_idx);
110 	mt7925_print_txpwr_entry(EHT996_484, eht996_484, band_idx);
111 	mt7925_print_txpwr_entry(EHT996_484_242, eht996_484_242, band_idx);
112 	mt7925_print_txpwr_entry(EHT996x2_484, eht996x2_484, band_idx);
113 	mt7925_print_txpwr_entry(EHT996x3, eht996x3, band_idx);
114 	mt7925_print_txpwr_entry(EHT996x3_484, eht996x3_484, band_idx);
115 }
116 
117 static int
118 mt7925_txpwr(struct seq_file *s, void *data)
119 {
120 	struct mt792x_dev *dev = dev_get_drvdata(s->private);
121 	struct mt7925_txpwr *txpwr = NULL;
122 	u8 band_idx = dev->mphy.band_idx;
123 	int ret = 0;
124 
125 	txpwr = devm_kmalloc(dev->mt76.dev, sizeof(*txpwr), GFP_KERNEL);
126 
127 	if (!txpwr)
128 		return -ENOMEM;
129 
130 	mt792x_mutex_acquire(dev);
131 	ret = mt7925_get_txpwr_info(dev, band_idx, txpwr);
132 	mt792x_mutex_release(dev);
133 
134 	if (ret)
135 		goto out;
136 
137 	seq_printf(s, "%-22s  %6s %6s %6s %6s\n",
138 		   " ", "1m", "2m", "5m", "11m");
139 	mt7925_print_txpwr_entry(CCK, cck, band_idx);
140 
141 	seq_printf(s, "%-22s  %6s %6s %6s %6s %6s %6s %6s %6s\n",
142 		   " ", "6m", "9m", "12m", "18m", "24m", "36m",
143 		   "48m", "54m");
144 	mt7925_print_txpwr_entry(OFDM, ofdm, band_idx);
145 
146 	seq_printf(s, "%-22s  %6s %6s %6s %6s %6s %6s %6s %6s\n",
147 		   " ", "mcs0", "mcs1", "mcs2", "mcs3", "mcs4", "mcs5",
148 		   "mcs6", "mcs7");
149 	mt7925_print_txpwr_entry(HT20, ht20, band_idx);
150 
151 	seq_printf(s, "%-22s  %6s %6s %6s %6s %6s %6s %6s %6s %6s\n",
152 		   " ", "mcs0", "mcs1", "mcs2", "mcs3", "mcs4", "mcs5",
153 		   "mcs6", "mcs7", "mcs32");
154 	mt7925_print_txpwr_entry(HT40, ht40, band_idx);
155 
156 	seq_printf(s, "%-22s  %6s %6s %6s %6s %6s %6s %6s %6s %6s %6s %6s %6s\n",
157 		   " ", "mcs0", "mcs1", "mcs2", "mcs3", "mcs4", "mcs5",
158 		   "mcs6", "mcs7", "mcs8", "mcs9", "mcs10", "mcs11");
159 	mt7925_print_txpwr_entry(VHT20, vht20, band_idx);
160 	mt7925_print_txpwr_entry(VHT40, vht40, band_idx);
161 
162 	mt7925_print_txpwr_entry(VHT80, vht80, band_idx);
163 	mt7925_print_txpwr_entry(VHT160, vht160, band_idx);
164 
165 	mt7925_print_txpwr_entry(HE26, he26, band_idx);
166 	mt7925_print_txpwr_entry(HE52, he52, band_idx);
167 	mt7925_print_txpwr_entry(HE106, he106, band_idx);
168 	mt7925_print_txpwr_entry(HE242, he242, band_idx);
169 	mt7925_print_txpwr_entry(HE484, he484, band_idx);
170 
171 	mt7925_print_txpwr_entry(HE996, he996, band_idx);
172 	mt7925_print_txpwr_entry(HE996x2, he996x2, band_idx);
173 
174 	mt7925_eht_txpwr(s, txpwr, band_idx);
175 
176 out:
177 	devm_kfree(dev->mt76.dev, txpwr);
178 	return ret;
179 }
180 
181 static int
182 mt7925_pm_set(void *data, u64 val)
183 {
184 	struct mt792x_dev *dev = data;
185 	struct mt76_connac_pm *pm = &dev->pm;
186 
187 	if (mt76_is_usb(&dev->mt76))
188 		return -EOPNOTSUPP;
189 
190 	mutex_lock(&dev->mt76.mutex);
191 
192 	if (val == pm->enable_user)
193 		goto out;
194 
195 	if (!pm->enable_user) {
196 		pm->stats.last_wake_event = jiffies;
197 		pm->stats.last_doze_event = jiffies;
198 	}
199 	/* make sure the chip is awake here and ps_work is scheduled
200 	 * just at end of the this routine.
201 	 */
202 	pm->enable = false;
203 	mt76_connac_pm_wake(&dev->mphy, pm);
204 
205 	pm->enable_user = val;
206 	mt7925_set_runtime_pm(dev);
207 	mt76_connac_power_save_sched(&dev->mphy, pm);
208 out:
209 	mutex_unlock(&dev->mt76.mutex);
210 
211 	return 0;
212 }
213 
214 static int
215 mt7925_pm_get(void *data, u64 *val)
216 {
217 	struct mt792x_dev *dev = data;
218 
219 	*val = dev->pm.enable_user;
220 
221 	return 0;
222 }
223 
224 DEFINE_DEBUGFS_ATTRIBUTE(fops_pm, mt7925_pm_get, mt7925_pm_set, "%lld\n");
225 
226 static int
227 mt7925_deep_sleep_set(void *data, u64 val)
228 {
229 	struct mt792x_dev *dev = data;
230 	struct mt76_connac_pm *pm = &dev->pm;
231 	bool monitor = !!(dev->mphy.hw->conf.flags & IEEE80211_CONF_MONITOR);
232 	bool enable = !!val;
233 
234 	if (mt76_is_usb(&dev->mt76))
235 		return -EOPNOTSUPP;
236 
237 	mt792x_mutex_acquire(dev);
238 	if (pm->ds_enable_user == enable)
239 		goto out;
240 
241 	pm->ds_enable_user = enable;
242 	pm->ds_enable = enable && !monitor;
243 	mt7925_mcu_set_deep_sleep(dev, pm->ds_enable);
244 out:
245 	mt792x_mutex_release(dev);
246 
247 	return 0;
248 }
249 
250 static int
251 mt7925_deep_sleep_get(void *data, u64 *val)
252 {
253 	struct mt792x_dev *dev = data;
254 
255 	*val = dev->pm.ds_enable_user;
256 
257 	return 0;
258 }
259 
260 DEFINE_DEBUGFS_ATTRIBUTE(fops_ds, mt7925_deep_sleep_get,
261 			 mt7925_deep_sleep_set, "%lld\n");
262 
263 DEFINE_DEBUGFS_ATTRIBUTE(fops_pm_idle_timeout, mt792x_pm_idle_timeout_get,
264 			 mt792x_pm_idle_timeout_set, "%lld\n");
265 
266 static int mt7925_chip_reset(void *data, u64 val)
267 {
268 	struct mt792x_dev *dev = data;
269 	int ret = 0;
270 
271 	switch (val) {
272 	case 1:
273 		/* Reset wifisys directly. */
274 		mt792x_reset(&dev->mt76);
275 		break;
276 	default:
277 		/* Collect the core dump before reset wifisys. */
278 		mt792x_mutex_acquire(dev);
279 		ret = mt7925_mcu_chip_config(dev, "assert");
280 		mt792x_mutex_release(dev);
281 		break;
282 	}
283 
284 	return ret;
285 }
286 
287 DEFINE_DEBUGFS_ATTRIBUTE(fops_reset, NULL, mt7925_chip_reset, "%lld\n");
288 
289 int mt7925_init_debugfs(struct mt792x_dev *dev)
290 {
291 	struct dentry *dir;
292 
293 	dir = mt76_register_debugfs_fops(&dev->mphy, &fops_regval);
294 	if (!dir)
295 		return -ENOMEM;
296 
297 	if (mt76_is_mmio(&dev->mt76))
298 		debugfs_create_devm_seqfile(dev->mt76.dev, "xmit-queues",
299 					    dir, mt792x_queues_read);
300 	else
301 		debugfs_create_devm_seqfile(dev->mt76.dev, "xmit-queues",
302 					    dir, mt76_queues_read);
303 
304 	debugfs_create_devm_seqfile(dev->mt76.dev, "acq", dir,
305 				    mt792x_queues_acq);
306 	debugfs_create_devm_seqfile(dev->mt76.dev, "txpower_sku", dir,
307 				    mt7925_txpwr);
308 	debugfs_create_file("tx_stats", 0400, dir, dev, &mt792x_tx_stats_fops);
309 	debugfs_create_file("fw_debug", 0600, dir, dev, &fops_fw_debug);
310 	debugfs_create_file("runtime-pm", 0600, dir, dev, &fops_pm);
311 	debugfs_create_file("idle-timeout", 0600, dir, dev,
312 			    &fops_pm_idle_timeout);
313 	debugfs_create_file("chip_reset", 0600, dir, dev, &fops_reset);
314 	debugfs_create_devm_seqfile(dev->mt76.dev, "runtime_pm_stats", dir,
315 				    mt792x_pm_stats);
316 	debugfs_create_file("deep-sleep", 0600, dir, dev, &fops_ds);
317 
318 	return 0;
319 }
320