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 (33245B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * This file is part of wl1271
      4 *
      5 * Copyright (C) 2009 Nokia Corporation
      6 *
      7 * Contact: Luciano Coelho <luciano.coelho@nokia.com>
      8 */
      9
     10#include "debugfs.h"
     11
     12#include <linux/skbuff.h>
     13#include <linux/slab.h>
     14#include <linux/module.h>
     15#include <linux/pm_runtime.h>
     16
     17#include "wlcore.h"
     18#include "debug.h"
     19#include "acx.h"
     20#include "ps.h"
     21#include "io.h"
     22#include "tx.h"
     23#include "hw_ops.h"
     24
     25/* ms */
     26#define WL1271_DEBUGFS_STATS_LIFETIME 1000
     27
     28#define WLCORE_MAX_BLOCK_SIZE ((size_t)(4*PAGE_SIZE))
     29
     30/* debugfs macros idea from mac80211 */
     31int wl1271_format_buffer(char __user *userbuf, size_t count,
     32			 loff_t *ppos, char *fmt, ...)
     33{
     34	va_list args;
     35	char buf[DEBUGFS_FORMAT_BUFFER_SIZE];
     36	int res;
     37
     38	va_start(args, fmt);
     39	res = vscnprintf(buf, sizeof(buf), fmt, args);
     40	va_end(args);
     41
     42	return simple_read_from_buffer(userbuf, count, ppos, buf, res);
     43}
     44EXPORT_SYMBOL_GPL(wl1271_format_buffer);
     45
     46void wl1271_debugfs_update_stats(struct wl1271 *wl)
     47{
     48	int ret;
     49
     50	mutex_lock(&wl->mutex);
     51
     52	if (unlikely(wl->state != WLCORE_STATE_ON))
     53		goto out;
     54
     55	ret = pm_runtime_resume_and_get(wl->dev);
     56	if (ret < 0)
     57		goto out;
     58
     59	if (!wl->plt &&
     60	    time_after(jiffies, wl->stats.fw_stats_update +
     61		       msecs_to_jiffies(WL1271_DEBUGFS_STATS_LIFETIME))) {
     62		wl1271_acx_statistics(wl, wl->stats.fw_stats);
     63		wl->stats.fw_stats_update = jiffies;
     64	}
     65
     66	pm_runtime_mark_last_busy(wl->dev);
     67	pm_runtime_put_autosuspend(wl->dev);
     68
     69out:
     70	mutex_unlock(&wl->mutex);
     71}
     72EXPORT_SYMBOL_GPL(wl1271_debugfs_update_stats);
     73
     74DEBUGFS_READONLY_FILE(retry_count, "%u", wl->stats.retry_count);
     75DEBUGFS_READONLY_FILE(excessive_retries, "%u",
     76		      wl->stats.excessive_retries);
     77
     78static ssize_t tx_queue_len_read(struct file *file, char __user *userbuf,
     79				 size_t count, loff_t *ppos)
     80{
     81	struct wl1271 *wl = file->private_data;
     82	u32 queue_len;
     83	char buf[20];
     84	int res;
     85
     86	queue_len = wl1271_tx_total_queue_count(wl);
     87
     88	res = scnprintf(buf, sizeof(buf), "%u\n", queue_len);
     89	return simple_read_from_buffer(userbuf, count, ppos, buf, res);
     90}
     91
     92static const struct file_operations tx_queue_len_ops = {
     93	.read = tx_queue_len_read,
     94	.open = simple_open,
     95	.llseek = default_llseek,
     96};
     97
     98static void chip_op_handler(struct wl1271 *wl, unsigned long value,
     99			    void *arg)
    100{
    101	int ret;
    102	int (*chip_op) (struct wl1271 *wl);
    103
    104	if (!arg) {
    105		wl1271_warning("debugfs chip_op_handler with no callback");
    106		return;
    107	}
    108
    109	ret = pm_runtime_resume_and_get(wl->dev);
    110	if (ret < 0)
    111		return;
    112
    113	chip_op = arg;
    114	chip_op(wl);
    115
    116	pm_runtime_mark_last_busy(wl->dev);
    117	pm_runtime_put_autosuspend(wl->dev);
    118}
    119
    120#define WL12XX_CONF_DEBUGFS(param, conf_sub_struct,			\
    121			    min_val, max_val, write_handler_locked,	\
    122			    write_handler_arg)				\
    123	static ssize_t param##_read(struct file *file,			\
    124				      char __user *user_buf,		\
    125				      size_t count, loff_t *ppos)	\
    126	{								\
    127	struct wl1271 *wl = file->private_data;				\
    128	return wl1271_format_buffer(user_buf, count,			\
    129				    ppos, "%d\n",			\
    130				    wl->conf.conf_sub_struct.param);	\
    131	}								\
    132									\
    133	static ssize_t param##_write(struct file *file,			\
    134				     const char __user *user_buf,	\
    135				     size_t count, loff_t *ppos)	\
    136	{								\
    137	struct wl1271 *wl = file->private_data;				\
    138	unsigned long value;						\
    139	int ret;							\
    140									\
    141	ret = kstrtoul_from_user(user_buf, count, 10, &value);		\
    142	if (ret < 0) {							\
    143		wl1271_warning("illegal value for " #param);		\
    144		return -EINVAL;						\
    145	}								\
    146									\
    147	if (value < min_val || value > max_val) {			\
    148		wl1271_warning(#param " is not in valid range");	\
    149		return -ERANGE;						\
    150	}								\
    151									\
    152	mutex_lock(&wl->mutex);						\
    153	wl->conf.conf_sub_struct.param = value;				\
    154									\
    155	write_handler_locked(wl, value, write_handler_arg);		\
    156									\
    157	mutex_unlock(&wl->mutex);					\
    158	return count;							\
    159	}								\
    160									\
    161	static const struct file_operations param##_ops = {		\
    162		.read = param##_read,					\
    163		.write = param##_write,					\
    164		.open = simple_open,					\
    165		.llseek = default_llseek,				\
    166	};
    167
    168WL12XX_CONF_DEBUGFS(irq_pkt_threshold, rx, 0, 65535,
    169		    chip_op_handler, wl1271_acx_init_rx_interrupt)
    170WL12XX_CONF_DEBUGFS(irq_blk_threshold, rx, 0, 65535,
    171		    chip_op_handler, wl1271_acx_init_rx_interrupt)
    172WL12XX_CONF_DEBUGFS(irq_timeout, rx, 0, 100,
    173		    chip_op_handler, wl1271_acx_init_rx_interrupt)
    174
    175static ssize_t gpio_power_read(struct file *file, char __user *user_buf,
    176			  size_t count, loff_t *ppos)
    177{
    178	struct wl1271 *wl = file->private_data;
    179	bool state = test_bit(WL1271_FLAG_GPIO_POWER, &wl->flags);
    180
    181	int res;
    182	char buf[10];
    183
    184	res = scnprintf(buf, sizeof(buf), "%d\n", state);
    185
    186	return simple_read_from_buffer(user_buf, count, ppos, buf, res);
    187}
    188
    189static ssize_t gpio_power_write(struct file *file,
    190			   const char __user *user_buf,
    191			   size_t count, loff_t *ppos)
    192{
    193	struct wl1271 *wl = file->private_data;
    194	unsigned long value;
    195	int ret;
    196
    197	ret = kstrtoul_from_user(user_buf, count, 10, &value);
    198	if (ret < 0) {
    199		wl1271_warning("illegal value in gpio_power");
    200		return -EINVAL;
    201	}
    202
    203	mutex_lock(&wl->mutex);
    204
    205	if (value)
    206		wl1271_power_on(wl);
    207	else
    208		wl1271_power_off(wl);
    209
    210	mutex_unlock(&wl->mutex);
    211	return count;
    212}
    213
    214static const struct file_operations gpio_power_ops = {
    215	.read = gpio_power_read,
    216	.write = gpio_power_write,
    217	.open = simple_open,
    218	.llseek = default_llseek,
    219};
    220
    221static ssize_t start_recovery_write(struct file *file,
    222				    const char __user *user_buf,
    223				    size_t count, loff_t *ppos)
    224{
    225	struct wl1271 *wl = file->private_data;
    226
    227	mutex_lock(&wl->mutex);
    228	wl12xx_queue_recovery_work(wl);
    229	mutex_unlock(&wl->mutex);
    230
    231	return count;
    232}
    233
    234static const struct file_operations start_recovery_ops = {
    235	.write = start_recovery_write,
    236	.open = simple_open,
    237	.llseek = default_llseek,
    238};
    239
    240static ssize_t dynamic_ps_timeout_read(struct file *file, char __user *user_buf,
    241			  size_t count, loff_t *ppos)
    242{
    243	struct wl1271 *wl = file->private_data;
    244
    245	return wl1271_format_buffer(user_buf, count,
    246				    ppos, "%d\n",
    247				    wl->conf.conn.dynamic_ps_timeout);
    248}
    249
    250static ssize_t dynamic_ps_timeout_write(struct file *file,
    251				    const char __user *user_buf,
    252				    size_t count, loff_t *ppos)
    253{
    254	struct wl1271 *wl = file->private_data;
    255	struct wl12xx_vif *wlvif;
    256	unsigned long value;
    257	int ret;
    258
    259	ret = kstrtoul_from_user(user_buf, count, 10, &value);
    260	if (ret < 0) {
    261		wl1271_warning("illegal value in dynamic_ps");
    262		return -EINVAL;
    263	}
    264
    265	if (value < 1 || value > 65535) {
    266		wl1271_warning("dynamic_ps_timeout is not in valid range");
    267		return -ERANGE;
    268	}
    269
    270	mutex_lock(&wl->mutex);
    271
    272	wl->conf.conn.dynamic_ps_timeout = value;
    273
    274	if (unlikely(wl->state != WLCORE_STATE_ON))
    275		goto out;
    276
    277	ret = pm_runtime_resume_and_get(wl->dev);
    278	if (ret < 0)
    279		goto out;
    280
    281	/* In case we're already in PSM, trigger it again to set new timeout
    282	 * immediately without waiting for re-association
    283	 */
    284
    285	wl12xx_for_each_wlvif_sta(wl, wlvif) {
    286		if (test_bit(WLVIF_FLAG_IN_PS, &wlvif->flags))
    287			wl1271_ps_set_mode(wl, wlvif, STATION_AUTO_PS_MODE);
    288	}
    289
    290	pm_runtime_mark_last_busy(wl->dev);
    291	pm_runtime_put_autosuspend(wl->dev);
    292
    293out:
    294	mutex_unlock(&wl->mutex);
    295	return count;
    296}
    297
    298static const struct file_operations dynamic_ps_timeout_ops = {
    299	.read = dynamic_ps_timeout_read,
    300	.write = dynamic_ps_timeout_write,
    301	.open = simple_open,
    302	.llseek = default_llseek,
    303};
    304
    305static ssize_t forced_ps_read(struct file *file, char __user *user_buf,
    306			  size_t count, loff_t *ppos)
    307{
    308	struct wl1271 *wl = file->private_data;
    309
    310	return wl1271_format_buffer(user_buf, count,
    311				    ppos, "%d\n",
    312				    wl->conf.conn.forced_ps);
    313}
    314
    315static ssize_t forced_ps_write(struct file *file,
    316				    const char __user *user_buf,
    317				    size_t count, loff_t *ppos)
    318{
    319	struct wl1271 *wl = file->private_data;
    320	struct wl12xx_vif *wlvif;
    321	unsigned long value;
    322	int ret, ps_mode;
    323
    324	ret = kstrtoul_from_user(user_buf, count, 10, &value);
    325	if (ret < 0) {
    326		wl1271_warning("illegal value in forced_ps");
    327		return -EINVAL;
    328	}
    329
    330	if (value != 1 && value != 0) {
    331		wl1271_warning("forced_ps should be either 0 or 1");
    332		return -ERANGE;
    333	}
    334
    335	mutex_lock(&wl->mutex);
    336
    337	if (wl->conf.conn.forced_ps == value)
    338		goto out;
    339
    340	wl->conf.conn.forced_ps = value;
    341
    342	if (unlikely(wl->state != WLCORE_STATE_ON))
    343		goto out;
    344
    345	ret = pm_runtime_resume_and_get(wl->dev);
    346	if (ret < 0)
    347		goto out;
    348
    349	/* In case we're already in PSM, trigger it again to switch mode
    350	 * immediately without waiting for re-association
    351	 */
    352
    353	ps_mode = value ? STATION_POWER_SAVE_MODE : STATION_AUTO_PS_MODE;
    354
    355	wl12xx_for_each_wlvif_sta(wl, wlvif) {
    356		if (test_bit(WLVIF_FLAG_IN_PS, &wlvif->flags))
    357			wl1271_ps_set_mode(wl, wlvif, ps_mode);
    358	}
    359
    360	pm_runtime_mark_last_busy(wl->dev);
    361	pm_runtime_put_autosuspend(wl->dev);
    362
    363out:
    364	mutex_unlock(&wl->mutex);
    365	return count;
    366}
    367
    368static const struct file_operations forced_ps_ops = {
    369	.read = forced_ps_read,
    370	.write = forced_ps_write,
    371	.open = simple_open,
    372	.llseek = default_llseek,
    373};
    374
    375static ssize_t split_scan_timeout_read(struct file *file, char __user *user_buf,
    376			  size_t count, loff_t *ppos)
    377{
    378	struct wl1271 *wl = file->private_data;
    379
    380	return wl1271_format_buffer(user_buf, count,
    381				    ppos, "%d\n",
    382				    wl->conf.scan.split_scan_timeout / 1000);
    383}
    384
    385static ssize_t split_scan_timeout_write(struct file *file,
    386				    const char __user *user_buf,
    387				    size_t count, loff_t *ppos)
    388{
    389	struct wl1271 *wl = file->private_data;
    390	unsigned long value;
    391	int ret;
    392
    393	ret = kstrtoul_from_user(user_buf, count, 10, &value);
    394	if (ret < 0) {
    395		wl1271_warning("illegal value in split_scan_timeout");
    396		return -EINVAL;
    397	}
    398
    399	if (value == 0)
    400		wl1271_info("split scan will be disabled");
    401
    402	mutex_lock(&wl->mutex);
    403
    404	wl->conf.scan.split_scan_timeout = value * 1000;
    405
    406	mutex_unlock(&wl->mutex);
    407	return count;
    408}
    409
    410static const struct file_operations split_scan_timeout_ops = {
    411	.read = split_scan_timeout_read,
    412	.write = split_scan_timeout_write,
    413	.open = simple_open,
    414	.llseek = default_llseek,
    415};
    416
    417static ssize_t driver_state_read(struct file *file, char __user *user_buf,
    418				 size_t count, loff_t *ppos)
    419{
    420	struct wl1271 *wl = file->private_data;
    421	int res = 0;
    422	ssize_t ret;
    423	char *buf;
    424	struct wl12xx_vif *wlvif;
    425
    426#define DRIVER_STATE_BUF_LEN 1024
    427
    428	buf = kmalloc(DRIVER_STATE_BUF_LEN, GFP_KERNEL);
    429	if (!buf)
    430		return -ENOMEM;
    431
    432	mutex_lock(&wl->mutex);
    433
    434#define DRIVER_STATE_PRINT(x, fmt)   \
    435	(res += scnprintf(buf + res, DRIVER_STATE_BUF_LEN - res,\
    436			  #x " = " fmt "\n", wl->x))
    437
    438#define DRIVER_STATE_PRINT_GENERIC(x, fmt, args...)   \
    439	(res += scnprintf(buf + res, DRIVER_STATE_BUF_LEN - res,\
    440			  #x " = " fmt "\n", args))
    441
    442#define DRIVER_STATE_PRINT_LONG(x) DRIVER_STATE_PRINT(x, "%ld")
    443#define DRIVER_STATE_PRINT_INT(x)  DRIVER_STATE_PRINT(x, "%d")
    444#define DRIVER_STATE_PRINT_STR(x)  DRIVER_STATE_PRINT(x, "%s")
    445#define DRIVER_STATE_PRINT_LHEX(x) DRIVER_STATE_PRINT(x, "0x%lx")
    446#define DRIVER_STATE_PRINT_HEX(x)  DRIVER_STATE_PRINT(x, "0x%x")
    447
    448	wl12xx_for_each_wlvif_sta(wl, wlvif) {
    449		if (!test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags))
    450			continue;
    451
    452		DRIVER_STATE_PRINT_GENERIC(channel, "%d (%s)", wlvif->channel,
    453					   wlvif->p2p ? "P2P-CL" : "STA");
    454	}
    455
    456	wl12xx_for_each_wlvif_ap(wl, wlvif)
    457		DRIVER_STATE_PRINT_GENERIC(channel, "%d (%s)", wlvif->channel,
    458					   wlvif->p2p ? "P2P-GO" : "AP");
    459
    460	DRIVER_STATE_PRINT_INT(tx_blocks_available);
    461	DRIVER_STATE_PRINT_INT(tx_allocated_blocks);
    462	DRIVER_STATE_PRINT_INT(tx_allocated_pkts[0]);
    463	DRIVER_STATE_PRINT_INT(tx_allocated_pkts[1]);
    464	DRIVER_STATE_PRINT_INT(tx_allocated_pkts[2]);
    465	DRIVER_STATE_PRINT_INT(tx_allocated_pkts[3]);
    466	DRIVER_STATE_PRINT_INT(tx_frames_cnt);
    467	DRIVER_STATE_PRINT_LHEX(tx_frames_map[0]);
    468	DRIVER_STATE_PRINT_INT(tx_queue_count[0]);
    469	DRIVER_STATE_PRINT_INT(tx_queue_count[1]);
    470	DRIVER_STATE_PRINT_INT(tx_queue_count[2]);
    471	DRIVER_STATE_PRINT_INT(tx_queue_count[3]);
    472	DRIVER_STATE_PRINT_INT(tx_packets_count);
    473	DRIVER_STATE_PRINT_INT(tx_results_count);
    474	DRIVER_STATE_PRINT_LHEX(flags);
    475	DRIVER_STATE_PRINT_INT(tx_blocks_freed);
    476	DRIVER_STATE_PRINT_INT(rx_counter);
    477	DRIVER_STATE_PRINT_INT(state);
    478	DRIVER_STATE_PRINT_INT(band);
    479	DRIVER_STATE_PRINT_INT(power_level);
    480	DRIVER_STATE_PRINT_INT(sg_enabled);
    481	DRIVER_STATE_PRINT_INT(enable_11a);
    482	DRIVER_STATE_PRINT_INT(noise);
    483	DRIVER_STATE_PRINT_LHEX(ap_fw_ps_map);
    484	DRIVER_STATE_PRINT_LHEX(ap_ps_map);
    485	DRIVER_STATE_PRINT_HEX(quirks);
    486	DRIVER_STATE_PRINT_HEX(irq);
    487	/* TODO: ref_clock and tcxo_clock were moved to wl12xx priv */
    488	DRIVER_STATE_PRINT_HEX(hw_pg_ver);
    489	DRIVER_STATE_PRINT_HEX(irq_flags);
    490	DRIVER_STATE_PRINT_HEX(chip.id);
    491	DRIVER_STATE_PRINT_STR(chip.fw_ver_str);
    492	DRIVER_STATE_PRINT_STR(chip.phy_fw_ver_str);
    493	DRIVER_STATE_PRINT_INT(recovery_count);
    494
    495#undef DRIVER_STATE_PRINT_INT
    496#undef DRIVER_STATE_PRINT_LONG
    497#undef DRIVER_STATE_PRINT_HEX
    498#undef DRIVER_STATE_PRINT_LHEX
    499#undef DRIVER_STATE_PRINT_STR
    500#undef DRIVER_STATE_PRINT
    501#undef DRIVER_STATE_BUF_LEN
    502
    503	mutex_unlock(&wl->mutex);
    504
    505	ret = simple_read_from_buffer(user_buf, count, ppos, buf, res);
    506	kfree(buf);
    507	return ret;
    508}
    509
    510static const struct file_operations driver_state_ops = {
    511	.read = driver_state_read,
    512	.open = simple_open,
    513	.llseek = default_llseek,
    514};
    515
    516static ssize_t vifs_state_read(struct file *file, char __user *user_buf,
    517				 size_t count, loff_t *ppos)
    518{
    519	struct wl1271 *wl = file->private_data;
    520	struct wl12xx_vif *wlvif;
    521	int ret, res = 0;
    522	const int buf_size = 4096;
    523	char *buf;
    524	char tmp_buf[64];
    525
    526	buf = kzalloc(buf_size, GFP_KERNEL);
    527	if (!buf)
    528		return -ENOMEM;
    529
    530	mutex_lock(&wl->mutex);
    531
    532#define VIF_STATE_PRINT(x, fmt)				\
    533	(res += scnprintf(buf + res, buf_size - res,	\
    534			  #x " = " fmt "\n", wlvif->x))
    535
    536#define VIF_STATE_PRINT_LONG(x)  VIF_STATE_PRINT(x, "%ld")
    537#define VIF_STATE_PRINT_INT(x)   VIF_STATE_PRINT(x, "%d")
    538#define VIF_STATE_PRINT_STR(x)   VIF_STATE_PRINT(x, "%s")
    539#define VIF_STATE_PRINT_LHEX(x)  VIF_STATE_PRINT(x, "0x%lx")
    540#define VIF_STATE_PRINT_LLHEX(x) VIF_STATE_PRINT(x, "0x%llx")
    541#define VIF_STATE_PRINT_HEX(x)   VIF_STATE_PRINT(x, "0x%x")
    542
    543#define VIF_STATE_PRINT_NSTR(x, len)				\
    544	do {							\
    545		memset(tmp_buf, 0, sizeof(tmp_buf));		\
    546		memcpy(tmp_buf, wlvif->x,			\
    547		       min_t(u8, len, sizeof(tmp_buf) - 1));	\
    548		res += scnprintf(buf + res, buf_size - res,	\
    549				 #x " = %s\n", tmp_buf);	\
    550	} while (0)
    551
    552	wl12xx_for_each_wlvif(wl, wlvif) {
    553		VIF_STATE_PRINT_INT(role_id);
    554		VIF_STATE_PRINT_INT(bss_type);
    555		VIF_STATE_PRINT_LHEX(flags);
    556		VIF_STATE_PRINT_INT(p2p);
    557		VIF_STATE_PRINT_INT(dev_role_id);
    558		VIF_STATE_PRINT_INT(dev_hlid);
    559
    560		if (wlvif->bss_type == BSS_TYPE_STA_BSS ||
    561		    wlvif->bss_type == BSS_TYPE_IBSS) {
    562			VIF_STATE_PRINT_INT(sta.hlid);
    563			VIF_STATE_PRINT_INT(sta.basic_rate_idx);
    564			VIF_STATE_PRINT_INT(sta.ap_rate_idx);
    565			VIF_STATE_PRINT_INT(sta.p2p_rate_idx);
    566			VIF_STATE_PRINT_INT(sta.qos);
    567		} else {
    568			VIF_STATE_PRINT_INT(ap.global_hlid);
    569			VIF_STATE_PRINT_INT(ap.bcast_hlid);
    570			VIF_STATE_PRINT_LHEX(ap.sta_hlid_map[0]);
    571			VIF_STATE_PRINT_INT(ap.mgmt_rate_idx);
    572			VIF_STATE_PRINT_INT(ap.bcast_rate_idx);
    573			VIF_STATE_PRINT_INT(ap.ucast_rate_idx[0]);
    574			VIF_STATE_PRINT_INT(ap.ucast_rate_idx[1]);
    575			VIF_STATE_PRINT_INT(ap.ucast_rate_idx[2]);
    576			VIF_STATE_PRINT_INT(ap.ucast_rate_idx[3]);
    577		}
    578		VIF_STATE_PRINT_INT(last_tx_hlid);
    579		VIF_STATE_PRINT_INT(tx_queue_count[0]);
    580		VIF_STATE_PRINT_INT(tx_queue_count[1]);
    581		VIF_STATE_PRINT_INT(tx_queue_count[2]);
    582		VIF_STATE_PRINT_INT(tx_queue_count[3]);
    583		VIF_STATE_PRINT_LHEX(links_map[0]);
    584		VIF_STATE_PRINT_NSTR(ssid, wlvif->ssid_len);
    585		VIF_STATE_PRINT_INT(band);
    586		VIF_STATE_PRINT_INT(channel);
    587		VIF_STATE_PRINT_HEX(bitrate_masks[0]);
    588		VIF_STATE_PRINT_HEX(bitrate_masks[1]);
    589		VIF_STATE_PRINT_HEX(basic_rate_set);
    590		VIF_STATE_PRINT_HEX(basic_rate);
    591		VIF_STATE_PRINT_HEX(rate_set);
    592		VIF_STATE_PRINT_INT(beacon_int);
    593		VIF_STATE_PRINT_INT(default_key);
    594		VIF_STATE_PRINT_INT(aid);
    595		VIF_STATE_PRINT_INT(psm_entry_retry);
    596		VIF_STATE_PRINT_INT(power_level);
    597		VIF_STATE_PRINT_INT(rssi_thold);
    598		VIF_STATE_PRINT_INT(last_rssi_event);
    599		VIF_STATE_PRINT_INT(ba_support);
    600		VIF_STATE_PRINT_INT(ba_allowed);
    601		VIF_STATE_PRINT_LLHEX(total_freed_pkts);
    602	}
    603
    604#undef VIF_STATE_PRINT_INT
    605#undef VIF_STATE_PRINT_LONG
    606#undef VIF_STATE_PRINT_HEX
    607#undef VIF_STATE_PRINT_LHEX
    608#undef VIF_STATE_PRINT_LLHEX
    609#undef VIF_STATE_PRINT_STR
    610#undef VIF_STATE_PRINT_NSTR
    611#undef VIF_STATE_PRINT
    612
    613	mutex_unlock(&wl->mutex);
    614
    615	ret = simple_read_from_buffer(user_buf, count, ppos, buf, res);
    616	kfree(buf);
    617	return ret;
    618}
    619
    620static const struct file_operations vifs_state_ops = {
    621	.read = vifs_state_read,
    622	.open = simple_open,
    623	.llseek = default_llseek,
    624};
    625
    626static ssize_t dtim_interval_read(struct file *file, char __user *user_buf,
    627				  size_t count, loff_t *ppos)
    628{
    629	struct wl1271 *wl = file->private_data;
    630	u8 value;
    631
    632	if (wl->conf.conn.wake_up_event == CONF_WAKE_UP_EVENT_DTIM ||
    633	    wl->conf.conn.wake_up_event == CONF_WAKE_UP_EVENT_N_DTIM)
    634		value = wl->conf.conn.listen_interval;
    635	else
    636		value = 0;
    637
    638	return wl1271_format_buffer(user_buf, count, ppos, "%d\n", value);
    639}
    640
    641static ssize_t dtim_interval_write(struct file *file,
    642				   const char __user *user_buf,
    643				   size_t count, loff_t *ppos)
    644{
    645	struct wl1271 *wl = file->private_data;
    646	unsigned long value;
    647	int ret;
    648
    649	ret = kstrtoul_from_user(user_buf, count, 10, &value);
    650	if (ret < 0) {
    651		wl1271_warning("illegal value for dtim_interval");
    652		return -EINVAL;
    653	}
    654
    655	if (value < 1 || value > 10) {
    656		wl1271_warning("dtim value is not in valid range");
    657		return -ERANGE;
    658	}
    659
    660	mutex_lock(&wl->mutex);
    661
    662	wl->conf.conn.listen_interval = value;
    663	/* for some reason there are different event types for 1 and >1 */
    664	if (value == 1)
    665		wl->conf.conn.wake_up_event = CONF_WAKE_UP_EVENT_DTIM;
    666	else
    667		wl->conf.conn.wake_up_event = CONF_WAKE_UP_EVENT_N_DTIM;
    668
    669	/*
    670	 * we don't reconfigure ACX_WAKE_UP_CONDITIONS now, so it will only
    671	 * take effect on the next time we enter psm.
    672	 */
    673	mutex_unlock(&wl->mutex);
    674	return count;
    675}
    676
    677static const struct file_operations dtim_interval_ops = {
    678	.read = dtim_interval_read,
    679	.write = dtim_interval_write,
    680	.open = simple_open,
    681	.llseek = default_llseek,
    682};
    683
    684
    685
    686static ssize_t suspend_dtim_interval_read(struct file *file,
    687					  char __user *user_buf,
    688					  size_t count, loff_t *ppos)
    689{
    690	struct wl1271 *wl = file->private_data;
    691	u8 value;
    692
    693	if (wl->conf.conn.suspend_wake_up_event == CONF_WAKE_UP_EVENT_DTIM ||
    694	    wl->conf.conn.suspend_wake_up_event == CONF_WAKE_UP_EVENT_N_DTIM)
    695		value = wl->conf.conn.suspend_listen_interval;
    696	else
    697		value = 0;
    698
    699	return wl1271_format_buffer(user_buf, count, ppos, "%d\n", value);
    700}
    701
    702static ssize_t suspend_dtim_interval_write(struct file *file,
    703					   const char __user *user_buf,
    704					   size_t count, loff_t *ppos)
    705{
    706	struct wl1271 *wl = file->private_data;
    707	unsigned long value;
    708	int ret;
    709
    710	ret = kstrtoul_from_user(user_buf, count, 10, &value);
    711	if (ret < 0) {
    712		wl1271_warning("illegal value for suspend_dtim_interval");
    713		return -EINVAL;
    714	}
    715
    716	if (value < 1 || value > 10) {
    717		wl1271_warning("suspend_dtim value is not in valid range");
    718		return -ERANGE;
    719	}
    720
    721	mutex_lock(&wl->mutex);
    722
    723	wl->conf.conn.suspend_listen_interval = value;
    724	/* for some reason there are different event types for 1 and >1 */
    725	if (value == 1)
    726		wl->conf.conn.suspend_wake_up_event = CONF_WAKE_UP_EVENT_DTIM;
    727	else
    728		wl->conf.conn.suspend_wake_up_event = CONF_WAKE_UP_EVENT_N_DTIM;
    729
    730	mutex_unlock(&wl->mutex);
    731	return count;
    732}
    733
    734
    735static const struct file_operations suspend_dtim_interval_ops = {
    736	.read = suspend_dtim_interval_read,
    737	.write = suspend_dtim_interval_write,
    738	.open = simple_open,
    739	.llseek = default_llseek,
    740};
    741
    742static ssize_t beacon_interval_read(struct file *file, char __user *user_buf,
    743				    size_t count, loff_t *ppos)
    744{
    745	struct wl1271 *wl = file->private_data;
    746	u8 value;
    747
    748	if (wl->conf.conn.wake_up_event == CONF_WAKE_UP_EVENT_BEACON ||
    749	    wl->conf.conn.wake_up_event == CONF_WAKE_UP_EVENT_N_BEACONS)
    750		value = wl->conf.conn.listen_interval;
    751	else
    752		value = 0;
    753
    754	return wl1271_format_buffer(user_buf, count, ppos, "%d\n", value);
    755}
    756
    757static ssize_t beacon_interval_write(struct file *file,
    758				     const char __user *user_buf,
    759				     size_t count, loff_t *ppos)
    760{
    761	struct wl1271 *wl = file->private_data;
    762	unsigned long value;
    763	int ret;
    764
    765	ret = kstrtoul_from_user(user_buf, count, 10, &value);
    766	if (ret < 0) {
    767		wl1271_warning("illegal value for beacon_interval");
    768		return -EINVAL;
    769	}
    770
    771	if (value < 1 || value > 255) {
    772		wl1271_warning("beacon interval value is not in valid range");
    773		return -ERANGE;
    774	}
    775
    776	mutex_lock(&wl->mutex);
    777
    778	wl->conf.conn.listen_interval = value;
    779	/* for some reason there are different event types for 1 and >1 */
    780	if (value == 1)
    781		wl->conf.conn.wake_up_event = CONF_WAKE_UP_EVENT_BEACON;
    782	else
    783		wl->conf.conn.wake_up_event = CONF_WAKE_UP_EVENT_N_BEACONS;
    784
    785	/*
    786	 * we don't reconfigure ACX_WAKE_UP_CONDITIONS now, so it will only
    787	 * take effect on the next time we enter psm.
    788	 */
    789	mutex_unlock(&wl->mutex);
    790	return count;
    791}
    792
    793static const struct file_operations beacon_interval_ops = {
    794	.read = beacon_interval_read,
    795	.write = beacon_interval_write,
    796	.open = simple_open,
    797	.llseek = default_llseek,
    798};
    799
    800static ssize_t rx_streaming_interval_write(struct file *file,
    801			   const char __user *user_buf,
    802			   size_t count, loff_t *ppos)
    803{
    804	struct wl1271 *wl = file->private_data;
    805	struct wl12xx_vif *wlvif;
    806	unsigned long value;
    807	int ret;
    808
    809	ret = kstrtoul_from_user(user_buf, count, 10, &value);
    810	if (ret < 0) {
    811		wl1271_warning("illegal value in rx_streaming_interval!");
    812		return -EINVAL;
    813	}
    814
    815	/* valid values: 0, 10-100 */
    816	if (value && (value < 10 || value > 100)) {
    817		wl1271_warning("value is not in range!");
    818		return -ERANGE;
    819	}
    820
    821	mutex_lock(&wl->mutex);
    822
    823	wl->conf.rx_streaming.interval = value;
    824
    825	ret = pm_runtime_resume_and_get(wl->dev);
    826	if (ret < 0)
    827		goto out;
    828
    829	wl12xx_for_each_wlvif_sta(wl, wlvif) {
    830		wl1271_recalc_rx_streaming(wl, wlvif);
    831	}
    832
    833	pm_runtime_mark_last_busy(wl->dev);
    834	pm_runtime_put_autosuspend(wl->dev);
    835out:
    836	mutex_unlock(&wl->mutex);
    837	return count;
    838}
    839
    840static ssize_t rx_streaming_interval_read(struct file *file,
    841			    char __user *userbuf,
    842			    size_t count, loff_t *ppos)
    843{
    844	struct wl1271 *wl = file->private_data;
    845	return wl1271_format_buffer(userbuf, count, ppos,
    846				    "%d\n", wl->conf.rx_streaming.interval);
    847}
    848
    849static const struct file_operations rx_streaming_interval_ops = {
    850	.read = rx_streaming_interval_read,
    851	.write = rx_streaming_interval_write,
    852	.open = simple_open,
    853	.llseek = default_llseek,
    854};
    855
    856static ssize_t rx_streaming_always_write(struct file *file,
    857			   const char __user *user_buf,
    858			   size_t count, loff_t *ppos)
    859{
    860	struct wl1271 *wl = file->private_data;
    861	struct wl12xx_vif *wlvif;
    862	unsigned long value;
    863	int ret;
    864
    865	ret = kstrtoul_from_user(user_buf, count, 10, &value);
    866	if (ret < 0) {
    867		wl1271_warning("illegal value in rx_streaming_write!");
    868		return -EINVAL;
    869	}
    870
    871	/* valid values: 0, 10-100 */
    872	if (!(value == 0 || value == 1)) {
    873		wl1271_warning("value is not in valid!");
    874		return -EINVAL;
    875	}
    876
    877	mutex_lock(&wl->mutex);
    878
    879	wl->conf.rx_streaming.always = value;
    880
    881	ret = pm_runtime_resume_and_get(wl->dev);
    882	if (ret < 0)
    883		goto out;
    884
    885	wl12xx_for_each_wlvif_sta(wl, wlvif) {
    886		wl1271_recalc_rx_streaming(wl, wlvif);
    887	}
    888
    889	pm_runtime_mark_last_busy(wl->dev);
    890	pm_runtime_put_autosuspend(wl->dev);
    891out:
    892	mutex_unlock(&wl->mutex);
    893	return count;
    894}
    895
    896static ssize_t rx_streaming_always_read(struct file *file,
    897			    char __user *userbuf,
    898			    size_t count, loff_t *ppos)
    899{
    900	struct wl1271 *wl = file->private_data;
    901	return wl1271_format_buffer(userbuf, count, ppos,
    902				    "%d\n", wl->conf.rx_streaming.always);
    903}
    904
    905static const struct file_operations rx_streaming_always_ops = {
    906	.read = rx_streaming_always_read,
    907	.write = rx_streaming_always_write,
    908	.open = simple_open,
    909	.llseek = default_llseek,
    910};
    911
    912static ssize_t beacon_filtering_write(struct file *file,
    913				      const char __user *user_buf,
    914				      size_t count, loff_t *ppos)
    915{
    916	struct wl1271 *wl = file->private_data;
    917	struct wl12xx_vif *wlvif;
    918	unsigned long value;
    919	int ret;
    920
    921	ret = kstrtoul_from_user(user_buf, count, 0, &value);
    922	if (ret < 0) {
    923		wl1271_warning("illegal value for beacon_filtering!");
    924		return -EINVAL;
    925	}
    926
    927	mutex_lock(&wl->mutex);
    928
    929	ret = pm_runtime_resume_and_get(wl->dev);
    930	if (ret < 0)
    931		goto out;
    932
    933	wl12xx_for_each_wlvif(wl, wlvif) {
    934		ret = wl1271_acx_beacon_filter_opt(wl, wlvif, !!value);
    935	}
    936
    937	pm_runtime_mark_last_busy(wl->dev);
    938	pm_runtime_put_autosuspend(wl->dev);
    939out:
    940	mutex_unlock(&wl->mutex);
    941	return count;
    942}
    943
    944static const struct file_operations beacon_filtering_ops = {
    945	.write = beacon_filtering_write,
    946	.open = simple_open,
    947	.llseek = default_llseek,
    948};
    949
    950static ssize_t fw_stats_raw_read(struct file *file,
    951				 char __user *userbuf,
    952				 size_t count, loff_t *ppos)
    953{
    954	struct wl1271 *wl = file->private_data;
    955
    956	wl1271_debugfs_update_stats(wl);
    957
    958	return simple_read_from_buffer(userbuf, count, ppos,
    959				       wl->stats.fw_stats,
    960				       wl->stats.fw_stats_len);
    961}
    962
    963static const struct file_operations fw_stats_raw_ops = {
    964	.read = fw_stats_raw_read,
    965	.open = simple_open,
    966	.llseek = default_llseek,
    967};
    968
    969static ssize_t sleep_auth_read(struct file *file, char __user *user_buf,
    970			       size_t count, loff_t *ppos)
    971{
    972	struct wl1271 *wl = file->private_data;
    973
    974	return wl1271_format_buffer(user_buf, count,
    975				    ppos, "%d\n",
    976				    wl->sleep_auth);
    977}
    978
    979static ssize_t sleep_auth_write(struct file *file,
    980				const char __user *user_buf,
    981				size_t count, loff_t *ppos)
    982{
    983	struct wl1271 *wl = file->private_data;
    984	unsigned long value;
    985	int ret;
    986
    987	ret = kstrtoul_from_user(user_buf, count, 0, &value);
    988	if (ret < 0) {
    989		wl1271_warning("illegal value in sleep_auth");
    990		return -EINVAL;
    991	}
    992
    993	if (value > WL1271_PSM_MAX) {
    994		wl1271_warning("sleep_auth must be between 0 and %d",
    995			       WL1271_PSM_MAX);
    996		return -ERANGE;
    997	}
    998
    999	mutex_lock(&wl->mutex);
   1000
   1001	wl->conf.conn.sta_sleep_auth = value;
   1002
   1003	if (unlikely(wl->state != WLCORE_STATE_ON)) {
   1004		/* this will show up on "read" in case we are off */
   1005		wl->sleep_auth = value;
   1006		goto out;
   1007	}
   1008
   1009	ret = pm_runtime_resume_and_get(wl->dev);
   1010	if (ret < 0)
   1011		goto out;
   1012
   1013	ret = wl1271_acx_sleep_auth(wl, value);
   1014	if (ret < 0)
   1015		goto out_sleep;
   1016
   1017out_sleep:
   1018	pm_runtime_mark_last_busy(wl->dev);
   1019	pm_runtime_put_autosuspend(wl->dev);
   1020out:
   1021	mutex_unlock(&wl->mutex);
   1022	return count;
   1023}
   1024
   1025static const struct file_operations sleep_auth_ops = {
   1026	.read = sleep_auth_read,
   1027	.write = sleep_auth_write,
   1028	.open = simple_open,
   1029	.llseek = default_llseek,
   1030};
   1031
   1032static ssize_t dev_mem_read(struct file *file,
   1033	     char __user *user_buf, size_t count,
   1034	     loff_t *ppos)
   1035{
   1036	struct wl1271 *wl = file->private_data;
   1037	struct wlcore_partition_set part, old_part;
   1038	size_t bytes = count;
   1039	int ret;
   1040	char *buf;
   1041
   1042	/* only requests of dword-aligned size and offset are supported */
   1043	if (bytes % 4)
   1044		return -EINVAL;
   1045
   1046	if (*ppos % 4)
   1047		return -EINVAL;
   1048
   1049	/* function should return in reasonable time */
   1050	bytes = min(bytes, WLCORE_MAX_BLOCK_SIZE);
   1051
   1052	if (bytes == 0)
   1053		return -EINVAL;
   1054
   1055	memset(&part, 0, sizeof(part));
   1056	part.mem.start = *ppos;
   1057	part.mem.size = bytes;
   1058
   1059	buf = kmalloc(bytes, GFP_KERNEL);
   1060	if (!buf)
   1061		return -ENOMEM;
   1062
   1063	mutex_lock(&wl->mutex);
   1064
   1065	if (unlikely(wl->state == WLCORE_STATE_OFF)) {
   1066		ret = -EFAULT;
   1067		goto skip_read;
   1068	}
   1069
   1070	/*
   1071	 * Don't fail if elp_wakeup returns an error, so the device's memory
   1072	 * could be read even if the FW crashed
   1073	 */
   1074	pm_runtime_get_sync(wl->dev);
   1075
   1076	/* store current partition and switch partition */
   1077	memcpy(&old_part, &wl->curr_part, sizeof(old_part));
   1078	ret = wlcore_set_partition(wl, &part);
   1079	if (ret < 0)
   1080		goto part_err;
   1081
   1082	ret = wlcore_raw_read(wl, 0, buf, bytes, false);
   1083	if (ret < 0)
   1084		goto read_err;
   1085
   1086read_err:
   1087	/* recover partition */
   1088	ret = wlcore_set_partition(wl, &old_part);
   1089	if (ret < 0)
   1090		goto part_err;
   1091
   1092part_err:
   1093	pm_runtime_mark_last_busy(wl->dev);
   1094	pm_runtime_put_autosuspend(wl->dev);
   1095
   1096skip_read:
   1097	mutex_unlock(&wl->mutex);
   1098
   1099	if (ret == 0) {
   1100		ret = copy_to_user(user_buf, buf, bytes);
   1101		if (ret < bytes) {
   1102			bytes -= ret;
   1103			*ppos += bytes;
   1104			ret = 0;
   1105		} else {
   1106			ret = -EFAULT;
   1107		}
   1108	}
   1109
   1110	kfree(buf);
   1111
   1112	return ((ret == 0) ? bytes : ret);
   1113}
   1114
   1115static ssize_t dev_mem_write(struct file *file, const char __user *user_buf,
   1116		size_t count, loff_t *ppos)
   1117{
   1118	struct wl1271 *wl = file->private_data;
   1119	struct wlcore_partition_set part, old_part;
   1120	size_t bytes = count;
   1121	int ret;
   1122	char *buf;
   1123
   1124	/* only requests of dword-aligned size and offset are supported */
   1125	if (bytes % 4)
   1126		return -EINVAL;
   1127
   1128	if (*ppos % 4)
   1129		return -EINVAL;
   1130
   1131	/* function should return in reasonable time */
   1132	bytes = min(bytes, WLCORE_MAX_BLOCK_SIZE);
   1133
   1134	if (bytes == 0)
   1135		return -EINVAL;
   1136
   1137	memset(&part, 0, sizeof(part));
   1138	part.mem.start = *ppos;
   1139	part.mem.size = bytes;
   1140
   1141	buf = memdup_user(user_buf, bytes);
   1142	if (IS_ERR(buf))
   1143		return PTR_ERR(buf);
   1144
   1145	mutex_lock(&wl->mutex);
   1146
   1147	if (unlikely(wl->state == WLCORE_STATE_OFF)) {
   1148		ret = -EFAULT;
   1149		goto skip_write;
   1150	}
   1151
   1152	/*
   1153	 * Don't fail if elp_wakeup returns an error, so the device's memory
   1154	 * could be read even if the FW crashed
   1155	 */
   1156	pm_runtime_get_sync(wl->dev);
   1157
   1158	/* store current partition and switch partition */
   1159	memcpy(&old_part, &wl->curr_part, sizeof(old_part));
   1160	ret = wlcore_set_partition(wl, &part);
   1161	if (ret < 0)
   1162		goto part_err;
   1163
   1164	ret = wlcore_raw_write(wl, 0, buf, bytes, false);
   1165	if (ret < 0)
   1166		goto write_err;
   1167
   1168write_err:
   1169	/* recover partition */
   1170	ret = wlcore_set_partition(wl, &old_part);
   1171	if (ret < 0)
   1172		goto part_err;
   1173
   1174part_err:
   1175	pm_runtime_mark_last_busy(wl->dev);
   1176	pm_runtime_put_autosuspend(wl->dev);
   1177
   1178skip_write:
   1179	mutex_unlock(&wl->mutex);
   1180
   1181	if (ret == 0)
   1182		*ppos += bytes;
   1183
   1184	kfree(buf);
   1185
   1186	return ((ret == 0) ? bytes : ret);
   1187}
   1188
   1189static loff_t dev_mem_seek(struct file *file, loff_t offset, int orig)
   1190{
   1191	/* only requests of dword-aligned size and offset are supported */
   1192	if (offset % 4)
   1193		return -EINVAL;
   1194
   1195	return no_seek_end_llseek(file, offset, orig);
   1196}
   1197
   1198static const struct file_operations dev_mem_ops = {
   1199	.open = simple_open,
   1200	.read = dev_mem_read,
   1201	.write = dev_mem_write,
   1202	.llseek = dev_mem_seek,
   1203};
   1204
   1205static ssize_t fw_logger_read(struct file *file, char __user *user_buf,
   1206			      size_t count, loff_t *ppos)
   1207{
   1208	struct wl1271 *wl = file->private_data;
   1209
   1210	return wl1271_format_buffer(user_buf, count,
   1211					ppos, "%d\n",
   1212					wl->conf.fwlog.output);
   1213}
   1214
   1215static ssize_t fw_logger_write(struct file *file,
   1216			       const char __user *user_buf,
   1217			       size_t count, loff_t *ppos)
   1218{
   1219	struct wl1271 *wl = file->private_data;
   1220	unsigned long value;
   1221	int ret;
   1222
   1223	ret = kstrtoul_from_user(user_buf, count, 0, &value);
   1224	if (ret < 0) {
   1225		wl1271_warning("illegal value in fw_logger");
   1226		return -EINVAL;
   1227	}
   1228
   1229	if ((value > 2) || (value == 0)) {
   1230		wl1271_warning("fw_logger value must be 1-UART 2-SDIO");
   1231		return -ERANGE;
   1232	}
   1233
   1234	if (wl->conf.fwlog.output == 0) {
   1235		wl1271_warning("invalid operation - fw logger disabled by default, please change mode via wlconf");
   1236		return -EINVAL;
   1237	}
   1238
   1239	mutex_lock(&wl->mutex);
   1240	ret = pm_runtime_resume_and_get(wl->dev);
   1241	if (ret < 0) {
   1242		count = ret;
   1243		goto out;
   1244	}
   1245
   1246	wl->conf.fwlog.output = value;
   1247
   1248	ret = wl12xx_cmd_config_fwlog(wl);
   1249
   1250	pm_runtime_mark_last_busy(wl->dev);
   1251	pm_runtime_put_autosuspend(wl->dev);
   1252
   1253out:
   1254	mutex_unlock(&wl->mutex);
   1255	return count;
   1256}
   1257
   1258static const struct file_operations fw_logger_ops = {
   1259	.open = simple_open,
   1260	.read = fw_logger_read,
   1261	.write = fw_logger_write,
   1262	.llseek = default_llseek,
   1263};
   1264
   1265static void wl1271_debugfs_add_files(struct wl1271 *wl,
   1266				     struct dentry *rootdir)
   1267{
   1268	struct dentry *streaming;
   1269
   1270	DEBUGFS_ADD(tx_queue_len, rootdir);
   1271	DEBUGFS_ADD(retry_count, rootdir);
   1272	DEBUGFS_ADD(excessive_retries, rootdir);
   1273
   1274	DEBUGFS_ADD(gpio_power, rootdir);
   1275	DEBUGFS_ADD(start_recovery, rootdir);
   1276	DEBUGFS_ADD(driver_state, rootdir);
   1277	DEBUGFS_ADD(vifs_state, rootdir);
   1278	DEBUGFS_ADD(dtim_interval, rootdir);
   1279	DEBUGFS_ADD(suspend_dtim_interval, rootdir);
   1280	DEBUGFS_ADD(beacon_interval, rootdir);
   1281	DEBUGFS_ADD(beacon_filtering, rootdir);
   1282	DEBUGFS_ADD(dynamic_ps_timeout, rootdir);
   1283	DEBUGFS_ADD(forced_ps, rootdir);
   1284	DEBUGFS_ADD(split_scan_timeout, rootdir);
   1285	DEBUGFS_ADD(irq_pkt_threshold, rootdir);
   1286	DEBUGFS_ADD(irq_blk_threshold, rootdir);
   1287	DEBUGFS_ADD(irq_timeout, rootdir);
   1288	DEBUGFS_ADD(fw_stats_raw, rootdir);
   1289	DEBUGFS_ADD(sleep_auth, rootdir);
   1290	DEBUGFS_ADD(fw_logger, rootdir);
   1291
   1292	streaming = debugfs_create_dir("rx_streaming", rootdir);
   1293
   1294	DEBUGFS_ADD_PREFIX(rx_streaming, interval, streaming);
   1295	DEBUGFS_ADD_PREFIX(rx_streaming, always, streaming);
   1296
   1297	DEBUGFS_ADD_PREFIX(dev, mem, rootdir);
   1298}
   1299
   1300void wl1271_debugfs_reset(struct wl1271 *wl)
   1301{
   1302	if (!wl->stats.fw_stats)
   1303		return;
   1304
   1305	memset(wl->stats.fw_stats, 0, wl->stats.fw_stats_len);
   1306	wl->stats.retry_count = 0;
   1307	wl->stats.excessive_retries = 0;
   1308}
   1309
   1310int wl1271_debugfs_init(struct wl1271 *wl)
   1311{
   1312	int ret;
   1313	struct dentry *rootdir;
   1314
   1315	rootdir = debugfs_create_dir(KBUILD_MODNAME,
   1316				     wl->hw->wiphy->debugfsdir);
   1317
   1318	wl->stats.fw_stats = kzalloc(wl->stats.fw_stats_len, GFP_KERNEL);
   1319	if (!wl->stats.fw_stats) {
   1320		ret = -ENOMEM;
   1321		goto out_remove;
   1322	}
   1323
   1324	wl->stats.fw_stats_update = jiffies;
   1325
   1326	wl1271_debugfs_add_files(wl, rootdir);
   1327
   1328	ret = wlcore_debugfs_init(wl, rootdir);
   1329	if (ret < 0)
   1330		goto out_exit;
   1331
   1332	goto out;
   1333
   1334out_exit:
   1335	wl1271_debugfs_exit(wl);
   1336
   1337out_remove:
   1338	debugfs_remove_recursive(rootdir);
   1339
   1340out:
   1341	return ret;
   1342}
   1343
   1344void wl1271_debugfs_exit(struct wl1271 *wl)
   1345{
   1346	kfree(wl->stats.fw_stats);
   1347	wl->stats.fw_stats = NULL;
   1348}