xref: /linux/drivers/net/wireless/mediatek/mt7601u/debugfs.c (revision c869f77d6abb5d5f9f2f1a661d5c53862a9cad34)
1*c869f77dSJakub Kicinski /*
2*c869f77dSJakub Kicinski  * Copyright (C) 2014 Felix Fietkau <nbd@openwrt.org>
3*c869f77dSJakub Kicinski  * Copyright (C) 2015 Jakub Kicinski <kubakici@wp.pl>
4*c869f77dSJakub Kicinski  *
5*c869f77dSJakub Kicinski  * This program is free software; you can redistribute it and/or modify
6*c869f77dSJakub Kicinski  * it under the terms of the GNU General Public License version 2
7*c869f77dSJakub Kicinski  * as published by the Free Software Foundation
8*c869f77dSJakub Kicinski  *
9*c869f77dSJakub Kicinski  * This program is distributed in the hope that it will be useful,
10*c869f77dSJakub Kicinski  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11*c869f77dSJakub Kicinski  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12*c869f77dSJakub Kicinski  * GNU General Public License for more details.
13*c869f77dSJakub Kicinski  */
14*c869f77dSJakub Kicinski 
15*c869f77dSJakub Kicinski #include <linux/debugfs.h>
16*c869f77dSJakub Kicinski 
17*c869f77dSJakub Kicinski #include "mt7601u.h"
18*c869f77dSJakub Kicinski #include "eeprom.h"
19*c869f77dSJakub Kicinski 
20*c869f77dSJakub Kicinski static int
21*c869f77dSJakub Kicinski mt76_reg_set(void *data, u64 val)
22*c869f77dSJakub Kicinski {
23*c869f77dSJakub Kicinski 	struct mt7601u_dev *dev = data;
24*c869f77dSJakub Kicinski 
25*c869f77dSJakub Kicinski 	mt76_wr(dev, dev->debugfs_reg, val);
26*c869f77dSJakub Kicinski 	return 0;
27*c869f77dSJakub Kicinski }
28*c869f77dSJakub Kicinski 
29*c869f77dSJakub Kicinski static int
30*c869f77dSJakub Kicinski mt76_reg_get(void *data, u64 *val)
31*c869f77dSJakub Kicinski {
32*c869f77dSJakub Kicinski 	struct mt7601u_dev *dev = data;
33*c869f77dSJakub Kicinski 
34*c869f77dSJakub Kicinski 	*val = mt76_rr(dev, dev->debugfs_reg);
35*c869f77dSJakub Kicinski 	return 0;
36*c869f77dSJakub Kicinski }
37*c869f77dSJakub Kicinski 
38*c869f77dSJakub Kicinski DEFINE_SIMPLE_ATTRIBUTE(fops_regval, mt76_reg_get, mt76_reg_set, "0x%08llx\n");
39*c869f77dSJakub Kicinski 
40*c869f77dSJakub Kicinski static int
41*c869f77dSJakub Kicinski mt7601u_ampdu_stat_read(struct seq_file *file, void *data)
42*c869f77dSJakub Kicinski {
43*c869f77dSJakub Kicinski 	struct mt7601u_dev *dev = file->private;
44*c869f77dSJakub Kicinski 	int i, j;
45*c869f77dSJakub Kicinski 
46*c869f77dSJakub Kicinski #define stat_printf(grp, off, name)					\
47*c869f77dSJakub Kicinski 	seq_printf(file, #name ":\t%llu\n", dev->stats.grp[off])
48*c869f77dSJakub Kicinski 
49*c869f77dSJakub Kicinski 	stat_printf(rx_stat, 0, rx_crc_err);
50*c869f77dSJakub Kicinski 	stat_printf(rx_stat, 1, rx_phy_err);
51*c869f77dSJakub Kicinski 	stat_printf(rx_stat, 2, rx_false_cca);
52*c869f77dSJakub Kicinski 	stat_printf(rx_stat, 3, rx_plcp_err);
53*c869f77dSJakub Kicinski 	stat_printf(rx_stat, 4, rx_fifo_overflow);
54*c869f77dSJakub Kicinski 	stat_printf(rx_stat, 5, rx_duplicate);
55*c869f77dSJakub Kicinski 
56*c869f77dSJakub Kicinski 	stat_printf(tx_stat, 0, tx_fail_cnt);
57*c869f77dSJakub Kicinski 	stat_printf(tx_stat, 1, tx_bcn_cnt);
58*c869f77dSJakub Kicinski 	stat_printf(tx_stat, 2, tx_success);
59*c869f77dSJakub Kicinski 	stat_printf(tx_stat, 3, tx_retransmit);
60*c869f77dSJakub Kicinski 	stat_printf(tx_stat, 4, tx_zero_len);
61*c869f77dSJakub Kicinski 	stat_printf(tx_stat, 5, tx_underflow);
62*c869f77dSJakub Kicinski 
63*c869f77dSJakub Kicinski 	stat_printf(aggr_stat, 0, non_aggr_tx);
64*c869f77dSJakub Kicinski 	stat_printf(aggr_stat, 1, aggr_tx);
65*c869f77dSJakub Kicinski 
66*c869f77dSJakub Kicinski 	stat_printf(zero_len_del, 0, tx_zero_len_del);
67*c869f77dSJakub Kicinski 	stat_printf(zero_len_del, 1, rx_zero_len_del);
68*c869f77dSJakub Kicinski #undef stat_printf
69*c869f77dSJakub Kicinski 
70*c869f77dSJakub Kicinski 	seq_puts(file, "Aggregations stats:\n");
71*c869f77dSJakub Kicinski 	for (i = 0; i < 4; i++) {
72*c869f77dSJakub Kicinski 		for (j = 0; j < 8; j++)
73*c869f77dSJakub Kicinski 			seq_printf(file, "%08llx ",
74*c869f77dSJakub Kicinski 				   dev->stats.aggr_n[i * 8 + j]);
75*c869f77dSJakub Kicinski 		seq_putc(file, '\n');
76*c869f77dSJakub Kicinski 	}
77*c869f77dSJakub Kicinski 
78*c869f77dSJakub Kicinski 	seq_printf(file, "recent average AMPDU len: %d\n",
79*c869f77dSJakub Kicinski 		   atomic_read(&dev->avg_ampdu_len));
80*c869f77dSJakub Kicinski 
81*c869f77dSJakub Kicinski 	return 0;
82*c869f77dSJakub Kicinski }
83*c869f77dSJakub Kicinski 
84*c869f77dSJakub Kicinski static int
85*c869f77dSJakub Kicinski mt7601u_ampdu_stat_open(struct inode *inode, struct file *f)
86*c869f77dSJakub Kicinski {
87*c869f77dSJakub Kicinski 	return single_open(f, mt7601u_ampdu_stat_read, inode->i_private);
88*c869f77dSJakub Kicinski }
89*c869f77dSJakub Kicinski 
90*c869f77dSJakub Kicinski static const struct file_operations fops_ampdu_stat = {
91*c869f77dSJakub Kicinski 	.open = mt7601u_ampdu_stat_open,
92*c869f77dSJakub Kicinski 	.read = seq_read,
93*c869f77dSJakub Kicinski 	.llseek = seq_lseek,
94*c869f77dSJakub Kicinski 	.release = single_release,
95*c869f77dSJakub Kicinski };
96*c869f77dSJakub Kicinski 
97*c869f77dSJakub Kicinski static int
98*c869f77dSJakub Kicinski mt7601u_eeprom_param_read(struct seq_file *file, void *data)
99*c869f77dSJakub Kicinski {
100*c869f77dSJakub Kicinski 	struct mt7601u_dev *dev = file->private;
101*c869f77dSJakub Kicinski 	struct mt7601u_rate_power *rp = &dev->ee->power_rate_table;
102*c869f77dSJakub Kicinski 	struct tssi_data *td = &dev->ee->tssi_data;
103*c869f77dSJakub Kicinski 	int i;
104*c869f77dSJakub Kicinski 
105*c869f77dSJakub Kicinski 	seq_printf(file, "RF freq offset: %hhx\n", dev->ee->rf_freq_off);
106*c869f77dSJakub Kicinski 	seq_printf(file, "RSSI offset: %hhx %hhx\n",
107*c869f77dSJakub Kicinski 		   dev->ee->rssi_offset[0], dev->ee->rssi_offset[1]);
108*c869f77dSJakub Kicinski 	seq_printf(file, "Reference temp: %hhx\n", dev->ee->ref_temp);
109*c869f77dSJakub Kicinski 	seq_printf(file, "LNA gain: %hhx\n", dev->ee->lna_gain);
110*c869f77dSJakub Kicinski 	seq_printf(file, "Reg channels: %hhu-%hhu\n", dev->ee->reg.start,
111*c869f77dSJakub Kicinski 		   dev->ee->reg.start + dev->ee->reg.num - 1);
112*c869f77dSJakub Kicinski 
113*c869f77dSJakub Kicinski 	seq_puts(file, "Per rate power:\n");
114*c869f77dSJakub Kicinski 	for (i = 0; i < 2; i++)
115*c869f77dSJakub Kicinski 		seq_printf(file, "\t raw:%02hhx bw20:%02hhx bw40:%02hhx\n",
116*c869f77dSJakub Kicinski 			   rp->cck[i].raw, rp->cck[i].bw20, rp->cck[i].bw40);
117*c869f77dSJakub Kicinski 	for (i = 0; i < 4; i++)
118*c869f77dSJakub Kicinski 		seq_printf(file, "\t raw:%02hhx bw20:%02hhx bw40:%02hhx\n",
119*c869f77dSJakub Kicinski 			   rp->ofdm[i].raw, rp->ofdm[i].bw20, rp->ofdm[i].bw40);
120*c869f77dSJakub Kicinski 	for (i = 0; i < 4; i++)
121*c869f77dSJakub Kicinski 		seq_printf(file, "\t raw:%02hhx bw20:%02hhx bw40:%02hhx\n",
122*c869f77dSJakub Kicinski 			   rp->ht[i].raw, rp->ht[i].bw20, rp->ht[i].bw40);
123*c869f77dSJakub Kicinski 
124*c869f77dSJakub Kicinski 	seq_puts(file, "Per channel power:\n");
125*c869f77dSJakub Kicinski 	for (i = 0; i < 7; i++)
126*c869f77dSJakub Kicinski 		seq_printf(file, "\t tx_power  ch%u:%02hhx ch%u:%02hhx\n",
127*c869f77dSJakub Kicinski 			   i * 2 + 1, dev->ee->chan_pwr[i * 2],
128*c869f77dSJakub Kicinski 			   i * 2 + 2, dev->ee->chan_pwr[i * 2 + 1]);
129*c869f77dSJakub Kicinski 
130*c869f77dSJakub Kicinski 	if (!dev->ee->tssi_enabled)
131*c869f77dSJakub Kicinski 		return 0;
132*c869f77dSJakub Kicinski 
133*c869f77dSJakub Kicinski 	seq_puts(file, "TSSI:\n");
134*c869f77dSJakub Kicinski 	seq_printf(file, "\t slope:%02hhx\n", td->slope);
135*c869f77dSJakub Kicinski 	seq_printf(file, "\t offset=%02hhx %02hhx %02hhx\n",
136*c869f77dSJakub Kicinski 		   td->offset[0], td->offset[1], td->offset[2]);
137*c869f77dSJakub Kicinski 	seq_printf(file, "\t delta_off:%08x\n", td->tx0_delta_offset);
138*c869f77dSJakub Kicinski 
139*c869f77dSJakub Kicinski 	return 0;
140*c869f77dSJakub Kicinski }
141*c869f77dSJakub Kicinski 
142*c869f77dSJakub Kicinski static int
143*c869f77dSJakub Kicinski mt7601u_eeprom_param_open(struct inode *inode, struct file *f)
144*c869f77dSJakub Kicinski {
145*c869f77dSJakub Kicinski 	return single_open(f, mt7601u_eeprom_param_read, inode->i_private);
146*c869f77dSJakub Kicinski }
147*c869f77dSJakub Kicinski 
148*c869f77dSJakub Kicinski static const struct file_operations fops_eeprom_param = {
149*c869f77dSJakub Kicinski 	.open = mt7601u_eeprom_param_open,
150*c869f77dSJakub Kicinski 	.read = seq_read,
151*c869f77dSJakub Kicinski 	.llseek = seq_lseek,
152*c869f77dSJakub Kicinski 	.release = single_release,
153*c869f77dSJakub Kicinski };
154*c869f77dSJakub Kicinski 
155*c869f77dSJakub Kicinski void mt7601u_init_debugfs(struct mt7601u_dev *dev)
156*c869f77dSJakub Kicinski {
157*c869f77dSJakub Kicinski 	struct dentry *dir;
158*c869f77dSJakub Kicinski 
159*c869f77dSJakub Kicinski 	dir = debugfs_create_dir("mt7601u", dev->hw->wiphy->debugfsdir);
160*c869f77dSJakub Kicinski 	if (!dir)
161*c869f77dSJakub Kicinski 		return;
162*c869f77dSJakub Kicinski 
163*c869f77dSJakub Kicinski 	debugfs_create_u8("temperature", S_IRUSR, dir, &dev->raw_temp);
164*c869f77dSJakub Kicinski 	debugfs_create_u32("temp_mode", S_IRUSR, dir, &dev->temp_mode);
165*c869f77dSJakub Kicinski 
166*c869f77dSJakub Kicinski 	debugfs_create_u32("regidx", S_IRUSR | S_IWUSR, dir, &dev->debugfs_reg);
167*c869f77dSJakub Kicinski 	debugfs_create_file("regval", S_IRUSR | S_IWUSR, dir, dev,
168*c869f77dSJakub Kicinski 			    &fops_regval);
169*c869f77dSJakub Kicinski 	debugfs_create_file("ampdu_stat", S_IRUSR, dir, dev, &fops_ampdu_stat);
170*c869f77dSJakub Kicinski 	debugfs_create_file("eeprom_param", S_IRUSR, dir, dev,
171*c869f77dSJakub Kicinski 			    &fops_eeprom_param);
172*c869f77dSJakub Kicinski }
173