xref: /kernel/linux/linux-5.10/net/wireless/debugfs.c (revision 8c2ecf20)
18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * cfg80211 debugfs
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Copyright 2009	Luis R. Rodriguez <lrodriguez@atheros.com>
68c2ecf20Sopenharmony_ci * Copyright 2007	Johannes Berg <johannes@sipsolutions.net>
78c2ecf20Sopenharmony_ci */
88c2ecf20Sopenharmony_ci
98c2ecf20Sopenharmony_ci#include <linux/slab.h>
108c2ecf20Sopenharmony_ci#include "core.h"
118c2ecf20Sopenharmony_ci#include "debugfs.h"
128c2ecf20Sopenharmony_ci
138c2ecf20Sopenharmony_ci#define DEBUGFS_READONLY_FILE(name, buflen, fmt, value...)		\
148c2ecf20Sopenharmony_cistatic ssize_t name## _read(struct file *file, char __user *userbuf,	\
158c2ecf20Sopenharmony_ci			    size_t count, loff_t *ppos)			\
168c2ecf20Sopenharmony_ci{									\
178c2ecf20Sopenharmony_ci	struct wiphy *wiphy = file->private_data;			\
188c2ecf20Sopenharmony_ci	char buf[buflen];						\
198c2ecf20Sopenharmony_ci	int res;							\
208c2ecf20Sopenharmony_ci									\
218c2ecf20Sopenharmony_ci	res = scnprintf(buf, buflen, fmt "\n", ##value);		\
228c2ecf20Sopenharmony_ci	return simple_read_from_buffer(userbuf, count, ppos, buf, res);	\
238c2ecf20Sopenharmony_ci}									\
248c2ecf20Sopenharmony_ci									\
258c2ecf20Sopenharmony_cistatic const struct file_operations name## _ops = {			\
268c2ecf20Sopenharmony_ci	.read = name## _read,						\
278c2ecf20Sopenharmony_ci	.open = simple_open,						\
288c2ecf20Sopenharmony_ci	.llseek = generic_file_llseek,					\
298c2ecf20Sopenharmony_ci}
308c2ecf20Sopenharmony_ci
318c2ecf20Sopenharmony_ciDEBUGFS_READONLY_FILE(rts_threshold, 20, "%d",
328c2ecf20Sopenharmony_ci		      wiphy->rts_threshold);
338c2ecf20Sopenharmony_ciDEBUGFS_READONLY_FILE(fragmentation_threshold, 20, "%d",
348c2ecf20Sopenharmony_ci		      wiphy->frag_threshold);
358c2ecf20Sopenharmony_ciDEBUGFS_READONLY_FILE(short_retry_limit, 20, "%d",
368c2ecf20Sopenharmony_ci		      wiphy->retry_short);
378c2ecf20Sopenharmony_ciDEBUGFS_READONLY_FILE(long_retry_limit, 20, "%d",
388c2ecf20Sopenharmony_ci		      wiphy->retry_long);
398c2ecf20Sopenharmony_ci
408c2ecf20Sopenharmony_cistatic int ht_print_chan(struct ieee80211_channel *chan,
418c2ecf20Sopenharmony_ci			 char *buf, int buf_size, int offset)
428c2ecf20Sopenharmony_ci{
438c2ecf20Sopenharmony_ci	if (WARN_ON(offset > buf_size))
448c2ecf20Sopenharmony_ci		return 0;
458c2ecf20Sopenharmony_ci
468c2ecf20Sopenharmony_ci	if (chan->flags & IEEE80211_CHAN_DISABLED)
478c2ecf20Sopenharmony_ci		return scnprintf(buf + offset,
488c2ecf20Sopenharmony_ci				 buf_size - offset,
498c2ecf20Sopenharmony_ci				 "%d Disabled\n",
508c2ecf20Sopenharmony_ci				 chan->center_freq);
518c2ecf20Sopenharmony_ci
528c2ecf20Sopenharmony_ci	return scnprintf(buf + offset,
538c2ecf20Sopenharmony_ci			 buf_size - offset,
548c2ecf20Sopenharmony_ci			 "%d HT40 %c%c\n",
558c2ecf20Sopenharmony_ci			 chan->center_freq,
568c2ecf20Sopenharmony_ci			 (chan->flags & IEEE80211_CHAN_NO_HT40MINUS) ?
578c2ecf20Sopenharmony_ci				' ' : '-',
588c2ecf20Sopenharmony_ci			 (chan->flags & IEEE80211_CHAN_NO_HT40PLUS) ?
598c2ecf20Sopenharmony_ci				' ' : '+');
608c2ecf20Sopenharmony_ci}
618c2ecf20Sopenharmony_ci
628c2ecf20Sopenharmony_cistatic ssize_t ht40allow_map_read(struct file *file,
638c2ecf20Sopenharmony_ci				  char __user *user_buf,
648c2ecf20Sopenharmony_ci				  size_t count, loff_t *ppos)
658c2ecf20Sopenharmony_ci{
668c2ecf20Sopenharmony_ci	struct wiphy *wiphy = file->private_data;
678c2ecf20Sopenharmony_ci	char *buf;
688c2ecf20Sopenharmony_ci	unsigned int offset = 0, buf_size = PAGE_SIZE, i;
698c2ecf20Sopenharmony_ci	enum nl80211_band band;
708c2ecf20Sopenharmony_ci	struct ieee80211_supported_band *sband;
718c2ecf20Sopenharmony_ci	ssize_t r;
728c2ecf20Sopenharmony_ci
738c2ecf20Sopenharmony_ci	buf = kzalloc(buf_size, GFP_KERNEL);
748c2ecf20Sopenharmony_ci	if (!buf)
758c2ecf20Sopenharmony_ci		return -ENOMEM;
768c2ecf20Sopenharmony_ci
778c2ecf20Sopenharmony_ci	rtnl_lock();
788c2ecf20Sopenharmony_ci
798c2ecf20Sopenharmony_ci	for (band = 0; band < NUM_NL80211_BANDS; band++) {
808c2ecf20Sopenharmony_ci		sband = wiphy->bands[band];
818c2ecf20Sopenharmony_ci		if (!sband)
828c2ecf20Sopenharmony_ci			continue;
838c2ecf20Sopenharmony_ci		for (i = 0; i < sband->n_channels; i++)
848c2ecf20Sopenharmony_ci			offset += ht_print_chan(&sband->channels[i],
858c2ecf20Sopenharmony_ci						buf, buf_size, offset);
868c2ecf20Sopenharmony_ci	}
878c2ecf20Sopenharmony_ci
888c2ecf20Sopenharmony_ci	rtnl_unlock();
898c2ecf20Sopenharmony_ci
908c2ecf20Sopenharmony_ci	r = simple_read_from_buffer(user_buf, count, ppos, buf, offset);
918c2ecf20Sopenharmony_ci
928c2ecf20Sopenharmony_ci	kfree(buf);
938c2ecf20Sopenharmony_ci
948c2ecf20Sopenharmony_ci	return r;
958c2ecf20Sopenharmony_ci}
968c2ecf20Sopenharmony_ci
978c2ecf20Sopenharmony_cistatic const struct file_operations ht40allow_map_ops = {
988c2ecf20Sopenharmony_ci	.read = ht40allow_map_read,
998c2ecf20Sopenharmony_ci	.open = simple_open,
1008c2ecf20Sopenharmony_ci	.llseek = default_llseek,
1018c2ecf20Sopenharmony_ci};
1028c2ecf20Sopenharmony_ci
1038c2ecf20Sopenharmony_ci#define DEBUGFS_ADD(name)						\
1048c2ecf20Sopenharmony_ci	debugfs_create_file(#name, 0444, phyd, &rdev->wiphy, &name## _ops)
1058c2ecf20Sopenharmony_ci
1068c2ecf20Sopenharmony_civoid cfg80211_debugfs_rdev_add(struct cfg80211_registered_device *rdev)
1078c2ecf20Sopenharmony_ci{
1088c2ecf20Sopenharmony_ci	struct dentry *phyd = rdev->wiphy.debugfsdir;
1098c2ecf20Sopenharmony_ci
1108c2ecf20Sopenharmony_ci	DEBUGFS_ADD(rts_threshold);
1118c2ecf20Sopenharmony_ci	DEBUGFS_ADD(fragmentation_threshold);
1128c2ecf20Sopenharmony_ci	DEBUGFS_ADD(short_retry_limit);
1138c2ecf20Sopenharmony_ci	DEBUGFS_ADD(long_retry_limit);
1148c2ecf20Sopenharmony_ci	DEBUGFS_ADD(ht40allow_map);
1158c2ecf20Sopenharmony_ci}
116