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