a05829a722
Currently, _everything_ in cfg80211 holds the RTNL, and if you have a slow USB device (or a few) you can get some bad lock contention on that. Fix that by re-adding a mutex to each wiphy/rdev as we had at some point, so we have locking for the wireless_dev lists and all the other things in there, and also so that drivers still don't have to worry too much about it (they still won't get parallel calls for a single device). Then, we can restrict the RTNL to a few cases where we add or remove interfaces and really need the added protection. Some of the global list management still also uses the RTNL, since we need to have it anyway for netdev management, but we only hold the RTNL for very short periods of time here. Link: https://lore.kernel.org/r/20210122161942.81df9f5e047a.I4a8e1a60b18863ea8c5e6d3a0faeafb2d45b2f40@changeid Tested-by: Marek Szyprowski <m.szyprowski@samsung.com> [marvell driver issues] Signed-off-by: Johannes Berg <johannes.berg@intel.com>
111 lines
2.8 KiB
C
111 lines
2.8 KiB
C
// SPDX-License-Identifier: GPL-2.0-only
|
|
/*
|
|
* cfg80211 debugfs
|
|
*
|
|
* Copyright 2009 Luis R. Rodriguez <lrodriguez@atheros.com>
|
|
* Copyright 2007 Johannes Berg <johannes@sipsolutions.net>
|
|
*/
|
|
|
|
#include <linux/slab.h>
|
|
#include "core.h"
|
|
#include "debugfs.h"
|
|
|
|
#define DEBUGFS_READONLY_FILE(name, buflen, fmt, value...) \
|
|
static ssize_t name## _read(struct file *file, char __user *userbuf, \
|
|
size_t count, loff_t *ppos) \
|
|
{ \
|
|
struct wiphy *wiphy = file->private_data; \
|
|
char buf[buflen]; \
|
|
int res; \
|
|
\
|
|
res = scnprintf(buf, buflen, fmt "\n", ##value); \
|
|
return simple_read_from_buffer(userbuf, count, ppos, buf, res); \
|
|
} \
|
|
\
|
|
static const struct file_operations name## _ops = { \
|
|
.read = name## _read, \
|
|
.open = simple_open, \
|
|
.llseek = generic_file_llseek, \
|
|
}
|
|
|
|
DEBUGFS_READONLY_FILE(rts_threshold, 20, "%d",
|
|
wiphy->rts_threshold);
|
|
DEBUGFS_READONLY_FILE(fragmentation_threshold, 20, "%d",
|
|
wiphy->frag_threshold);
|
|
DEBUGFS_READONLY_FILE(short_retry_limit, 20, "%d",
|
|
wiphy->retry_short);
|
|
DEBUGFS_READONLY_FILE(long_retry_limit, 20, "%d",
|
|
wiphy->retry_long);
|
|
|
|
static int ht_print_chan(struct ieee80211_channel *chan,
|
|
char *buf, int buf_size, int offset)
|
|
{
|
|
if (WARN_ON(offset > buf_size))
|
|
return 0;
|
|
|
|
if (chan->flags & IEEE80211_CHAN_DISABLED)
|
|
return scnprintf(buf + offset,
|
|
buf_size - offset,
|
|
"%d Disabled\n",
|
|
chan->center_freq);
|
|
|
|
return scnprintf(buf + offset,
|
|
buf_size - offset,
|
|
"%d HT40 %c%c\n",
|
|
chan->center_freq,
|
|
(chan->flags & IEEE80211_CHAN_NO_HT40MINUS) ?
|
|
' ' : '-',
|
|
(chan->flags & IEEE80211_CHAN_NO_HT40PLUS) ?
|
|
' ' : '+');
|
|
}
|
|
|
|
static ssize_t ht40allow_map_read(struct file *file,
|
|
char __user *user_buf,
|
|
size_t count, loff_t *ppos)
|
|
{
|
|
struct wiphy *wiphy = file->private_data;
|
|
char *buf;
|
|
unsigned int offset = 0, buf_size = PAGE_SIZE, i, r;
|
|
enum nl80211_band band;
|
|
struct ieee80211_supported_band *sband;
|
|
|
|
buf = kzalloc(buf_size, GFP_KERNEL);
|
|
if (!buf)
|
|
return -ENOMEM;
|
|
|
|
for (band = 0; band < NUM_NL80211_BANDS; band++) {
|
|
sband = wiphy->bands[band];
|
|
if (!sband)
|
|
continue;
|
|
for (i = 0; i < sband->n_channels; i++)
|
|
offset += ht_print_chan(&sband->channels[i],
|
|
buf, buf_size, offset);
|
|
}
|
|
|
|
r = simple_read_from_buffer(user_buf, count, ppos, buf, offset);
|
|
|
|
kfree(buf);
|
|
|
|
return r;
|
|
}
|
|
|
|
static const struct file_operations ht40allow_map_ops = {
|
|
.read = ht40allow_map_read,
|
|
.open = simple_open,
|
|
.llseek = default_llseek,
|
|
};
|
|
|
|
#define DEBUGFS_ADD(name) \
|
|
debugfs_create_file(#name, 0444, phyd, &rdev->wiphy, &name## _ops)
|
|
|
|
void cfg80211_debugfs_rdev_add(struct cfg80211_registered_device *rdev)
|
|
{
|
|
struct dentry *phyd = rdev->wiphy.debugfsdir;
|
|
|
|
DEBUGFS_ADD(rts_threshold);
|
|
DEBUGFS_ADD(fragmentation_threshold);
|
|
DEBUGFS_ADD(short_retry_limit);
|
|
DEBUGFS_ADD(long_retry_limit);
|
|
DEBUGFS_ADD(ht40allow_map);
|
|
}
|