xref: /openbmc/linux/net/mac80211/debugfs.c (revision 81d67439)
1 
2 /*
3  * mac80211 debugfs for wireless PHYs
4  *
5  * Copyright 2007	Johannes Berg <johannes@sipsolutions.net>
6  *
7  * GPLv2
8  *
9  */
10 
11 #include <linux/debugfs.h>
12 #include <linux/rtnetlink.h>
13 #include "ieee80211_i.h"
14 #include "driver-ops.h"
15 #include "rate.h"
16 #include "debugfs.h"
17 
18 int mac80211_open_file_generic(struct inode *inode, struct file *file)
19 {
20 	file->private_data = inode->i_private;
21 	return 0;
22 }
23 
24 #define DEBUGFS_FORMAT_BUFFER_SIZE 100
25 
26 int mac80211_format_buffer(char __user *userbuf, size_t count,
27 				  loff_t *ppos, char *fmt, ...)
28 {
29 	va_list args;
30 	char buf[DEBUGFS_FORMAT_BUFFER_SIZE];
31 	int res;
32 
33 	va_start(args, fmt);
34 	res = vscnprintf(buf, sizeof(buf), fmt, args);
35 	va_end(args);
36 
37 	return simple_read_from_buffer(userbuf, count, ppos, buf, res);
38 }
39 
40 #define DEBUGFS_READONLY_FILE_FN(name, fmt, value...)			\
41 static ssize_t name## _read(struct file *file, char __user *userbuf,	\
42 			    size_t count, loff_t *ppos)			\
43 {									\
44 	struct ieee80211_local *local = file->private_data;		\
45 									\
46 	return mac80211_format_buffer(userbuf, count, ppos, 		\
47 				      fmt "\n", ##value);		\
48 }
49 
50 #define DEBUGFS_READONLY_FILE_OPS(name)			\
51 static const struct file_operations name## _ops = {			\
52 	.read = name## _read,						\
53 	.open = mac80211_open_file_generic,				\
54 	.llseek = generic_file_llseek,					\
55 };
56 
57 #define DEBUGFS_READONLY_FILE(name, fmt, value...)		\
58 	DEBUGFS_READONLY_FILE_FN(name, fmt, value)		\
59 	DEBUGFS_READONLY_FILE_OPS(name)
60 
61 #define DEBUGFS_ADD(name)						\
62 	debugfs_create_file(#name, 0400, phyd, local, &name## _ops);
63 
64 #define DEBUGFS_ADD_MODE(name, mode)					\
65 	debugfs_create_file(#name, mode, phyd, local, &name## _ops);
66 
67 
68 DEBUGFS_READONLY_FILE(user_power, "%d",
69 		      local->user_power_level);
70 DEBUGFS_READONLY_FILE(power, "%d",
71 		      local->hw.conf.power_level);
72 DEBUGFS_READONLY_FILE(frequency, "%d",
73 		      local->hw.conf.channel->center_freq);
74 DEBUGFS_READONLY_FILE(total_ps_buffered, "%d",
75 		      local->total_ps_buffered);
76 DEBUGFS_READONLY_FILE(wep_iv, "%#08x",
77 		      local->wep_iv & 0xffffff);
78 DEBUGFS_READONLY_FILE(rate_ctrl_alg, "%s",
79 	local->rate_ctrl ? local->rate_ctrl->ops->name : "hw/driver");
80 
81 static ssize_t tsf_read(struct file *file, char __user *user_buf,
82 			     size_t count, loff_t *ppos)
83 {
84 	struct ieee80211_local *local = file->private_data;
85 	u64 tsf;
86 
87 	tsf = drv_get_tsf(local);
88 
89 	return mac80211_format_buffer(user_buf, count, ppos, "0x%016llx\n",
90 				      (unsigned long long) tsf);
91 }
92 
93 static ssize_t tsf_write(struct file *file,
94                          const char __user *user_buf,
95                          size_t count, loff_t *ppos)
96 {
97 	struct ieee80211_local *local = file->private_data;
98 	unsigned long long tsf;
99 	char buf[100];
100 	size_t len;
101 
102 	len = min(count, sizeof(buf) - 1);
103 	if (copy_from_user(buf, user_buf, len))
104 		return -EFAULT;
105 	buf[len] = '\0';
106 
107 	if (strncmp(buf, "reset", 5) == 0) {
108 		if (local->ops->reset_tsf) {
109 			drv_reset_tsf(local);
110 			wiphy_info(local->hw.wiphy, "debugfs reset TSF\n");
111 		}
112 	} else {
113 		tsf = simple_strtoul(buf, NULL, 0);
114 		if (local->ops->set_tsf) {
115 			drv_set_tsf(local, tsf);
116 			wiphy_info(local->hw.wiphy,
117 				   "debugfs set TSF to %#018llx\n", tsf);
118 
119 		}
120 	}
121 
122 	return count;
123 }
124 
125 static const struct file_operations tsf_ops = {
126 	.read = tsf_read,
127 	.write = tsf_write,
128 	.open = mac80211_open_file_generic,
129 	.llseek = default_llseek,
130 };
131 
132 static ssize_t reset_write(struct file *file, const char __user *user_buf,
133 			   size_t count, loff_t *ppos)
134 {
135 	struct ieee80211_local *local = file->private_data;
136 
137 	rtnl_lock();
138 	__ieee80211_suspend(&local->hw, NULL);
139 	__ieee80211_resume(&local->hw);
140 	rtnl_unlock();
141 
142 	return count;
143 }
144 
145 static const struct file_operations reset_ops = {
146 	.write = reset_write,
147 	.open = mac80211_open_file_generic,
148 	.llseek = noop_llseek,
149 };
150 
151 static ssize_t noack_read(struct file *file, char __user *user_buf,
152 			  size_t count, loff_t *ppos)
153 {
154 	struct ieee80211_local *local = file->private_data;
155 
156 	return mac80211_format_buffer(user_buf, count, ppos, "%d\n",
157 				      local->wifi_wme_noack_test);
158 }
159 
160 static ssize_t noack_write(struct file *file,
161 			   const char __user *user_buf,
162 			   size_t count, loff_t *ppos)
163 {
164 	struct ieee80211_local *local = file->private_data;
165 	char buf[10];
166 	size_t len;
167 
168 	len = min(count, sizeof(buf) - 1);
169 	if (copy_from_user(buf, user_buf, len))
170 		return -EFAULT;
171 	buf[len] = '\0';
172 
173 	local->wifi_wme_noack_test = !!simple_strtoul(buf, NULL, 0);
174 
175 	return count;
176 }
177 
178 static const struct file_operations noack_ops = {
179 	.read = noack_read,
180 	.write = noack_write,
181 	.open = mac80211_open_file_generic,
182 	.llseek = default_llseek,
183 };
184 
185 static ssize_t uapsd_queues_read(struct file *file, char __user *user_buf,
186 				 size_t count, loff_t *ppos)
187 {
188 	struct ieee80211_local *local = file->private_data;
189 	return mac80211_format_buffer(user_buf, count, ppos, "0x%x\n",
190 				      local->uapsd_queues);
191 }
192 
193 static ssize_t uapsd_queues_write(struct file *file,
194 				  const char __user *user_buf,
195 				  size_t count, loff_t *ppos)
196 {
197 	struct ieee80211_local *local = file->private_data;
198 	unsigned long val;
199 	char buf[10];
200 	size_t len;
201 	int ret;
202 
203 	len = min(count, sizeof(buf) - 1);
204 	if (copy_from_user(buf, user_buf, len))
205 		return -EFAULT;
206 	buf[len] = '\0';
207 
208 	ret = strict_strtoul(buf, 0, &val);
209 
210 	if (ret)
211 		return -EINVAL;
212 
213 	if (val & ~IEEE80211_WMM_IE_STA_QOSINFO_AC_MASK)
214 		return -ERANGE;
215 
216 	local->uapsd_queues = val;
217 
218 	return count;
219 }
220 
221 static const struct file_operations uapsd_queues_ops = {
222 	.read = uapsd_queues_read,
223 	.write = uapsd_queues_write,
224 	.open = mac80211_open_file_generic,
225 	.llseek = default_llseek,
226 };
227 
228 static ssize_t uapsd_max_sp_len_read(struct file *file, char __user *user_buf,
229 				     size_t count, loff_t *ppos)
230 {
231 	struct ieee80211_local *local = file->private_data;
232 
233 	return mac80211_format_buffer(user_buf, count, ppos, "0x%x\n",
234 				      local->uapsd_max_sp_len);
235 }
236 
237 static ssize_t uapsd_max_sp_len_write(struct file *file,
238 				      const char __user *user_buf,
239 				      size_t count, loff_t *ppos)
240 {
241 	struct ieee80211_local *local = file->private_data;
242 	unsigned long val;
243 	char buf[10];
244 	size_t len;
245 	int ret;
246 
247 	len = min(count, sizeof(buf) - 1);
248 	if (copy_from_user(buf, user_buf, len))
249 		return -EFAULT;
250 	buf[len] = '\0';
251 
252 	ret = strict_strtoul(buf, 0, &val);
253 
254 	if (ret)
255 		return -EINVAL;
256 
257 	if (val & ~IEEE80211_WMM_IE_STA_QOSINFO_SP_MASK)
258 		return -ERANGE;
259 
260 	local->uapsd_max_sp_len = val;
261 
262 	return count;
263 }
264 
265 static const struct file_operations uapsd_max_sp_len_ops = {
266 	.read = uapsd_max_sp_len_read,
267 	.write = uapsd_max_sp_len_write,
268 	.open = mac80211_open_file_generic,
269 	.llseek = default_llseek,
270 };
271 
272 static ssize_t channel_type_read(struct file *file, char __user *user_buf,
273 		       size_t count, loff_t *ppos)
274 {
275 	struct ieee80211_local *local = file->private_data;
276 	const char *buf;
277 
278 	switch (local->hw.conf.channel_type) {
279 	case NL80211_CHAN_NO_HT:
280 		buf = "no ht\n";
281 		break;
282 	case NL80211_CHAN_HT20:
283 		buf = "ht20\n";
284 		break;
285 	case NL80211_CHAN_HT40MINUS:
286 		buf = "ht40-\n";
287 		break;
288 	case NL80211_CHAN_HT40PLUS:
289 		buf = "ht40+\n";
290 		break;
291 	default:
292 		buf = "???";
293 		break;
294 	}
295 
296 	return simple_read_from_buffer(user_buf, count, ppos, buf, strlen(buf));
297 }
298 
299 static ssize_t hwflags_read(struct file *file, char __user *user_buf,
300 			    size_t count, loff_t *ppos)
301 {
302 	struct ieee80211_local *local = file->private_data;
303 	int mxln = 500;
304 	ssize_t rv;
305 	char *buf = kzalloc(mxln, GFP_KERNEL);
306 	int sf = 0; /* how many written so far */
307 
308 	sf += snprintf(buf, mxln - sf, "0x%x\n", local->hw.flags);
309 	if (local->hw.flags & IEEE80211_HW_HAS_RATE_CONTROL)
310 		sf += snprintf(buf + sf, mxln - sf, "HAS_RATE_CONTROL\n");
311 	if (local->hw.flags & IEEE80211_HW_RX_INCLUDES_FCS)
312 		sf += snprintf(buf + sf, mxln - sf, "RX_INCLUDES_FCS\n");
313 	if (local->hw.flags & IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING)
314 		sf += snprintf(buf + sf, mxln - sf,
315 			       "HOST_BCAST_PS_BUFFERING\n");
316 	if (local->hw.flags & IEEE80211_HW_2GHZ_SHORT_SLOT_INCAPABLE)
317 		sf += snprintf(buf + sf, mxln - sf,
318 			       "2GHZ_SHORT_SLOT_INCAPABLE\n");
319 	if (local->hw.flags & IEEE80211_HW_2GHZ_SHORT_PREAMBLE_INCAPABLE)
320 		sf += snprintf(buf + sf, mxln - sf,
321 			       "2GHZ_SHORT_PREAMBLE_INCAPABLE\n");
322 	if (local->hw.flags & IEEE80211_HW_SIGNAL_UNSPEC)
323 		sf += snprintf(buf + sf, mxln - sf, "SIGNAL_UNSPEC\n");
324 	if (local->hw.flags & IEEE80211_HW_SIGNAL_DBM)
325 		sf += snprintf(buf + sf, mxln - sf, "SIGNAL_DBM\n");
326 	if (local->hw.flags & IEEE80211_HW_NEED_DTIM_PERIOD)
327 		sf += snprintf(buf + sf, mxln - sf, "NEED_DTIM_PERIOD\n");
328 	if (local->hw.flags & IEEE80211_HW_SPECTRUM_MGMT)
329 		sf += snprintf(buf + sf, mxln - sf, "SPECTRUM_MGMT\n");
330 	if (local->hw.flags & IEEE80211_HW_AMPDU_AGGREGATION)
331 		sf += snprintf(buf + sf, mxln - sf, "AMPDU_AGGREGATION\n");
332 	if (local->hw.flags & IEEE80211_HW_SUPPORTS_PS)
333 		sf += snprintf(buf + sf, mxln - sf, "SUPPORTS_PS\n");
334 	if (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK)
335 		sf += snprintf(buf + sf, mxln - sf, "PS_NULLFUNC_STACK\n");
336 	if (local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_PS)
337 		sf += snprintf(buf + sf, mxln - sf, "SUPPORTS_DYNAMIC_PS\n");
338 	if (local->hw.flags & IEEE80211_HW_MFP_CAPABLE)
339 		sf += snprintf(buf + sf, mxln - sf, "MFP_CAPABLE\n");
340 	if (local->hw.flags & IEEE80211_HW_BEACON_FILTER)
341 		sf += snprintf(buf + sf, mxln - sf, "BEACON_FILTER\n");
342 	if (local->hw.flags & IEEE80211_HW_SUPPORTS_STATIC_SMPS)
343 		sf += snprintf(buf + sf, mxln - sf, "SUPPORTS_STATIC_SMPS\n");
344 	if (local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS)
345 		sf += snprintf(buf + sf, mxln - sf, "SUPPORTS_DYNAMIC_SMPS\n");
346 	if (local->hw.flags & IEEE80211_HW_SUPPORTS_UAPSD)
347 		sf += snprintf(buf + sf, mxln - sf, "SUPPORTS_UAPSD\n");
348 	if (local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS)
349 		sf += snprintf(buf + sf, mxln - sf, "REPORTS_TX_ACK_STATUS\n");
350 	if (local->hw.flags & IEEE80211_HW_CONNECTION_MONITOR)
351 		sf += snprintf(buf + sf, mxln - sf, "CONNECTION_MONITOR\n");
352 	if (local->hw.flags & IEEE80211_HW_SUPPORTS_CQM_RSSI)
353 		sf += snprintf(buf + sf, mxln - sf, "SUPPORTS_CQM_RSSI\n");
354 	if (local->hw.flags & IEEE80211_HW_SUPPORTS_PER_STA_GTK)
355 		sf += snprintf(buf + sf, mxln - sf, "SUPPORTS_PER_STA_GTK\n");
356 	if (local->hw.flags & IEEE80211_HW_AP_LINK_PS)
357 		sf += snprintf(buf + sf, mxln - sf, "AP_LINK_PS\n");
358 
359 	rv = simple_read_from_buffer(user_buf, count, ppos, buf, strlen(buf));
360 	kfree(buf);
361 	return rv;
362 }
363 
364 static ssize_t queues_read(struct file *file, char __user *user_buf,
365 			   size_t count, loff_t *ppos)
366 {
367 	struct ieee80211_local *local = file->private_data;
368 	unsigned long flags;
369 	char buf[IEEE80211_MAX_QUEUES * 20];
370 	int q, res = 0;
371 
372 	spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
373 	for (q = 0; q < local->hw.queues; q++)
374 		res += sprintf(buf + res, "%02d: %#.8lx/%d\n", q,
375 				local->queue_stop_reasons[q],
376 				skb_queue_len(&local->pending[q]));
377 	spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
378 
379 	return simple_read_from_buffer(user_buf, count, ppos, buf, res);
380 }
381 
382 DEBUGFS_READONLY_FILE_OPS(hwflags);
383 DEBUGFS_READONLY_FILE_OPS(channel_type);
384 DEBUGFS_READONLY_FILE_OPS(queues);
385 
386 /* statistics stuff */
387 
388 static ssize_t format_devstat_counter(struct ieee80211_local *local,
389 	char __user *userbuf,
390 	size_t count, loff_t *ppos,
391 	int (*printvalue)(struct ieee80211_low_level_stats *stats, char *buf,
392 			  int buflen))
393 {
394 	struct ieee80211_low_level_stats stats;
395 	char buf[20];
396 	int res;
397 
398 	rtnl_lock();
399 	res = drv_get_stats(local, &stats);
400 	rtnl_unlock();
401 	if (res)
402 		return res;
403 	res = printvalue(&stats, buf, sizeof(buf));
404 	return simple_read_from_buffer(userbuf, count, ppos, buf, res);
405 }
406 
407 #define DEBUGFS_DEVSTATS_FILE(name)					\
408 static int print_devstats_##name(struct ieee80211_low_level_stats *stats,\
409 				 char *buf, int buflen)			\
410 {									\
411 	return scnprintf(buf, buflen, "%u\n", stats->name);		\
412 }									\
413 static ssize_t stats_ ##name## _read(struct file *file,			\
414 				     char __user *userbuf,		\
415 				     size_t count, loff_t *ppos)	\
416 {									\
417 	return format_devstat_counter(file->private_data,		\
418 				      userbuf,				\
419 				      count,				\
420 				      ppos,				\
421 				      print_devstats_##name);		\
422 }									\
423 									\
424 static const struct file_operations stats_ ##name## _ops = {		\
425 	.read = stats_ ##name## _read,					\
426 	.open = mac80211_open_file_generic,				\
427 	.llseek = generic_file_llseek,					\
428 };
429 
430 #define DEBUGFS_STATS_ADD(name, field)					\
431 	debugfs_create_u32(#name, 0400, statsd, (u32 *) &field);
432 #define DEBUGFS_DEVSTATS_ADD(name)					\
433 	debugfs_create_file(#name, 0400, statsd, local, &stats_ ##name## _ops);
434 
435 DEBUGFS_DEVSTATS_FILE(dot11ACKFailureCount);
436 DEBUGFS_DEVSTATS_FILE(dot11RTSFailureCount);
437 DEBUGFS_DEVSTATS_FILE(dot11FCSErrorCount);
438 DEBUGFS_DEVSTATS_FILE(dot11RTSSuccessCount);
439 
440 void debugfs_hw_add(struct ieee80211_local *local)
441 {
442 	struct dentry *phyd = local->hw.wiphy->debugfsdir;
443 	struct dentry *statsd;
444 
445 	if (!phyd)
446 		return;
447 
448 	local->debugfs.keys = debugfs_create_dir("keys", phyd);
449 
450 	DEBUGFS_ADD(frequency);
451 	DEBUGFS_ADD(total_ps_buffered);
452 	DEBUGFS_ADD(wep_iv);
453 	DEBUGFS_ADD(tsf);
454 	DEBUGFS_ADD(queues);
455 	DEBUGFS_ADD_MODE(reset, 0200);
456 	DEBUGFS_ADD(noack);
457 	DEBUGFS_ADD(uapsd_queues);
458 	DEBUGFS_ADD(uapsd_max_sp_len);
459 	DEBUGFS_ADD(channel_type);
460 	DEBUGFS_ADD(hwflags);
461 	DEBUGFS_ADD(user_power);
462 	DEBUGFS_ADD(power);
463 
464 	statsd = debugfs_create_dir("statistics", phyd);
465 
466 	/* if the dir failed, don't put all the other things into the root! */
467 	if (!statsd)
468 		return;
469 
470 	DEBUGFS_STATS_ADD(transmitted_fragment_count,
471 		local->dot11TransmittedFragmentCount);
472 	DEBUGFS_STATS_ADD(multicast_transmitted_frame_count,
473 		local->dot11MulticastTransmittedFrameCount);
474 	DEBUGFS_STATS_ADD(failed_count, local->dot11FailedCount);
475 	DEBUGFS_STATS_ADD(retry_count, local->dot11RetryCount);
476 	DEBUGFS_STATS_ADD(multiple_retry_count,
477 		local->dot11MultipleRetryCount);
478 	DEBUGFS_STATS_ADD(frame_duplicate_count,
479 		local->dot11FrameDuplicateCount);
480 	DEBUGFS_STATS_ADD(received_fragment_count,
481 		local->dot11ReceivedFragmentCount);
482 	DEBUGFS_STATS_ADD(multicast_received_frame_count,
483 		local->dot11MulticastReceivedFrameCount);
484 	DEBUGFS_STATS_ADD(transmitted_frame_count,
485 		local->dot11TransmittedFrameCount);
486 #ifdef CONFIG_MAC80211_DEBUG_COUNTERS
487 	DEBUGFS_STATS_ADD(tx_handlers_drop, local->tx_handlers_drop);
488 	DEBUGFS_STATS_ADD(tx_handlers_queued, local->tx_handlers_queued);
489 	DEBUGFS_STATS_ADD(tx_handlers_drop_unencrypted,
490 		local->tx_handlers_drop_unencrypted);
491 	DEBUGFS_STATS_ADD(tx_handlers_drop_fragment,
492 		local->tx_handlers_drop_fragment);
493 	DEBUGFS_STATS_ADD(tx_handlers_drop_wep,
494 		local->tx_handlers_drop_wep);
495 	DEBUGFS_STATS_ADD(tx_handlers_drop_not_assoc,
496 		local->tx_handlers_drop_not_assoc);
497 	DEBUGFS_STATS_ADD(tx_handlers_drop_unauth_port,
498 		local->tx_handlers_drop_unauth_port);
499 	DEBUGFS_STATS_ADD(rx_handlers_drop, local->rx_handlers_drop);
500 	DEBUGFS_STATS_ADD(rx_handlers_queued, local->rx_handlers_queued);
501 	DEBUGFS_STATS_ADD(rx_handlers_drop_nullfunc,
502 		local->rx_handlers_drop_nullfunc);
503 	DEBUGFS_STATS_ADD(rx_handlers_drop_defrag,
504 		local->rx_handlers_drop_defrag);
505 	DEBUGFS_STATS_ADD(rx_handlers_drop_short,
506 		local->rx_handlers_drop_short);
507 	DEBUGFS_STATS_ADD(rx_handlers_drop_passive_scan,
508 		local->rx_handlers_drop_passive_scan);
509 	DEBUGFS_STATS_ADD(tx_expand_skb_head,
510 		local->tx_expand_skb_head);
511 	DEBUGFS_STATS_ADD(tx_expand_skb_head_cloned,
512 		local->tx_expand_skb_head_cloned);
513 	DEBUGFS_STATS_ADD(rx_expand_skb_head,
514 		local->rx_expand_skb_head);
515 	DEBUGFS_STATS_ADD(rx_expand_skb_head2,
516 		local->rx_expand_skb_head2);
517 	DEBUGFS_STATS_ADD(rx_handlers_fragments,
518 		local->rx_handlers_fragments);
519 	DEBUGFS_STATS_ADD(tx_status_drop,
520 		local->tx_status_drop);
521 #endif
522 	DEBUGFS_DEVSTATS_ADD(dot11ACKFailureCount);
523 	DEBUGFS_DEVSTATS_ADD(dot11RTSFailureCount);
524 	DEBUGFS_DEVSTATS_ADD(dot11FCSErrorCount);
525 	DEBUGFS_DEVSTATS_ADD(dot11RTSSuccessCount);
526 }
527