cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

debugfs.c (18841B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * mac80211 debugfs for wireless PHYs
      4 *
      5 * Copyright 2007	Johannes Berg <johannes@sipsolutions.net>
      6 * Copyright 2013-2014  Intel Mobile Communications GmbH
      7 * Copyright (C) 2018 - 2019, 2021 Intel Corporation
      8 */
      9
     10#include <linux/debugfs.h>
     11#include <linux/rtnetlink.h>
     12#include <linux/vmalloc.h>
     13#include "ieee80211_i.h"
     14#include "driver-ops.h"
     15#include "rate.h"
     16#include "debugfs.h"
     17
     18#define DEBUGFS_FORMAT_BUFFER_SIZE 100
     19
     20int mac80211_format_buffer(char __user *userbuf, size_t count,
     21				  loff_t *ppos, char *fmt, ...)
     22{
     23	va_list args;
     24	char buf[DEBUGFS_FORMAT_BUFFER_SIZE];
     25	int res;
     26
     27	va_start(args, fmt);
     28	res = vscnprintf(buf, sizeof(buf), fmt, args);
     29	va_end(args);
     30
     31	return simple_read_from_buffer(userbuf, count, ppos, buf, res);
     32}
     33
     34#define DEBUGFS_READONLY_FILE_FN(name, fmt, value...)			\
     35static ssize_t name## _read(struct file *file, char __user *userbuf,	\
     36			    size_t count, loff_t *ppos)			\
     37{									\
     38	struct ieee80211_local *local = file->private_data;		\
     39									\
     40	return mac80211_format_buffer(userbuf, count, ppos, 		\
     41				      fmt "\n", ##value);		\
     42}
     43
     44#define DEBUGFS_READONLY_FILE_OPS(name)			\
     45static const struct file_operations name## _ops = {			\
     46	.read = name## _read,						\
     47	.open = simple_open,						\
     48	.llseek = generic_file_llseek,					\
     49};
     50
     51#define DEBUGFS_READONLY_FILE(name, fmt, value...)		\
     52	DEBUGFS_READONLY_FILE_FN(name, fmt, value)		\
     53	DEBUGFS_READONLY_FILE_OPS(name)
     54
     55#define DEBUGFS_ADD(name)						\
     56	debugfs_create_file(#name, 0400, phyd, local, &name## _ops)
     57
     58#define DEBUGFS_ADD_MODE(name, mode)					\
     59	debugfs_create_file(#name, mode, phyd, local, &name## _ops);
     60
     61
     62DEBUGFS_READONLY_FILE(hw_conf, "%x",
     63		      local->hw.conf.flags);
     64DEBUGFS_READONLY_FILE(user_power, "%d",
     65		      local->user_power_level);
     66DEBUGFS_READONLY_FILE(power, "%d",
     67		      local->hw.conf.power_level);
     68DEBUGFS_READONLY_FILE(total_ps_buffered, "%d",
     69		      local->total_ps_buffered);
     70DEBUGFS_READONLY_FILE(wep_iv, "%#08x",
     71		      local->wep_iv & 0xffffff);
     72DEBUGFS_READONLY_FILE(rate_ctrl_alg, "%s",
     73	local->rate_ctrl ? local->rate_ctrl->ops->name : "hw/driver");
     74
     75static ssize_t aqm_read(struct file *file,
     76			char __user *user_buf,
     77			size_t count,
     78			loff_t *ppos)
     79{
     80	struct ieee80211_local *local = file->private_data;
     81	struct fq *fq = &local->fq;
     82	char buf[200];
     83	int len = 0;
     84
     85	spin_lock_bh(&local->fq.lock);
     86	rcu_read_lock();
     87
     88	len = scnprintf(buf, sizeof(buf),
     89			"access name value\n"
     90			"R fq_flows_cnt %u\n"
     91			"R fq_backlog %u\n"
     92			"R fq_overlimit %u\n"
     93			"R fq_overmemory %u\n"
     94			"R fq_collisions %u\n"
     95			"R fq_memory_usage %u\n"
     96			"RW fq_memory_limit %u\n"
     97			"RW fq_limit %u\n"
     98			"RW fq_quantum %u\n",
     99			fq->flows_cnt,
    100			fq->backlog,
    101			fq->overmemory,
    102			fq->overlimit,
    103			fq->collisions,
    104			fq->memory_usage,
    105			fq->memory_limit,
    106			fq->limit,
    107			fq->quantum);
    108
    109	rcu_read_unlock();
    110	spin_unlock_bh(&local->fq.lock);
    111
    112	return simple_read_from_buffer(user_buf, count, ppos,
    113				       buf, len);
    114}
    115
    116static ssize_t aqm_write(struct file *file,
    117			 const char __user *user_buf,
    118			 size_t count,
    119			 loff_t *ppos)
    120{
    121	struct ieee80211_local *local = file->private_data;
    122	char buf[100];
    123
    124	if (count >= sizeof(buf))
    125		return -EINVAL;
    126
    127	if (copy_from_user(buf, user_buf, count))
    128		return -EFAULT;
    129
    130	if (count && buf[count - 1] == '\n')
    131		buf[count - 1] = '\0';
    132	else
    133		buf[count] = '\0';
    134
    135	if (sscanf(buf, "fq_limit %u", &local->fq.limit) == 1)
    136		return count;
    137	else if (sscanf(buf, "fq_memory_limit %u", &local->fq.memory_limit) == 1)
    138		return count;
    139	else if (sscanf(buf, "fq_quantum %u", &local->fq.quantum) == 1)
    140		return count;
    141
    142	return -EINVAL;
    143}
    144
    145static const struct file_operations aqm_ops = {
    146	.write = aqm_write,
    147	.read = aqm_read,
    148	.open = simple_open,
    149	.llseek = default_llseek,
    150};
    151
    152static ssize_t airtime_flags_read(struct file *file,
    153				  char __user *user_buf,
    154				  size_t count, loff_t *ppos)
    155{
    156	struct ieee80211_local *local = file->private_data;
    157	char buf[128] = {}, *pos, *end;
    158
    159	pos = buf;
    160	end = pos + sizeof(buf) - 1;
    161
    162	if (local->airtime_flags & AIRTIME_USE_TX)
    163		pos += scnprintf(pos, end - pos, "AIRTIME_TX\t(%lx)\n",
    164				 AIRTIME_USE_TX);
    165	if (local->airtime_flags & AIRTIME_USE_RX)
    166		pos += scnprintf(pos, end - pos, "AIRTIME_RX\t(%lx)\n",
    167				 AIRTIME_USE_RX);
    168
    169	return simple_read_from_buffer(user_buf, count, ppos, buf,
    170				       strlen(buf));
    171}
    172
    173static ssize_t airtime_flags_write(struct file *file,
    174				   const char __user *user_buf,
    175				   size_t count, loff_t *ppos)
    176{
    177	struct ieee80211_local *local = file->private_data;
    178	char buf[16];
    179
    180	if (count >= sizeof(buf))
    181		return -EINVAL;
    182
    183	if (copy_from_user(buf, user_buf, count))
    184		return -EFAULT;
    185
    186	if (count && buf[count - 1] == '\n')
    187		buf[count - 1] = '\0';
    188	else
    189		buf[count] = '\0';
    190
    191	if (kstrtou16(buf, 0, &local->airtime_flags))
    192		return -EINVAL;
    193
    194	return count;
    195}
    196
    197static const struct file_operations airtime_flags_ops = {
    198	.write = airtime_flags_write,
    199	.read = airtime_flags_read,
    200	.open = simple_open,
    201	.llseek = default_llseek,
    202};
    203
    204static ssize_t aql_txq_limit_read(struct file *file,
    205				  char __user *user_buf,
    206				  size_t count,
    207				  loff_t *ppos)
    208{
    209	struct ieee80211_local *local = file->private_data;
    210	char buf[400];
    211	int len = 0;
    212
    213	len = scnprintf(buf, sizeof(buf),
    214			"AC	AQL limit low	AQL limit high\n"
    215			"VO	%u		%u\n"
    216			"VI	%u		%u\n"
    217			"BE	%u		%u\n"
    218			"BK	%u		%u\n",
    219			local->airtime[IEEE80211_AC_VO].aql_txq_limit_low,
    220			local->airtime[IEEE80211_AC_VO].aql_txq_limit_high,
    221			local->airtime[IEEE80211_AC_VI].aql_txq_limit_low,
    222			local->airtime[IEEE80211_AC_VI].aql_txq_limit_high,
    223			local->airtime[IEEE80211_AC_BE].aql_txq_limit_low,
    224			local->airtime[IEEE80211_AC_BE].aql_txq_limit_high,
    225			local->airtime[IEEE80211_AC_BK].aql_txq_limit_low,
    226			local->airtime[IEEE80211_AC_BK].aql_txq_limit_high);
    227	return simple_read_from_buffer(user_buf, count, ppos,
    228				       buf, len);
    229}
    230
    231static ssize_t aql_txq_limit_write(struct file *file,
    232				   const char __user *user_buf,
    233				   size_t count,
    234				   loff_t *ppos)
    235{
    236	struct ieee80211_local *local = file->private_data;
    237	char buf[100];
    238	u32 ac, q_limit_low, q_limit_high, q_limit_low_old, q_limit_high_old;
    239	struct sta_info *sta;
    240
    241	if (count >= sizeof(buf))
    242		return -EINVAL;
    243
    244	if (copy_from_user(buf, user_buf, count))
    245		return -EFAULT;
    246
    247	if (count && buf[count - 1] == '\n')
    248		buf[count - 1] = '\0';
    249	else
    250		buf[count] = '\0';
    251
    252	if (sscanf(buf, "%u %u %u", &ac, &q_limit_low, &q_limit_high) != 3)
    253		return -EINVAL;
    254
    255	if (ac >= IEEE80211_NUM_ACS)
    256		return -EINVAL;
    257
    258	q_limit_low_old = local->airtime[ac].aql_txq_limit_low;
    259	q_limit_high_old = local->airtime[ac].aql_txq_limit_high;
    260
    261	local->airtime[ac].aql_txq_limit_low = q_limit_low;
    262	local->airtime[ac].aql_txq_limit_high = q_limit_high;
    263
    264	mutex_lock(&local->sta_mtx);
    265	list_for_each_entry(sta, &local->sta_list, list) {
    266		/* If a sta has customized queue limits, keep it */
    267		if (sta->airtime[ac].aql_limit_low == q_limit_low_old &&
    268		    sta->airtime[ac].aql_limit_high == q_limit_high_old) {
    269			sta->airtime[ac].aql_limit_low = q_limit_low;
    270			sta->airtime[ac].aql_limit_high = q_limit_high;
    271		}
    272	}
    273	mutex_unlock(&local->sta_mtx);
    274	return count;
    275}
    276
    277static const struct file_operations aql_txq_limit_ops = {
    278	.write = aql_txq_limit_write,
    279	.read = aql_txq_limit_read,
    280	.open = simple_open,
    281	.llseek = default_llseek,
    282};
    283
    284static ssize_t aql_enable_read(struct file *file, char __user *user_buf,
    285			       size_t count, loff_t *ppos)
    286{
    287	char buf[3];
    288	int len;
    289
    290	len = scnprintf(buf, sizeof(buf), "%d\n",
    291			!static_key_false(&aql_disable.key));
    292
    293	return simple_read_from_buffer(user_buf, count, ppos, buf, len);
    294}
    295
    296static ssize_t aql_enable_write(struct file *file, const char __user *user_buf,
    297				size_t count, loff_t *ppos)
    298{
    299	bool aql_disabled = static_key_false(&aql_disable.key);
    300	char buf[3];
    301	size_t len;
    302
    303	if (count > sizeof(buf))
    304		return -EINVAL;
    305
    306	if (copy_from_user(buf, user_buf, count))
    307		return -EFAULT;
    308
    309	buf[sizeof(buf) - 1] = '\0';
    310	len = strlen(buf);
    311	if (len > 0 && buf[len - 1] == '\n')
    312		buf[len - 1] = 0;
    313
    314	if (buf[0] == '0' && buf[1] == '\0') {
    315		if (!aql_disabled)
    316			static_branch_inc(&aql_disable);
    317	} else if (buf[0] == '1' && buf[1] == '\0') {
    318		if (aql_disabled)
    319			static_branch_dec(&aql_disable);
    320	} else {
    321		return -EINVAL;
    322	}
    323
    324	return count;
    325}
    326
    327static const struct file_operations aql_enable_ops = {
    328	.write = aql_enable_write,
    329	.read = aql_enable_read,
    330	.open = simple_open,
    331	.llseek = default_llseek,
    332};
    333
    334static ssize_t force_tx_status_read(struct file *file,
    335				    char __user *user_buf,
    336				    size_t count,
    337				    loff_t *ppos)
    338{
    339	struct ieee80211_local *local = file->private_data;
    340	char buf[3];
    341	int len = 0;
    342
    343	len = scnprintf(buf, sizeof(buf), "%d\n", (int)local->force_tx_status);
    344
    345	return simple_read_from_buffer(user_buf, count, ppos,
    346				       buf, len);
    347}
    348
    349static ssize_t force_tx_status_write(struct file *file,
    350				     const char __user *user_buf,
    351				     size_t count,
    352				     loff_t *ppos)
    353{
    354	struct ieee80211_local *local = file->private_data;
    355	char buf[3];
    356
    357	if (count >= sizeof(buf))
    358		return -EINVAL;
    359
    360	if (copy_from_user(buf, user_buf, count))
    361		return -EFAULT;
    362
    363	if (count && buf[count - 1] == '\n')
    364		buf[count - 1] = '\0';
    365	else
    366		buf[count] = '\0';
    367
    368	if (buf[0] == '0' && buf[1] == '\0')
    369		local->force_tx_status = 0;
    370	else if (buf[0] == '1' && buf[1] == '\0')
    371		local->force_tx_status = 1;
    372	else
    373		return -EINVAL;
    374
    375	return count;
    376}
    377
    378static const struct file_operations force_tx_status_ops = {
    379	.write = force_tx_status_write,
    380	.read = force_tx_status_read,
    381	.open = simple_open,
    382	.llseek = default_llseek,
    383};
    384
    385static ssize_t airtime_read(struct file *file,
    386			    char __user *user_buf,
    387			    size_t count,
    388			    loff_t *ppos)
    389{
    390	struct ieee80211_local *local = file->private_data;
    391	char buf[200];
    392	u64 v_t[IEEE80211_NUM_ACS];
    393	u64 wt[IEEE80211_NUM_ACS];
    394	int len = 0, ac;
    395
    396	for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) {
    397		spin_lock_bh(&local->airtime[ac].lock);
    398		v_t[ac] = local->airtime[ac].v_t;
    399		wt[ac] = local->airtime[ac].weight_sum;
    400		spin_unlock_bh(&local->airtime[ac].lock);
    401	}
    402	len = scnprintf(buf, sizeof(buf),
    403			"\tVO         VI         BE         BK\n"
    404			"Virt-t\t%-10llu %-10llu %-10llu %-10llu\n"
    405			"Weight\t%-10llu %-10llu %-10llu %-10llu\n",
    406			v_t[0],
    407			v_t[1],
    408			v_t[2],
    409			v_t[3],
    410			wt[0],
    411			wt[1],
    412			wt[2],
    413			wt[3]);
    414
    415	return simple_read_from_buffer(user_buf, count, ppos,
    416				       buf, len);
    417}
    418
    419static const struct file_operations airtime_ops = {
    420	.read = airtime_read,
    421	.open = simple_open,
    422	.llseek = default_llseek,
    423};
    424
    425#ifdef CONFIG_PM
    426static ssize_t reset_write(struct file *file, const char __user *user_buf,
    427			   size_t count, loff_t *ppos)
    428{
    429	struct ieee80211_local *local = file->private_data;
    430	int ret;
    431
    432	rtnl_lock();
    433	wiphy_lock(local->hw.wiphy);
    434	__ieee80211_suspend(&local->hw, NULL);
    435	ret = __ieee80211_resume(&local->hw);
    436	wiphy_unlock(local->hw.wiphy);
    437
    438	if (ret)
    439		cfg80211_shutdown_all_interfaces(local->hw.wiphy);
    440
    441	rtnl_unlock();
    442
    443	return count;
    444}
    445
    446static const struct file_operations reset_ops = {
    447	.write = reset_write,
    448	.open = simple_open,
    449	.llseek = noop_llseek,
    450};
    451#endif
    452
    453static const char *hw_flag_names[] = {
    454#define FLAG(F)	[IEEE80211_HW_##F] = #F
    455	FLAG(HAS_RATE_CONTROL),
    456	FLAG(RX_INCLUDES_FCS),
    457	FLAG(HOST_BROADCAST_PS_BUFFERING),
    458	FLAG(SIGNAL_UNSPEC),
    459	FLAG(SIGNAL_DBM),
    460	FLAG(NEED_DTIM_BEFORE_ASSOC),
    461	FLAG(SPECTRUM_MGMT),
    462	FLAG(AMPDU_AGGREGATION),
    463	FLAG(SUPPORTS_PS),
    464	FLAG(PS_NULLFUNC_STACK),
    465	FLAG(SUPPORTS_DYNAMIC_PS),
    466	FLAG(MFP_CAPABLE),
    467	FLAG(WANT_MONITOR_VIF),
    468	FLAG(NO_AUTO_VIF),
    469	FLAG(SW_CRYPTO_CONTROL),
    470	FLAG(SUPPORT_FAST_XMIT),
    471	FLAG(REPORTS_TX_ACK_STATUS),
    472	FLAG(CONNECTION_MONITOR),
    473	FLAG(QUEUE_CONTROL),
    474	FLAG(SUPPORTS_PER_STA_GTK),
    475	FLAG(AP_LINK_PS),
    476	FLAG(TX_AMPDU_SETUP_IN_HW),
    477	FLAG(SUPPORTS_RC_TABLE),
    478	FLAG(P2P_DEV_ADDR_FOR_INTF),
    479	FLAG(TIMING_BEACON_ONLY),
    480	FLAG(SUPPORTS_HT_CCK_RATES),
    481	FLAG(CHANCTX_STA_CSA),
    482	FLAG(SUPPORTS_CLONED_SKBS),
    483	FLAG(SINGLE_SCAN_ON_ALL_BANDS),
    484	FLAG(TDLS_WIDER_BW),
    485	FLAG(SUPPORTS_AMSDU_IN_AMPDU),
    486	FLAG(BEACON_TX_STATUS),
    487	FLAG(NEEDS_UNIQUE_STA_ADDR),
    488	FLAG(SUPPORTS_REORDERING_BUFFER),
    489	FLAG(USES_RSS),
    490	FLAG(TX_AMSDU),
    491	FLAG(TX_FRAG_LIST),
    492	FLAG(REPORTS_LOW_ACK),
    493	FLAG(SUPPORTS_TX_FRAG),
    494	FLAG(SUPPORTS_TDLS_BUFFER_STA),
    495	FLAG(DEAUTH_NEED_MGD_TX_PREP),
    496	FLAG(DOESNT_SUPPORT_QOS_NDP),
    497	FLAG(BUFF_MMPDU_TXQ),
    498	FLAG(SUPPORTS_VHT_EXT_NSS_BW),
    499	FLAG(STA_MMPDU_TXQ),
    500	FLAG(TX_STATUS_NO_AMPDU_LEN),
    501	FLAG(SUPPORTS_MULTI_BSSID),
    502	FLAG(SUPPORTS_ONLY_HE_MULTI_BSSID),
    503	FLAG(AMPDU_KEYBORDER_SUPPORT),
    504	FLAG(SUPPORTS_TX_ENCAP_OFFLOAD),
    505	FLAG(SUPPORTS_RX_DECAP_OFFLOAD),
    506	FLAG(SUPPORTS_CONC_MON_RX_DECAP),
    507	FLAG(DETECTS_COLOR_COLLISION),
    508#undef FLAG
    509};
    510
    511static ssize_t hwflags_read(struct file *file, char __user *user_buf,
    512			    size_t count, loff_t *ppos)
    513{
    514	struct ieee80211_local *local = file->private_data;
    515	size_t bufsz = 30 * NUM_IEEE80211_HW_FLAGS;
    516	char *buf = kzalloc(bufsz, GFP_KERNEL);
    517	char *pos = buf, *end = buf + bufsz - 1;
    518	ssize_t rv;
    519	int i;
    520
    521	if (!buf)
    522		return -ENOMEM;
    523
    524	/* fail compilation if somebody adds or removes
    525	 * a flag without updating the name array above
    526	 */
    527	BUILD_BUG_ON(ARRAY_SIZE(hw_flag_names) != NUM_IEEE80211_HW_FLAGS);
    528
    529	for (i = 0; i < NUM_IEEE80211_HW_FLAGS; i++) {
    530		if (test_bit(i, local->hw.flags))
    531			pos += scnprintf(pos, end - pos, "%s\n",
    532					 hw_flag_names[i]);
    533	}
    534
    535	rv = simple_read_from_buffer(user_buf, count, ppos, buf, strlen(buf));
    536	kfree(buf);
    537	return rv;
    538}
    539
    540static ssize_t misc_read(struct file *file, char __user *user_buf,
    541			 size_t count, loff_t *ppos)
    542{
    543	struct ieee80211_local *local = file->private_data;
    544	/* Max len of each line is 16 characters, plus 9 for 'pending:\n' */
    545	size_t bufsz = IEEE80211_MAX_QUEUES * 16 + 9;
    546	char *buf;
    547	char *pos, *end;
    548	ssize_t rv;
    549	int i;
    550	int ln;
    551
    552	buf = kzalloc(bufsz, GFP_KERNEL);
    553	if (!buf)
    554		return -ENOMEM;
    555
    556	pos = buf;
    557	end = buf + bufsz - 1;
    558
    559	pos += scnprintf(pos, end - pos, "pending:\n");
    560
    561	for (i = 0; i < IEEE80211_MAX_QUEUES; i++) {
    562		ln = skb_queue_len(&local->pending[i]);
    563		pos += scnprintf(pos, end - pos, "[%i] %d\n",
    564				 i, ln);
    565	}
    566
    567	rv = simple_read_from_buffer(user_buf, count, ppos, buf, strlen(buf));
    568	kfree(buf);
    569	return rv;
    570}
    571
    572static ssize_t queues_read(struct file *file, char __user *user_buf,
    573			   size_t count, loff_t *ppos)
    574{
    575	struct ieee80211_local *local = file->private_data;
    576	unsigned long flags;
    577	char buf[IEEE80211_MAX_QUEUES * 20];
    578	int q, res = 0;
    579
    580	spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
    581	for (q = 0; q < local->hw.queues; q++)
    582		res += sprintf(buf + res, "%02d: %#.8lx/%d\n", q,
    583				local->queue_stop_reasons[q],
    584				skb_queue_len(&local->pending[q]));
    585	spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
    586
    587	return simple_read_from_buffer(user_buf, count, ppos, buf, res);
    588}
    589
    590DEBUGFS_READONLY_FILE_OPS(hwflags);
    591DEBUGFS_READONLY_FILE_OPS(queues);
    592DEBUGFS_READONLY_FILE_OPS(misc);
    593
    594/* statistics stuff */
    595
    596static ssize_t format_devstat_counter(struct ieee80211_local *local,
    597	char __user *userbuf,
    598	size_t count, loff_t *ppos,
    599	int (*printvalue)(struct ieee80211_low_level_stats *stats, char *buf,
    600			  int buflen))
    601{
    602	struct ieee80211_low_level_stats stats;
    603	char buf[20];
    604	int res;
    605
    606	rtnl_lock();
    607	res = drv_get_stats(local, &stats);
    608	rtnl_unlock();
    609	if (res)
    610		return res;
    611	res = printvalue(&stats, buf, sizeof(buf));
    612	return simple_read_from_buffer(userbuf, count, ppos, buf, res);
    613}
    614
    615#define DEBUGFS_DEVSTATS_FILE(name)					\
    616static int print_devstats_##name(struct ieee80211_low_level_stats *stats,\
    617				 char *buf, int buflen)			\
    618{									\
    619	return scnprintf(buf, buflen, "%u\n", stats->name);		\
    620}									\
    621static ssize_t stats_ ##name## _read(struct file *file,			\
    622				     char __user *userbuf,		\
    623				     size_t count, loff_t *ppos)	\
    624{									\
    625	return format_devstat_counter(file->private_data,		\
    626				      userbuf,				\
    627				      count,				\
    628				      ppos,				\
    629				      print_devstats_##name);		\
    630}									\
    631									\
    632static const struct file_operations stats_ ##name## _ops = {		\
    633	.read = stats_ ##name## _read,					\
    634	.open = simple_open,						\
    635	.llseek = generic_file_llseek,					\
    636};
    637
    638#ifdef CONFIG_MAC80211_DEBUG_COUNTERS
    639#define DEBUGFS_STATS_ADD(name)					\
    640	debugfs_create_u32(#name, 0400, statsd, &local->name);
    641#endif
    642#define DEBUGFS_DEVSTATS_ADD(name)					\
    643	debugfs_create_file(#name, 0400, statsd, local, &stats_ ##name## _ops);
    644
    645DEBUGFS_DEVSTATS_FILE(dot11ACKFailureCount);
    646DEBUGFS_DEVSTATS_FILE(dot11RTSFailureCount);
    647DEBUGFS_DEVSTATS_FILE(dot11FCSErrorCount);
    648DEBUGFS_DEVSTATS_FILE(dot11RTSSuccessCount);
    649
    650void debugfs_hw_add(struct ieee80211_local *local)
    651{
    652	struct dentry *phyd = local->hw.wiphy->debugfsdir;
    653	struct dentry *statsd;
    654
    655	if (!phyd)
    656		return;
    657
    658	local->debugfs.keys = debugfs_create_dir("keys", phyd);
    659
    660	DEBUGFS_ADD(total_ps_buffered);
    661	DEBUGFS_ADD(wep_iv);
    662	DEBUGFS_ADD(rate_ctrl_alg);
    663	DEBUGFS_ADD(queues);
    664	DEBUGFS_ADD(misc);
    665#ifdef CONFIG_PM
    666	DEBUGFS_ADD_MODE(reset, 0200);
    667#endif
    668	DEBUGFS_ADD(hwflags);
    669	DEBUGFS_ADD(user_power);
    670	DEBUGFS_ADD(power);
    671	DEBUGFS_ADD(hw_conf);
    672	DEBUGFS_ADD_MODE(force_tx_status, 0600);
    673	DEBUGFS_ADD_MODE(aql_enable, 0600);
    674
    675	if (local->ops->wake_tx_queue)
    676		DEBUGFS_ADD_MODE(aqm, 0600);
    677
    678	if (wiphy_ext_feature_isset(local->hw.wiphy,
    679				    NL80211_EXT_FEATURE_AIRTIME_FAIRNESS)) {
    680		DEBUGFS_ADD_MODE(airtime, 0600);
    681		DEBUGFS_ADD_MODE(airtime_flags, 0600);
    682	}
    683
    684	DEBUGFS_ADD(aql_txq_limit);
    685	debugfs_create_u32("aql_threshold", 0600,
    686			   phyd, &local->aql_threshold);
    687
    688	statsd = debugfs_create_dir("statistics", phyd);
    689
    690	/* if the dir failed, don't put all the other things into the root! */
    691	if (!statsd)
    692		return;
    693
    694#ifdef CONFIG_MAC80211_DEBUG_COUNTERS
    695	DEBUGFS_STATS_ADD(dot11TransmittedFragmentCount);
    696	DEBUGFS_STATS_ADD(dot11MulticastTransmittedFrameCount);
    697	DEBUGFS_STATS_ADD(dot11FailedCount);
    698	DEBUGFS_STATS_ADD(dot11RetryCount);
    699	DEBUGFS_STATS_ADD(dot11MultipleRetryCount);
    700	DEBUGFS_STATS_ADD(dot11FrameDuplicateCount);
    701	DEBUGFS_STATS_ADD(dot11ReceivedFragmentCount);
    702	DEBUGFS_STATS_ADD(dot11MulticastReceivedFrameCount);
    703	DEBUGFS_STATS_ADD(dot11TransmittedFrameCount);
    704	DEBUGFS_STATS_ADD(tx_handlers_drop);
    705	DEBUGFS_STATS_ADD(tx_handlers_queued);
    706	DEBUGFS_STATS_ADD(tx_handlers_drop_wep);
    707	DEBUGFS_STATS_ADD(tx_handlers_drop_not_assoc);
    708	DEBUGFS_STATS_ADD(tx_handlers_drop_unauth_port);
    709	DEBUGFS_STATS_ADD(rx_handlers_drop);
    710	DEBUGFS_STATS_ADD(rx_handlers_queued);
    711	DEBUGFS_STATS_ADD(rx_handlers_drop_nullfunc);
    712	DEBUGFS_STATS_ADD(rx_handlers_drop_defrag);
    713	DEBUGFS_STATS_ADD(tx_expand_skb_head);
    714	DEBUGFS_STATS_ADD(tx_expand_skb_head_cloned);
    715	DEBUGFS_STATS_ADD(rx_expand_skb_head_defrag);
    716	DEBUGFS_STATS_ADD(rx_handlers_fragments);
    717	DEBUGFS_STATS_ADD(tx_status_drop);
    718#endif
    719	DEBUGFS_DEVSTATS_ADD(dot11ACKFailureCount);
    720	DEBUGFS_DEVSTATS_ADD(dot11RTSFailureCount);
    721	DEBUGFS_DEVSTATS_ADD(dot11FCSErrorCount);
    722	DEBUGFS_DEVSTATS_ADD(dot11RTSSuccessCount);
    723}