Blame view

net/mac80211/rc80211_minstrel_ht_debugfs.c 8.76 KB
d2912cb15   Thomas Gleixner   treewide: Replace...
1
  // SPDX-License-Identifier: GPL-2.0-only
ec8aa669b   Felix Fietkau   mac80211: add the...
2
3
  /*
   * Copyright (C) 2010 Felix Fietkau <nbd@openwrt.org>
ec8aa669b   Felix Fietkau   mac80211: add the...
4
5
6
7
8
9
   */
  #include <linux/netdevice.h>
  #include <linux/types.h>
  #include <linux/skbuff.h>
  #include <linux/debugfs.h>
  #include <linux/ieee80211.h>
bc3b2d7fb   Paul Gortmaker   net: Add export.h...
10
  #include <linux/export.h>
ec8aa669b   Felix Fietkau   mac80211: add the...
11
12
13
  #include <net/mac80211.h>
  #include "rc80211_minstrel.h"
  #include "rc80211_minstrel_ht.h"
b1c4f6833   Felix Fietkau   mac80211: minstre...
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
  static ssize_t
  minstrel_stats_read(struct file *file, char __user *buf, size_t len, loff_t *ppos)
  {
  	struct minstrel_debugfs_info *ms;
  
  	ms = file->private_data;
  	return simple_read_from_buffer(buf, len, ppos, ms->buf, ms->len);
  }
  
  static int
  minstrel_stats_release(struct inode *inode, struct file *file)
  {
  	kfree(file->private_data);
  	return 0;
  }
a0497f9f5   Felix Fietkau   mac80211/minstrel...
29
30
31
  static char *
  minstrel_ht_stats_dump(struct minstrel_ht_sta *mi, int i, char *p)
  {
a0497f9f5   Felix Fietkau   mac80211/minstrel...
32
  	const struct mcs_group *mg;
1109dc392   Felix Fietkau   mac80211: minstre...
33
  	unsigned int j, tp_max, tp_avg, eprob, tx_time;
a0497f9f5   Felix Fietkau   mac80211/minstrel...
34
35
  	char htmode = '2';
  	char gimode = 'L';
8ec7886b1   Karl Beldan   mac80211: minstre...
36
  	u32 gflags;
a0497f9f5   Felix Fietkau   mac80211/minstrel...
37

41d085835   Felix Fietkau   mac80211: minstre...
38
  	if (!mi->supported[i])
a0497f9f5   Felix Fietkau   mac80211/minstrel...
39
40
41
  		return p;
  
  	mg = &minstrel_mcs_groups[i];
8ec7886b1   Karl Beldan   mac80211: minstre...
42
43
44
  	gflags = mg->flags;
  
  	if (gflags & IEEE80211_TX_RC_40_MHZ_WIDTH)
a0497f9f5   Felix Fietkau   mac80211/minstrel...
45
  		htmode = '4';
8ec7886b1   Karl Beldan   mac80211: minstre...
46
  	else if (gflags & IEEE80211_TX_RC_80_MHZ_WIDTH)
9208247d7   Karl Beldan   mac80211: minstre...
47
  		htmode = '8';
8ec7886b1   Karl Beldan   mac80211: minstre...
48
  	if (gflags & IEEE80211_TX_RC_SHORT_GI)
a0497f9f5   Felix Fietkau   mac80211/minstrel...
49
50
51
  		gimode = 'S';
  
  	for (j = 0; j < MCS_GROUP_RATES; j++) {
9134073bc   Thomas Huehn   mac80211: improve...
52
  		struct minstrel_rate_stats *mrs = &mi->groups[i].rates[j];
a0497f9f5   Felix Fietkau   mac80211/minstrel...
53
54
  		static const int bitrates[4] = { 10, 20, 55, 110 };
  		int idx = i * MCS_GROUP_RATES + j;
202df504d   Felix Fietkau   mac80211: minstre...
55
  		unsigned int duration;
a0497f9f5   Felix Fietkau   mac80211/minstrel...
56

41d085835   Felix Fietkau   mac80211: minstre...
57
  		if (!(mi->supported[i] & BIT(j)))
a0497f9f5   Felix Fietkau   mac80211/minstrel...
58
  			continue;
9c00bb721   Thomas Huehn   mac80211: enhance...
59
60
61
62
63
64
65
66
67
68
69
70
71
  		if (gflags & IEEE80211_TX_RC_MCS) {
  			p += sprintf(p, "HT%c0  ", htmode);
  			p += sprintf(p, "%cGI  ", gimode);
  			p += sprintf(p, "%d  ", mg->streams);
  		} else if (gflags & IEEE80211_TX_RC_VHT_MCS) {
  			p += sprintf(p, "VHT%c0 ", htmode);
  			p += sprintf(p, "%cGI ", gimode);
  			p += sprintf(p, "%d  ", mg->streams);
  		} else {
  			p += sprintf(p, "CCK    ");
  			p += sprintf(p, "%cP  ", j < 4 ? 'L' : 'S');
  			p += sprintf(p, "1 ");
  		}
a0497f9f5   Felix Fietkau   mac80211/minstrel...
72

5935839ad   Thomas Huehn   mac80211: improve...
73
74
75
76
  		*(p++) = (idx == mi->max_tp_rate[0]) ? 'A' : ' ';
  		*(p++) = (idx == mi->max_tp_rate[1]) ? 'B' : ' ';
  		*(p++) = (idx == mi->max_tp_rate[2]) ? 'C' : ' ';
  		*(p++) = (idx == mi->max_tp_rate[3]) ? 'D' : ' ';
a0497f9f5   Felix Fietkau   mac80211/minstrel...
77
  		*(p++) = (idx == mi->max_prob_rate) ? 'P' : ' ';
8ec7886b1   Karl Beldan   mac80211: minstre...
78
  		if (gflags & IEEE80211_TX_RC_MCS) {
9c00bb721   Thomas Huehn   mac80211: enhance...
79
  			p += sprintf(p, "  MCS%-2u", (mg->streams - 1) * 8 + j);
8ec7886b1   Karl Beldan   mac80211: minstre...
80
  		} else if (gflags & IEEE80211_TX_RC_VHT_MCS) {
9c00bb721   Thomas Huehn   mac80211: enhance...
81
  			p += sprintf(p, "  MCS%-1u/%1u", j, mg->streams);
a0497f9f5   Felix Fietkau   mac80211/minstrel...
82
  		} else {
8ec7886b1   Karl Beldan   mac80211: minstre...
83
  			int r = bitrates[j % 4];
9c00bb721   Thomas Huehn   mac80211: enhance...
84
  			p += sprintf(p, "   %2u.%1uM", r / 10, r % 10);
a0497f9f5   Felix Fietkau   mac80211/minstrel...
85
  		}
9c00bb721   Thomas Huehn   mac80211: enhance...
86
87
88
  		p += sprintf(p, "  %3u  ", idx);
  
  		/* tx_time[rate(i)] in usec */
202df504d   Felix Fietkau   mac80211: minstre...
89
90
91
  		duration = mg->duration[j];
  		duration <<= mg->shift;
  		tx_time = DIV_ROUND_CLOSEST(duration, 1000);
50e55a8ea   Thomas Huehn   mac80211: add max...
92
  		p += sprintf(p, "%6u  ", tx_time);
9c00bb721   Thomas Huehn   mac80211: enhance...
93

50e55a8ea   Thomas Huehn   mac80211: add max...
94
  		tp_max = minstrel_ht_get_tp_avg(mi, i, j, MINSTREL_FRAC(100, 100));
5f63afe02   Felix Fietkau   mac80211: minstre...
95
96
  		tp_avg = minstrel_ht_get_tp_avg(mi, i, j, mrs->prob_avg);
  		eprob = MINSTREL_TRUNC(mrs->prob_avg * 1000);
a0497f9f5   Felix Fietkau   mac80211/minstrel...
97

506dbf90c   Felix Fietkau   mac80211: rc80211...
98
  		p += sprintf(p, "%4u.%1u    %4u.%1u     %3u.%1u"
1109dc392   Felix Fietkau   mac80211: minstre...
99
  				"     %3u   %3u %-3u   "
5f919abc7   Thomas Huehn   mac80211: add sta...
100
101
  				"%9llu   %-9llu
  ",
50e55a8ea   Thomas Huehn   mac80211: add max...
102
  				tp_max / 10, tp_max % 10,
6a27b2c40   Thomas Huehn   mac80211: restruc...
103
  				tp_avg / 10, tp_avg % 10,
a0497f9f5   Felix Fietkau   mac80211/minstrel...
104
  				eprob / 10, eprob % 10,
9134073bc   Thomas Huehn   mac80211: improve...
105
106
107
108
109
  				mrs->retry_count,
  				mrs->last_success,
  				mrs->last_attempts,
  				(unsigned long long)mrs->succ_hist,
  				(unsigned long long)mrs->att_hist);
a0497f9f5   Felix Fietkau   mac80211/minstrel...
110
111
112
113
  	}
  
  	return p;
  }
ec8aa669b   Felix Fietkau   mac80211: add the...
114
115
116
117
118
119
  static int
  minstrel_ht_stats_open(struct inode *inode, struct file *file)
  {
  	struct minstrel_ht_sta_priv *msp = inode->i_private;
  	struct minstrel_ht_sta *mi = &msp->ht;
  	struct minstrel_debugfs_info *ms;
a0497f9f5   Felix Fietkau   mac80211/minstrel...
120
  	unsigned int i;
ec8aa669b   Felix Fietkau   mac80211: add the...
121
  	int ret;
2cae0b6a7   Thomas Huehn   mac80211: add new...
122
  	char *p;
ec8aa669b   Felix Fietkau   mac80211: add the...
123
124
125
126
127
128
129
  
  	if (!msp->is_ht) {
  		inode->i_private = &msp->legacy;
  		ret = minstrel_stats_open(inode, file);
  		inode->i_private = msp;
  		return ret;
  	}
9208247d7   Karl Beldan   mac80211: minstre...
130
  	ms = kmalloc(32768, GFP_KERNEL);
ec8aa669b   Felix Fietkau   mac80211: add the...
131
132
133
134
135
  	if (!ms)
  		return -ENOMEM;
  
  	file->private_data = ms;
  	p = ms->buf;
9c00bb721   Thomas Huehn   mac80211: enhance...
136
137
138
  
  	p += sprintf(p, "
  ");
a0c391b13   Johannes Berg   mac80211: minstre...
139
  	p += sprintf(p,
506dbf90c   Felix Fietkau   mac80211: rc80211...
140
141
  		     "              best   ____________rate__________    ____statistics___    _____last____    ______sum-of________
  ");
a0c391b13   Johannes Berg   mac80211: minstre...
142
  	p += sprintf(p,
506dbf90c   Felix Fietkau   mac80211: rc80211...
143
144
  		     "mode guard #  rate  [name   idx airtime  max_tp]  [avg(tp) avg(prob)]  [retry|suc|att]  [#success | #attempts]
  ");
11b2357d5   Karl Beldan   mac80211: minstre...
145

8a0ee4fe1   Karl Beldan   mac80211: minstre...
146
147
  	p = minstrel_ht_stats_dump(mi, MINSTREL_CCK_GROUP, p);
  	for (i = 0; i < MINSTREL_CCK_GROUP; i++)
a0497f9f5   Felix Fietkau   mac80211/minstrel...
148
  		p = minstrel_ht_stats_dump(mi, i, p);
9208247d7   Karl Beldan   mac80211: minstre...
149
150
  	for (i++; i < ARRAY_SIZE(mi->groups); i++)
  		p = minstrel_ht_stats_dump(mi, i, p);
ec8aa669b   Felix Fietkau   mac80211: add the...
151

ec8aa669b   Felix Fietkau   mac80211: add the...
152
153
154
155
156
157
  	p += sprintf(p, "
  Total packet count::    ideal %d      "
  			"lookaround %d
  ",
  			max(0, (int) mi->total_packets - (int) mi->sample_packets),
  			mi->sample_packets);
77f7ffdc3   Felix Fietkau   mac80211: minstre...
158
159
160
161
162
  	if (mi->avg_ampdu_len)
  		p += sprintf(p, "Average # of aggregated frames per A-MPDU: %d.%d
  ",
  			MINSTREL_TRUNC(mi->avg_ampdu_len),
  			MINSTREL_TRUNC(mi->avg_ampdu_len * 10) % 10);
ec8aa669b   Felix Fietkau   mac80211: add the...
163
  	ms->len = p - ms->buf;
9208247d7   Karl Beldan   mac80211: minstre...
164
  	WARN_ON(ms->len + sizeof(*ms) > 32768);
11b2357d5   Karl Beldan   mac80211: minstre...
165

a0572d93c   Arnd Bergmann   mac80211: disallo...
166
  	return nonseekable_open(inode, file);
ec8aa669b   Felix Fietkau   mac80211: add the...
167
168
169
170
171
172
173
  }
  
  static const struct file_operations minstrel_ht_stat_fops = {
  	.owner = THIS_MODULE,
  	.open = minstrel_ht_stats_open,
  	.read = minstrel_stats_read,
  	.release = minstrel_stats_release,
a0572d93c   Arnd Bergmann   mac80211: disallo...
174
  	.llseek = no_llseek,
ec8aa669b   Felix Fietkau   mac80211: add the...
175
  };
2cae0b6a7   Thomas Huehn   mac80211: add new...
176
177
178
179
  static char *
  minstrel_ht_stats_csv_dump(struct minstrel_ht_sta *mi, int i, char *p)
  {
  	const struct mcs_group *mg;
1109dc392   Felix Fietkau   mac80211: minstre...
180
  	unsigned int j, tp_max, tp_avg, eprob, tx_time;
2cae0b6a7   Thomas Huehn   mac80211: add new...
181
182
183
  	char htmode = '2';
  	char gimode = 'L';
  	u32 gflags;
41d085835   Felix Fietkau   mac80211: minstre...
184
  	if (!mi->supported[i])
2cae0b6a7   Thomas Huehn   mac80211: add new...
185
186
187
188
189
190
191
192
193
194
195
196
197
  		return p;
  
  	mg = &minstrel_mcs_groups[i];
  	gflags = mg->flags;
  
  	if (gflags & IEEE80211_TX_RC_40_MHZ_WIDTH)
  		htmode = '4';
  	else if (gflags & IEEE80211_TX_RC_80_MHZ_WIDTH)
  		htmode = '8';
  	if (gflags & IEEE80211_TX_RC_SHORT_GI)
  		gimode = 'S';
  
  	for (j = 0; j < MCS_GROUP_RATES; j++) {
9134073bc   Thomas Huehn   mac80211: improve...
198
  		struct minstrel_rate_stats *mrs = &mi->groups[i].rates[j];
2cae0b6a7   Thomas Huehn   mac80211: add new...
199
200
  		static const int bitrates[4] = { 10, 20, 55, 110 };
  		int idx = i * MCS_GROUP_RATES + j;
202df504d   Felix Fietkau   mac80211: minstre...
201
  		unsigned int duration;
2cae0b6a7   Thomas Huehn   mac80211: add new...
202

41d085835   Felix Fietkau   mac80211: minstre...
203
  		if (!(mi->supported[i] & BIT(j)))
2cae0b6a7   Thomas Huehn   mac80211: add new...
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
  			continue;
  
  		if (gflags & IEEE80211_TX_RC_MCS) {
  			p += sprintf(p, "HT%c0,", htmode);
  			p += sprintf(p, "%cGI,", gimode);
  			p += sprintf(p, "%d,", mg->streams);
  		} else if (gflags & IEEE80211_TX_RC_VHT_MCS) {
  			p += sprintf(p, "VHT%c0,", htmode);
  			p += sprintf(p, "%cGI,", gimode);
  			p += sprintf(p, "%d,", mg->streams);
  		} else {
  			p += sprintf(p, "CCK,");
  			p += sprintf(p, "%cP,", j < 4 ? 'L' : 'S');
  			p += sprintf(p, "1,");
  		}
  
  		p += sprintf(p, "%s" ,((idx == mi->max_tp_rate[0]) ? "A" : ""));
  		p += sprintf(p, "%s" ,((idx == mi->max_tp_rate[1]) ? "B" : ""));
  		p += sprintf(p, "%s" ,((idx == mi->max_tp_rate[2]) ? "C" : ""));
  		p += sprintf(p, "%s" ,((idx == mi->max_tp_rate[3]) ? "D" : ""));
  		p += sprintf(p, "%s" ,((idx == mi->max_prob_rate) ? "P" : ""));
  
  		if (gflags & IEEE80211_TX_RC_MCS) {
  			p += sprintf(p, ",MCS%-2u,", (mg->streams - 1) * 8 + j);
  		} else if (gflags & IEEE80211_TX_RC_VHT_MCS) {
  			p += sprintf(p, ",MCS%-1u/%1u,", j, mg->streams);
  		} else {
  			int r = bitrates[j % 4];
  			p += sprintf(p, ",%2u.%1uM,", r / 10, r % 10);
  		}
  
  		p += sprintf(p, "%u,", idx);
202df504d   Felix Fietkau   mac80211: minstre...
236
237
238
239
  
  		duration = mg->duration[j];
  		duration <<= mg->shift;
  		tx_time = DIV_ROUND_CLOSEST(duration, 1000);
2cae0b6a7   Thomas Huehn   mac80211: add new...
240
  		p += sprintf(p, "%u,", tx_time);
50e55a8ea   Thomas Huehn   mac80211: add max...
241
  		tp_max = minstrel_ht_get_tp_avg(mi, i, j, MINSTREL_FRAC(100, 100));
5f63afe02   Felix Fietkau   mac80211: minstre...
242
243
  		tp_avg = minstrel_ht_get_tp_avg(mi, i, j, mrs->prob_avg);
  		eprob = MINSTREL_TRUNC(mrs->prob_avg * 1000);
2cae0b6a7   Thomas Huehn   mac80211: add new...
244

506dbf90c   Felix Fietkau   mac80211: rc80211...
245
  		p += sprintf(p, "%u.%u,%u.%u,%u.%u,%u,%u,"
5f919abc7   Thomas Huehn   mac80211: add sta...
246
  				"%u,%llu,%llu,",
50e55a8ea   Thomas Huehn   mac80211: add max...
247
  				tp_max / 10, tp_max % 10,
6a27b2c40   Thomas Huehn   mac80211: restruc...
248
  				tp_avg / 10, tp_avg % 10,
2cae0b6a7   Thomas Huehn   mac80211: add new...
249
  				eprob / 10, eprob % 10,
9134073bc   Thomas Huehn   mac80211: improve...
250
251
252
253
254
  				mrs->retry_count,
  				mrs->last_success,
  				mrs->last_attempts,
  				(unsigned long long)mrs->succ_hist,
  				(unsigned long long)mrs->att_hist);
2cae0b6a7   Thomas Huehn   mac80211: add new...
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
  		p += sprintf(p, "%d,%d,%d.%d
  ",
  				max(0, (int) mi->total_packets -
  				(int) mi->sample_packets),
  				mi->sample_packets,
  				MINSTREL_TRUNC(mi->avg_ampdu_len),
  				MINSTREL_TRUNC(mi->avg_ampdu_len * 10) % 10);
  	}
  
  	return p;
  }
  
  static int
  minstrel_ht_stats_csv_open(struct inode *inode, struct file *file)
  {
  	struct minstrel_ht_sta_priv *msp = inode->i_private;
  	struct minstrel_ht_sta *mi = &msp->ht;
  	struct minstrel_debugfs_info *ms;
  	unsigned int i;
  	int ret;
  	char *p;
  
  	if (!msp->is_ht) {
  		inode->i_private = &msp->legacy;
  		ret = minstrel_stats_csv_open(inode, file);
  		inode->i_private = msp;
  		return ret;
  	}
  
  	ms = kmalloc(32768, GFP_KERNEL);
  
  	if (!ms)
  		return -ENOMEM;
  
  	file->private_data = ms;
  
  	p = ms->buf;
  
  	p = minstrel_ht_stats_csv_dump(mi, MINSTREL_CCK_GROUP, p);
  	for (i = 0; i < MINSTREL_CCK_GROUP; i++)
  		p = minstrel_ht_stats_csv_dump(mi, i, p);
  	for (i++; i < ARRAY_SIZE(mi->groups); i++)
  		p = minstrel_ht_stats_csv_dump(mi, i, p);
  
  	ms->len = p - ms->buf;
  	WARN_ON(ms->len + sizeof(*ms) > 32768);
  
  	return nonseekable_open(inode, file);
  }
  
  static const struct file_operations minstrel_ht_stat_csv_fops = {
  	.owner = THIS_MODULE,
  	.open = minstrel_ht_stats_csv_open,
  	.read = minstrel_stats_read,
  	.release = minstrel_stats_release,
  	.llseek = no_llseek,
  };
ec8aa669b   Felix Fietkau   mac80211: add the...
312
313
314
315
  void
  minstrel_ht_add_sta_debugfs(void *priv, void *priv_sta, struct dentry *dir)
  {
  	struct minstrel_ht_sta_priv *msp = priv_sta;
5b5e87314   Felix Fietkau   mac80211: minstre...
316
317
318
319
  	debugfs_create_file("rc_stats", 0444, dir, msp,
  			    &minstrel_ht_stat_fops);
  	debugfs_create_file("rc_stats_csv", 0444, dir, msp,
  			    &minstrel_ht_stat_csv_fops);
ec8aa669b   Felix Fietkau   mac80211: add the...
320
  }